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/GlobalISel/MachineIRBuilder.h" 20 21 using namespace llvm; 22 23 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) 24 : CallLowering(&TLI) {} 25 26 bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, 27 unsigned vreg) { 28 if (VA.isRegLoc()) { 29 assignValueToReg(vreg, VA.getLocReg()); 30 } else { 31 return false; 32 } 33 return true; 34 } 35 36 namespace { 37 class IncomingValueHandler : public MipsCallLowering::MipsHandler { 38 public: 39 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 40 : MipsHandler(MIRBuilder, MRI) {} 41 42 bool handle(ArrayRef<CCValAssign> ArgLocs, 43 ArrayRef<CallLowering::ArgInfo> Args); 44 45 private: 46 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 47 48 virtual void markPhysRegUsed(unsigned PhysReg) { 49 MIRBuilder.getMBB().addLiveIn(PhysReg); 50 } 51 }; 52 53 class CallReturnHandler : public IncomingValueHandler { 54 public: 55 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 56 MachineInstrBuilder &MIB) 57 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 58 59 private: 60 virtual void markPhysRegUsed(unsigned PhysReg) override { 61 MIB.addDef(PhysReg, RegState::Implicit); 62 } 63 64 MachineInstrBuilder &MIB; 65 }; 66 67 } // end anonymous namespace 68 69 void IncomingValueHandler::assignValueToReg(unsigned ValVReg, 70 unsigned PhysReg) { 71 MIRBuilder.buildCopy(ValVReg, PhysReg); 72 markPhysRegUsed(PhysReg); 73 } 74 75 bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 76 ArrayRef<CallLowering::ArgInfo> Args) { 77 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { 78 if (!assign(ArgLocs[i], Args[i].Reg)) 79 return false; 80 } 81 return true; 82 } 83 84 namespace { 85 class OutgoingValueHandler : public MipsCallLowering::MipsHandler { 86 public: 87 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 88 MachineInstrBuilder &MIB) 89 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} 90 91 bool handle(ArrayRef<CCValAssign> ArgLocs, 92 ArrayRef<CallLowering::ArgInfo> Args); 93 94 private: 95 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 96 97 MachineInstrBuilder &MIB; 98 }; 99 } // end anonymous namespace 100 101 void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, 102 unsigned PhysReg) { 103 MIRBuilder.buildCopy(PhysReg, ValVReg); 104 MIB.addUse(PhysReg, RegState::Implicit); 105 } 106 107 bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 108 ArrayRef<CallLowering::ArgInfo> Args) { 109 for (unsigned i = 0; i < Args.size(); ++i) { 110 if (!assign(ArgLocs[i], Args[i].Reg)) 111 return false; 112 } 113 return true; 114 } 115 116 static bool isSupportedType(Type *T) { 117 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) 118 return true; 119 return false; 120 } 121 122 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 123 const Value *Val, unsigned VReg) const { 124 125 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); 126 127 if (Val != nullptr) { 128 if (!isSupportedType(Val->getType())) 129 return false; 130 131 MachineFunction &MF = MIRBuilder.getMF(); 132 const Function &F = MF.getFunction(); 133 const DataLayout &DL = MF.getDataLayout(); 134 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 135 136 SmallVector<ArgInfo, 8> RetInfos; 137 SmallVector<unsigned, 8> OrigArgIndices; 138 139 ArgInfo ArgRetInfo(VReg, Val->getType()); 140 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); 141 splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices); 142 143 SmallVector<ISD::OutputArg, 8> Outs; 144 subTargetRegTypeForCallingConv( 145 MIRBuilder, RetInfos, OrigArgIndices, 146 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 147 unsigned origIdx, unsigned partOffs) { 148 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 149 }); 150 151 SmallVector<CCValAssign, 16> ArgLocs; 152 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 153 F.getContext()); 154 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); 155 156 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 157 if (!RetHandler.handle(ArgLocs, RetInfos)) { 158 return false; 159 } 160 } 161 MIRBuilder.insertInstr(Ret); 162 return true; 163 } 164 165 bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 166 const Function &F, 167 ArrayRef<unsigned> VRegs) const { 168 169 // Quick exit if there aren't any args. 170 if (F.arg_empty()) 171 return true; 172 173 if (F.isVarArg()) { 174 return false; 175 } 176 177 for (auto &Arg : F.args()) { 178 if (!isSupportedType(Arg.getType())) 179 return false; 180 } 181 182 MachineFunction &MF = MIRBuilder.getMF(); 183 const DataLayout &DL = MF.getDataLayout(); 184 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 185 186 SmallVector<ArgInfo, 8> ArgInfos; 187 SmallVector<unsigned, 8> OrigArgIndices; 188 unsigned i = 0; 189 for (auto &Arg : F.args()) { 190 ArgInfo AInfo(VRegs[i], Arg.getType()); 191 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); 192 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); 193 ++i; 194 } 195 196 SmallVector<ISD::InputArg, 8> Ins; 197 subTargetRegTypeForCallingConv( 198 MIRBuilder, ArgInfos, OrigArgIndices, 199 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, 200 unsigned partOffs) { 201 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 202 }); 203 204 SmallVector<CCValAssign, 16> ArgLocs; 205 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 206 F.getContext()); 207 208 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); 209 210 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); 211 if (!Handler.handle(ArgLocs, ArgInfos)) 212 return false; 213 214 return true; 215 } 216 217 bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 218 CallingConv::ID CallConv, 219 const MachineOperand &Callee, 220 const ArgInfo &OrigRet, 221 ArrayRef<ArgInfo> OrigArgs) const { 222 223 if (CallConv != CallingConv::C) 224 return false; 225 226 for (auto &Arg : OrigArgs) { 227 if (!isSupportedType(Arg.Ty)) 228 return false; 229 if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) 230 return false; 231 } 232 if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) 233 return false; 234 235 MachineFunction &MF = MIRBuilder.getMF(); 236 const Function &F = MF.getFunction(); 237 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 238 const MipsTargetMachine &TM = 239 static_cast<const MipsTargetMachine &>(MF.getTarget()); 240 const MipsABIInfo &ABI = TM.getABI(); 241 242 MachineInstrBuilder CallSeqStart = 243 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); 244 245 // FIXME: Add support for pic calling sequences, long call sequences for O32, 246 // N32 and N64. First handle the case when Callee.isReg(). 247 if (Callee.isReg()) 248 return false; 249 250 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); 251 MIB.addDef(Mips::SP, RegState::Implicit); 252 MIB.add(Callee); 253 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 254 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); 255 256 TargetLowering::ArgListTy FuncOrigArgs; 257 FuncOrigArgs.reserve(OrigArgs.size()); 258 259 SmallVector<ArgInfo, 8> ArgInfos; 260 SmallVector<unsigned, 8> OrigArgIndices; 261 unsigned i = 0; 262 for (auto &Arg : OrigArgs) { 263 264 TargetLowering::ArgListEntry Entry; 265 Entry.Ty = Arg.Ty; 266 FuncOrigArgs.push_back(Entry); 267 268 splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); 269 ++i; 270 } 271 272 SmallVector<ISD::OutputArg, 8> Outs; 273 subTargetRegTypeForCallingConv( 274 MIRBuilder, ArgInfos, OrigArgIndices, 275 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, 276 unsigned partOffs) { 277 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 278 }); 279 280 SmallVector<CCValAssign, 8> ArgLocs; 281 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 282 F.getContext()); 283 284 const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; 285 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); 286 287 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); 288 if (!RetHandler.handle(ArgLocs, ArgInfos)) { 289 return false; 290 } 291 292 // TODO: Calculate stack offset. 293 CallSeqStart.addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)).addImm(0); 294 MIRBuilder.insertInstr(MIB); 295 296 if (OrigRet.Reg) { 297 298 ArgInfos.clear(); 299 SmallVector<unsigned, 8> OrigRetIndices; 300 301 splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); 302 303 SmallVector<ISD::InputArg, 8> Ins; 304 subTargetRegTypeForCallingConv( 305 MIRBuilder, ArgInfos, OrigRetIndices, 306 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 307 unsigned origIdx, unsigned partOffs) { 308 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 309 }); 310 311 SmallVector<CCValAssign, 8> ArgLocs; 312 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 313 F.getContext()); 314 315 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); 316 317 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); 318 if (!Handler.handle(ArgLocs, ArgInfos)) 319 return false; 320 } 321 322 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP) 323 .addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)) 324 .addImm(0); 325 326 return true; 327 } 328 329 void MipsCallLowering::subTargetRegTypeForCallingConv( 330 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, 331 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { 332 MachineFunction &MF = MIRBuilder.getMF(); 333 const Function &F = MF.getFunction(); 334 const DataLayout &DL = F.getParent()->getDataLayout(); 335 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 336 337 unsigned ArgNo = 0; 338 for (auto &Arg : Args) { 339 340 EVT VT = TLI.getValueType(DL, Arg.Ty); 341 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT); 342 343 ISD::ArgFlagsTy Flags = Arg.Flags; 344 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); 345 346 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0); 347 348 ++ArgNo; 349 } 350 } 351 352 void MipsCallLowering::splitToValueTypes( 353 const ArgInfo &OrigArg, unsigned OriginalIndex, 354 SmallVectorImpl<ArgInfo> &SplitArgs, 355 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { 356 357 // TODO : perform structure and array split. For now we only deal with 358 // types that pass isSupportedType check. 359 SplitArgs.push_back(OrigArg); 360 SplitArgsOrigIndices.push_back(OriginalIndex); 361 } 362