diff options
Diffstat (limited to 'contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp new file mode 100644 index 0000000..52c95b6 --- /dev/null +++ b/contrib/llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -0,0 +1,203 @@ +//===-- 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 "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); + if (!VT.isSimple() || !VT.isInteger() || VT.isVector()) + return false; + + unsigned VTSize = VT.getSimpleVT().getSizeInBits(); + return VTSize == 8 || VTSize == 16 || VTSize == 32; +} + +namespace { +struct FuncReturnHandler : public CallLowering::ValueHandler { + FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB) + : ValueHandler(MIRBuilder, MRI), 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"); + + assert(VA.getLocInfo() != CCValAssign::SExt && + VA.getLocInfo() != CCValAssign::ZExt && + "ABI extensions not supported yet"); + + MIRBuilder.buildCopy(PhysReg, ValVReg); + 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. + +/// 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; + + CCAssignFn *AssignFn = + TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); + + ArgInfo RetInfo(VReg, Val->getType()); + setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F); + + FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); + return handleAssignments(MIRBuilder, AssignFn, RetInfo, RetHandler); +} + +bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, + const Value *Val, unsigned VReg) const { + assert(!Val == !VReg && "Return value without a vreg"); + + auto Ret = AddDefaultPred(MIRBuilder.buildInstrNoInsert(ARM::BX_RET)); + + if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret)) + return false; + + MIRBuilder.insertInstr(Ret); + return true; +} + +namespace { +struct FormalArgHandler : public CallLowering::ValueHandler { + FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) + : ValueHandler(MIRBuilder, MRI) {} + + unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) override { + assert(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 == 4 && "Unsupported size"); + + 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"); + + 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 DL = MIRBuilder.getMF().getDataLayout(); + auto &TLI = *getTLI<ARMTargetLowering>(); + + auto &Args = F.getArgumentList(); + unsigned ArgIdx = 0; + for (auto &Arg : Args) { + ArgIdx++; + if (!isSupportedType(DL, TLI, Arg.getType())) + return false; + + // FIXME: This check as well as ArgIdx are going away as soon as we support + // loading values < 32 bits. + if (ArgIdx > 4 && Arg.getType()->getIntegerBitWidth() != 32) + 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); + ArgInfos.push_back(AInfo); + Idx++; + } + + FormalArgHandler ArgHandler(MIRBuilder, MIRBuilder.getMF().getRegInfo()); + return handleAssignments(MIRBuilder, AssignFn, ArgInfos, ArgHandler); +} |