forked from OSchip/llvm-project
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. llvm-svn: 294493
This commit is contained in:
parent
f19d467ff6
commit
e9600d861c
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include "AArch64CallLowering.h"
|
#include "AArch64CallLowering.h"
|
||||||
#include "AArch64ISelLowering.h"
|
#include "AArch64ISelLowering.h"
|
||||||
|
#include "AArch64MachineFunctionInfo.h"
|
||||||
|
#include "AArch64Subtarget.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/CodeGen/Analysis.h"
|
#include "llvm/CodeGen/Analysis.h"
|
||||||
|
@ -55,7 +57,7 @@ AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
|
||||||
struct IncomingArgHandler : public CallLowering::ValueHandler {
|
struct IncomingArgHandler : public CallLowering::ValueHandler {
|
||||||
IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
||||||
CCAssignFn *AssignFn)
|
CCAssignFn *AssignFn)
|
||||||
: ValueHandler(MIRBuilder, MRI, AssignFn) {}
|
: ValueHandler(MIRBuilder, MRI, AssignFn), StackUsed(0) {}
|
||||||
|
|
||||||
unsigned getStackAddress(uint64_t Size, int64_t Offset,
|
unsigned getStackAddress(uint64_t Size, int64_t Offset,
|
||||||
MachinePointerInfo &MPO) override {
|
MachinePointerInfo &MPO) override {
|
||||||
|
@ -64,6 +66,7 @@ struct IncomingArgHandler : public CallLowering::ValueHandler {
|
||||||
MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
|
MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
|
||||||
unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64));
|
unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64));
|
||||||
MIRBuilder.buildFrameIndex(AddrReg, FI);
|
MIRBuilder.buildFrameIndex(AddrReg, FI);
|
||||||
|
StackUsed = std::max(StackUsed, Size + Offset);
|
||||||
return AddrReg;
|
return AddrReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +89,8 @@ struct IncomingArgHandler : public CallLowering::ValueHandler {
|
||||||
/// parameters (it's a basic-block live-in), and a call instruction
|
/// parameters (it's a basic-block live-in), and a call instruction
|
||||||
/// (it's an implicit-def of the BL).
|
/// (it's an implicit-def of the BL).
|
||||||
virtual void markPhysRegUsed(unsigned PhysReg) = 0;
|
virtual void markPhysRegUsed(unsigned PhysReg) = 0;
|
||||||
|
|
||||||
|
uint64_t StackUsed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FormalArgHandler : public IncomingArgHandler {
|
struct FormalArgHandler : public IncomingArgHandler {
|
||||||
|
@ -265,6 +270,21 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
||||||
if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
|
if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (F.isVarArg()) {
|
||||||
|
if (!MF.getSubtarget<AArch64Subtarget>().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<AArch64FunctionInfo>();
|
||||||
|
FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true));
|
||||||
|
}
|
||||||
|
|
||||||
// Move back to the end of the basic block.
|
// Move back to the end of the basic block.
|
||||||
MIRBuilder.setMBB(MBB);
|
MIRBuilder.setMBB(MBB);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "AArch64InstructionSelector.h"
|
#include "AArch64InstructionSelector.h"
|
||||||
#include "AArch64InstrInfo.h"
|
#include "AArch64InstrInfo.h"
|
||||||
|
#include "AArch64MachineFunctionInfo.h"
|
||||||
#include "AArch64RegisterBankInfo.h"
|
#include "AArch64RegisterBankInfo.h"
|
||||||
#include "AArch64RegisterInfo.h"
|
#include "AArch64RegisterInfo.h"
|
||||||
#include "AArch64Subtarget.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<AArch64FunctionInfo>();
|
||||||
|
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 {
|
bool AArch64InstructionSelector::select(MachineInstr &I) const {
|
||||||
assert(I.getParent() && "Instruction should be in a basic block!");
|
assert(I.getParent() && "Instruction should be in a basic block!");
|
||||||
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
||||||
|
@ -1125,6 +1158,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
|
||||||
I.eraseFromParent();
|
I.eraseFromParent();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case TargetOpcode::G_VASTART:
|
||||||
|
return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
|
||||||
|
: selectVaStartAAPCS(I, MF, MRI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -24,6 +24,9 @@ class AArch64RegisterInfo;
|
||||||
class AArch64Subtarget;
|
class AArch64Subtarget;
|
||||||
class AArch64TargetMachine;
|
class AArch64TargetMachine;
|
||||||
|
|
||||||
|
class MachineFunction;
|
||||||
|
class MachineRegisterInfo;
|
||||||
|
|
||||||
class AArch64InstructionSelector : public InstructionSelector {
|
class AArch64InstructionSelector : public InstructionSelector {
|
||||||
public:
|
public:
|
||||||
AArch64InstructionSelector(const AArch64TargetMachine &TM,
|
AArch64InstructionSelector(const AArch64TargetMachine &TM,
|
||||||
|
@ -33,6 +36,11 @@ public:
|
||||||
bool select(MachineInstr &I) const override;
|
bool select(MachineInstr &I) const override;
|
||||||
|
|
||||||
private:
|
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
|
/// tblgen-erated 'select' implementation, used as the initial selector for
|
||||||
/// the patterns that don't require complex C++.
|
/// the patterns that don't require complex C++.
|
||||||
bool selectImpl(MachineInstr &I) const;
|
bool selectImpl(MachineInstr &I) const;
|
||||||
|
|
|
@ -225,5 +225,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() {
|
||||||
setAction({G_BITCAST, 1, LLT::vector(32/EltSize, EltSize)}, Legal);
|
setAction({G_BITCAST, 1, LLT::vector(32/EltSize, EltSize)}, Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAction({G_VASTART, p0}, Legal);
|
||||||
|
|
||||||
computeTables();
|
computeTables();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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*)
|
Loading…
Reference in New Issue