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   // TODO: add all necessary setOperationAction calls.
53 
54   setBooleanContents(ZeroOrOneBooleanContent);
55 
56   // Function alignments (log2).
57   setMinFunctionAlignment(3);
58   setPrefFunctionAlignment(3);
59 }
60 
61 SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
62                                             SelectionDAG &DAG) const {
63   switch (Op.getOpcode()) {
64   default:
65     report_fatal_error("unimplemented operand");
66   }
67 }
68 
69 // Calling Convention Implementation.
70 #include "RISCVGenCallingConv.inc"
71 
72 // Transform physical registers into virtual registers.
73 SDValue RISCVTargetLowering::LowerFormalArguments(
74     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
75     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
76     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
77 
78   switch (CallConv) {
79   default:
80     report_fatal_error("Unsupported calling convention");
81   case CallingConv::C:
82     break;
83   }
84 
85   MachineFunction &MF = DAG.getMachineFunction();
86   MachineRegisterInfo &RegInfo = MF.getRegInfo();
87   MVT XLenVT = Subtarget.getXLenVT();
88 
89   if (IsVarArg)
90     report_fatal_error("VarArg not supported");
91 
92   // Assign locations to all of the incoming arguments.
93   SmallVector<CCValAssign, 16> ArgLocs;
94   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
95   CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
96 
97   for (auto &VA : ArgLocs) {
98     if (!VA.isRegLoc())
99       report_fatal_error("Defined with too many args");
100 
101     // Arguments passed in registers.
102     EVT RegVT = VA.getLocVT();
103     if (RegVT != XLenVT) {
104       DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
105           << RegVT.getEVTString() << "\n");
106       report_fatal_error("unhandled argument type");
107     }
108     const unsigned VReg =
109       RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
110     RegInfo.addLiveIn(VA.getLocReg(), VReg);
111     SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
112 
113     InVals.push_back(ArgIn);
114   }
115   return Chain;
116 }
117 
118 SDValue
119 RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
120                                  bool IsVarArg,
121                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
122                                  const SmallVectorImpl<SDValue> &OutVals,
123                                  const SDLoc &DL, SelectionDAG &DAG) const {
124   if (IsVarArg) {
125     report_fatal_error("VarArg not supported");
126   }
127 
128   // Stores the assignment of the return value to a location.
129   SmallVector<CCValAssign, 16> RVLocs;
130 
131   // Info about the registers and stack slot.
132   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
133                  *DAG.getContext());
134 
135   CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
136 
137   SDValue Flag;
138   SmallVector<SDValue, 4> RetOps(1, Chain);
139 
140   // Copy the result values into the output registers.
141   for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
142     CCValAssign &VA = RVLocs[i];
143     assert(VA.isRegLoc() && "Can only return in registers!");
144 
145     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
146 
147     // Guarantee that all emitted copies are stuck together.
148     Flag = Chain.getValue(1);
149     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
150   }
151 
152   RetOps[0] = Chain; // Update chain.
153 
154   // Add the flag if we have it.
155   if (Flag.getNode()) {
156     RetOps.push_back(Flag);
157   }
158 
159   return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
160 }
161 
162 const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
163   switch ((RISCVISD::NodeType)Opcode) {
164   case RISCVISD::FIRST_NUMBER:
165     break;
166   case RISCVISD::RET_FLAG:
167     return "RISCVISD::RET_FLAG";
168   }
169   return nullptr;
170 }
171