1//===-- SystemZMCInstLower.cpp - Lower 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#include "SystemZMCInstLower.h"
10#include "SystemZAsmPrinter.h"
11#include "llvm/IR/Mangler.h"
12#include "llvm/MC/MCExpr.h"
13#include "llvm/MC/MCInst.h"
14#include "llvm/MC/MCStreamer.h"
15
16using namespace llvm;
17
18// Return the VK_* enumeration for MachineOperand target flags Flags.
19static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
20  switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
21    case 0:
22      return MCSymbolRefExpr::VK_None;
23    case SystemZII::MO_GOT:
24      return MCSymbolRefExpr::VK_GOT;
25    case SystemZII::MO_INDNTPOFF:
26      return MCSymbolRefExpr::VK_INDNTPOFF;
27  }
28  llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
29}
30
31SystemZMCInstLower::SystemZMCInstLower(MCContext &ctx,
32                                       SystemZAsmPrinter &asmprinter)
33  : Ctx(ctx), AsmPrinter(asmprinter) {}
34
35const MCExpr *
36SystemZMCInstLower::getExpr(const MachineOperand &MO,
37                            MCSymbolRefExpr::VariantKind Kind) const {
38  const MCSymbol *Symbol;
39  bool HasOffset = true;
40  switch (MO.getType()) {
41  case MachineOperand::MO_MachineBasicBlock:
42    Symbol = MO.getMBB()->getSymbol();
43    HasOffset = false;
44    break;
45
46  case MachineOperand::MO_GlobalAddress:
47    Symbol = AsmPrinter.getSymbol(MO.getGlobal());
48    break;
49
50  case MachineOperand::MO_ExternalSymbol:
51    Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
52    break;
53
54  case MachineOperand::MO_JumpTableIndex:
55    Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
56    HasOffset = false;
57    break;
58
59  case MachineOperand::MO_ConstantPoolIndex:
60    Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
61    break;
62
63  case MachineOperand::MO_BlockAddress:
64    Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
65    break;
66
67  default:
68    llvm_unreachable("unknown operand type");
69  }
70  const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, Ctx);
71  if (HasOffset)
72    if (int64_t Offset = MO.getOffset()) {
73      const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
74      Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
75    }
76  return Expr;
77}
78
79MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
80  switch (MO.getType()) {
81  case MachineOperand::MO_Register:
82    return MCOperand::createReg(MO.getReg());
83
84  case MachineOperand::MO_Immediate:
85    return MCOperand::createImm(MO.getImm());
86
87  default: {
88    MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
89    return MCOperand::createExpr(getExpr(MO, Kind));
90  }
91  }
92}
93
94void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
95  OutMI.setOpcode(MI->getOpcode());
96  for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
97    const MachineOperand &MO = MI->getOperand(I);
98    // Ignore all implicit register operands.
99    if (!MO.isReg() || !MO.isImplicit())
100      OutMI.addOperand(lowerOperand(MO));
101  }
102}
103