blob: 9f19cda8910120a4b7df52cf79572441f331c42a [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
Alex Bradbury74913e12017-11-08 13:31:40 +000058 setOperationAction(ISD::BR_CC, XLenVT, Expand);
Alex Bradbury89718422017-10-19 21:37:38 +000059 setBooleanContents(ZeroOrOneBooleanContent);
60
61 // Function alignments (log2).
62 setMinFunctionAlignment(3);
63 setPrefFunctionAlignment(3);
64}
65
66SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
67 SelectionDAG &DAG) const {
68 switch (Op.getOpcode()) {
69 default:
70 report_fatal_error("unimplemented operand");
Alex Bradburyec8aa912017-11-08 13:24:21 +000071 case ISD::GlobalAddress:
72 return lowerGlobalAddress(Op, DAG);
73 }
74}
75
76SDValue 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");
Alex Bradbury89718422017-10-19 21:37:38 +000095 }
96}
97
98// Calling Convention Implementation.
99#include "RISCVGenCallingConv.inc"
100
101// Transform physical registers into virtual registers.
102SDValue 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 break;
112 }
113
114 MachineFunction &MF = DAG.getMachineFunction();
115 MachineRegisterInfo &RegInfo = MF.getRegInfo();
116 MVT XLenVT = Subtarget.getXLenVT();
117
118 if (IsVarArg)
119 report_fatal_error("VarArg not supported");
120
121 // Assign locations to all of the incoming arguments.
122 SmallVector<CCValAssign, 16> ArgLocs;
123 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
124 CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
125
126 for (auto &VA : ArgLocs) {
127 if (!VA.isRegLoc())
128 report_fatal_error("Defined with too many args");
129
130 // Arguments passed in registers.
131 EVT RegVT = VA.getLocVT();
132 if (RegVT != XLenVT) {
133 DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
134 << RegVT.getEVTString() << "\n");
135 report_fatal_error("unhandled argument type");
136 }
137 const unsigned VReg =
138 RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
139 RegInfo.addLiveIn(VA.getLocReg(), VReg);
140 SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
141
142 InVals.push_back(ArgIn);
143 }
144 return Chain;
145}
146
147SDValue
148RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
149 bool IsVarArg,
150 const SmallVectorImpl<ISD::OutputArg> &Outs,
151 const SmallVectorImpl<SDValue> &OutVals,
152 const SDLoc &DL, SelectionDAG &DAG) const {
153 if (IsVarArg) {
154 report_fatal_error("VarArg not supported");
155 }
156
157 // Stores the assignment of the return value to a location.
158 SmallVector<CCValAssign, 16> RVLocs;
159
160 // Info about the registers and stack slot.
161 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
162 *DAG.getContext());
163
164 CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
165
166 SDValue Flag;
167 SmallVector<SDValue, 4> RetOps(1, Chain);
168
169 // Copy the result values into the output registers.
170 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
171 CCValAssign &VA = RVLocs[i];
172 assert(VA.isRegLoc() && "Can only return in registers!");
173
174 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
175
176 // Guarantee that all emitted copies are stuck together.
177 Flag = Chain.getValue(1);
178 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
179 }
180
181 RetOps[0] = Chain; // Update chain.
182
183 // Add the flag if we have it.
184 if (Flag.getNode()) {
185 RetOps.push_back(Flag);
186 }
187
188 return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
189}
190
191const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
192 switch ((RISCVISD::NodeType)Opcode) {
193 case RISCVISD::FIRST_NUMBER:
194 break;
195 case RISCVISD::RET_FLAG:
196 return "RISCVISD::RET_FLAG";
197 }
198 return nullptr;
199}