1//===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "SystemZMCInstLower.h"
11#include "SystemZAsmPrinter.h"
12#include "llvm/IR/Mangler.h"
13#include "llvm/MC/MCExpr.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  }
26  llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
27}
28
29SystemZMCInstLower::SystemZMCInstLower(MCContext &ctx,
30                                       SystemZAsmPrinter &asmprinter)
31  : Ctx(ctx), AsmPrinter(asmprinter) {}
32
33const MCExpr *
34SystemZMCInstLower::getExpr(const MachineOperand &MO,
35                            MCSymbolRefExpr::VariantKind Kind) const {
36  const MCSymbol *Symbol;
37  bool HasOffset = true;
38  switch (MO.getType()) {
39  case MachineOperand::MO_MachineBasicBlock:
40    Symbol = MO.getMBB()->getSymbol();
41    HasOffset = false;
42    break;
43
44  case MachineOperand::MO_GlobalAddress:
45    Symbol = AsmPrinter.getSymbol(MO.getGlobal());
46    break;
47
48  case MachineOperand::MO_ExternalSymbol:
49    Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
50    break;
51
52  case MachineOperand::MO_JumpTableIndex:
53    Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
54    HasOffset = false;
55    break;
56
57  case MachineOperand::MO_ConstantPoolIndex:
58    Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
59    break;
60
61  case MachineOperand::MO_BlockAddress:
62    Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
63    break;
64
65  default:
66    llvm_unreachable("unknown operand type");
67  }
68  const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx);
69  if (HasOffset)
70    if (int64_t Offset = MO.getOffset()) {
71      const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
72      Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
73    }
74  return Expr;
75}
76
77MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
78  switch (MO.getType()) {
79  case MachineOperand::MO_Register:
80    return MCOperand::CreateReg(MO.getReg());
81
82  case MachineOperand::MO_Immediate:
83    return MCOperand::CreateImm(MO.getImm());
84
85  default: {
86    MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
87    return MCOperand::CreateExpr(getExpr(MO, Kind));
88  }
89  }
90}
91
92void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
93  OutMI.setOpcode(MI->getOpcode());
94  for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
95    const MachineOperand &MO = MI->getOperand(I);
96    // Ignore all implicit register operands.
97    if (!MO.isReg() || !MO.isImplicit())
98      OutMI.addOperand(lowerOperand(MO));
99  }
100}
101