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