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