507 lines · cpp
1//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This file implements the lowering of LLVM calls to machine code calls for11/// GlobalISel.12//13//===----------------------------------------------------------------------===//14 15#include "MipsCallLowering.h"16#include "MipsCCState.h"17#include "MipsMachineFunction.h"18#include "MipsTargetMachine.h"19#include "llvm/CodeGen/Analysis.h"20#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22 23using namespace llvm;24 25MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)26 : CallLowering(&TLI) {}27 28namespace {29class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler {30 const MipsSubtarget &STI;31 32public:33 MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder,34 MachineRegisterInfo &MRI)35 : IncomingValueHandler(MIRBuilder, MRI),36 STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {}37 38private:39 void assignValueToReg(Register ValVReg, Register PhysReg,40 const CCValAssign &VA) override;41 42 Register getStackAddress(uint64_t Size, int64_t Offset,43 MachinePointerInfo &MPO,44 ISD::ArgFlagsTy Flags) override;45 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,46 const MachinePointerInfo &MPO,47 const CCValAssign &VA) override;48 49 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,50 ArrayRef<CCValAssign> VAs,51 std::function<void()> *Thunk = nullptr) override;52 53 virtual void markPhysRegUsed(unsigned PhysReg) {54 MIRBuilder.getMRI()->addLiveIn(PhysReg);55 MIRBuilder.getMBB().addLiveIn(PhysReg);56 }57};58 59class CallReturnHandler : public MipsIncomingValueHandler {60public:61 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,62 MachineInstrBuilder &MIB)63 : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}64 65private:66 void markPhysRegUsed(unsigned PhysReg) override {67 MIB.addDef(PhysReg, RegState::Implicit);68 }69 70 MachineInstrBuilder &MIB;71};72 73} // end anonymous namespace74 75void MipsIncomingValueHandler::assignValueToReg(Register ValVReg,76 Register PhysReg,77 const CCValAssign &VA) {78 markPhysRegUsed(PhysReg);79 IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);80}81 82Register MipsIncomingValueHandler::getStackAddress(uint64_t Size,83 int64_t Offset,84 MachinePointerInfo &MPO,85 ISD::ArgFlagsTy Flags) {86 87 MachineFunction &MF = MIRBuilder.getMF();88 MachineFrameInfo &MFI = MF.getFrameInfo();89 90 // FIXME: This should only be immutable for non-byval memory arguments.91 int FI = MFI.CreateFixedObject(Size, Offset, true);92 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);93 94 return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0);95}96 97void MipsIncomingValueHandler::assignValueToAddress(98 Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,99 const CCValAssign &VA) {100 MachineFunction &MF = MIRBuilder.getMF();101 auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,102 inferAlignFromPtrInfo(MF, MPO));103 MIRBuilder.buildLoad(ValVReg, Addr, *MMO);104}105 106/// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom107/// assignment because generic code assumes getNumRegistersForCallingConv is108/// accurate. In this case it is not because the type/number are context109/// dependent on other arguments.110unsigned111MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,112 ArrayRef<CCValAssign> VAs,113 std::function<void()> *Thunk) {114 const CCValAssign &VALo = VAs[0];115 const CCValAssign &VAHi = VAs[1];116 117 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&118 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&119 "unexpected custom value");120 121 auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg());122 auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg());123 if (!STI.isLittle())124 std::swap(CopyLo, CopyHi);125 126 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());127 Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) };128 MIRBuilder.buildMergeLikeInstr(Arg.OrigRegs[0], {CopyLo, CopyHi});129 130 markPhysRegUsed(VALo.getLocReg());131 markPhysRegUsed(VAHi.getLocReg());132 return 2;133}134 135namespace {136class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler {137 const MipsSubtarget &STI;138 139public:140 MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder,141 MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)142 : OutgoingValueHandler(MIRBuilder, MRI),143 STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {}144 145private:146 void assignValueToReg(Register ValVReg, Register PhysReg,147 const CCValAssign &VA) override;148 149 Register getStackAddress(uint64_t Size, int64_t Offset,150 MachinePointerInfo &MPO,151 ISD::ArgFlagsTy Flags) override;152 153 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,154 const MachinePointerInfo &MPO,155 const CCValAssign &VA) override;156 unsigned assignCustomValue(CallLowering::ArgInfo &Arg,157 ArrayRef<CCValAssign> VAs,158 std::function<void()> *Thunk) override;159 160 MachineInstrBuilder &MIB;161};162} // end anonymous namespace163 164void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg,165 Register PhysReg,166 const CCValAssign &VA) {167 Register ExtReg = extendRegister(ValVReg, VA);168 MIRBuilder.buildCopy(PhysReg, ExtReg);169 MIB.addUse(PhysReg, RegState::Implicit);170}171 172Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size,173 int64_t Offset,174 MachinePointerInfo &MPO,175 ISD::ArgFlagsTy Flags) {176 MachineFunction &MF = MIRBuilder.getMF();177 MPO = MachinePointerInfo::getStack(MF, Offset);178 179 LLT p0 = LLT::pointer(0, 32);180 LLT s32 = LLT::scalar(32);181 auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP));182 183 auto OffsetReg = MIRBuilder.buildConstant(s32, Offset);184 auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);185 return AddrReg.getReg(0);186}187 188void MipsOutgoingValueHandler::assignValueToAddress(189 Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,190 const CCValAssign &VA) {191 MachineFunction &MF = MIRBuilder.getMF();192 uint64_t LocMemOffset = VA.getLocMemOffset();193 194 auto MMO = MF.getMachineMemOperand(195 MPO, MachineMemOperand::MOStore, MemTy,196 commonAlignment(STI.getStackAlignment(), LocMemOffset));197 198 Register ExtReg = extendRegister(ValVReg, VA);199 MIRBuilder.buildStore(ExtReg, Addr, *MMO);200}201 202unsigned203MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg,204 ArrayRef<CCValAssign> VAs,205 std::function<void()> *Thunk) {206 const CCValAssign &VALo = VAs[0];207 const CCValAssign &VAHi = VAs[1];208 209 assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&210 VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&211 "unexpected custom value");212 213 auto Unmerge =214 MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]);215 Register Lo = Unmerge.getReg(0);216 Register Hi = Unmerge.getReg(1);217 218 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());219 Arg.Regs = { Lo, Hi };220 if (!STI.isLittle())221 std::swap(Lo, Hi);222 223 // If we can return a thunk, just include the register copies. The unmerge can224 // be emitted earlier.225 if (Thunk) {226 *Thunk = [=]() {227 MIRBuilder.buildCopy(VALo.getLocReg(), Lo);228 MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);229 };230 return 2;231 }232 MIRBuilder.buildCopy(VALo.getLocReg(), Lo);233 MIRBuilder.buildCopy(VAHi.getLocReg(), Hi);234 return 2;235}236 237static bool isSupportedArgumentType(Type *T) {238 if (T->isIntegerTy())239 return true;240 if (T->isPointerTy())241 return true;242 if (T->isFloatingPointTy())243 return true;244 return false;245}246 247static bool isSupportedReturnType(Type *T) {248 if (T->isIntegerTy())249 return true;250 if (T->isPointerTy())251 return true;252 if (T->isFloatingPointTy())253 return true;254 if (T->isAggregateType())255 return true;256 return false;257}258 259bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,260 const Value *Val, ArrayRef<Register> VRegs,261 FunctionLoweringInfo &FLI) const {262 263 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);264 265 if (Val != nullptr && !isSupportedReturnType(Val->getType()))266 return false;267 268 if (!VRegs.empty()) {269 MachineFunction &MF = MIRBuilder.getMF();270 const Function &F = MF.getFunction();271 const DataLayout &DL = MF.getDataLayout();272 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();273 274 SmallVector<ArgInfo, 8> RetInfos;275 276 ArgInfo ArgRetInfo(VRegs, *Val, 0);277 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);278 splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv());279 280 SmallVector<CCValAssign, 16> ArgLocs;281 282 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,283 F.getContext());284 285 MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);286 OutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn());287 288 if (!determineAssignments(Assigner, RetInfos, CCInfo))289 return false;290 291 if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder))292 return false;293 }294 295 MIRBuilder.insertInstr(Ret);296 return true;297}298 299bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,300 const Function &F,301 ArrayRef<ArrayRef<Register>> VRegs,302 FunctionLoweringInfo &FLI) const {303 304 // Quick exit if there aren't any args.305 if (F.arg_empty())306 return true;307 308 for (auto &Arg : F.args()) {309 if (!isSupportedArgumentType(Arg.getType()))310 return false;311 }312 313 MachineFunction &MF = MIRBuilder.getMF();314 const DataLayout &DL = MF.getDataLayout();315 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();316 317 SmallVector<ArgInfo, 8> ArgInfos;318 unsigned i = 0;319 for (auto &Arg : F.args()) {320 ArgInfo AInfo(VRegs[i], Arg, i);321 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);322 323 splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv());324 ++i;325 }326 327 SmallVector<CCValAssign, 16> ArgLocs;328 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,329 F.getContext());330 331 const MipsTargetMachine &TM =332 static_cast<const MipsTargetMachine &>(MF.getTarget());333 const MipsABIInfo &ABI = TM.getABI();334 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),335 Align(1));336 337 IncomingValueAssigner Assigner(TLI.CCAssignFnForCall());338 if (!determineAssignments(Assigner, ArgInfos, CCInfo))339 return false;340 341 MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());342 if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))343 return false;344 345 if (F.isVarArg()) {346 ArrayRef<MCPhysReg> ArgRegs =347 ABI.getVarArgRegs(MF.getSubtarget<MipsSubtarget>().isGP64bit());348 unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);349 350 int VaArgOffset;351 unsigned RegSize = 4;352 if (ArgRegs.size() == Idx)353 VaArgOffset = alignTo(CCInfo.getStackSize(), RegSize);354 else {355 VaArgOffset =356 (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) -357 (int)(RegSize * (ArgRegs.size() - Idx));358 }359 360 MachineFrameInfo &MFI = MF.getFrameInfo();361 int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);362 MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI);363 364 for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) {365 MIRBuilder.getMBB().addLiveIn(ArgRegs[I]);366 LLT RegTy = LLT::scalar(RegSize * 8);367 MachineInstrBuilder Copy =368 MIRBuilder.buildCopy(RegTy, Register(ArgRegs[I]));369 FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true);370 MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI);371 372 const LLT PtrTy = LLT::pointer(MPO.getAddrSpace(), 32);373 auto FrameIndex = MIRBuilder.buildFrameIndex(PtrTy, FI);374 MachineMemOperand *MMO = MF.getMachineMemOperand(375 MPO, MachineMemOperand::MOStore, RegTy, Align(RegSize));376 MIRBuilder.buildStore(Copy, FrameIndex, *MMO);377 }378 }379 380 return true;381}382 383bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,384 CallLoweringInfo &Info) const {385 386 if (Info.CallConv != CallingConv::C)387 return false;388 389 for (auto &Arg : Info.OrigArgs) {390 if (!isSupportedArgumentType(Arg.Ty))391 return false;392 if (Arg.Flags[0].isByVal())393 return false;394 if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy())395 return false;396 }397 398 if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty))399 return false;400 401 MachineFunction &MF = MIRBuilder.getMF();402 const Function &F = MF.getFunction();403 const DataLayout &DL = MF.getDataLayout();404 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();405 const MipsTargetMachine &TM =406 static_cast<const MipsTargetMachine &>(MF.getTarget());407 const MipsABIInfo &ABI = TM.getABI();408 409 MachineInstrBuilder CallSeqStart =410 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);411 412 const bool IsCalleeGlobalPIC =413 Info.Callee.isGlobal() && TM.isPositionIndependent();414 415 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(416 Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);417 MIB.addDef(Mips::SP, RegState::Implicit);418 if (IsCalleeGlobalPIC) {419 Register CalleeReg =420 MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32));421 MachineInstr *CalleeGlobalValue =422 MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal());423 if (!Info.Callee.getGlobal()->hasLocalLinkage())424 CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL);425 MIB.addUse(CalleeReg);426 } else427 MIB.add(Info.Callee);428 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();429 MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));430 431 TargetLowering::ArgListTy FuncOrigArgs;432 FuncOrigArgs.reserve(Info.OrigArgs.size());433 434 SmallVector<ArgInfo, 8> ArgInfos;435 for (auto &Arg : Info.OrigArgs)436 splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv);437 438 SmallVector<CCValAssign, 8> ArgLocs;439 bool IsCalleeVarArg = false;440 if (Info.Callee.isGlobal()) {441 const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal());442 IsCalleeVarArg = CF->isVarArg();443 }444 445 // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it446 // depends on looking directly at the call target.447 MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs,448 F.getContext());449 450 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv),451 Align(1));452 453 OutgoingValueAssigner Assigner(TLI.CCAssignFnForCall());454 if (!determineAssignments(Assigner, ArgInfos, CCInfo))455 return false;456 457 MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB);458 if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))459 return false;460 461 unsigned StackSize = CCInfo.getStackSize();462 unsigned StackAlignment = F.getParent()->getOverrideStackAlignment();463 if (!StackAlignment) {464 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();465 StackAlignment = TFL->getStackAlignment();466 }467 StackSize = alignTo(StackSize, StackAlignment);468 CallSeqStart.addImm(StackSize).addImm(0);469 470 if (IsCalleeGlobalPIC) {471 MIRBuilder.buildCopy(472 Register(Mips::GP),473 MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF));474 MIB.addDef(Mips::GP, RegState::Implicit);475 }476 MIRBuilder.insertInstr(MIB);477 if (MIB->getOpcode() == Mips::JALRPseudo) {478 const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>();479 MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),480 *STI.getRegBankInfo());481 }482 483 if (!Info.OrigRet.Ty->isVoidTy()) {484 ArgInfos.clear();485 486 CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL,487 F.getCallingConv());488 489 SmallVector<CCValAssign, 8> ArgLocs;490 IncomingValueAssigner Assigner(TLI.CCAssignFnForReturn());491 CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);492 493 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,494 F.getContext());495 496 if (!determineAssignments(Assigner, ArgInfos, CCInfo))497 return false;498 499 if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder))500 return false;501 }502 503 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(StackSize).addImm(0);504 505 return true;506}507