1//===- ARCMCInstLower.cpp - ARC MachineInstr to MCInst ----------*- C++ -*-===//
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/// \file
10/// This file contains code to lower ARC MachineInstrs to their
11/// corresponding MCInst records.
12///
13//===----------------------------------------------------------------------===//
14
15#include "ARCMCInstLower.h"
16#include "llvm/CodeGen/AsmPrinter.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineInstr.h"
19#include "llvm/CodeGen/MachineOperand.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
23
24using namespace llvm;
25
26ARCMCInstLower::ARCMCInstLower(MCContext *C, AsmPrinter &AsmPrinter)
27    : Ctx(C), Printer(AsmPrinter) {}
28
29MCOperand ARCMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
30                                             MachineOperandType MOTy,
31                                             unsigned Offset) const {
32  MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
33  const MCSymbol *Symbol;
34
35  switch (MOTy) {
36  case MachineOperand::MO_MachineBasicBlock:
37    Symbol = MO.getMBB()->getSymbol();
38    break;
39  case MachineOperand::MO_GlobalAddress:
40    Symbol = Printer.getSymbol(MO.getGlobal());
41    Offset += MO.getOffset();
42    break;
43  case MachineOperand::MO_BlockAddress:
44    Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress());
45    Offset += MO.getOffset();
46    break;
47  case MachineOperand::MO_ExternalSymbol:
48    Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName());
49    Offset += MO.getOffset();
50    break;
51  case MachineOperand::MO_JumpTableIndex:
52    Symbol = Printer.GetJTISymbol(MO.getIndex());
53    break;
54  case MachineOperand::MO_ConstantPoolIndex:
55    Symbol = Printer.GetCPISymbol(MO.getIndex());
56    Offset += MO.getOffset();
57    break;
58  default:
59    llvm_unreachable("<unknown operand type>");
60  }
61
62  assert(Symbol && "Symbol creation failed.\n");
63  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
64
65  if (!Offset)
66    return MCOperand::createExpr(MCSym);
67
68  // Assume offset is never negative.
69  assert(Offset > 0);
70
71  const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx);
72  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
73  return MCOperand::createExpr(Add);
74}
75
76MCOperand ARCMCInstLower::LowerOperand(const MachineOperand &MO,
77                                       unsigned Offset) const {
78  MachineOperandType MOTy = MO.getType();
79
80  switch (MOTy) {
81  default:
82    llvm_unreachable("unknown operand type");
83  case MachineOperand::MO_Register:
84    // Ignore all implicit register operands.
85    if (MO.isImplicit())
86      break;
87    return MCOperand::createReg(MO.getReg());
88  case MachineOperand::MO_Immediate:
89    return MCOperand::createImm(MO.getImm() + Offset);
90  case MachineOperand::MO_MachineBasicBlock:
91  case MachineOperand::MO_GlobalAddress:
92  case MachineOperand::MO_ExternalSymbol:
93  case MachineOperand::MO_JumpTableIndex:
94  case MachineOperand::MO_ConstantPoolIndex:
95  case MachineOperand::MO_BlockAddress:
96    return LowerSymbolOperand(MO, MOTy, Offset);
97  case MachineOperand::MO_RegisterMask:
98    break;
99  }
100
101  return {};
102}
103
104void ARCMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
105  OutMI.setOpcode(MI->getOpcode());
106
107  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
108    const MachineOperand &MO = MI->getOperand(i);
109    MCOperand MCOp = LowerOperand(MO);
110
111    if (MCOp.isValid())
112      OutMI.addOperand(MCOp);
113  }
114}
115