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