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