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