1 //===-- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering -----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// This file implements the lowering of LLVM calls to machine code calls for 12 /// GlobalISel. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #include "ARMCallLowering.h" 17 18 #include "ARMBaseInstrInfo.h" 19 #include "ARMISelLowering.h" 20 21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 24 using namespace llvm; 25 26 #ifndef LLVM_BUILD_GLOBAL_ISEL 27 #error "This shouldn't be built without GISel" 28 #endif 29 30 ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) 31 : CallLowering(&TLI) {} 32 33 static bool isSupportedType(const DataLayout DL, const ARMTargetLowering &TLI, 34 Type *T) { 35 EVT VT = TLI.getValueType(DL, T); 36 if (!VT.isSimple() || !VT.isInteger() || VT.isVector()) 37 return false; 38 39 unsigned VTSize = VT.getSimpleVT().getSizeInBits(); 40 return VTSize == 8 || VTSize == 16 || VTSize == 32; 41 } 42 43 namespace { 44 struct FuncReturnHandler : public CallLowering::ValueHandler { 45 FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 46 MachineInstrBuilder &MIB) 47 : ValueHandler(MIRBuilder, MRI), MIB(MIB) {} 48 49 unsigned getStackAddress(uint64_t Size, int64_t Offset, 50 MachinePointerInfo &MPO) override { 51 llvm_unreachable("Don't know how to get a stack address yet"); 52 } 53 54 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 55 CCValAssign &VA) override { 56 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 57 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 58 59 assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size"); 60 assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size"); 61 62 assert(VA.getLocInfo() != CCValAssign::SExt && 63 VA.getLocInfo() != CCValAssign::ZExt && 64 "ABI extensions not supported yet"); 65 66 MIRBuilder.buildCopy(PhysReg, ValVReg); 67 MIB.addUse(PhysReg, RegState::Implicit); 68 } 69 70 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 71 MachinePointerInfo &MPO, CCValAssign &VA) override { 72 llvm_unreachable("Don't know how to assign a value to an address yet"); 73 } 74 75 MachineInstrBuilder &MIB; 76 }; 77 } // End anonymous namespace. 78 79 /// Lower the return value for the already existing \p Ret. This assumes that 80 /// \p MIRBuilder's insertion point is correct. 81 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, 82 const Value *Val, unsigned VReg, 83 MachineInstrBuilder &Ret) const { 84 if (!Val) 85 // Nothing to do here. 86 return true; 87 88 auto &MF = MIRBuilder.getMF(); 89 const auto &F = *MF.getFunction(); 90 91 auto DL = MF.getDataLayout(); 92 auto &TLI = *getTLI<ARMTargetLowering>(); 93 if (!isSupportedType(DL, TLI, Val->getType())) 94 return false; 95 96 CCAssignFn *AssignFn = 97 TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); 98 99 ArgInfo RetInfo(VReg, Val->getType()); 100 setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F); 101 102 FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 103 return handleAssignments(MIRBuilder, AssignFn, RetInfo, RetHandler); 104 } 105 106 bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 107 const Value *Val, unsigned VReg) const { 108 assert(!Val == !VReg && "Return value without a vreg"); 109 110 auto Ret = AddDefaultPred(MIRBuilder.buildInstrNoInsert(ARM::BX_RET)); 111 112 if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret)) 113 return false; 114 115 MIRBuilder.insertInstr(Ret); 116 return true; 117 } 118 119 namespace { 120 struct FormalArgHandler : public CallLowering::ValueHandler { 121 FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 122 : ValueHandler(MIRBuilder, MRI) {} 123 124 unsigned getStackAddress(uint64_t Size, int64_t Offset, 125 MachinePointerInfo &MPO) override { 126 assert(Size == 4 && "Unsupported size"); 127 128 auto &MFI = MIRBuilder.getMF().getFrameInfo(); 129 130 int FI = MFI.CreateFixedObject(Size, Offset, true); 131 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 132 133 unsigned AddrReg = 134 MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32)); 135 MIRBuilder.buildFrameIndex(AddrReg, FI); 136 137 return AddrReg; 138 } 139 140 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 141 MachinePointerInfo &MPO, CCValAssign &VA) override { 142 assert(Size == 4 && "Unsupported size"); 143 144 auto MMO = MIRBuilder.getMF().getMachineMemOperand( 145 MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0); 146 MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 147 } 148 149 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 150 CCValAssign &VA) override { 151 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 152 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 153 154 assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size"); 155 assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size"); 156 157 MIRBuilder.getMBB().addLiveIn(PhysReg); 158 MIRBuilder.buildCopy(ValVReg, PhysReg); 159 } 160 }; 161 } // End anonymous namespace 162 163 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 164 const Function &F, 165 ArrayRef<unsigned> VRegs) const { 166 // Quick exit if there aren't any args 167 if (F.arg_empty()) 168 return true; 169 170 if (F.isVarArg()) 171 return false; 172 173 auto DL = MIRBuilder.getMF().getDataLayout(); 174 auto &TLI = *getTLI<ARMTargetLowering>(); 175 176 auto &Args = F.getArgumentList(); 177 unsigned ArgIdx = 0; 178 for (auto &Arg : Args) { 179 ArgIdx++; 180 if (!isSupportedType(DL, TLI, Arg.getType())) 181 return false; 182 183 // FIXME: This check as well as ArgIdx are going away as soon as we support 184 // loading values < 32 bits. 185 if (ArgIdx > 4 && Arg.getType()->getIntegerBitWidth() != 32) 186 return false; 187 } 188 189 CCAssignFn *AssignFn = 190 TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg()); 191 192 SmallVector<ArgInfo, 8> ArgInfos; 193 unsigned Idx = 0; 194 for (auto &Arg : Args) { 195 ArgInfo AInfo(VRegs[Idx], Arg.getType()); 196 setArgFlags(AInfo, Idx + 1, DL, F); 197 ArgInfos.push_back(AInfo); 198 Idx++; 199 } 200 201 FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo()); 202 return handleAssignments(MIRBuilder, AssignFn, ArgInfos, ArgHandler); 203 } 204