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 "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 19 20 using namespace llvm; 21 22 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) 23 : CallLowering(&TLI) {} 24 25 bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, 26 unsigned vreg) { 27 if (VA.isRegLoc()) { 28 assignValueToReg(vreg, VA.getLocReg()); 29 } else { 30 return false; 31 } 32 return true; 33 } 34 35 namespace { 36 class IncomingValueHandler : public MipsCallLowering::MipsHandler { 37 public: 38 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 39 : MipsHandler(MIRBuilder, MRI) {} 40 41 bool handle(ArrayRef<CCValAssign> ArgLocs, 42 ArrayRef<CallLowering::ArgInfo> Args); 43 44 private: 45 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 46 47 void markPhysRegUsed(unsigned PhysReg) { 48 MIRBuilder.getMBB().addLiveIn(PhysReg); 49 } 50 }; 51 } // end anonymous namespace 52 53 void IncomingValueHandler::assignValueToReg(unsigned ValVReg, 54 unsigned PhysReg) { 55 MIRBuilder.buildCopy(ValVReg, PhysReg); 56 markPhysRegUsed(PhysReg); 57 } 58 59 bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 60 ArrayRef<CallLowering::ArgInfo> Args) { 61 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { 62 if (!assign(ArgLocs[i], Args[i].Reg)) 63 return false; 64 } 65 return true; 66 } 67 68 namespace { 69 class OutgoingValueHandler : public MipsCallLowering::MipsHandler { 70 public: 71 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 72 MachineInstrBuilder &MIB) 73 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} 74 75 bool handle(ArrayRef<CCValAssign> ArgLocs, 76 ArrayRef<CallLowering::ArgInfo> Args); 77 78 private: 79 virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; 80 81 MachineInstrBuilder &MIB; 82 }; 83 } // end anonymous namespace 84 85 void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, 86 unsigned PhysReg) { 87 MIRBuilder.buildCopy(PhysReg, ValVReg); 88 MIB.addUse(PhysReg, RegState::Implicit); 89 } 90 91 bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, 92 ArrayRef<CallLowering::ArgInfo> Args) { 93 for (unsigned i = 0; i < Args.size(); ++i) { 94 if (!assign(ArgLocs[i], Args[i].Reg)) 95 return false; 96 } 97 return true; 98 } 99 100 static bool isSupportedType(Type *T) { 101 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) 102 return true; 103 return false; 104 } 105 106 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 107 const Value *Val, unsigned VReg) const { 108 109 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); 110 111 if (Val != nullptr) { 112 if (!isSupportedType(Val->getType())) 113 return false; 114 115 MachineFunction &MF = MIRBuilder.getMF(); 116 const Function &F = MF.getFunction(); 117 const DataLayout &DL = MF.getDataLayout(); 118 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 119 120 SmallVector<ArgInfo, 8> RetInfos; 121 SmallVector<unsigned, 8> OrigArgIndices; 122 123 ArgInfo ArgRetInfo(VReg, Val->getType()); 124 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); 125 splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices); 126 127 SmallVector<ISD::OutputArg, 8> Outs; 128 subTargetRegTypeForCallingConv( 129 MIRBuilder, RetInfos, OrigArgIndices, 130 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 131 unsigned origIdx, unsigned partOffs) { 132 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 133 }); 134 135 SmallVector<CCValAssign, 16> ArgLocs; 136 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 137 F.getContext()); 138 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); 139 140 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); 141 if (!RetHandler.handle(ArgLocs, RetInfos)) { 142 return false; 143 } 144 } 145 MIRBuilder.insertInstr(Ret); 146 return true; 147 } 148 149 bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 150 const Function &F, 151 ArrayRef<unsigned> VRegs) const { 152 153 // Quick exit if there aren't any args. 154 if (F.arg_empty()) 155 return true; 156 157 if (F.isVarArg()) { 158 return false; 159 } 160 161 for (auto &Arg : F.args()) { 162 if (!isSupportedType(Arg.getType())) 163 return false; 164 } 165 166 MachineFunction &MF = MIRBuilder.getMF(); 167 const DataLayout &DL = MF.getDataLayout(); 168 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 169 170 SmallVector<ArgInfo, 8> ArgInfos; 171 SmallVector<unsigned, 8> OrigArgIndices; 172 unsigned i = 0; 173 for (auto &Arg : F.args()) { 174 ArgInfo AInfo(VRegs[i], Arg.getType()); 175 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); 176 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); 177 ++i; 178 } 179 180 SmallVector<ISD::InputArg, 8> Ins; 181 subTargetRegTypeForCallingConv( 182 MIRBuilder, ArgInfos, OrigArgIndices, 183 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, 184 unsigned partOffs) { 185 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); 186 }); 187 188 SmallVector<CCValAssign, 16> ArgLocs; 189 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, 190 F.getContext()); 191 192 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); 193 194 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); 195 if (!Handler.handle(ArgLocs, ArgInfos)) 196 return false; 197 198 return true; 199 } 200 201 void MipsCallLowering::subTargetRegTypeForCallingConv( 202 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, 203 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { 204 MachineFunction &MF = MIRBuilder.getMF(); 205 const Function &F = MF.getFunction(); 206 const DataLayout &DL = F.getParent()->getDataLayout(); 207 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); 208 209 unsigned ArgNo = 0; 210 for (auto &Arg : Args) { 211 212 EVT VT = TLI.getValueType(DL, Arg.Ty); 213 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT); 214 215 ISD::ArgFlagsTy Flags = Arg.Flags; 216 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); 217 218 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0); 219 220 ++ArgNo; 221 } 222 } 223 224 void MipsCallLowering::splitToValueTypes( 225 const ArgInfo &OrigArg, unsigned OriginalIndex, 226 SmallVectorImpl<ArgInfo> &SplitArgs, 227 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { 228 229 // TODO : perform structure and array split. For now we only deal with 230 // types that pass isSupportedType check. 231 SplitArgs.push_back(OrigArg); 232 SplitArgsOrigIndices.push_back(OriginalIndex); 233 } 234