1 //===-- RISCVISelLowering.cpp - RISCV 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 defines the interfaces that RISCV uses to lower LLVM code into a
11 // selection DAG.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RISCVISelLowering.h"
16 #include "RISCV.h"
17 #include "RISCVRegisterInfo.h"
18 #include "RISCVSubtarget.h"
19 #include "RISCVTargetMachine.h"
20 #include "llvm/CodeGen/CallingConvLower.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/SelectionDAGISel.h"
26 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
27 #include "llvm/CodeGen/ValueTypes.h"
28 #include "llvm/IR/DiagnosticInfo.h"
29 #include "llvm/IR/DiagnosticPrinter.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/raw_ostream.h"
33 
34 using namespace llvm;
35 
36 #define DEBUG_TYPE "riscv-lower"
37 
38 RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
39                                          const RISCVSubtarget &STI)
40     : TargetLowering(TM), Subtarget(STI) {
41 
42   MVT XLenVT = Subtarget.getXLenVT();
43 
44   // Set up the register classes.
45   addRegisterClass(XLenVT, &RISCV::GPRRegClass);
46 
47   // Compute derived properties from the register classes.
48   computeRegisterProperties(STI.getRegisterInfo());
49 
50   setStackPointerRegisterToSaveRestore(RISCV::X2);
51 
52   for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD})
53     setLoadExtAction(N, XLenVT, MVT::i1, Promote);
54 
55   // TODO: add all necessary setOperationAction calls.
56   setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
57 
58   setOperationAction(ISD::BR_CC, XLenVT, Expand);
59   setBooleanContents(ZeroOrOneBooleanContent);
60 
61   // Function alignments (log2).
62   setMinFunctionAlignment(3);
63   setPrefFunctionAlignment(3);
64 }
65 
66 SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
67                                             SelectionDAG &DAG) const {
68   switch (Op.getOpcode()) {
69   default:
70     report_fatal_error("unimplemented operand");
71   case ISD::GlobalAddress:
72     return lowerGlobalAddress(Op, DAG);
73   }
74 }
75 
76 SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
77                                                 SelectionDAG &DAG) const {
78   SDLoc DL(Op);
79   EVT Ty = Op.getValueType();
80   GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
81   const GlobalValue *GV = N->getGlobal();
82   int64_t Offset = N->getOffset();
83 
84   if (!isPositionIndependent() && !Subtarget.is64Bit()) {
85     SDValue GAHi =
86         DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_HI);
87     SDValue GALo =
88         DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_LO);
89     SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
90     SDValue MNLo =
91         SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
92     return MNLo;
93   } else {
94     report_fatal_error("Unable to lowerGlobalAddress");
95   }
96 }
97 
98 // Calling Convention Implementation.
99 #include "RISCVGenCallingConv.inc"
100 
101 // Transform physical registers into virtual registers.
102 SDValue RISCVTargetLowering::LowerFormalArguments(
103     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
104     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
105     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
106 
107   switch (CallConv) {
108   default:
109     report_fatal_error("Unsupported calling convention");
110   case CallingConv::C:
111   case CallingConv::Fast:
112     break;
113   }
114 
115   MachineFunction &MF = DAG.getMachineFunction();
116   MachineRegisterInfo &RegInfo = MF.getRegInfo();
117   MVT XLenVT = Subtarget.getXLenVT();
118 
119   if (IsVarArg)
120     report_fatal_error("VarArg not supported");
121 
122   // Assign locations to all of the incoming arguments.
123   SmallVector<CCValAssign, 16> ArgLocs;
124   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
125   CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
126 
127   for (auto &VA : ArgLocs) {
128     if (!VA.isRegLoc())
129       report_fatal_error("Defined with too many args");
130 
131     // Arguments passed in registers.
132     EVT RegVT = VA.getLocVT();
133     if (RegVT != XLenVT) {
134       DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
135           << RegVT.getEVTString() << "\n");
136       report_fatal_error("unhandled argument type");
137     }
138     const unsigned VReg =
139       RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
140     RegInfo.addLiveIn(VA.getLocReg(), VReg);
141     SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
142 
143     InVals.push_back(ArgIn);
144   }
145   return Chain;
146 }
147 
148 // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
149 // and output parameter nodes.
150 SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
151                                        SmallVectorImpl<SDValue> &InVals) const {
152   SelectionDAG &DAG = CLI.DAG;
153   SDLoc &DL = CLI.DL;
154   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
155   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
156   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
157   SDValue Chain = CLI.Chain;
158   SDValue Callee = CLI.Callee;
159   CLI.IsTailCall = false;
160   CallingConv::ID CallConv = CLI.CallConv;
161   bool IsVarArg = CLI.IsVarArg;
162   EVT PtrVT = getPointerTy(DAG.getDataLayout());
163 
164   if (IsVarArg) {
165     report_fatal_error("LowerCall with varargs not implemented");
166   }
167 
168   MachineFunction &MF = DAG.getMachineFunction();
169 
170   // Analyze the operands of the call, assigning locations to each operand.
171   SmallVector<CCValAssign, 16> ArgLocs;
172   CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
173   ArgCCInfo.AnalyzeCallOperands(Outs, CC_RISCV32);
174 
175   // Get a count of how many bytes are to be pushed on the stack.
176   unsigned NumBytes = ArgCCInfo.getNextStackOffset();
177 
178   for (auto &Arg : Outs) {
179     if (!Arg.Flags.isByVal())
180       continue;
181     report_fatal_error("Passing arguments byval not yet implemented");
182   }
183 
184   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
185 
186   // Copy argument values to their designated locations.
187   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
188   SDValue StackPtr;
189   for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) {
190     CCValAssign &VA = ArgLocs[I];
191     SDValue ArgValue = OutVals[I];
192 
193     // Promote the value if needed.
194     // For now, only handle fully promoted arguments.
195     switch (VA.getLocInfo()) {
196     case CCValAssign::Full:
197       break;
198     default:
199       llvm_unreachable("Unknown loc info!");
200     }
201 
202     if (VA.isRegLoc()) {
203       // Queue up the argument copies and emit them at the end.
204       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
205     } else {
206       assert(VA.isMemLoc() && "Argument not register or memory");
207       report_fatal_error("Passing arguments via the stack not yet implemented");
208     }
209   }
210 
211   SDValue Glue;
212 
213   // Build a sequence of copy-to-reg nodes, chained and glued together.
214   for (auto &Reg : RegsToPass) {
215     Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
216     Glue = Chain.getValue(1);
217   }
218 
219   if (isa<GlobalAddressSDNode>(Callee)) {
220     Callee = lowerGlobalAddress(Callee, DAG);
221   } else if (isa<ExternalSymbolSDNode>(Callee)) {
222     report_fatal_error(
223         "lowerExternalSymbol, needed for lowerCall, not yet handled");
224   }
225 
226   // The first call operand is the chain and the second is the target address.
227   SmallVector<SDValue, 8> Ops;
228   Ops.push_back(Chain);
229   Ops.push_back(Callee);
230 
231   // Add argument registers to the end of the list so that they are
232   // known live into the call.
233   for (auto &Reg : RegsToPass)
234     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
235 
236   // Add a register mask operand representing the call-preserved registers.
237   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
238   const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
239   assert(Mask && "Missing call preserved mask for calling convention");
240   Ops.push_back(DAG.getRegisterMask(Mask));
241 
242   // Glue the call to the argument copies, if any.
243   if (Glue.getNode())
244     Ops.push_back(Glue);
245 
246   // Emit the call.
247   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
248   Chain = DAG.getNode(RISCVISD::CALL, DL, NodeTys, Ops);
249   Glue = Chain.getValue(1);
250 
251   // Mark the end of the call, which is glued to the call itself.
252   Chain = DAG.getCALLSEQ_END(Chain,
253                              DAG.getConstant(NumBytes, DL, PtrVT, true),
254                              DAG.getConstant(0, DL, PtrVT, true),
255                              Glue, DL);
256   Glue = Chain.getValue(1);
257 
258   // Assign locations to each value returned by this call.
259   SmallVector<CCValAssign, 16> RVLocs;
260   CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
261   RetCCInfo.AnalyzeCallResult(Ins, RetCC_RISCV32);
262 
263   // Copy all of the result registers out of their specified physreg.
264   for (auto &VA : RVLocs) {
265     // Copy the value out, gluing the copy to the end of the call sequence.
266     SDValue RetValue = DAG.getCopyFromReg(Chain, DL, VA.getLocReg(),
267                                           VA.getLocVT(), Glue);
268     Chain = RetValue.getValue(1);
269     Glue = RetValue.getValue(2);
270 
271     InVals.push_back(Chain.getValue(0));
272   }
273 
274   return Chain;
275 }
276 
277 SDValue
278 RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
279                                  bool IsVarArg,
280                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
281                                  const SmallVectorImpl<SDValue> &OutVals,
282                                  const SDLoc &DL, SelectionDAG &DAG) const {
283   if (IsVarArg) {
284     report_fatal_error("VarArg not supported");
285   }
286 
287   // Stores the assignment of the return value to a location.
288   SmallVector<CCValAssign, 16> RVLocs;
289 
290   // Info about the registers and stack slot.
291   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
292                  *DAG.getContext());
293 
294   CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
295 
296   SDValue Flag;
297   SmallVector<SDValue, 4> RetOps(1, Chain);
298 
299   // Copy the result values into the output registers.
300   for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
301     CCValAssign &VA = RVLocs[i];
302     assert(VA.isRegLoc() && "Can only return in registers!");
303 
304     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
305 
306     // Guarantee that all emitted copies are stuck together.
307     Flag = Chain.getValue(1);
308     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
309   }
310 
311   RetOps[0] = Chain; // Update chain.
312 
313   // Add the flag if we have it.
314   if (Flag.getNode()) {
315     RetOps.push_back(Flag);
316   }
317 
318   return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
319 }
320 
321 const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
322   switch ((RISCVISD::NodeType)Opcode) {
323   case RISCVISD::FIRST_NUMBER:
324     break;
325   case RISCVISD::RET_FLAG:
326     return "RISCVISD::RET_FLAG";
327   case RISCVISD::CALL:
328     return "RISCVISD::CALL";
329   }
330   return nullptr;
331 }
332