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.getSymbol(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 } 126 return true; 127 } 128 129 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, 130 MCInst &OutMI) { 131 const RISCVVPseudosTable::PseudoInfo *RVV = 132 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode()); 133 if (!RVV) 134 return false; 135 136 OutMI.setOpcode(RVV->BaseInstr); 137 138 const MachineBasicBlock *MBB = MI->getParent(); 139 assert(MBB && "MI expected to be in a basic block"); 140 const MachineFunction *MF = MBB->getParent(); 141 assert(MF && "MBB expected to be in a machine function"); 142 143 const TargetRegisterInfo *TRI = 144 MF->getSubtarget<RISCVSubtarget>().getRegisterInfo(); 145 assert(TRI && "TargetRegisterInfo expected"); 146 147 for (const MachineOperand &MO : MI->explicit_operands()) { 148 int OpNo = (int)MI->getOperandNo(&MO); 149 assert(OpNo >= 0 && "Operand number doesn't fit in an 'int' type"); 150 151 // Skip VL, SEW and MergeOp operands 152 if (OpNo == RVV->getVLIndex() || OpNo == RVV->getSEWIndex() || 153 OpNo == RVV->getMergeOpIndex()) 154 continue; 155 156 MCOperand MCOp; 157 switch (MO.getType()) { 158 default: 159 llvm_unreachable("Unknown operand type"); 160 case MachineOperand::MO_Register: { 161 unsigned Reg = MO.getReg(); 162 163 if (RISCV::VRM2RegClass.contains(Reg) || 164 RISCV::VRM4RegClass.contains(Reg) || 165 RISCV::VRM8RegClass.contains(Reg)) { 166 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm2); 167 assert(Reg && "Subregister does not exist"); 168 } 169 170 MCOp = MCOperand::createReg(Reg); 171 break; 172 } 173 case MachineOperand::MO_Immediate: 174 MCOp = MCOperand::createImm(MO.getImm()); 175 break; 176 } 177 OutMI.addOperand(MCOp); 178 } 179 180 // Unmasked pseudo instructions need to append dummy mask operand to 181 // V instructions. All V instructions are modeled as the masked version. 182 if (RVV->hasDummyMask()) 183 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister)); 184 185 return true; 186 } 187 188 void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 189 const AsmPrinter &AP) { 190 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI)) 191 return; 192 193 OutMI.setOpcode(MI->getOpcode()); 194 195 for (const MachineOperand &MO : MI->operands()) { 196 MCOperand MCOp; 197 if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP)) 198 OutMI.addOperand(MCOp); 199 } 200 } 201