1 //===-- RISCVMCInstLower.cpp - Convert RISCV MachineInstr to an MCInst ------=// 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 contains code to lower RISCV MachineInstrs to their corresponding 10 // MCInst records. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RISCV.h" 15 #include "RISCVSubtarget.h" 16 #include "MCTargetDesc/RISCVMCExpr.h" 17 #include "llvm/CodeGen/AsmPrinter.h" 18 #include "llvm/CodeGen/MachineBasicBlock.h" 19 #include "llvm/CodeGen/MachineInstr.h" 20 #include "llvm/MC/MCAsmInfo.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/raw_ostream.h" 26 27 using namespace llvm; 28 29 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, 30 const AsmPrinter &AP) { 31 MCContext &Ctx = AP.OutContext; 32 RISCVMCExpr::VariantKind Kind; 33 34 switch (MO.getTargetFlags()) { 35 default: 36 llvm_unreachable("Unknown target flag on GV operand"); 37 case RISCVII::MO_None: 38 Kind = RISCVMCExpr::VK_RISCV_None; 39 break; 40 case RISCVII::MO_CALL: 41 Kind = RISCVMCExpr::VK_RISCV_CALL; 42 break; 43 case RISCVII::MO_PLT: 44 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 45 break; 46 case RISCVII::MO_LO: 47 Kind = RISCVMCExpr::VK_RISCV_LO; 48 break; 49 case RISCVII::MO_HI: 50 Kind = RISCVMCExpr::VK_RISCV_HI; 51 break; 52 case RISCVII::MO_PCREL_LO: 53 Kind = RISCVMCExpr::VK_RISCV_PCREL_LO; 54 break; 55 case RISCVII::MO_PCREL_HI: 56 Kind = RISCVMCExpr::VK_RISCV_PCREL_HI; 57 break; 58 case RISCVII::MO_GOT_HI: 59 Kind = RISCVMCExpr::VK_RISCV_GOT_HI; 60 break; 61 case RISCVII::MO_TPREL_LO: 62 Kind = RISCVMCExpr::VK_RISCV_TPREL_LO; 63 break; 64 case RISCVII::MO_TPREL_HI: 65 Kind = RISCVMCExpr::VK_RISCV_TPREL_HI; 66 break; 67 case RISCVII::MO_TPREL_ADD: 68 Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD; 69 break; 70 case RISCVII::MO_TLS_GOT_HI: 71 Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI; 72 break; 73 case RISCVII::MO_TLS_GD_HI: 74 Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI; 75 break; 76 } 77 78 const MCExpr *ME = 79 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 80 81 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 82 ME = MCBinaryExpr::createAdd( 83 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 84 85 if (Kind != RISCVMCExpr::VK_RISCV_None) 86 ME = RISCVMCExpr::create(ME, Kind, Ctx); 87 return MCOperand::createExpr(ME); 88 } 89 90 bool llvm::lowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, 91 MCOperand &MCOp, 92 const AsmPrinter &AP) { 93 switch (MO.getType()) { 94 default: 95 report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type"); 96 case MachineOperand::MO_Register: 97 // Ignore all implicit register operands. 98 if (MO.isImplicit()) 99 return false; 100 MCOp = MCOperand::createReg(MO.getReg()); 101 break; 102 case MachineOperand::MO_RegisterMask: 103 // Regmasks are like implicit defs. 104 return false; 105 case MachineOperand::MO_Immediate: 106 MCOp = MCOperand::createImm(MO.getImm()); 107 break; 108 case MachineOperand::MO_MachineBasicBlock: 109 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); 110 break; 111 case MachineOperand::MO_GlobalAddress: 112 MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); 113 break; 114 case MachineOperand::MO_BlockAddress: 115 MCOp = lowerSymbolOperand( 116 MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 117 break; 118 case MachineOperand::MO_ExternalSymbol: 119 MCOp = lowerSymbolOperand( 120 MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); 121 break; 122 case MachineOperand::MO_ConstantPoolIndex: 123 MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); 124 break; 125 case MachineOperand::MO_JumpTableIndex: 126 MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP); 127 break; 128 } 129 return true; 130 } 131 132 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, 133 MCInst &OutMI) { 134 const RISCVVPseudosTable::PseudoInfo *RVV = 135 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode()); 136 if (!RVV) 137 return false; 138 139 OutMI.setOpcode(RVV->BaseInstr); 140 141 const MachineBasicBlock *MBB = MI->getParent(); 142 assert(MBB && "MI expected to be in a basic block"); 143 const MachineFunction *MF = MBB->getParent(); 144 assert(MF && "MBB expected to be in a machine function"); 145 146 const TargetRegisterInfo *TRI = 147 MF->getSubtarget<RISCVSubtarget>().getRegisterInfo(); 148 const RISCVInstrInfo *TII = MF->getSubtarget<RISCVSubtarget>().getInstrInfo(); 149 150 assert(TRI && "TargetRegisterInfo expected"); 151 152 uint64_t TSFlags = MI->getDesc().TSFlags; 153 unsigned NumOps = MI->getNumExplicitOperands(); 154 155 // Skip policy, VL and SEW operands which are the last operands if present. 156 if (RISCVII::hasVecPolicyOp(TSFlags)) 157 --NumOps; 158 if (RISCVII::hasVLOp(TSFlags)) 159 --NumOps; 160 if (RISCVII::hasSEWOp(TSFlags)) 161 --NumOps; 162 163 bool hasVLOutput = TII->isFaultFirstLoad(*MI); 164 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) { 165 const MachineOperand &MO = MI->getOperand(OpNo); 166 // Skip vl ouput. It should be the second output. 167 if (hasVLOutput && OpNo == 1) 168 continue; 169 170 // Skip merge op. It should be the first operand after the result. 171 if (RISCVII::hasMergeOp(TSFlags) && OpNo == 1U + hasVLOutput) { 172 assert(MI->getNumExplicitDefs() == 1U + hasVLOutput); 173 continue; 174 } 175 176 MCOperand MCOp; 177 switch (MO.getType()) { 178 default: 179 llvm_unreachable("Unknown operand type"); 180 case MachineOperand::MO_Register: { 181 Register Reg = MO.getReg(); 182 183 if (RISCV::VRM2RegClass.contains(Reg) || 184 RISCV::VRM4RegClass.contains(Reg) || 185 RISCV::VRM8RegClass.contains(Reg)) { 186 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 187 assert(Reg && "Subregister does not exist"); 188 } else if (RISCV::FPR16RegClass.contains(Reg)) { 189 Reg = TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass); 190 assert(Reg && "Subregister does not exist"); 191 } else if (RISCV::FPR64RegClass.contains(Reg)) { 192 Reg = TRI->getSubReg(Reg, RISCV::sub_32); 193 assert(Reg && "Superregister does not exist"); 194 } 195 196 MCOp = MCOperand::createReg(Reg); 197 break; 198 } 199 case MachineOperand::MO_Immediate: 200 MCOp = MCOperand::createImm(MO.getImm()); 201 break; 202 } 203 OutMI.addOperand(MCOp); 204 } 205 206 // Unmasked pseudo instructions need to append dummy mask operand to 207 // V instructions. All V instructions are modeled as the masked version. 208 if (RISCVII::hasDummyMaskOp(TSFlags)) 209 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister)); 210 211 return true; 212 } 213 214 bool llvm::lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 215 AsmPrinter &AP) { 216 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI)) 217 return false; 218 219 OutMI.setOpcode(MI->getOpcode()); 220 221 for (const MachineOperand &MO : MI->operands()) { 222 MCOperand MCOp; 223 if (lowerRISCVMachineOperandToMCOperand(MO, MCOp, AP)) 224 OutMI.addOperand(MCOp); 225 } 226 227 switch (OutMI.getOpcode()) { 228 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { 229 const Function &F = MI->getParent()->getParent()->getFunction(); 230 if (F.hasFnAttribute("patchable-function-entry")) { 231 unsigned Num; 232 if (F.getFnAttribute("patchable-function-entry") 233 .getValueAsString() 234 .getAsInteger(10, Num)) 235 return false; 236 AP.emitNops(Num); 237 return true; 238 } 239 break; 240 } 241 case RISCV::PseudoReadVLENB: 242 OutMI.setOpcode(RISCV::CSRRS); 243 OutMI.addOperand(MCOperand::createImm( 244 RISCVSysReg::lookupSysRegByName("VLENB")->Encoding)); 245 OutMI.addOperand(MCOperand::createReg(RISCV::X0)); 246 break; 247 case RISCV::PseudoReadVL: 248 OutMI.setOpcode(RISCV::CSRRS); 249 OutMI.addOperand( 250 MCOperand::createImm(RISCVSysReg::lookupSysRegByName("VL")->Encoding)); 251 OutMI.addOperand(MCOperand::createReg(RISCV::X0)); 252 break; 253 } 254 return false; 255 } 256