forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2ebe3a0240
commit
326ec32403
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
|
||||
declare i32 @f(i32 %a, i32 %b);
|
||||
|
||||
define i32 @g(i32 %a0, i32 %a1, i32 %x, i32 %y) {
|
||||
; MIPS32-LABEL: name: g
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1, $a2, $a3
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
|
||||
; MIPS32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
|
||||
; MIPS32: $a0 = COPY [[COPY2]](s32)
|
||||
; MIPS32: $a1 = COPY [[COPY3]](s32)
|
||||
; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $v0
|
||||
; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY $v0
|
||||
; MIPS32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp
|
||||
; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[COPY4]]
|
||||
; MIPS32: $v0 = COPY [[ADD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
entry:
|
||||
%z = call i32 @f(i32 %x, i32 %y)
|
||||
%doublez = add i32 %z, %z
|
||||
ret i32 %doublez
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
|
||||
|
||||
declare i32 @f(i32 %a, i32 %b);
|
||||
|
||||
define i32 @g(i32 %a0, i32 %a1, i32 %x, i32 %y) {
|
||||
; MIPS32-LABEL: g:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: addiu $sp, $sp, -24
|
||||
; MIPS32-NEXT: .cfi_def_cfa_offset 24
|
||||
; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
|
||||
; MIPS32-NEXT: .cfi_offset 31, -4
|
||||
; MIPS32-NEXT: move $4, $6
|
||||
; MIPS32-NEXT: move $5, $7
|
||||
; MIPS32-NEXT: jal f
|
||||
; MIPS32-NEXT: nop
|
||||
; MIPS32-NEXT: addu $2, $2, $2
|
||||
; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
|
||||
; MIPS32-NEXT: addiu $sp, $sp, 24
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
%z = call i32 @f(i32 %x, i32 %y)
|
||||
%doublez = add i32 %z, %z
|
||||
ret i32 %doublez
|
||||
}
|
Loading…
Reference in New Issue