diff options
Diffstat (limited to 'lib/Target/Nios2/Nios2ISelLowering.cpp')
| -rw-r--r-- | lib/Target/Nios2/Nios2ISelLowering.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/Target/Nios2/Nios2ISelLowering.cpp b/lib/Target/Nios2/Nios2ISelLowering.cpp new file mode 100644 index 000000000000..99aa43f960c1 --- /dev/null +++ b/lib/Target/Nios2/Nios2ISelLowering.cpp @@ -0,0 +1,159 @@ +//===-- Nios2ISelLowering.cpp - Nios2 DAG Lowering Implementation ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the interfaces that Nios2 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "Nios2ISelLowering.h" +#include "Nios2MachineFunction.h" +#include "Nios2TargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "Nios2GenCallingConv.inc" + +SDValue +Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SDLoc &DL, SelectionDAG &DAG) const { + + SmallVector<SDValue, 4> RetOps(1, Chain); + + return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps); +} + +// addLiveIn - This helper function adds the specified physical register to the +// MachineFunction as a live in value. It also creates a corresponding +// virtual register for it. +static unsigned addLiveIn(MachineFunction &MF, unsigned PReg, + const TargetRegisterClass *RC) { + unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); + MF.getRegInfo().addLiveIn(PReg, VReg); + return VReg; +} + +//===----------------------------------------------------------------------===// +// Formal Arguments Calling Convention Implementation +//===----------------------------------------------------------------------===// + +// LowerFormalArguments - transform physical registers into virtual registers +// and generate load operations for arguments places on the stack. +SDValue Nios2TargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CC_Nios2); + + // Used with vargs to acumulate store chains. + std::vector<SDValue> OutChains; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + EVT ValVT = VA.getValVT(); + + // Arguments stored on registers + if (VA.isRegLoc()) { + MVT RegVT = VA.getLocVT(); + unsigned ArgReg = VA.getLocReg(); + const TargetRegisterClass *RC = getRegClassFor(RegVT); + + // Transform the arguments stored on + // physical registers into virtual ones + unsigned Reg = addLiveIn(MF, ArgReg, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); + + // If this is an 8 or 16-bit value, it has been passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. + if (VA.getLocInfo() != CCValAssign::Full) { + unsigned Opcode = 0; + if (VA.getLocInfo() == CCValAssign::SExt) + Opcode = ISD::AssertSext; + else if (VA.getLocInfo() == CCValAssign::ZExt) + Opcode = ISD::AssertZext; + if (Opcode) + ArgValue = + DAG.getNode(Opcode, DL, RegVT, ArgValue, DAG.getValueType(ValVT)); + ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); + } + + // Handle floating point arguments passed in integer registers. + if ((RegVT == MVT::i32 && ValVT == MVT::f32) || + (RegVT == MVT::i64 && ValVT == MVT::f64)) + ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); + InVals.push_back(ArgValue); + } else { // VA.isRegLoc() + MVT LocVT = VA.getLocVT(); + + // sanity check + assert(VA.isMemLoc()); + + // The stack pointer offset is relative to the caller stack frame. + int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, + VA.getLocMemOffset(), true); + + // Create load nodes to retrieve arguments from the stack + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); + SDValue Load = DAG.getLoad( + LocVT, DL, Chain, FIN, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); + InVals.push_back(Load); + OutChains.push_back(Load.getValue(1)); + } + } + if (!OutChains.empty()) { + OutChains.push_back(Chain); + Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); + } + + return Chain; +} + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +Nios2TargetLowering::Nios2TargetLowering(const TargetMachine &TM, + const Nios2Subtarget &STI) + : TargetLowering(TM), Subtarget(&STI) { + + addRegisterClass(MVT::i32, &Nios2::CPURegsRegClass); + computeRegisterProperties(Subtarget->getRegisterInfo()); +} + +const char *Nios2TargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + case Nios2ISD::Hi: + return "Nios2ISD::Hi"; + case Nios2ISD::Lo: + return "Nios2ISD::Lo"; + case Nios2ISD::Ret: + return "Nios2ISD::Ret"; + } + return nullptr; +} |
