1//===-- M68kMCInstLower.cpp - M68k 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 M68k MachineInstrs to their
11/// corresponding MCInst records.
12///
13//===----------------------------------------------------------------------===//
14
15#include "M68kMCInstLower.h"
16
17#include "M68kAsmPrinter.h"
18#include "M68kInstrInfo.h"
19
20#include "MCTargetDesc/M68kBaseInfo.h"
21
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstr.h"
24#include "llvm/CodeGen/MachineOperand.h"
25#include "llvm/IR/Mangler.h"
26#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCInst.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "m68k-mc-inst-lower"
33
34M68kMCInstLower::M68kMCInstLower(MachineFunction &MF, M68kAsmPrinter &AP)
35    : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()),
36      AsmPrinter(AP) {}
37
38MCSymbol *
39M68kMCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const {
40  assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) &&
41         "Isn't a symbol reference");
42
43  const auto &TT = TM.getTargetTriple();
44  if (MO.isGlobal() && TT.isOSBinFormatELF())
45    return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal());
46
47  const DataLayout &DL = MF.getDataLayout();
48
49  MCSymbol *Sym = nullptr;
50  SmallString<128> Name;
51  StringRef Suffix;
52
53  if (!Suffix.empty())
54    Name += DL.getPrivateGlobalPrefix();
55
56  if (MO.isGlobal()) {
57    const GlobalValue *GV = MO.getGlobal();
58    AsmPrinter.getNameWithPrefix(Name, GV);
59  } else if (MO.isSymbol()) {
60    Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
61  } else if (MO.isMBB()) {
62    assert(Suffix.empty());
63    Sym = MO.getMBB()->getSymbol();
64  }
65
66  Name += Suffix;
67  if (!Sym)
68    Sym = Ctx.getOrCreateSymbol(Name);
69
70  return Sym;
71}
72
73MCOperand M68kMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
74                                              MCSymbol *Sym) const {
75  // FIXME We would like an efficient form for this, so we don't have to do a
76  // lot of extra uniquing. This fixme is originally from X86
77  const MCExpr *Expr = nullptr;
78  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
79
80  switch (MO.getTargetFlags()) {
81  default:
82    llvm_unreachable("Unknown target flag on GV operand");
83  case M68kII::MO_NO_FLAG:
84  case M68kII::MO_ABSOLUTE_ADDRESS:
85  case M68kII::MO_PC_RELATIVE_ADDRESS:
86    break;
87  case M68kII::MO_GOTPCREL:
88    RefKind = MCSymbolRefExpr::VK_GOTPCREL;
89    break;
90  case M68kII::MO_GOT:
91    RefKind = MCSymbolRefExpr::VK_GOT;
92    break;
93  case M68kII::MO_GOTOFF:
94    RefKind = MCSymbolRefExpr::VK_GOTOFF;
95    break;
96  case M68kII::MO_PLT:
97    RefKind = MCSymbolRefExpr::VK_PLT;
98    break;
99  }
100
101  if (!Expr) {
102    Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
103  }
104
105  if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) {
106    Expr = MCBinaryExpr::createAdd(
107        Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
108  }
109
110  return MCOperand::createExpr(Expr);
111}
112
113Optional<MCOperand>
114M68kMCInstLower::LowerOperand(const MachineInstr *MI,
115                              const MachineOperand &MO) const {
116  switch (MO.getType()) {
117  default:
118    llvm_unreachable("unknown operand type");
119  case MachineOperand::MO_Register:
120    // Ignore all implicit register operands.
121    if (MO.isImplicit())
122      return None;
123    return MCOperand::createReg(MO.getReg());
124  case MachineOperand::MO_Immediate:
125    return MCOperand::createImm(MO.getImm());
126  case MachineOperand::MO_MachineBasicBlock:
127  case MachineOperand::MO_GlobalAddress:
128  case MachineOperand::MO_ExternalSymbol:
129    return LowerSymbolOperand(MO, GetSymbolFromOperand(MO));
130  case MachineOperand::MO_MCSymbol:
131    return LowerSymbolOperand(MO, MO.getMCSymbol());
132  case MachineOperand::MO_JumpTableIndex:
133    return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()));
134  case MachineOperand::MO_ConstantPoolIndex:
135    return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()));
136  case MachineOperand::MO_BlockAddress:
137    return LowerSymbolOperand(
138        MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()));
139  case MachineOperand::MO_RegisterMask:
140    // Ignore call clobbers.
141    return None;
142  }
143}
144
145void M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
146  unsigned Opcode = MI->getOpcode();
147  OutMI.setOpcode(Opcode);
148
149  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
150    const MachineOperand &MO = MI->getOperand(i);
151    Optional<MCOperand> MCOp = LowerOperand(MI, MO);
152
153    if (MCOp.hasValue() && MCOp.getValue().isValid())
154      OutMI.addOperand(MCOp.getValue());
155  }
156
157  // TAILJMPj, TAILJMPq - Lower to the correct jump instructions.
158  if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) {
159    assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands");
160    switch (Opcode) {
161    case M68k::TAILJMPj:
162      Opcode = M68k::JMP32j;
163      break;
164    case M68k::TAILJMPq:
165      Opcode = M68k::BRA8;
166      break;
167    }
168    OutMI.setOpcode(Opcode);
169  }
170}
171