Alex Bradbury | 8971842 | 2017-10-19 21:37:38 +0000 | [diff] [blame] | 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 | |
Alex Bradbury | cfa6291 | 2017-11-08 12:20:01 +0000 | [diff] [blame] | 52 | for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) |
| 53 | setLoadExtAction(N, XLenVT, MVT::i1, Promote); |
| 54 | |
Alex Bradbury | 8971842 | 2017-10-19 21:37:38 +0000 | [diff] [blame] | 55 | // TODO: add all necessary setOperationAction calls. |
| 56 | |
| 57 | setBooleanContents(ZeroOrOneBooleanContent); |
| 58 | |
| 59 | // Function alignments (log2). |
| 60 | setMinFunctionAlignment(3); |
| 61 | setPrefFunctionAlignment(3); |
| 62 | } |
| 63 | |
| 64 | SDValue 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. |
| 76 | SDValue 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 | |
| 121 | SDValue |
| 122 | RISCVTargetLowering::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 | |
| 165 | const 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 | } |