blob: 49bc6a29e45b368011c6b8dfe4c40ace6e4922b4 [file] [log] [blame]
Alex Bradbury89718422017-10-19 21:37:38 +00001//===-- 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
34using namespace llvm;
35
36#define DEBUG_TYPE "riscv-lower"
37
38RISCVTargetLowering::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
Alex Bradburycfa62912017-11-08 12:20:01 +000052 for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD})
53 setLoadExtAction(N, XLenVT, MVT::i1, Promote);
54
Alex Bradbury89718422017-10-19 21:37:38 +000055 // TODO: add all necessary setOperationAction calls.
Alex Bradburyec8aa912017-11-08 13:24:21 +000056 setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
Alex Bradbury89718422017-10-19 21:37:38 +000057
58 setBooleanContents(ZeroOrOneBooleanContent);
59
60 // Function alignments (log2).
61 setMinFunctionAlignment(3);
62 setPrefFunctionAlignment(3);
63}
64
65SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
66 SelectionDAG &DAG) const {
67 switch (Op.getOpcode()) {
68 default:
69 report_fatal_error("unimplemented operand");
Alex Bradburyec8aa912017-11-08 13:24:21 +000070 case ISD::GlobalAddress:
71 return lowerGlobalAddress(Op, DAG);
72 }
73}
74
75SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
76 SelectionDAG &DAG) const {
77 SDLoc DL(Op);
78 EVT Ty = Op.getValueType();
79 GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
80 const GlobalValue *GV = N->getGlobal();
81 int64_t Offset = N->getOffset();
82
83 if (!isPositionIndependent() && !Subtarget.is64Bit()) {
84 SDValue GAHi =
85 DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_HI);
86 SDValue GALo =
87 DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_LO);
88 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
89 SDValue MNLo =
90 SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
91 return MNLo;
92 } else {
93 report_fatal_error("Unable to lowerGlobalAddress");
Alex Bradbury89718422017-10-19 21:37:38 +000094 }
95}
96
97// Calling Convention Implementation.
98#include "RISCVGenCallingConv.inc"
99
100// Transform physical registers into virtual registers.
101SDValue RISCVTargetLowering::LowerFormalArguments(
102 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
103 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
104 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
105
106 switch (CallConv) {
107 default:
108 report_fatal_error("Unsupported calling convention");
109 case CallingConv::C:
110 break;
111 }
112
113 MachineFunction &MF = DAG.getMachineFunction();
114 MachineRegisterInfo &RegInfo = MF.getRegInfo();
115 MVT XLenVT = Subtarget.getXLenVT();
116
117 if (IsVarArg)
118 report_fatal_error("VarArg not supported");
119
120 // Assign locations to all of the incoming arguments.
121 SmallVector<CCValAssign, 16> ArgLocs;
122 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
123 CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
124
125 for (auto &VA : ArgLocs) {
126 if (!VA.isRegLoc())
127 report_fatal_error("Defined with too many args");
128
129 // Arguments passed in registers.
130 EVT RegVT = VA.getLocVT();
131 if (RegVT != XLenVT) {
132 DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
133 << RegVT.getEVTString() << "\n");
134 report_fatal_error("unhandled argument type");
135 }
136 const unsigned VReg =
137 RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
138 RegInfo.addLiveIn(VA.getLocReg(), VReg);
139 SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
140
141 InVals.push_back(ArgIn);
142 }
143 return Chain;
144}
145
146SDValue
147RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
148 bool IsVarArg,
149 const SmallVectorImpl<ISD::OutputArg> &Outs,
150 const SmallVectorImpl<SDValue> &OutVals,
151 const SDLoc &DL, SelectionDAG &DAG) const {
152 if (IsVarArg) {
153 report_fatal_error("VarArg not supported");
154 }
155
156 // Stores the assignment of the return value to a location.
157 SmallVector<CCValAssign, 16> RVLocs;
158
159 // Info about the registers and stack slot.
160 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
161 *DAG.getContext());
162
163 CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
164
165 SDValue Flag;
166 SmallVector<SDValue, 4> RetOps(1, Chain);
167
168 // Copy the result values into the output registers.
169 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
170 CCValAssign &VA = RVLocs[i];
171 assert(VA.isRegLoc() && "Can only return in registers!");
172
173 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
174
175 // Guarantee that all emitted copies are stuck together.
176 Flag = Chain.getValue(1);
177 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
178 }
179
180 RetOps[0] = Chain; // Update chain.
181
182 // Add the flag if we have it.
183 if (Flag.getNode()) {
184 RetOps.push_back(Flag);
185 }
186
187 return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
188}
189
190const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
191 switch ((RISCVISD::NodeType)Opcode) {
192 case RISCVISD::FIRST_NUMBER:
193 break;
194 case RISCVISD::RET_FLAG:
195 return "RISCVISD::RET_FLAG";
196 }
197 return nullptr;
198}