1//===-- CSKYMCInstLower.cpp - Convert CSKY 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 CSKY MachineInstrs to their corresponding
10// MCInst records.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CSKYMCInstLower.h"
15#include "MCTargetDesc/CSKYBaseInfo.h"
16#include "MCTargetDesc/CSKYMCExpr.h"
17#include "llvm/CodeGen/AsmPrinter.h"
18#include "llvm/MC/MCExpr.h"
19
20#define DEBUG_TYPE "csky-mcinst-lower"
21
22using namespace llvm;
23
24CSKYMCInstLower::CSKYMCInstLower(MCContext &Ctx, AsmPrinter &Printer)
25    : Ctx(Ctx), Printer(Printer) {}
26
27void CSKYMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
28  OutMI.setOpcode(MI->getOpcode());
29
30  for (const MachineOperand &MO : MI->operands()) {
31    MCOperand MCOp;
32    if (lowerOperand(MO, MCOp))
33      OutMI.addOperand(MCOp);
34  }
35}
36
37MCOperand CSKYMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
38                                              MCSymbol *Sym) const {
39  CSKYMCExpr::VariantKind Kind;
40  MCContext &Ctx = Printer.OutContext;
41
42  switch (MO.getTargetFlags()) {
43  default:
44    llvm_unreachable("Unknown target flag.");
45  case CSKYII::MO_None:
46    Kind = CSKYMCExpr::VK_CSKY_None;
47    break;
48  case CSKYII::MO_GOT32:
49    Kind = CSKYMCExpr::VK_CSKY_GOT;
50    break;
51  case CSKYII::MO_GOTOFF:
52    Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
53    break;
54  case CSKYII::MO_ADDR32:
55    Kind = CSKYMCExpr::VK_CSKY_ADDR;
56    break;
57  case CSKYII::MO_PLT32:
58    Kind = CSKYMCExpr::VK_CSKY_PLT;
59    break;
60  case CSKYII::MO_ADDR_HI16:
61    Kind = CSKYMCExpr::VK_CSKY_ADDR_HI16;
62    break;
63  case CSKYII::MO_ADDR_LO16:
64    Kind = CSKYMCExpr::VK_CSKY_ADDR_LO16;
65    break;
66  }
67  const MCExpr *ME =
68      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
69
70  if (Kind != CSKYMCExpr::VK_CSKY_None)
71    ME = CSKYMCExpr::create(ME, Kind, Ctx);
72
73  return MCOperand::createExpr(ME);
74}
75
76bool CSKYMCInstLower::lowerOperand(const MachineOperand &MO,
77                                   MCOperand &MCOp) const {
78  switch (MO.getType()) {
79  default:
80    llvm_unreachable("unknown operand type");
81  case MachineOperand::MO_RegisterMask:
82    break;
83  case MachineOperand::MO_Immediate:
84    MCOp = MCOperand::createImm(MO.getImm());
85    break;
86  case MachineOperand::MO_Register:
87    if (MO.isImplicit())
88      return false;
89    MCOp = MCOperand::createReg(MO.getReg());
90    break;
91  case MachineOperand::MO_MachineBasicBlock:
92    MCOp = MCOperand::createExpr(
93        MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
94    break;
95  case MachineOperand::MO_GlobalAddress:
96    MCOp = lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal()));
97    break;
98  case MachineOperand::MO_BlockAddress:
99    MCOp = lowerSymbolOperand(
100        MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
101    break;
102  case MachineOperand::MO_ExternalSymbol:
103    MCOp = lowerSymbolOperand(
104        MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()));
105    break;
106  case MachineOperand::MO_ConstantPoolIndex:
107    MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
108    break;
109  case MachineOperand::MO_JumpTableIndex:
110    MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
111    break;
112  case MachineOperand::MO_MCSymbol:
113    MCOp = lowerSymbolOperand(MO, MO.getMCSymbol());
114    break;
115  }
116  return true;
117}
118