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 "MCTargetDesc/RISCVMCExpr.h" 16 #include "llvm/CodeGen/AsmPrinter.h" 17 #include "llvm/CodeGen/MachineBasicBlock.h" 18 #include "llvm/CodeGen/MachineInstr.h" 19 #include "llvm/MC/MCAsmInfo.h" 20 #include "llvm/MC/MCContext.h" 21 #include "llvm/MC/MCExpr.h" 22 #include "llvm/MC/MCInst.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/raw_ostream.h" 25 26 using namespace llvm; 27 28 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, 29 const AsmPrinter &AP) { 30 MCContext &Ctx = AP.OutContext; 31 RISCVMCExpr::VariantKind Kind; 32 33 switch (MO.getTargetFlags()) { 34 default: 35 llvm_unreachable("Unknown target flag on GV operand"); 36 case RISCVII::MO_None: 37 Kind = RISCVMCExpr::VK_RISCV_None; 38 break; 39 case RISCVII::MO_CALL: 40 Kind = RISCVMCExpr::VK_RISCV_CALL; 41 break; 42 case RISCVII::MO_PLT: 43 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 44 break; 45 case RISCVII::MO_LO: 46 Kind = RISCVMCExpr::VK_RISCV_LO; 47 break; 48 case RISCVII::MO_HI: 49 Kind = RISCVMCExpr::VK_RISCV_HI; 50 break; 51 case RISCVII::MO_PCREL_LO: 52 Kind = RISCVMCExpr::VK_RISCV_PCREL_LO; 53 break; 54 case RISCVII::MO_PCREL_HI: 55 Kind = RISCVMCExpr::VK_RISCV_PCREL_HI; 56 break; 57 case RISCVII::MO_GOT_HI: 58 Kind = RISCVMCExpr::VK_RISCV_GOT_HI; 59 break; 60 case RISCVII::MO_TPREL_LO: 61 Kind = RISCVMCExpr::VK_RISCV_TPREL_LO; 62 break; 63 case RISCVII::MO_TPREL_HI: 64 Kind = RISCVMCExpr::VK_RISCV_TPREL_HI; 65 break; 66 case RISCVII::MO_TPREL_ADD: 67 Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD; 68 break; 69 case RISCVII::MO_TLS_GOT_HI: 70 Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI; 71 break; 72 case RISCVII::MO_TLS_GD_HI: 73 Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI; 74 break; 75 } 76 77 const MCExpr *ME = 78 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 79 80 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 81 ME = MCBinaryExpr::createAdd( 82 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 83 84 if (Kind != RISCVMCExpr::VK_RISCV_None) 85 ME = RISCVMCExpr::create(ME, Kind, Ctx); 86 return MCOperand::createExpr(ME); 87 } 88 89 bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, 90 MCOperand &MCOp, 91 const AsmPrinter &AP) { 92 switch (MO.getType()) { 93 default: 94 report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type"); 95 case MachineOperand::MO_Register: 96 // Ignore all implicit register operands. 97 if (MO.isImplicit()) 98 return false; 99 MCOp = MCOperand::createReg(MO.getReg()); 100 break; 101 case MachineOperand::MO_RegisterMask: 102 // Regmasks are like implicit defs. 103 return false; 104 case MachineOperand::MO_Immediate: 105 MCOp = MCOperand::createImm(MO.getImm()); 106 break; 107 case MachineOperand::MO_MachineBasicBlock: 108 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); 109 break; 110 case MachineOperand::MO_GlobalAddress: 111 MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); 112 break; 113 case MachineOperand::MO_BlockAddress: 114 MCOp = lowerSymbolOperand( 115 MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 116 break; 117 case MachineOperand::MO_ExternalSymbol: 118 MCOp = lowerSymbolOperand( 119 MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); 120 break; 121 case MachineOperand::MO_ConstantPoolIndex: 122 MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); 123 break; 124 case MachineOperand::MO_MCSymbol: 125 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), AP); 126 break; 127 } 128 return true; 129 } 130 131 void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 132 const AsmPrinter &AP) { 133 OutMI.setOpcode(MI->getOpcode()); 134 135 for (const MachineOperand &MO : MI->operands()) { 136 MCOperand MCOp; 137 if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP)) 138 OutMI.addOperand(MCOp); 139 } 140 } 141