summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMCallLowering.cpp
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2017-02-23 14:18:41 +0000
committerDiana Picus <diana.picus@linaro.org>2017-02-23 14:18:41 +0000
commita8cb0cd8f2fe086830f96f0c8c6e55e15f01b49a (patch)
treed7697d7703ca46045018f58d67f79d4406e5d21b /llvm/lib/Target/ARM/ARMCallLowering.cpp
parentf77d1656afb8599ac36b0b192b5fa5c9c721bd93 (diff)
downloadbcm5719-llvm-a8cb0cd8f2fe086830f96f0c8c6e55e15f01b49a.tar.gz
bcm5719-llvm-a8cb0cd8f2fe086830f96f0c8c6e55e15f01b49a.zip
[ARM] GlobalISel: Lower call returns
Introduce a common ValueHandler for call returns and formal arguments, and inherit two different versions for handling the differences (at the moment the only difference is the way physical registers are marked as used). llvm-svn: 295973
Diffstat (limited to 'llvm/lib/Target/ARM/ARMCallLowering.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMCallLowering.cpp63
1 files changed, 52 insertions, 11 deletions
diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp
index 7ba859921c2..f4f3b261bf5 100644
--- a/llvm/lib/Target/ARM/ARMCallLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMCallLowering.cpp
@@ -175,9 +175,11 @@ bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
}
namespace {
-struct FormalArgHandler : public CallLowering::ValueHandler {
- FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- CCAssignFn AssignFn)
+/// Helper class for values coming in through an ABI boundary (used for handling
+/// formal arguments and call return values).
+struct IncomingValueHandler : public CallLowering::ValueHandler {
+ IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn AssignFn)
: ValueHandler(MIRBuilder, MRI, AssignFn) {}
unsigned getStackAddress(uint64_t Size, int64_t Offset,
@@ -204,8 +206,8 @@ struct FormalArgHandler : public CallLowering::ValueHandler {
if (VA.getLocInfo() == CCValAssign::SExt ||
VA.getLocInfo() == CCValAssign::ZExt) {
- // If the argument is zero- or sign-extended by the caller, its size
- // becomes 4 bytes, so that's what we should load.
+ // If the value is zero- or sign-extended, its size becomes 4 bytes, so
+ // that's what we should load.
Size = 4;
assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm");
MRI.setType(ValVReg, LLT::scalar(32));
@@ -224,8 +226,9 @@ struct FormalArgHandler : public CallLowering::ValueHandler {
assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size");
assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size");
- // The caller should handle all necesary extensions.
- MIRBuilder.getMBB().addLiveIn(PhysReg);
+ // The necesary extensions are handled on the other side of the ABI
+ // boundary.
+ markPhysRegUsed(PhysReg);
MIRBuilder.buildCopy(ValVReg, PhysReg);
}
@@ -259,6 +262,21 @@ struct FormalArgHandler : public CallLowering::ValueHandler {
return 1;
}
+
+ /// Marking a physical register as used is different between formal
+ /// parameters, where it's a basic block live-in, and call returns, where it's
+ /// an implicit-def of the call instruction.
+ virtual void markPhysRegUsed(unsigned PhysReg) = 0;
+};
+
+struct FormalArgHandler : public IncomingValueHandler {
+ FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn AssignFn)
+ : IncomingValueHandler(MIRBuilder, MRI, AssignFn) {}
+
+ void markPhysRegUsed(unsigned PhysReg) override {
+ MIRBuilder.getMBB().addLiveIn(PhysReg);
+ }
};
} // End anonymous namespace
@@ -307,6 +325,20 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
return handleAssignments(MIRBuilder, ArgInfos, ArgHandler);
}
+namespace {
+struct CallReturnHandler : public IncomingValueHandler {
+ CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder MIB, CCAssignFn *AssignFn)
+ : IncomingValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
+
+ void markPhysRegUsed(unsigned PhysReg) override {
+ MIB.addDef(PhysReg, RegState::Implicit);
+ }
+
+ MachineInstrBuilder MIB;
+};
+} // End anonymous namespace.
+
bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
const MachineOperand &Callee,
const ArgInfo &OrigRet,
@@ -320,10 +352,6 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (MF.getSubtarget<ARMSubtarget>().genLongCalls())
return false;
- // FIXME: Support calling functions with return types.
- if (!OrigRet.Ty->isVoidTy())
- return false;
-
MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN)
.addImm(0)
.add(predOps(ARMCC::AL));
@@ -356,6 +384,19 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
// Now we can add the actual call instruction to the correct basic block.
MIRBuilder.insertInstr(MIB);
+ if (!OrigRet.Ty->isVoidTy()) {
+ if (!isSupportedType(DL, TLI, OrigRet.Ty))
+ return false;
+
+ ArgInfos.clear();
+ splitToValueTypes(OrigRet, ArgInfos, DL, MRI);
+
+ auto RetAssignFn = TLI.CCAssignFnForReturn(CallConv, /*IsVarArg=*/false);
+ CallReturnHandler RetHandler(MIRBuilder, MRI, MIB, RetAssignFn);
+ if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler))
+ return false;
+ }
+
MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP)
.addImm(0)
.addImm(0)
OpenPOWER on IntegriCloud