From cc504e80b7d2ac408d8084bbee17a8ee56f1fed3 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 8 Feb 2017 17:57:27 +0000 Subject: [PATCH] GlobalISel: select G_VASTART on iOS AArch64. The AAPCS ABI is substantially more complicated so that's coming in a separate patch. For now we can generate correct code for iOS though. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294493 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64CallLowering.cpp | 22 +++++++++++- .../AArch64/AArch64InstructionSelector.cpp | 36 +++++++++++++++++++ .../AArch64/AArch64InstructionSelector.h | 8 +++++ lib/Target/AArch64/AArch64LegalizerInfo.cpp | 2 ++ .../GlobalISel/varargs-ios-translator.ll | 16 +++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll diff --git a/lib/Target/AArch64/AArch64CallLowering.cpp b/lib/Target/AArch64/AArch64CallLowering.cpp index c8a3ce5463e..6148359da81 100644 --- a/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/lib/Target/AArch64/AArch64CallLowering.cpp @@ -15,6 +15,8 @@ #include "AArch64CallLowering.h" #include "AArch64ISelLowering.h" +#include "AArch64MachineFunctionInfo.h" +#include "AArch64Subtarget.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/Analysis.h" @@ -55,7 +57,7 @@ AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI) struct IncomingArgHandler : public CallLowering::ValueHandler { IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, CCAssignFn *AssignFn) - : ValueHandler(MIRBuilder, MRI, AssignFn) {} + : ValueHandler(MIRBuilder, MRI, AssignFn), StackUsed(0) {} unsigned getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO) override { @@ -64,6 +66,7 @@ struct IncomingArgHandler : public CallLowering::ValueHandler { MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64)); MIRBuilder.buildFrameIndex(AddrReg, FI); + StackUsed = std::max(StackUsed, Size + Offset); return AddrReg; } @@ -86,6 +89,8 @@ struct IncomingArgHandler : public CallLowering::ValueHandler { /// parameters (it's a basic-block live-in), and a call instruction /// (it's an implicit-def of the BL). virtual void markPhysRegUsed(unsigned PhysReg) = 0; + + uint64_t StackUsed; }; struct FormalArgHandler : public IncomingArgHandler { @@ -265,6 +270,21 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) return false; + if (F.isVarArg()) { + if (!MF.getSubtarget().isTargetDarwin()) { + // FIXME: we need to reimplement saveVarArgsRegisters from + // AArch64ISelLowering. + return false; + } + + // We currently pass all varargs at 8-byte alignment. + uint64_t StackOffset = alignTo(Handler.StackUsed, 8); + + auto &MFI = MIRBuilder.getMF().getFrameInfo(); + AArch64FunctionInfo *FuncInfo = MF.getInfo(); + FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true)); + } + // Move back to the end of the basic block. MIRBuilder.setMBB(MBB); diff --git a/lib/Target/AArch64/AArch64InstructionSelector.cpp b/lib/Target/AArch64/AArch64InstructionSelector.cpp index 21d80ca9f81..6981194525f 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -14,6 +14,7 @@ #include "AArch64InstructionSelector.h" #include "AArch64InstrInfo.h" +#include "AArch64MachineFunctionInfo.h" #include "AArch64RegisterBankInfo.h" #include "AArch64RegisterInfo.h" #include "AArch64Subtarget.h" @@ -440,6 +441,38 @@ static void changeFCMPPredToAArch64CC(CmpInst::Predicate P, } } +bool AArch64InstructionSelector::selectVaStartAAPCS( + MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const { + return false; +} + +bool AArch64InstructionSelector::selectVaStartDarwin( + MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const { + AArch64FunctionInfo *FuncInfo = MF.getInfo(); + unsigned ListReg = I.getOperand(0).getReg(); + + unsigned ArgsAddrReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass); + + auto MIB = + BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::ADDXri)) + .addDef(ArgsAddrReg) + .addFrameIndex(FuncInfo->getVarArgsStackIndex()) + .addImm(0) + .addImm(0); + + constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); + + MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::STRXui)) + .addUse(ArgsAddrReg) + .addUse(ListReg) + .addImm(0) + .addMemOperand(*I.memoperands_begin()); + + constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); + I.eraseFromParent(); + return true; +} + bool AArch64InstructionSelector::select(MachineInstr &I) const { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -1125,6 +1158,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { I.eraseFromParent(); return true; } + case TargetOpcode::G_VASTART: + return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI) + : selectVaStartAAPCS(I, MF, MRI); } return false; diff --git a/lib/Target/AArch64/AArch64InstructionSelector.h b/lib/Target/AArch64/AArch64InstructionSelector.h index 2c6e5a912fb..3f38c9fcd1a 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.h +++ b/lib/Target/AArch64/AArch64InstructionSelector.h @@ -24,6 +24,9 @@ class AArch64RegisterInfo; class AArch64Subtarget; class AArch64TargetMachine; +class MachineFunction; +class MachineRegisterInfo; + class AArch64InstructionSelector : public InstructionSelector { public: AArch64InstructionSelector(const AArch64TargetMachine &TM, @@ -33,6 +36,11 @@ public: bool select(MachineInstr &I) const override; private: + bool selectVaStartAAPCS(MachineInstr &I, MachineFunction &MF, + MachineRegisterInfo &MRI) const; + bool selectVaStartDarwin(MachineInstr &I, MachineFunction &MF, + MachineRegisterInfo &MRI) const; + /// tblgen-erated 'select' implementation, used as the initial selector for /// the patterns that don't require complex C++. bool selectImpl(MachineInstr &I) const; diff --git a/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/lib/Target/AArch64/AArch64LegalizerInfo.cpp index 3a97406c0d8..ad0482ac7d5 100644 --- a/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -225,5 +225,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() { setAction({G_BITCAST, 1, LLT::vector(32/EltSize, EltSize)}, Legal); } + setAction({G_VASTART, p0}, Legal); + computeTables(); } diff --git a/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll b/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll new file mode 100644 index 00000000000..3bd56fa4ceb --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll @@ -0,0 +1,16 @@ +; RUN: llc -mtriple=aarch64-apple-ios -stop-after=instruction-select -global-isel -verify-machineinstrs %s -o - | FileCheck %s + +define void @test_varargs_sentinel(i8* %list, i64, i64, i64, i64, i64, i64, i64, + i32, ...) { +; CHECK-LABEL: name: test_varargs_sentinel +; CHECK: fixedStack: +; CHECK: - { id: [[VARARGS_SLOT:[0-9]+]], offset: 8 +; CHECK: body: +; CHECK: [[LIST:%[0-9]+]] = COPY %x0 +; CHECK: [[VARARGS_AREA:%[0-9]+]] = ADDXri %fixed-stack.[[VARARGS_SLOT]], 0, 0 +; CHECK: STRXui [[VARARGS_AREA]], [[LIST]], 0 :: (store 8 into %ir.list, align 0) + call void @llvm.va_start(i8* %list) + ret void +} + +declare void @llvm.va_start(i8*) -- 2.50.1