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 26using namespace llvm; 27 28static 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 89bool 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 } 125 return true; 126} 127 128void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, 129 const AsmPrinter &AP) { 130 OutMI.setOpcode(MI->getOpcode()); 131 132 for (const MachineOperand &MO : MI->operands()) { 133 MCOperand MCOp; 134 if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP)) 135 OutMI.addOperand(MCOp); 136 } 137} 138