It is important to change the ArgInfo's type from pointer to integer, otherwise the CC assign function won't know what to do. Instead of hacking it up, we use ComputeValueVTs and introduce some of the helpers that we will need later on for lowering more complex types. llvm-svn: 293889
232 lines
8.1 KiB
C++
232 lines
8.1 KiB
C++
//===-- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements the lowering of LLVM calls to machine code calls for
|
|
/// GlobalISel.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ARMCallLowering.h"
|
|
|
|
#include "ARMBaseInstrInfo.h"
|
|
#include "ARMISelLowering.h"
|
|
#include "ARMSubtarget.h"
|
|
|
|
#include "llvm/CodeGen/Analysis.h"
|
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
|
#error "This shouldn't be built without GISel"
|
|
#endif
|
|
|
|
ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
|
|
: CallLowering(&TLI) {}
|
|
|
|
static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI,
|
|
Type *T) {
|
|
EVT VT = TLI.getValueType(DL, T, true);
|
|
if (!VT.isSimple() || !VT.isInteger() || VT.isVector())
|
|
return false;
|
|
|
|
unsigned VTSize = VT.getSimpleVT().getSizeInBits();
|
|
return VTSize == 1 || VTSize == 8 || VTSize == 16 || VTSize == 32;
|
|
}
|
|
|
|
namespace {
|
|
struct FuncReturnHandler : public CallLowering::ValueHandler {
|
|
FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
|
MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
|
|
: ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
|
|
|
|
unsigned getStackAddress(uint64_t Size, int64_t Offset,
|
|
MachinePointerInfo &MPO) override {
|
|
llvm_unreachable("Don't know how to get a stack address yet");
|
|
}
|
|
|
|
void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
|
|
CCValAssign &VA) override {
|
|
assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
|
|
assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
|
|
|
|
assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
|
|
assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
|
|
|
|
unsigned ExtReg = extendRegister(ValVReg, VA);
|
|
MIRBuilder.buildCopy(PhysReg, ExtReg);
|
|
MIB.addUse(PhysReg, RegState::Implicit);
|
|
}
|
|
|
|
void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
|
|
MachinePointerInfo &MPO, CCValAssign &VA) override {
|
|
llvm_unreachable("Don't know how to assign a value to an address yet");
|
|
}
|
|
|
|
MachineInstrBuilder &MIB;
|
|
};
|
|
} // End anonymous namespace.
|
|
|
|
void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg,
|
|
SmallVectorImpl<ArgInfo> &SplitArgs,
|
|
const DataLayout &DL,
|
|
MachineRegisterInfo &MRI) const {
|
|
const ARMTargetLowering &TLI = *getTLI<ARMTargetLowering>();
|
|
LLVMContext &Ctx = OrigArg.Ty->getContext();
|
|
|
|
SmallVector<EVT, 4> SplitVTs;
|
|
SmallVector<uint64_t, 4> Offsets;
|
|
ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
|
|
|
|
assert(SplitVTs.size() == 1 && "Unsupported type");
|
|
|
|
// Even if there is no splitting to do, we still want to replace the original
|
|
// type (e.g. pointer type -> integer).
|
|
SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx),
|
|
OrigArg.Flags, OrigArg.IsFixed);
|
|
}
|
|
|
|
/// 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,
|
|
MachineInstrBuilder &Ret) const {
|
|
if (!Val)
|
|
// Nothing to do here.
|
|
return true;
|
|
|
|
auto &MF = MIRBuilder.getMF();
|
|
const auto &F = *MF.getFunction();
|
|
|
|
auto DL = MF.getDataLayout();
|
|
auto &TLI = *getTLI<ARMTargetLowering>();
|
|
if (!isSupportedType(DL, TLI, Val->getType()))
|
|
return false;
|
|
|
|
SmallVector<ArgInfo, 4> SplitVTs;
|
|
ArgInfo RetInfo(VReg, Val->getType());
|
|
setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F);
|
|
splitToValueTypes(RetInfo, SplitVTs, DL, MF.getRegInfo());
|
|
|
|
CCAssignFn *AssignFn =
|
|
TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
|
|
|
|
FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn);
|
|
return handleAssignments(MIRBuilder, SplitVTs, RetHandler);
|
|
}
|
|
|
|
bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
|
const Value *Val, unsigned VReg) const {
|
|
assert(!Val == !VReg && "Return value without a vreg");
|
|
|
|
auto Ret = MIRBuilder.buildInstrNoInsert(ARM::BX_RET).add(predOps(ARMCC::AL));
|
|
|
|
if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret))
|
|
return false;
|
|
|
|
MIRBuilder.insertInstr(Ret);
|
|
return true;
|
|
}
|
|
|
|
namespace {
|
|
struct FormalArgHandler : public CallLowering::ValueHandler {
|
|
FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
|
CCAssignFn AssignFn)
|
|
: ValueHandler(MIRBuilder, MRI, AssignFn) {}
|
|
|
|
unsigned getStackAddress(uint64_t Size, int64_t Offset,
|
|
MachinePointerInfo &MPO) override {
|
|
assert((Size == 1 || Size == 2 || Size == 4) && "Unsupported size");
|
|
|
|
auto &MFI = MIRBuilder.getMF().getFrameInfo();
|
|
|
|
int FI = MFI.CreateFixedObject(Size, Offset, true);
|
|
MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
|
|
|
|
unsigned AddrReg =
|
|
MRI.createGenericVirtualRegister(LLT::pointer(MPO.getAddrSpace(), 32));
|
|
MIRBuilder.buildFrameIndex(AddrReg, FI);
|
|
|
|
return AddrReg;
|
|
}
|
|
|
|
void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
|
|
MachinePointerInfo &MPO, CCValAssign &VA) override {
|
|
assert((Size == 1 || Size == 2 || Size == 4) && "Unsupported size");
|
|
|
|
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.
|
|
Size = 4;
|
|
assert(MRI.getType(ValVReg).isScalar() && "Only scalars supported atm");
|
|
MRI.setType(ValVReg, LLT::scalar(32));
|
|
}
|
|
|
|
auto MMO = MIRBuilder.getMF().getMachineMemOperand(
|
|
MPO, MachineMemOperand::MOLoad, Size, /* Alignment */ 0);
|
|
MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
|
|
}
|
|
|
|
void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
|
|
CCValAssign &VA) override {
|
|
assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
|
|
assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
|
|
|
|
assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size");
|
|
assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size");
|
|
|
|
// The caller should handle all necesary extensions.
|
|
MIRBuilder.getMBB().addLiveIn(PhysReg);
|
|
MIRBuilder.buildCopy(ValVReg, PhysReg);
|
|
}
|
|
};
|
|
} // End anonymous namespace
|
|
|
|
bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
|
const Function &F,
|
|
ArrayRef<unsigned> VRegs) const {
|
|
// Quick exit if there aren't any args
|
|
if (F.arg_empty())
|
|
return true;
|
|
|
|
if (F.isVarArg())
|
|
return false;
|
|
|
|
auto &MF = MIRBuilder.getMF();
|
|
auto DL = MF.getDataLayout();
|
|
auto &TLI = *getTLI<ARMTargetLowering>();
|
|
|
|
if (TLI.getSubtarget()->isThumb())
|
|
return false;
|
|
|
|
auto &Args = F.getArgumentList();
|
|
for (auto &Arg : Args)
|
|
if (!isSupportedType(DL, TLI, Arg.getType()))
|
|
return false;
|
|
|
|
CCAssignFn *AssignFn =
|
|
TLI.CCAssignFnForCall(F.getCallingConv(), F.isVarArg());
|
|
|
|
SmallVector<ArgInfo, 8> ArgInfos;
|
|
unsigned Idx = 0;
|
|
for (auto &Arg : Args) {
|
|
ArgInfo AInfo(VRegs[Idx], Arg.getType());
|
|
setArgFlags(AInfo, Idx + 1, DL, F);
|
|
splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo());
|
|
Idx++;
|
|
}
|
|
|
|
FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo(),
|
|
AssignFn);
|
|
return handleAssignments(MIRBuilder, ArgInfos, ArgHandler);
|
|
}
|