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 149 assert(TRI && "TargetRegisterInfo expected"); 150 151 uint64_t TSFlags = MI->getDesc().TSFlags; 152 unsigned NumOps = MI->getNumExplicitOperands(); 153 154 // Skip policy, VL and SEW operands which are the last operands if present. 155 if (RISCVII::hasVecPolicyOp(TSFlags)) 156 --NumOps; 157 if (RISCVII::hasVLOp(TSFlags)) 158 --NumOps; 159 if (RISCVII::hasSEWOp(TSFlags)) 160 --NumOps; 161 162 bool hasVLOutput = RISCV::isFaultFirstLoad(*MI); 163 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) { 164 const MachineOperand &MO = MI->getOperand(OpNo); 165 // Skip vl ouput. It should be the second output. 166 if (hasVLOutput && OpNo == 1) 167 continue; 168 169 // Skip merge op. It should be the first operand after the result. 170 if (RISCVII::hasMergeOp(TSFlags) && OpNo == 1U + hasVLOutput) { 171 assert(MI->getNumExplicitDefs() == 1U + hasVLOutput); 172 continue; 173 } 174 175 MCOperand MCOp; 176 switch (MO.getType()) { 177 default: 178 llvm_unreachable("Unknown operand type"); 179 case MachineOperand::MO_Register: { 180 Register Reg = MO.getReg(); 181 182 if (RISCV::VRM2RegClass.contains(Reg) || 183 RISCV::VRM4RegClass.contains(Reg) || 184 RISCV::VRM8RegClass.contains(Reg)) { 185 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 186 assert(Reg && "Subregister does not exist"); 187 } else if (RISCV::FPR16RegClass.contains(Reg)) { 188 Reg = TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass); 189 assert(Reg && "Subregister does not exist"); 190 } else if (RISCV::FPR64RegClass.contains(Reg)) { 191 Reg = TRI->getSubReg(Reg, RISCV::sub_32); 192 assert(Reg && "Superregister does not exist"); 193 } 194 195 MCOp = MCOperand::createReg(Reg); 196 break; 197 } 198 case MachineOperand::MO_Immediate: 199 MCOp = MCOperand::createImm(MO.getImm()); 200 break; 201 } 202 OutMI.addOperand(MCOp); 203 } 204 205 // Unmasked pseudo instructions need to append dummy mask operand to 206 // V instructions. All V instructions are modeled as the masked version. 207 if (RISCVII::hasDummyMaskOp(TSFlags)) 208 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister)); 209 210 return true; 211 } 212 213 bool llvm::lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 214 AsmPrinter &AP) { 215 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI)) 216 return false; 217 218 OutMI.setOpcode(MI->getOpcode()); 219 220 for (const MachineOperand &MO : MI->operands()) { 221 MCOperand MCOp; 222 if (lowerRISCVMachineOperandToMCOperand(MO, MCOp, AP)) 223 OutMI.addOperand(MCOp); 224 } 225 226 switch (OutMI.getOpcode()) { 227 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { 228 const Function &F = MI->getParent()->getParent()->getFunction(); 229 if (F.hasFnAttribute("patchable-function-entry")) { 230 unsigned Num; 231 if (F.getFnAttribute("patchable-function-entry") 232 .getValueAsString() 233 .getAsInteger(10, Num)) 234 return false; 235 AP.emitNops(Num); 236 return true; 237 } 238 break; 239 } 240 case RISCV::PseudoReadVLENB: 241 OutMI.setOpcode(RISCV::CSRRS); 242 OutMI.addOperand(MCOperand::createImm( 243 RISCVSysReg::lookupSysRegByName("VLENB")->Encoding)); 244 OutMI.addOperand(MCOperand::createReg(RISCV::X0)); 245 break; 246 case RISCV::PseudoReadVL: 247 OutMI.setOpcode(RISCV::CSRRS); 248 OutMI.addOperand( 249 MCOperand::createImm(RISCVSysReg::lookupSysRegByName("VL")->Encoding)); 250 OutMI.addOperand(MCOperand::createReg(RISCV::X0)); 251 break; 252 } 253 return false; 254 } 255