aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMCallLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMCallLowering.cpp')
-rw-r--r--lib/Target/ARM/ARMCallLowering.cpp84
1 files changed, 58 insertions, 26 deletions
diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp
index 47f998b696f5..8e80c32bcf89 100644
--- a/lib/Target/ARM/ARMCallLowering.cpp
+++ b/lib/Target/ARM/ARMCallLowering.cpp
@@ -237,7 +237,7 @@ void ARMCallLowering::splitToValueTypes(
/// Lower the return value for the already existing \p Ret. This assumes that
/// \p MIRBuilder's insertion point is correct.
bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
- const Value *Val, unsigned VReg,
+ const Value *Val, ArrayRef<unsigned> VRegs,
MachineInstrBuilder &Ret) const {
if (!Val)
// Nothing to do here.
@@ -251,16 +251,24 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
if (!isSupportedType(DL, TLI, Val->getType()))
return false;
- SmallVector<ArgInfo, 4> SplitVTs;
- SmallVector<unsigned, 4> Regs;
- ArgInfo RetInfo(VReg, Val->getType());
- setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F);
- splitToValueTypes(RetInfo, SplitVTs, MF, [&](unsigned Reg, uint64_t Offset) {
- Regs.push_back(Reg);
- });
+ SmallVector<EVT, 4> SplitEVTs;
+ ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
+ assert(VRegs.size() == SplitEVTs.size() &&
+ "For each split Type there should be exactly one VReg.");
- if (Regs.size() > 1)
- MIRBuilder.buildUnmerge(Regs, VReg);
+ SmallVector<ArgInfo, 4> SplitVTs;
+ LLVMContext &Ctx = Val->getType()->getContext();
+ for (unsigned i = 0; i < SplitEVTs.size(); ++i) {
+ ArgInfo CurArgInfo(VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx));
+ setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F);
+
+ SmallVector<unsigned, 4> Regs;
+ splitToValueTypes(
+ CurArgInfo, SplitVTs, MF,
+ [&](unsigned Reg, uint64_t Offset) { Regs.push_back(Reg); });
+ if (Regs.size() > 1)
+ MIRBuilder.buildUnmerge(Regs, VRegs[i]);
+ }
CCAssignFn *AssignFn =
TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
@@ -270,14 +278,15 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
}
bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
- const Value *Val, unsigned VReg) const {
- assert(!Val == !VReg && "Return value without a vreg");
+ const Value *Val,
+ ArrayRef<unsigned> VRegs) const {
+ assert(!Val == VRegs.empty() && "Return value without a vreg");
auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>();
unsigned Opcode = ST.getReturnOpcode();
auto Ret = MIRBuilder.buildInstrNoInsert(Opcode).add(predOps(ARMCC::AL));
- if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
+ if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))
return false;
MIRBuilder.insertInstr(Ret);
@@ -420,7 +429,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
auto &TLI = *getTLI<ARMTargetLowering>();
auto Subtarget = TLI.getSubtarget();
- if (Subtarget->isThumb())
+ if (Subtarget->isThumb1Only())
return false;
// Quick exit if there aren't any args
@@ -491,6 +500,22 @@ struct CallReturnHandler : public IncomingValueHandler {
MachineInstrBuilder MIB;
};
+// FIXME: This should move to the ARMSubtarget when it supports all the opcodes.
+unsigned getCallOpcode(const ARMSubtarget &STI, bool isDirect) {
+ if (isDirect)
+ return STI.isThumb() ? ARM::tBL : ARM::BL;
+
+ if (STI.isThumb())
+ return ARM::tBLXr;
+
+ if (STI.hasV5TOps())
+ return ARM::BLX;
+
+ if (STI.hasV4TOps())
+ return ARM::BX_CALL;
+
+ return ARM::BMOVPCRX_CALL;
+}
} // end anonymous namespace
bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
@@ -508,27 +533,34 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (STI.genLongCalls())
return false;
+ if (STI.isThumb1Only())
+ return false;
+
auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN);
// Create the call instruction so we can add the implicit uses of arg
// registers, but don't insert it yet.
bool isDirect = !Callee.isReg();
- auto CallOpcode =
- isDirect ? ARM::BL
- : STI.hasV5TOps()
- ? ARM::BLX
- : STI.hasV4TOps() ? ARM::BX_CALL : ARM::BMOVPCRX_CALL;
- auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode)
- .add(Callee)
- .addRegMask(TRI->getCallPreservedMask(MF, CallConv));
- if (Callee.isReg()) {
+ auto CallOpcode = getCallOpcode(STI, isDirect);
+ auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode);
+
+ bool isThumb = STI.isThumb();
+ if (isThumb)
+ MIB.add(predOps(ARMCC::AL));
+
+ MIB.add(Callee);
+ if (!isDirect) {
auto CalleeReg = Callee.getReg();
- if (CalleeReg && !TRI->isPhysicalRegister(CalleeReg))
- MIB->getOperand(0).setReg(constrainOperandRegClass(
+ if (CalleeReg && !TRI->isPhysicalRegister(CalleeReg)) {
+ unsigned CalleeIdx = isThumb ? 2 : 0;
+ MIB->getOperand(CalleeIdx).setReg(constrainOperandRegClass(
MF, *TRI, MRI, *STI.getInstrInfo(), *STI.getRegBankInfo(),
- *MIB.getInstr(), MIB->getDesc(), Callee, 0));
+ *MIB.getInstr(), MIB->getDesc(), Callee, CalleeIdx));
+ }
}
+ MIB.addRegMask(TRI->getCallPreservedMask(MF, CallConv));
+
SmallVector<ArgInfo, 8> ArgInfos;
for (auto Arg : OrigArgs) {
if (!isSupportedType(DL, TLI, Arg.Ty))