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, CCAssignFn *AssignFn) 47 : ValueHandler(MIRBuilder, MRI, AssignFn), 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, AssignFn); 103 return handleAssignments(MIRBuilder, 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 = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL)); 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 CCAssignFn AssignFn) 123 : ValueHandler(MIRBuilder, MRI, AssignFn) {} 124 125 unsigned getStackAddress(uint64_t Size, int64_t Offset, 126 MachinePointerInfo &MPO) override { 127 assert(Size == 4 && "Unsupported size"); 128 129 auto &MFI = MIRBuilder.getMF().getFrameInfo(); 130 131 int FI = MFI.CreateFixedObject(Size, Offset, true); 132 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 133 134 unsigned AddrReg = 135 MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32)); 136 MIRBuilder.buildFrameIndex(AddrReg, FI); 137 138 return AddrReg; 139 } 140 141 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 142 MachinePointerInfo &MPO, CCValAssign &VA) override { 143 assert(Size == 4 && "Unsupported size"); 144 145 auto MMO = MIRBuilder.getMF().getMachineMemOperand( 146 MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0); 147 MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 148 } 149 150 void assignValueToReg(unsigned ValVReg, unsigned PhysReg, 151 CCValAssign &VA) override { 152 assert(VA.isRegLoc() && "Value shouldn't be assigned to reg"); 153 assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?"); 154 155 assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size"); 156 assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size"); 157 158 MIRBuilder.getMBB().addLiveIn(PhysReg); 159 MIRBuilder.buildCopy(ValVReg, PhysReg); 160 } 161 }; 162 } // End anonymous namespace 163 164 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 165 const Function &F, 166 ArrayRef<unsigned> VRegs) const { 167 // Quick exit if there aren't any args 168 if (F.arg_empty()) 169 return true; 170 171 if (F.isVarArg()) 172 return false; 173 174 auto DL = MIRBuilder.getMF().getDataLayout(); 175 auto &TLI = *getTLI<ARMTargetLowering>(); 176 177 auto &Args = F.getArgumentList(); 178 unsigned ArgIdx = 0; 179 for (auto &Arg : Args) { 180 ArgIdx++; 181 if (!isSupportedType(DL, TLI, Arg.getType())) 182 return false; 183 184 // FIXME: This check as well as ArgIdx are going away as soon as we support 185 // loading values < 32 bits. 186 if (ArgIdx > 4 && Arg.getType()->getIntegerBitWidth() != 32) 187 return false; 188 } 189 190 CCAssignFn *AssignFn = 191 TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg()); 192 193 SmallVector<ArgInfo, 8> ArgInfos; 194 unsigned Idx = 0; 195 for (auto &Arg : Args) { 196 ArgInfo AInfo(VRegs[Idx], Arg.getType()); 197 setArgFlags(AInfo, Idx + 1, DL, F); 198 ArgInfos.push_back(AInfo); 199 Idx++; 200 } 201 202 FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo(), 203 AssignFn); 204 return handleAssignments(MIRBuilder, ArgInfos, ArgHandler); 205 } 206