diff options
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64CallLowering.cpp')
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64CallLowering.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp new file mode 100644 index 00000000000..7df274d8b92 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -0,0 +1,111 @@ +//===-- llvm/lib/Target/AArch64/AArch64CallLowering.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 "AArch64CallLowering.h" +#include "AArch64ISelLowering.h" + +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; +#ifdef LLVM_BUILD_GLOBAL_ISEL +# define EMIT_IMPLEMENTATION 1 +#else +# define EMIT_IMPLEMENTATION 0 +#endif + +AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI) + : CallLowering(&TLI) { +} + +bool AArch64CallLowering::LowerReturn(MachineIRBuilder &MIRBuilder, + const Value *Val, unsigned VReg) const { + if (!EMIT_IMPLEMENTATION) + return false; + + MachineInstr *Return = MIRBuilder.buildInstr(AArch64::RET_ReallyLR); + assert(Return && "Unable to build a return instruction?!"); + + assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg"); + if (VReg) { + assert(Val->getType()->isIntegerTy() && "Type not supported yet"); + unsigned Size = Val->getType()->getPrimitiveSizeInBits(); + assert((Size == 64 || Size == 32) && "Size not supported yet"); + unsigned ResReg = (Size == 32) ? AArch64::W0 : AArch64::X0; + // Set the insertion point to be right before Return. + MIRBuilder.setInstr(*Return, /* Before */ true); + MachineInstr *Copy = + MIRBuilder.buildInstr(TargetOpcode::COPY, ResReg, VReg); + (void)Copy; + assert(Copy->getNextNode() == Return && + "The insertion did not happen where we expected"); + MachineInstrBuilder(MIRBuilder.getMF(), Return) + .addReg(ResReg, RegState::Implicit); + } + return true; +} + +bool AArch64CallLowering::LowerFormalArguments( + MachineIRBuilder &MIRBuilder, const Function::ArgumentListType &Args, + const SmallVectorImpl<unsigned> &VRegs) const { + if (!EMIT_IMPLEMENTATION) + return false; + + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = *MF.getFunction(); + + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); + + unsigned NumArgs = Args.size(); + Function::const_arg_iterator CurOrigArg = Args.begin(); + const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); + for (unsigned i = 0; i != NumArgs; ++i, ++CurOrigArg) { + MVT ValVT = MVT::getVT(CurOrigArg->getType()); + CCAssignFn *AssignFn = + TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false); + bool Res = + AssignFn(i, ValVT, ValVT, CCValAssign::Full, ISD::ArgFlagsTy(), CCInfo); + assert(!Res && "Call operand has unhandled type"); + (void)Res; + } + assert(ArgLocs.size() == Args.size() && + "We have a different number of location and args?!"); + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + assert(VA.isRegLoc() && "Not yet implemented"); + // Transform the arguments in physical registers into virtual ones. + MIRBuilder.getMBB().addLiveIn(VA.getLocReg()); + MIRBuilder.buildInstr(TargetOpcode::COPY, VRegs[i], VA.getLocReg()); + + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::BCvt: + // We don't care about bitcast. + break; + case CCValAssign::AExt: + case CCValAssign::SExt: + case CCValAssign::ZExt: + // Zero/Sign extend the register. + assert(0 && "Not yet implemented"); + break; + } + } + return true; +} |