diff options
| author | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-06-06 07:24:52 +0000 |
|---|---|---|
| committer | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-06-06 07:24:52 +0000 |
| commit | 326ec32403a0b83999878eeed01dc525974faef5 (patch) | |
| tree | e56cbabdfe3b6830bc8a41f541e190bfc4dbde42 /llvm/lib/Target | |
| parent | 2ebe3a0240564af7e5ca34faba81cbd8e58af5d5 (diff) | |
| download | bcm5719-llvm-326ec32403a0b83999878eeed01dc525974faef5.tar.gz bcm5719-llvm-326ec32403a0b83999878eeed01dc525974faef5.zip | |
[MIPS GlobalISel] Add lowerCall
Add minimal support to lower function calls.
Support only functions with arguments/return that go through registers
and have type i32.
Patch by Petar Avramovic.
Differential Revision: https://reviews.llvm.org/D45627
llvm-svn: 334071
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsCallLowering.cpp | 130 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsCallLowering.h | 4 |
2 files changed, 133 insertions, 1 deletions
diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp index 561b15bacb2..cd751e5825f 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ b/llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -15,6 +15,7 @@ #include "MipsCallLowering.h" #include "MipsCCState.h" +#include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" using namespace llvm; @@ -44,10 +45,25 @@ public: private: virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; - void markPhysRegUsed(unsigned PhysReg) { + virtual void markPhysRegUsed(unsigned PhysReg) { MIRBuilder.getMBB().addLiveIn(PhysReg); } }; + +class CallReturnHandler : public IncomingValueHandler { +public: + CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB) + : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} + +private: + virtual void markPhysRegUsed(unsigned PhysReg) override { + MIB.addDef(PhysReg, RegState::Implicit); + } + + MachineInstrBuilder &MIB; +}; + } // end anonymous namespace void IncomingValueHandler::assignValueToReg(unsigned ValVReg, @@ -198,6 +214,118 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, return true; } +bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, + CallingConv::ID CallConv, + const MachineOperand &Callee, + const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs) const { + + if (CallConv != CallingConv::C) + return false; + + for (auto &Arg : OrigArgs) { + if (!isSupportedType(Arg.Ty)) + return false; + if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) + return false; + } + if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) + return false; + + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + const MipsTargetMachine &TM = + static_cast<const MipsTargetMachine &>(MF.getTarget()); + const MipsABIInfo &ABI = TM.getABI(); + + MachineInstrBuilder CallSeqStart = + MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); + + // FIXME: Add support for pic calling sequences, long call sequences for O32, + // N32 and N64. First handle the case when Callee.isReg(). + if (Callee.isReg()) + return false; + + MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); + MIB.addDef(Mips::SP, RegState::Implicit); + MIB.add(Callee); + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); + + TargetLowering::ArgListTy FuncOrigArgs; + FuncOrigArgs.reserve(OrigArgs.size()); + + SmallVector<ArgInfo, 8> ArgInfos; + SmallVector<unsigned, 8> OrigArgIndices; + unsigned i = 0; + for (auto &Arg : OrigArgs) { + + TargetLowering::ArgListEntry Entry; + Entry.Ty = Arg.Ty; + FuncOrigArgs.push_back(Entry); + + splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); + ++i; + } + + SmallVector<ISD::OutputArg, 8> Outs; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigArgIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, + unsigned partOffs) { + Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 8> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; + CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); + + OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); + if (!RetHandler.handle(ArgLocs, ArgInfos)) { + return false; + } + + // TODO: Calculate stack offset. + CallSeqStart.addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)).addImm(0); + MIRBuilder.insertInstr(MIB); + + if (OrigRet.Reg) { + + ArgInfos.clear(); + SmallVector<unsigned, 8> OrigRetIndices; + + splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); + + SmallVector<ISD::InputArg, 8> Ins; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigRetIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, + unsigned origIdx, unsigned partOffs) { + Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 8> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); + + CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); + if (!Handler.handle(ArgLocs, ArgInfos)) + return false; + } + + MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP) + .addImm(ABI.GetCalleeAllocdArgSizeInBytes(CallConv)) + .addImm(0); + + return true; +} + void MipsCallLowering::subTargetRegTypeForCallingConv( MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { diff --git a/llvm/lib/Target/Mips/MipsCallLowering.h b/llvm/lib/Target/Mips/MipsCallLowering.h index fe072c7dfc7..cdff19a0eb1 100644 --- a/llvm/lib/Target/Mips/MipsCallLowering.h +++ b/llvm/lib/Target/Mips/MipsCallLowering.h @@ -48,6 +48,10 @@ public: bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) const override; + bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs) const override; + private: using FunTy = std::function<void(ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, |

