LLVM 18.0.0git
AArch64MCInstLower.cpp
Go to the documentation of this file.
1//==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an 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// This file contains code to lower AArch64 MachineInstrs to their corresponding
10// MCInst records.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AArch64MCInstLower.h"
21#include "llvm/IR/Mangler.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCStreamer.h"
30using namespace llvm;
31
33
35 : Ctx(ctx), Printer(printer) {}
36
39 const GlobalValue *GV = MO.getGlobal();
40 unsigned TargetFlags = MO.getTargetFlags();
41 const Triple &TheTriple = Printer.TM.getTargetTriple();
42 if (!TheTriple.isOSBinFormatCOFF())
43 return Printer.getSymbolPreferLocal(*GV);
44
45 assert(TheTriple.isOSWindows() &&
46 "Windows is the only supported COFF target");
47
48 bool IsIndirect =
51 if (!IsIndirect)
52 return Printer.getSymbol(GV);
53
55
56 if (TargetFlags & AArch64II::MO_DLLIMPORTAUX) {
57 // __imp_aux is specific to arm64EC; it represents the actual address of
58 // an imported function without any thunks.
59 //
60 // If we see a reference to an "aux" symbol, also emit a reference to the
61 // corresponding non-aux symbol. Otherwise, the Microsoft linker behaves
62 // strangely when linking against x64 import libararies.
63 //
64 // emitSymbolAttribute() doesn't have any real effect here; it just
65 // ensures the symbol name appears in the assembly without any
66 // side-effects. It might make sense to design a cleaner way to express
67 // this.
68 Name = "__imp_";
69 Printer.TM.getNameWithPrefix(Name, GV,
70 Printer.getObjFileLowering().getMangler());
71 MCSymbol *ExtraSym = Ctx.getOrCreateSymbol(Name);
72 Printer.OutStreamer->emitSymbolAttribute(ExtraSym, MCSA_Global);
73
74 Name = "__imp_aux_";
75 } else if (TargetFlags & AArch64II::MO_DLLIMPORT) {
76 Name = "__imp_";
77 } else if (TargetFlags & AArch64II::MO_COFFSTUB) {
78 Name = ".refptr.";
79 }
80 Printer.TM.getNameWithPrefix(Name, GV,
81 Printer.getObjFileLowering().getMangler());
82
83 MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name);
84
85 if (TargetFlags & AArch64II::MO_COFFSTUB) {
86 MachineModuleInfoCOFF &MMICOFF =
89 MMICOFF.getGVStubEntry(MCSym);
90
91 if (!StubSym.getPointer())
92 StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true);
93 }
94
95 return MCSym;
96}
97
100 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
101}
102
104 MCSymbol *Sym) const {
105 // FIXME: We would like an efficient form for this, so we don't have to do a
106 // lot of extra uniquing.
108 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
111 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
114 else
115 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
116 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
119 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
122 else
123 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
124 } else {
126 RefKind = MCSymbolRefExpr::VK_PAGE;
127 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
130 }
131 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
132 if (!MO.isJTI() && MO.getOffset())
134 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
135 return MCOperand::createExpr(Expr);
136}
137
139 MCSymbol *Sym) const {
140 uint32_t RefFlags = 0;
141
143 RefFlags |= AArch64MCExpr::VK_GOT;
144 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
145 TLSModel::Model Model;
146 if (MO.isGlobal()) {
147 const GlobalValue *GV = MO.getGlobal();
148 Model = Printer.TM.getTLSModel(GV);
150 Model == TLSModel::LocalDynamic)
152
153 } else {
154 assert(MO.isSymbol() &&
155 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
156 "unexpected external TLS symbol");
157 // The general dynamic access sequence is used to get the
158 // address of _TLS_MODULE_BASE_.
160 }
161 switch (Model) {
163 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
164 break;
166 RefFlags |= AArch64MCExpr::VK_TPREL;
167 break;
169 RefFlags |= AArch64MCExpr::VK_DTPREL;
170 break;
172 RefFlags |= AArch64MCExpr::VK_TLSDESC;
173 break;
174 }
175 } else if (MO.getTargetFlags() & AArch64II::MO_PREL) {
176 RefFlags |= AArch64MCExpr::VK_PREL;
177 } else {
178 // No modifier means this is a generic reference, classified as absolute for
179 // the cases where it matters (:abs_g0: etc).
180 RefFlags |= AArch64MCExpr::VK_ABS;
181 }
182
184 RefFlags |= AArch64MCExpr::VK_PAGE;
185 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
187 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
189 RefFlags |= AArch64MCExpr::VK_G3;
191 RefFlags |= AArch64MCExpr::VK_G2;
193 RefFlags |= AArch64MCExpr::VK_G1;
195 RefFlags |= AArch64MCExpr::VK_G0;
197 RefFlags |= AArch64MCExpr::VK_HI12;
198
200 RefFlags |= AArch64MCExpr::VK_NC;
201
202 const MCExpr *Expr =
204 if (!MO.isJTI() && MO.getOffset())
206 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
207
209 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
210 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
211
212 return MCOperand::createExpr(Expr);
213}
214
216 MCSymbol *Sym) const {
217 uint32_t RefFlags = 0;
218
222 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
225
226 } else if (MO.getTargetFlags() & AArch64II::MO_S) {
227 RefFlags |= AArch64MCExpr::VK_SABS;
228 } else {
229 RefFlags |= AArch64MCExpr::VK_ABS;
230
232 RefFlags |= AArch64MCExpr::VK_PAGE;
233 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
236 }
237
239 RefFlags |= AArch64MCExpr::VK_G3;
241 RefFlags |= AArch64MCExpr::VK_G2;
243 RefFlags |= AArch64MCExpr::VK_G1;
245 RefFlags |= AArch64MCExpr::VK_G0;
246
247 // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
248 // because setting VK_NC for others would mean setting their respective
249 // RefFlags correctly. We should do this in a separate patch.
250 if (MO.getTargetFlags() & AArch64II::MO_NC) {
251 auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
252 if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
253 MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
254 RefFlags |= AArch64MCExpr::VK_NC;
255 }
256
257 const MCExpr *Expr =
259 if (!MO.isJTI() && MO.getOffset())
261 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
262
263 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
265 "Invalid relocation requested");
266 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
267
268 return MCOperand::createExpr(Expr);
269}
270
272 MCSymbol *Sym) const {
273 if (Printer.TM.getTargetTriple().isOSBinFormatMachO())
274 return lowerSymbolOperandMachO(MO, Sym);
275 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
276 return lowerSymbolOperandCOFF(MO, Sym);
277
278 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
279 return lowerSymbolOperandELF(MO, Sym);
280}
281
283 MCOperand &MCOp) const {
284 switch (MO.getType()) {
285 default:
286 llvm_unreachable("unknown operand type");
288 // Ignore all implicit register operands.
289 if (MO.isImplicit())
290 return false;
291 MCOp = MCOperand::createReg(MO.getReg());
292 break;
294 // Regmasks are like implicit defs.
295 return false;
297 MCOp = MCOperand::createImm(MO.getImm());
298 break;
302 break;
305 break;
308 break;
310 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
311 break;
313 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
314 break;
316 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
317 break;
319 MCOp = LowerSymbolOperand(
320 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
321 break;
322 }
323 return true;
324}
325
327 OutMI.setOpcode(MI->getOpcode());
328
329 for (const MachineOperand &MO : MI->operands()) {
330 MCOperand MCOp;
331 if (lowerOperand(MO, MCOp))
332 OutMI.addOperand(MCOp);
333 }
334
335 switch (OutMI.getOpcode()) {
336 case AArch64::CATCHRET:
337 OutMI = MCInst();
338 OutMI.setOpcode(AArch64::RET);
339 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
340 break;
341 case AArch64::CLEANUPRET:
342 OutMI = MCInst();
343 OutMI.setOpcode(AArch64::RET);
344 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
345 break;
346 }
347}
cl::opt< bool > EnableAArch64ELFLocalDynamicTLSGeneration("aarch64-elf-ldtls-generation", cl::Hidden, cl::desc("Allow AArch64 Local Dynamic TLS code generation"), cl::init(false))
cl::opt< bool > EnableAArch64ELFLocalDynamicTLSGeneration
dxil pretty printer
dxil pretty DXIL Metadata Pretty Printer
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:468
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
MCSymbol * GetExternalSymbolSymbol(const MachineOperand &MO) const
MCOperand lowerSymbolOperandCOFF(const MachineOperand &MO, MCSymbol *Sym) const
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const
MCOperand lowerSymbolOperandELF(const MachineOperand &MO, MCSymbol *Sym) const
AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
MCSymbol * GetGlobalAddressSymbol(const MachineOperand &MO) const
MCOperand lowerSymbolOperandMachO(const MachineOperand &MO, MCSymbol *Sym) const
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:85
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:381
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:671
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:88
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
Definition: AsmPrinter.cpp:675
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:106
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:100
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:528
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:389
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Representation of each machine instruction.
Definition: MachineInstr.h:68
MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation for COFF targets.
StubValueTy & getGVStubEntry(MCSymbol *Sym)
Ty & getObjFileInfo()
Keep track of various per-module pieces of information for backends that would like to do so.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isImplicit() const
MachineBasicBlock * getMBB() const
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
PointerIntPair - This class implements a pair of a pointer and small integer.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
void getNameWithPrefix(SmallVectorImpl< char > &Name, const GlobalValue *GV, Mangler &Mang, bool MayAlwaysUsePrivate=false) const
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:688
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Definition: Triple.h:680
bool isOSWindows() const
Tests whether the OS is Windows.
Definition: Triple.h:584
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:675
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_DLLIMPORTAUX
MO_DLLIMPORTAUX - Symbol refers to "auxilliary" import stub.
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
@ GeneralDynamic
Definition: CodeGen.h:46
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30