aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Nios2/Nios2ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Nios2/Nios2ISelLowering.cpp')
-rw-r--r--lib/Target/Nios2/Nios2ISelLowering.cpp159
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;
+}