1 //===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===// 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 "MipsCallLowering.h" 17 #include "MipsCCState.h" 18 #include "MipsTargetMachine.h" 19 #include "llvm/CodeGen/Analysis.h" 20 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 21 22 using namespace llvm; 23 24 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) 25 : CallLowering(&TLI) {} 26 27 bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, 28 unsigned vreg) { 29 if (VA.isRegLoc()) { 30 assignValueToReg(vreg, VA.getLocReg()); 31 } else if (VA.isMemLoc()) { 32 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; 33 unsigned Offset = VA.getLocMemOffset(); 34 MachinePointerInfo MPO; 35 unsigned StackAddr = getStackAddress(Size, Offset, MPO); 36 assignValueToAddress(vreg, StackAddr, Size, MPO); 37 } else { 38 return false; 39 } 40 return true; 41 } 42 43 namespace { 44 class IncomingValueHandler : public MipsCallLowering::MipsHandler { 45 public: 46 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 47 : MipsHandler(MIRBuilder, MRI) {} 48 49 bool handle(ArrayRef<CCValAssign> ArgLocs, 50 ArrayRef<CallLowering::ArgInfo> Args); 51 52 private: 53 void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 54 55 unsigned getStackAddress(uint64_t Size, int64_t Offset, 56 MachinePointerInfo &MPO) override; 57 58 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 59 MachinePointerInfo &MPO) override; 60 61 virtual void markPhysRegUsed(unsigned PhysReg) { 62 MIRBuilder.getMBB().addLiveIn(PhysReg); 63 } 64 65 void buildLoad(unsigned Val, unsigned Addr, uint64_t Size, unsigned Alignment, 66 MachinePointerInfo &MPO) { 67 MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( 68 MPO, MachineMemOperand::MOLoad, Size, Alignment); 69 MIRBuilder.buildLoad(Val, Addr, *MMO); 70 } 71 }; 72 73 class CallReturnHandler : public IncomingValueHandler { 74 public: 75 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 76 MachineInstrBuilder &MIB) 77 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 78 79 private: 80 void markPhysRegUsed(unsigned PhysReg) override { 81 MIB.addDef(PhysReg, RegState::Implicit); 82 } 83 84 MachineInstrBuilder &MIB; 85 }; 86 87 } // end anonymous namespace 88 89 void IncomingValueHandler::assignValueToReg(unsigned ValVReg, 90 unsigned PhysReg) { 91 MIRBuilder.buildCopy(ValVReg, PhysReg); 92 markPhysRegUsed(PhysReg); 93 } 94 95 unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, 96 MachinePointerInfo &MPO) { 97 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); 98 99 int FI = MFI.CreateFixedObject(Size, Offset, true); 100 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 101 102 unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); 103 MIRBuilder.buildFrameIndex(AddrReg, FI); 104 105 return AddrReg; 106 } 107 108 void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, 109 uint64_t Size, 110 MachinePointerInfo &MPO) { 111 // If the value is not extended, a simple load will suffice. 112 buildLoad(ValVReg, Addr, Size, /* Alignment */ 0, MPO); 113 } 114 115 bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 116 ArrayRef<CallLowering::ArgInfo> Args) { 117 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { 118 if (!assign(ArgLocs[i], Args[i].Reg)) 119 return false; 120 } 121 return true; 122 } 123 124 namespace { 125 class OutgoingValueHandler : public MipsCallLowering::MipsHandler { 126 public: 127 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 128 MachineInstrBuilder &MIB) 129 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} 130 131 bool handle(ArrayRef<CCValAssign> ArgLocs, 132 ArrayRef<CallLowering::ArgInfo> Args); 133 134 private: 135 void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 136 137 unsigned getStackAddress(uint64_t Size, int64_t Offset, 138 MachinePointerInfo &MPO) override; 139 140 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, 141 MachinePointerInfo &MPO) override; 142 143 MachineInstrBuilder &MIB; 144 }; 145 } // end anonymous namespace 146 147 void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, 148 unsigned PhysReg) { 149 MIRBuilder.buildCopy(PhysReg, ValVReg); 150 MIB.addUse(PhysReg, RegState::Implicit); 151 } 152 153 unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, 154 MachinePointerInfo &MPO) { 155 LLT p0 = LLT::pointer(0, 32); 156 LLT s32 = LLT::scalar(32); 157 unsigned SPReg = MRI.createGenericVirtualRegister(p0); 158 MIRBuilder.buildCopy(SPReg, Mips::SP); 159 160 unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); 161 MIRBuilder.buildConstant(OffsetReg, Offset); 162 163 unsigned AddrReg = MRI.createGenericVirtualRegister(p0); 164 MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); 165 166 MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 167 return AddrReg; 168 } 169 170 void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, 171 uint64_t Size, 172 MachinePointerInfo &MPO) { 173 MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( 174 MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0); 175 MIRBuilder.buildStore(ValVReg, Addr, *MMO); 176 } 177 178 bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 179 ArrayRef<CallLowering::ArgInfo> Args) { 180 for (unsigned i = 0; i < Args.size(); ++i) { 181 if (!assign(ArgLocs[i], Args[i].Reg)) 182 return false; 183 } 184 return true; 185 } 186 187 static bool isSupportedType(Type *T) { 188 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) 189 return true; 190 if (T->isPointerTy()) 191 return true; 192 return false; 193 } 194 195 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 196 const Value *Val, 197 ArrayRef<unsigned> VRegs) const { 198 199 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); 200 201 if (Val != nullptr && !isSupportedType(Val->getType())) 202 return false; 203 204 if (!VRegs.empty()) { 205 MachineFunction &MF = MIRBuilder.getMF(); 206 const Function &F = MF.getFunction(); 207 const DataLayout &DL = MF.getDataLayout(); 208 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 209 LLVMContext &Ctx = Val->getType()->getContext(); 210 211 SmallVector<EVT, 4> SplitEVTs; 212 ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); 213 assert(VRegs.size() == SplitEVTs.size() && 214 "For each split Type there should be exactly one VReg."); 215 216 SmallVector<ArgInfo, 8> RetInfos; 217 SmallVector<unsigned, 8> OrigArgIndices; 218 219 for (unsigned i = 0; i < SplitEVTs.size(); ++i) { 220 ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)}; 221 setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); 222 splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices); 223 } 224 225 SmallVector<ISD::OutputArg, 8> Outs; 226 subTargetRegTypeForCallingConv( 227 MIRBuilder, RetInfos, OrigArgIndices, 228 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 229 unsigned origIdx, unsigned partOffs) { 230 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 231 }); 232 233 SmallVector<CCValAssign, 16> ArgLocs; 234 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 235 F.getContext()); 236 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); 237 238 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 239 if (!RetHandler.handle(ArgLocs, RetInfos)) { 240 return false; 241 } 242 } 243 MIRBuilder.insertInstr(Ret); 244 return true; 245 } 246 247 bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 248 const Function &F, 249 ArrayRef<unsigned> VRegs) const { 250 251 // Quick exit if there aren't any args. 252 if (F.arg_empty()) 253 return true; 254 255 if (F.isVarArg()) { 256 return false; 257 } 258 259 for (auto &Arg : F.args()) { 260 if (!isSupportedType(Arg.getType())) 261 return false; 262 } 263 264 MachineFunction &MF = MIRBuilder.getMF(); 265 const DataLayout &DL = MF.getDataLayout(); 266 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 267 268 SmallVector<ArgInfo, 8> ArgInfos; 269 SmallVector<unsigned, 8> OrigArgIndices; 270 unsigned i = 0; 271 for (auto &Arg : F.args()) { 272 ArgInfo AInfo(VRegs[i], Arg.getType()); 273 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); 274 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); 275 ++i; 276 } 277 278 SmallVector<ISD::InputArg, 8> Ins; 279 subTargetRegTypeForCallingConv( 280 MIRBuilder, ArgInfos, OrigArgIndices, 281 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, 282 unsigned partOffs) { 283 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 284 }); 285 286 SmallVector<CCValAssign, 16> ArgLocs; 287 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 288 F.getContext()); 289 290 const MipsTargetMachine &TM = 291 static_cast<const MipsTargetMachine &>(MF.getTarget()); 292 const MipsABIInfo &ABI = TM.getABI(); 293 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), 294 1); 295 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); 296 297 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); 298 if (!Handler.handle(ArgLocs, ArgInfos)) 299 return false; 300 301 return true; 302 } 303 304 bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 305 CallingConv::ID CallConv, 306 const MachineOperand &Callee, 307 const ArgInfo &OrigRet, 308 ArrayRef<ArgInfo> OrigArgs) const { 309 310 if (CallConv != CallingConv::C) 311 return false; 312 313 for (auto &Arg : OrigArgs) { 314 if (!isSupportedType(Arg.Ty)) 315 return false; 316 if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) 317 return false; 318 } 319 if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) 320 return false; 321 322 MachineFunction &MF = MIRBuilder.getMF(); 323 const Function &F = MF.getFunction(); 324 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 325 const MipsTargetMachine &TM = 326 static_cast<const MipsTargetMachine &>(MF.getTarget()); 327 const MipsABIInfo &ABI = TM.getABI(); 328 329 MachineInstrBuilder CallSeqStart = 330 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); 331 332 // FIXME: Add support for pic calling sequences, long call sequences for O32, 333 // N32 and N64. First handle the case when Callee.isReg(). 334 if (Callee.isReg()) 335 return false; 336 337 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); 338 MIB.addDef(Mips::SP, RegState::Implicit); 339 MIB.add(Callee); 340 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 341 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); 342 343 TargetLowering::ArgListTy FuncOrigArgs; 344 FuncOrigArgs.reserve(OrigArgs.size()); 345 346 SmallVector<ArgInfo, 8> ArgInfos; 347 SmallVector<unsigned, 8> OrigArgIndices; 348 unsigned i = 0; 349 for (auto &Arg : OrigArgs) { 350 351 TargetLowering::ArgListEntry Entry; 352 Entry.Ty = Arg.Ty; 353 FuncOrigArgs.push_back(Entry); 354 355 splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); 356 ++i; 357 } 358 359 SmallVector<ISD::OutputArg, 8> Outs; 360 subTargetRegTypeForCallingConv( 361 MIRBuilder, ArgInfos, OrigArgIndices, 362 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, 363 unsigned partOffs) { 364 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 365 }); 366 367 SmallVector<CCValAssign, 8> ArgLocs; 368 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 369 F.getContext()); 370 371 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); 372 const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; 373 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); 374 375 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); 376 if (!RetHandler.handle(ArgLocs, ArgInfos)) { 377 return false; 378 } 379 380 unsigned NextStackOffset = CCInfo.getNextStackOffset(); 381 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); 382 unsigned StackAlignment = TFL->getStackAlignment(); 383 NextStackOffset = alignTo(NextStackOffset, StackAlignment); 384 CallSeqStart.addImm(NextStackOffset).addImm(0); 385 386 MIRBuilder.insertInstr(MIB); 387 388 if (OrigRet.Reg) { 389 390 ArgInfos.clear(); 391 SmallVector<unsigned, 8> OrigRetIndices; 392 393 splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); 394 395 SmallVector<ISD::InputArg, 8> Ins; 396 subTargetRegTypeForCallingConv( 397 MIRBuilder, ArgInfos, OrigRetIndices, 398 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 399 unsigned origIdx, unsigned partOffs) { 400 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 401 }); 402 403 SmallVector<CCValAssign, 8> ArgLocs; 404 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 405 F.getContext()); 406 407 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); 408 409 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); 410 if (!Handler.handle(ArgLocs, ArgInfos)) 411 return false; 412 } 413 414 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); 415 416 return true; 417 } 418 419 void MipsCallLowering::subTargetRegTypeForCallingConv( 420 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, 421 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { 422 MachineFunction &MF = MIRBuilder.getMF(); 423 const Function &F = MF.getFunction(); 424 const DataLayout &DL = F.getParent()->getDataLayout(); 425 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 426 427 unsigned ArgNo = 0; 428 for (auto &Arg : Args) { 429 430 EVT VT = TLI.getValueType(DL, Arg.Ty); 431 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), 432 F.getCallingConv(), VT); 433 434 ISD::ArgFlagsTy Flags = Arg.Flags; 435 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); 436 437 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0); 438 439 ++ArgNo; 440 } 441 } 442 443 void MipsCallLowering::splitToValueTypes( 444 const ArgInfo &OrigArg, unsigned OriginalIndex, 445 SmallVectorImpl<ArgInfo> &SplitArgs, 446 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { 447 448 // TODO : perform structure and array split. For now we only deal with 449 // types that pass isSupportedType check. 450 SplitArgs.push_back(OrigArg); 451 SplitArgsOrigIndices.push_back(OriginalIndex); 452 } 453