From 326ec32403a0b83999878eeed01dc525974faef5 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Wed, 6 Jun 2018 07:24:52 +0000 Subject: [PATCH] [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 --- llvm/lib/Target/Mips/MipsCallLowering.cpp | 130 +++++++++++++++++- llvm/lib/Target/Mips/MipsCallLowering.h | 4 + .../Mips/GlobalISel/irtranslator/call.ll | 27 ++++ .../CodeGen/Mips/GlobalISel/llvm-ir/call.ll | 26 ++++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/Mips/GlobalISel/irtranslator/call.ll create mode 100644 llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/call.ll diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp index 561b15bacb27..cd751e5825fc 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 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(); + const MipsTargetMachine &TM = + static_cast(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 ArgInfos; + SmallVector 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 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 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 OrigRetIndices; + + splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); + + SmallVector 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 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 Args, ArrayRef OrigArgIndices, const FunTy &PushBack) const { diff --git a/llvm/lib/Target/Mips/MipsCallLowering.h b/llvm/lib/Target/Mips/MipsCallLowering.h index fe072c7dfc70..cdff19a0eb1e 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 VRegs) const override; + bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef OrigArgs) const override; + private: using FunTy = std::function