1 //=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the interfaces that LoongArch uses to lower LLVM code into 10 // a selection DAG. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "LoongArchISelLowering.h" 15 #include "LoongArch.h" 16 #include "LoongArchMachineFunctionInfo.h" 17 #include "LoongArchRegisterInfo.h" 18 #include "LoongArchSubtarget.h" 19 #include "LoongArchTargetMachine.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/Support/Debug.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "loongarch-isel-lowering" 26 27 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, 28 const LoongArchSubtarget &STI) 29 : TargetLowering(TM), Subtarget(STI) { 30 31 MVT GRLenVT = Subtarget.getGRLenVT(); 32 // Set up the register classes. 33 addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); 34 35 // TODO: add necessary setOperationAction calls later. 36 37 // Compute derived properties from the register classes. 38 computeRegisterProperties(STI.getRegisterInfo()); 39 40 setStackPointerRegisterToSaveRestore(LoongArch::R3); 41 42 // Function alignments. 43 const Align FunctionAlignment(4); 44 setMinFunctionAlignment(FunctionAlignment); 45 } 46 47 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { 48 switch ((LoongArchISD::NodeType)Opcode) { 49 case LoongArchISD::FIRST_NUMBER: 50 break; 51 52 #define NODE_NAME_CASE(node) \ 53 case LoongArchISD::node: \ 54 return "LoongArchISD::" #node; 55 56 // TODO: Add more target-dependent nodes later. 57 NODE_NAME_CASE(RET) 58 } 59 #undef NODE_NAME_CASE 60 return nullptr; 61 } 62 63 //===----------------------------------------------------------------------===// 64 // Calling Convention Implementation 65 //===----------------------------------------------------------------------===// 66 // FIXME: Now, we only support CallingConv::C with fixed arguments which are 67 // passed with integer registers. 68 const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, 69 LoongArch::R7, LoongArch::R8, LoongArch::R9, 70 LoongArch::R10, LoongArch::R11}; 71 72 // Implements the LoongArch calling convention. Returns true upon failure. 73 static bool CC_LoongArch(unsigned ValNo, MVT ValVT, 74 CCValAssign::LocInfo LocInfo, CCState &State) { 75 // Allocate to a register if possible. 76 Register Reg = State.AllocateReg(ArgGPRs); 77 if (Reg) { 78 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); 79 return false; 80 } 81 82 // TODO: Handle arguments passed without register. 83 return true; 84 } 85 86 void LoongArchTargetLowering::analyzeInputArgs( 87 CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins, 88 LoongArchCCAssignFn Fn) const { 89 for (unsigned i = 0, e = Ins.size(); i != e; ++i) { 90 MVT ArgVT = Ins[i].VT; 91 92 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 93 LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " 94 << EVT(ArgVT).getEVTString() << '\n'); 95 llvm_unreachable(""); 96 } 97 } 98 } 99 100 void LoongArchTargetLowering::analyzeOutputArgs( 101 CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs, 102 LoongArchCCAssignFn Fn) const { 103 for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 104 MVT ArgVT = Outs[i].VT; 105 106 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 107 LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " 108 << EVT(ArgVT).getEVTString() << "\n"); 109 llvm_unreachable(""); 110 } 111 } 112 } 113 114 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, 115 const CCValAssign &VA, const SDLoc &DL, 116 const LoongArchTargetLowering &TLI) { 117 MachineFunction &MF = DAG.getMachineFunction(); 118 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 119 EVT LocVT = VA.getLocVT(); 120 const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); 121 Register VReg = RegInfo.createVirtualRegister(RC); 122 RegInfo.addLiveIn(VA.getLocReg(), VReg); 123 124 return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 125 } 126 127 // Transform physical registers into virtual registers. 128 SDValue LoongArchTargetLowering::LowerFormalArguments( 129 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 130 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 131 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 132 133 MachineFunction &MF = DAG.getMachineFunction(); 134 135 switch (CallConv) { 136 default: 137 llvm_unreachable("Unsupported calling convention"); 138 case CallingConv::C: 139 break; 140 } 141 142 // Assign locations to all of the incoming arguments. 143 SmallVector<CCValAssign> ArgLocs; 144 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 145 146 analyzeInputArgs(CCInfo, Ins, CC_LoongArch); 147 148 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) 149 InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); 150 151 return Chain; 152 } 153 154 bool LoongArchTargetLowering::CanLowerReturn( 155 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 156 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 157 // Any return value split in to more than two values can't be returned 158 // directly. 159 return Outs.size() <= 2; 160 } 161 162 SDValue LoongArchTargetLowering::LowerReturn( 163 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 164 const SmallVectorImpl<ISD::OutputArg> &Outs, 165 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 166 SelectionDAG &DAG) const { 167 // Stores the assignment of the return value to a location. 168 SmallVector<CCValAssign> RVLocs; 169 170 // Info about the registers and stack slot. 171 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 172 *DAG.getContext()); 173 174 analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); 175 176 SDValue Glue; 177 SmallVector<SDValue, 4> RetOps(1, Chain); 178 179 // Copy the result values into the output registers. 180 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { 181 CCValAssign &VA = RVLocs[i]; 182 assert(VA.isRegLoc() && "Can only return in registers!"); 183 184 // Handle a 'normal' return. 185 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); 186 187 // Guarantee that all emitted copies are stuck together. 188 Glue = Chain.getValue(1); 189 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 190 } 191 192 RetOps[0] = Chain; // Update chain. 193 194 // Add the glue node if we have it. 195 if (Glue.getNode()) 196 RetOps.push_back(Glue); 197 198 return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); 199 } 200