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(GV: *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(OutName&: Name, GVName: 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 case M68kII::MO_TLSGD:
100 RefKind = MCSymbolRefExpr::VK_TLSGD;
101 break;
102 case M68kII::MO_TLSLD:
103 RefKind = MCSymbolRefExpr::VK_TLSLD;
104 break;
105 case M68kII::MO_TLSLDM:
106 RefKind = MCSymbolRefExpr::VK_TLSLDM;
107 break;
108 case M68kII::MO_TLSIE:
109 RefKind = MCSymbolRefExpr::VK_GOTTPOFF;
110 break;
111 case M68kII::MO_TLSLE:
112 RefKind = MCSymbolRefExpr::VK_TPOFF;
113 break;
114 }
115
116 if (!Expr) {
117 Expr = MCSymbolRefExpr::create(Symbol: Sym, Kind: RefKind, Ctx);
118 }
119
120 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) {
121 Expr = MCBinaryExpr::createAdd(
122 LHS: Expr, RHS: MCConstantExpr::create(Value: MO.getOffset(), Ctx), Ctx);
123 }
124
125 return MCOperand::createExpr(Val: Expr);
126}
127
128std::optional<MCOperand>
129M68kMCInstLower::LowerOperand(const MachineInstr *MI,
130 const MachineOperand &MO) const {
131 switch (MO.getType()) {
132 default:
133 llvm_unreachable("unknown operand type");
134 case MachineOperand::MO_Register:
135 // Ignore all implicit register operands.
136 if (MO.isImplicit())
137 return std::nullopt;
138 return MCOperand::createReg(Reg: MO.getReg());
139 case MachineOperand::MO_Immediate:
140 return MCOperand::createImm(Val: MO.getImm());
141 case MachineOperand::MO_MachineBasicBlock:
142 case MachineOperand::MO_GlobalAddress:
143 case MachineOperand::MO_ExternalSymbol:
144 return LowerSymbolOperand(MO, Sym: GetSymbolFromOperand(MO));
145 case MachineOperand::MO_MCSymbol:
146 return LowerSymbolOperand(MO, Sym: MO.getMCSymbol());
147 case MachineOperand::MO_JumpTableIndex:
148 return LowerSymbolOperand(MO, Sym: AsmPrinter.GetJTISymbol(JTID: MO.getIndex()));
149 case MachineOperand::MO_ConstantPoolIndex:
150 return LowerSymbolOperand(MO, Sym: AsmPrinter.GetCPISymbol(CPID: MO.getIndex()));
151 case MachineOperand::MO_BlockAddress:
152 return LowerSymbolOperand(
153 MO, Sym: AsmPrinter.GetBlockAddressSymbol(BA: MO.getBlockAddress()));
154 case MachineOperand::MO_RegisterMask:
155 // Ignore call clobbers.
156 return std::nullopt;
157 }
158}
159
160void M68kMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
161 unsigned Opcode = MI->getOpcode();
162 OutMI.setOpcode(Opcode);
163
164 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
165 const MachineOperand &MO = MI->getOperand(i);
166 std::optional<MCOperand> MCOp = LowerOperand(MI, MO);
167
168 if (MCOp.has_value() && MCOp.value().isValid())
169 OutMI.addOperand(Op: MCOp.value());
170 }
171
172 // TAILJMPj, TAILJMPq - Lower to the correct jump instructions.
173 if (Opcode == M68k::TAILJMPj || Opcode == M68k::TAILJMPq) {
174 assert(OutMI.getNumOperands() == 1 && "Unexpected number of operands");
175 switch (Opcode) {
176 case M68k::TAILJMPj:
177 Opcode = M68k::JMP32j;
178 break;
179 case M68k::TAILJMPq:
180 Opcode = M68k::BRA8;
181 break;
182 }
183 OutMI.setOpcode(Opcode);
184 }
185}
186

source code of llvm/lib/Target/M68k/M68kMCInstLower.cpp