1 //===-- Nios2ISelLowering.cpp - Nios2 DAG Lowering Implementation ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the interfaces that Nios2 uses to lower LLVM code into a
11 // selection DAG.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Nios2ISelLowering.h"
16 #include "Nios2MachineFunction.h"
17 #include "Nios2TargetMachine.h"
18 #include "llvm/CodeGen/CallingConvLower.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20
21 using namespace llvm;
22
23 //===----------------------------------------------------------------------===//
24 // Calling Convention Implementation
25 //===----------------------------------------------------------------------===//
26
27 #include "Nios2GenCallingConv.inc"
28
29 SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const30 Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
31 bool IsVarArg,
32 const SmallVectorImpl<ISD::OutputArg> &Outs,
33 const SmallVectorImpl<SDValue> &OutVals,
34 const SDLoc &DL, SelectionDAG &DAG) const {
35 // CCValAssign - represent the assignment of
36 // the return value to a location
37 SmallVector<CCValAssign, 16> RVLocs;
38 MachineFunction &MF = DAG.getMachineFunction();
39
40 // CCState - Info about the registers and stack slot.
41 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
42 // Analyze return values.
43 CCInfo.CheckReturn(Outs, RetCC_Nios2EABI);
44
45 SDValue Flag;
46 SmallVector<SDValue, 4> RetOps(1, Chain);
47
48 // Copy the result values into the output registers.
49 for (unsigned i = 0; i != RVLocs.size(); ++i) {
50 SDValue Val = OutVals[i];
51 CCValAssign &VA = RVLocs[i];
52 assert(VA.isRegLoc() && "Can only return in registers!");
53
54 if (RVLocs[i].getValVT() != RVLocs[i].getLocVT())
55 Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getLocVT(), Val);
56
57 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag);
58
59 // Guarantee that all emitted copies are stuck together with flags.
60 Flag = Chain.getValue(1);
61 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
62 }
63
64 if (Flag.getNode())
65 RetOps.push_back(Flag);
66
67 return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps);
68 }
69
70 // addLiveIn - This helper function adds the specified physical register to the
71 // MachineFunction as a live in value. It also creates a corresponding
72 // virtual register for it.
addLiveIn(MachineFunction & MF,unsigned PReg,const TargetRegisterClass * RC)73 static unsigned addLiveIn(MachineFunction &MF, unsigned PReg,
74 const TargetRegisterClass *RC) {
75 unsigned VReg = MF.getRegInfo().createVirtualRegister(RC);
76 MF.getRegInfo().addLiveIn(PReg, VReg);
77 return VReg;
78 }
79
80 //===----------------------------------------------------------------------===//
81 // Formal Arguments Calling Convention Implementation
82 //===----------------------------------------------------------------------===//
83
84 // LowerFormalArguments - transform physical registers into virtual registers
85 // and generate load operations for arguments places on the stack.
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const86 SDValue Nios2TargetLowering::LowerFormalArguments(
87 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
88 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
89 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
90 MachineFunction &MF = DAG.getMachineFunction();
91 MachineFrameInfo &MFI = MF.getFrameInfo();
92
93 // Assign locations to all of the incoming arguments.
94 SmallVector<CCValAssign, 16> ArgLocs;
95 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
96 *DAG.getContext());
97
98 CCInfo.AnalyzeFormalArguments(Ins, CC_Nios2);
99
100 // Used with vargs to acumulate store chains.
101 std::vector<SDValue> OutChains;
102
103 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
104 CCValAssign &VA = ArgLocs[i];
105
106 EVT ValVT = VA.getValVT();
107
108 // Arguments stored on registers
109 if (VA.isRegLoc()) {
110 MVT RegVT = VA.getLocVT();
111 unsigned ArgReg = VA.getLocReg();
112 const TargetRegisterClass *RC = getRegClassFor(RegVT);
113
114 // Transform the arguments stored on
115 // physical registers into virtual ones
116 unsigned Reg = addLiveIn(MF, ArgReg, RC);
117 SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
118
119 // If this is an 8 or 16-bit value, it has been passed promoted
120 // to 32 bits. Insert an assert[sz]ext to capture this, then
121 // truncate to the right size.
122 if (VA.getLocInfo() != CCValAssign::Full) {
123 unsigned Opcode = 0;
124 if (VA.getLocInfo() == CCValAssign::SExt)
125 Opcode = ISD::AssertSext;
126 else if (VA.getLocInfo() == CCValAssign::ZExt)
127 Opcode = ISD::AssertZext;
128 if (Opcode)
129 ArgValue =
130 DAG.getNode(Opcode, DL, RegVT, ArgValue, DAG.getValueType(ValVT));
131 ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue);
132 }
133
134 // Handle floating point arguments passed in integer registers.
135 if ((RegVT == MVT::i32 && ValVT == MVT::f32) ||
136 (RegVT == MVT::i64 && ValVT == MVT::f64))
137 ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue);
138 InVals.push_back(ArgValue);
139 } else { // VA.isRegLoc()
140 MVT LocVT = VA.getLocVT();
141
142 // sanity check
143 assert(VA.isMemLoc());
144
145 // The stack pointer offset is relative to the caller stack frame.
146 int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
147 VA.getLocMemOffset(), true);
148
149 // Create load nodes to retrieve arguments from the stack
150 SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
151 SDValue Load = DAG.getLoad(
152 LocVT, DL, Chain, FIN,
153 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
154 InVals.push_back(Load);
155 OutChains.push_back(Load.getValue(1));
156 }
157 }
158 if (!OutChains.empty()) {
159 OutChains.push_back(Chain);
160 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
161 }
162
163 return Chain;
164 }
165
166 //===----------------------------------------------------------------------===//
167 // TargetLowering Implementation
168 //===----------------------------------------------------------------------===//
169
Nios2TargetLowering(const TargetMachine & TM,const Nios2Subtarget & STI)170 Nios2TargetLowering::Nios2TargetLowering(const TargetMachine &TM,
171 const Nios2Subtarget &STI)
172 : TargetLowering(TM), Subtarget(&STI) {
173
174 addRegisterClass(MVT::i32, &Nios2::CPURegsRegClass);
175 computeRegisterProperties(Subtarget->getRegisterInfo());
176 }
177
getTargetNodeName(unsigned Opcode) const178 const char *Nios2TargetLowering::getTargetNodeName(unsigned Opcode) const {
179 switch (Opcode) {
180 case Nios2ISD::Hi:
181 return "Nios2ISD::Hi";
182 case Nios2ISD::Lo:
183 return "Nios2ISD::Lo";
184 case Nios2ISD::Ret:
185 return "Nios2ISD::Ret";
186 }
187 return nullptr;
188 }
189