LLVM 19.0.0git
AArch64ELFStreamer.cpp
Go to the documentation of this file.
1//===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===//
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 assembles .s files and emits AArch64 ELF .o object files. Different
10// from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit
11// regions of data and code.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AArch64ELFStreamer.h"
16#include "AArch64MCTargetDesc.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
24#include "llvm/MC/MCAssembler.h"
26#include "llvm/MC/MCContext.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCStreamer.h"
34#include "llvm/MC/MCSymbolELF.h"
40
41using namespace llvm;
42
43namespace {
44
45class AArch64ELFStreamer;
46
47class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
49
50 void emitInst(uint32_t Inst) override;
51
52 void emitDirectiveVariantPCS(MCSymbol *Symbol) override {
53 OS << "\t.variant_pcs\t" << Symbol->getName() << "\n";
54 }
55
56 void emitARM64WinCFIAllocStack(unsigned Size) override {
57 OS << "\t.seh_stackalloc\t" << Size << "\n";
58 }
59 void emitARM64WinCFISaveR19R20X(int Offset) override {
60 OS << "\t.seh_save_r19r20_x\t" << Offset << "\n";
61 }
62 void emitARM64WinCFISaveFPLR(int Offset) override {
63 OS << "\t.seh_save_fplr\t" << Offset << "\n";
64 }
65 void emitARM64WinCFISaveFPLRX(int Offset) override {
66 OS << "\t.seh_save_fplr_x\t" << Offset << "\n";
67 }
68 void emitARM64WinCFISaveReg(unsigned Reg, int Offset) override {
69 OS << "\t.seh_save_reg\tx" << Reg << ", " << Offset << "\n";
70 }
71 void emitARM64WinCFISaveRegX(unsigned Reg, int Offset) override {
72 OS << "\t.seh_save_reg_x\tx" << Reg << ", " << Offset << "\n";
73 }
74 void emitARM64WinCFISaveRegP(unsigned Reg, int Offset) override {
75 OS << "\t.seh_save_regp\tx" << Reg << ", " << Offset << "\n";
76 }
77 void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override {
78 OS << "\t.seh_save_regp_x\tx" << Reg << ", " << Offset << "\n";
79 }
80 void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override {
81 OS << "\t.seh_save_lrpair\tx" << Reg << ", " << Offset << "\n";
82 }
83 void emitARM64WinCFISaveFReg(unsigned Reg, int Offset) override {
84 OS << "\t.seh_save_freg\td" << Reg << ", " << Offset << "\n";
85 }
86 void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override {
87 OS << "\t.seh_save_freg_x\td" << Reg << ", " << Offset << "\n";
88 }
89 void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override {
90 OS << "\t.seh_save_fregp\td" << Reg << ", " << Offset << "\n";
91 }
92 void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override {
93 OS << "\t.seh_save_fregp_x\td" << Reg << ", " << Offset << "\n";
94 }
95 void emitARM64WinCFISetFP() override { OS << "\t.seh_set_fp\n"; }
96 void emitARM64WinCFIAddFP(unsigned Size) override {
97 OS << "\t.seh_add_fp\t" << Size << "\n";
98 }
99 void emitARM64WinCFINop() override { OS << "\t.seh_nop\n"; }
100 void emitARM64WinCFISaveNext() override { OS << "\t.seh_save_next\n"; }
101 void emitARM64WinCFIPrologEnd() override { OS << "\t.seh_endprologue\n"; }
102 void emitARM64WinCFIEpilogStart() override { OS << "\t.seh_startepilogue\n"; }
103 void emitARM64WinCFIEpilogEnd() override { OS << "\t.seh_endepilogue\n"; }
104 void emitARM64WinCFITrapFrame() override { OS << "\t.seh_trap_frame\n"; }
105 void emitARM64WinCFIMachineFrame() override { OS << "\t.seh_pushframe\n"; }
106 void emitARM64WinCFIContext() override { OS << "\t.seh_context\n"; }
107 void emitARM64WinCFIECContext() override { OS << "\t.seh_ec_context\n"; }
108 void emitARM64WinCFIClearUnwoundToCall() override {
109 OS << "\t.seh_clear_unwound_to_call\n";
110 }
111 void emitARM64WinCFIPACSignLR() override {
112 OS << "\t.seh_pac_sign_lr\n";
113 }
114
115 void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) override {
116 OS << "\t.seh_save_any_reg\tx" << Reg << ", " << Offset << "\n";
117 }
118 void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset) override {
119 OS << "\t.seh_save_any_reg_p\tx" << Reg << ", " << Offset << "\n";
120 }
121 void emitARM64WinCFISaveAnyRegD(unsigned Reg, int Offset) override {
122 OS << "\t.seh_save_any_reg\td" << Reg << ", " << Offset << "\n";
123 }
124 void emitARM64WinCFISaveAnyRegDP(unsigned Reg, int Offset) override {
125 OS << "\t.seh_save_any_reg_p\td" << Reg << ", " << Offset << "\n";
126 }
127 void emitARM64WinCFISaveAnyRegQ(unsigned Reg, int Offset) override {
128 OS << "\t.seh_save_any_reg\tq" << Reg << ", " << Offset << "\n";
129 }
130 void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset) override {
131 OS << "\t.seh_save_any_reg_p\tq" << Reg << ", " << Offset << "\n";
132 }
133 void emitARM64WinCFISaveAnyRegIX(unsigned Reg, int Offset) override {
134 OS << "\t.seh_save_any_reg_x\tx" << Reg << ", " << Offset << "\n";
135 }
136 void emitARM64WinCFISaveAnyRegIPX(unsigned Reg, int Offset) override {
137 OS << "\t.seh_save_any_reg_px\tx" << Reg << ", " << Offset << "\n";
138 }
139 void emitARM64WinCFISaveAnyRegDX(unsigned Reg, int Offset) override {
140 OS << "\t.seh_save_any_reg_x\td" << Reg << ", " << Offset << "\n";
141 }
142 void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override {
143 OS << "\t.seh_save_any_reg_px\td" << Reg << ", " << Offset << "\n";
144 }
145 void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override {
146 OS << "\t.seh_save_any_reg_x\tq" << Reg << ", " << Offset << "\n";
147 }
148 void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override {
149 OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
150 }
151
152public:
153 AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
154};
155
156AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
158 : AArch64TargetStreamer(S), OS(OS) {}
159
160void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
161 OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
162}
163
164/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
165/// the appropriate points in the object files. These symbols are defined in the
166/// AArch64 ELF ABI:
167/// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf
168///
169/// In brief: $x or $d should be emitted at the start of each contiguous region
170/// of A64 code or data in a section. In practice, this emission does not rely
171/// on explicit assembler directives but on inherent properties of the
172/// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an
173/// instruction).
174///
175/// As a result this system is orthogonal to the DataRegion infrastructure used
176/// by MachO. Beware!
177class AArch64ELFStreamer : public MCELFStreamer {
178public:
179 AArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
180 std::unique_ptr<MCObjectWriter> OW,
181 std::unique_ptr<MCCodeEmitter> Emitter)
182 : MCELFStreamer(Context, std::move(TAB), std::move(OW),
183 std::move(Emitter)),
184 MappingSymbolCounter(0), LastEMS(EMS_None) {}
185
186 void changeSection(MCSection *Section, uint32_t Subsection = 0) override {
187 // We have to keep track of the mapping symbol state of any sections we
188 // use. Each one should start off as EMS_None, which is provided as the
189 // default constructor by DenseMap::lookup.
190 LastMappingSymbols[getCurrentSection().first] = LastEMS;
191 LastEMS = LastMappingSymbols.lookup(Section);
192
193 MCELFStreamer::changeSection(Section, Subsection);
194 }
195
196 // Reset state between object emissions
197 void reset() override {
198 MappingSymbolCounter = 0;
200 LastMappingSymbols.clear();
201 LastEMS = EMS_None;
202 }
203
204 /// This function is the one used to emit instruction data into the ELF
205 /// streamer. We override it to add the appropriate mapping symbol if
206 /// necessary.
207 void emitInstruction(const MCInst &Inst,
208 const MCSubtargetInfo &STI) override {
209 emitA64MappingSymbol();
211 }
212
213 /// Emit a 32-bit value as an instruction. This is only used for the .inst
214 /// directive, EmitInstruction should be used in other cases.
215 void emitInst(uint32_t Inst) {
216 char Buffer[4];
217
218 // We can't just use EmitIntValue here, as that will emit a data mapping
219 // symbol, and swap the endianness on big-endian systems (instructions are
220 // always little-endian).
221 for (char &C : Buffer) {
222 C = uint8_t(Inst);
223 Inst >>= 8;
224 }
225
226 emitA64MappingSymbol();
228 }
229
230 /// This is one of the functions used to emit data into an ELF section, so the
231 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
232 /// if necessary.
233 void emitBytes(StringRef Data) override {
234 emitDataMappingSymbol();
236 }
237
238 /// This is one of the functions used to emit data into an ELF section, so the
239 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
240 /// if necessary.
241 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
242 emitDataMappingSymbol();
244 }
245
246 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
247 SMLoc Loc) override {
248 emitDataMappingSymbol();
249 MCObjectStreamer::emitFill(NumBytes, FillValue, Loc);
250 }
251
252private:
253 enum ElfMappingSymbol {
254 EMS_None,
255 EMS_A64,
256 EMS_Data
257 };
258
259 void emitDataMappingSymbol() {
260 if (LastEMS == EMS_Data)
261 return;
262 emitMappingSymbol("$d");
263 LastEMS = EMS_Data;
264 }
265
266 void emitA64MappingSymbol() {
267 if (LastEMS == EMS_A64)
268 return;
269 emitMappingSymbol("$x");
270 LastEMS = EMS_A64;
271 }
272
273 void emitMappingSymbol(StringRef Name) {
274 auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
275 Name + "." + Twine(MappingSymbolCounter++)));
276 emitLabel(Symbol);
277 Symbol->setType(ELF::STT_NOTYPE);
278 Symbol->setBinding(ELF::STB_LOCAL);
279 Symbol->setExternal(false);
280 }
281
282 int64_t MappingSymbolCounter;
283
285 ElfMappingSymbol LastEMS;
286};
287} // end anonymous namespace
288
289AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
290 return static_cast<AArch64ELFStreamer &>(Streamer);
291}
292
293void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
294 getStreamer().emitInst(Inst);
295}
296
297void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {
298 getStreamer().getAssembler().registerSymbol(*Symbol);
299 cast<MCSymbolELF>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);
300}
301
302void AArch64TargetELFStreamer::finish() {
304 AArch64ELFStreamer &S = getStreamer();
305 MCContext &Ctx = S.getContext();
306 auto &Asm = S.getAssembler();
307 MCSectionELF *MemtagSec = nullptr;
308 for (const MCSymbol &Symbol : Asm.symbols()) {
309 const auto &Sym = cast<MCSymbolELF>(Symbol);
310 if (Sym.isMemtag()) {
311 MemtagSec = Ctx.getELFSection(".memtag.globals.static",
313 break;
314 }
315 }
316 if (!MemtagSec)
317 return;
318
319 // switchSection registers the section symbol and invalidates symbols(). We
320 // need a separate symbols() loop.
321 S.switchSection(MemtagSec);
322 const auto *Zero = MCConstantExpr::create(0, Ctx);
323 for (const MCSymbol &Symbol : Asm.symbols()) {
324 const auto &Sym = cast<MCSymbolELF>(Symbol);
325 if (!Sym.isMemtag())
326 continue;
328 (void)S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE, SMLoc(),
329 *Ctx.getSubtargetInfo());
330 }
331}
332
335 MCInstPrinter *InstPrint,
336 bool isVerboseAsm) {
337 return new AArch64TargetAsmStreamer(S, OS);
338}
339
342 std::unique_ptr<MCAsmBackend> TAB,
343 std::unique_ptr<MCObjectWriter> OW,
344 std::unique_ptr<MCCodeEmitter> Emitter) {
345 AArch64ELFStreamer *S = new AArch64ELFStreamer(
346 Context, std::move(TAB), std::move(OW), std::move(Emitter));
347 return S;
348}
dxil DXContainer Global Emitter
This file defines the DenseMap class.
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
raw_pwrite_stream & OS
virtual void emitARM64WinCFISaveAnyRegIX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegDX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQ(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegD(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFISaveR19R20X(int Offset)
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFIClearUnwoundToCall()
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegDP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegIPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitInst(uint32_t Inst)
Callback used to implement the .inst directive.
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:193
Context object for machine code objects.
Definition: MCContext.h:83
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:547
const MCSubtargetInfo * getSubtargetInfo() const
Definition: MCContext.h:418
void changeSection(MCSection *Section, uint32_t Subsection=0) override
This is called by popSection and switchSection, if the current section changes.
void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc()) override
Emit the expression Value into the output as a native integer of the given Size bytes.
void reset() override
state management
Definition: MCELFStreamer.h:40
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:45
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc=SMLoc()) override
Emit Size bytes worth of the value specified by FillValue.
void emitBytes(StringRef Data) override
Emit the bytes in Data into the output.
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override
Emit the given Instruction into the current section.
This represents a section on linux, lots of unix variants and some bare metal systems.
Definition: MCSectionELF.h:27
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:36
Streaming machine code generation interface.
Definition: MCStreamer.h:213
MCContext & getContext() const
Definition: MCStreamer.h:300
MCSectionSubPair getCurrentSection() const
Return the current section that the streamer is emitting code to.
Definition: MCStreamer.h:393
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:393
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Target specific streamer interface.
Definition: MCStreamer.h:94
MCStreamer & Streamer
Definition: MCStreamer.h:96
Represents a location in source code.
Definition: SMLoc.h:23
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:416
LLVM Value Representation.
Definition: Value.h:74
formatted_raw_ostream - A raw_ostream that wraps another one and keeps track of line and column posit...
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ STT_NOTYPE
Definition: ELF.h:1330
@ SHT_AARCH64_MEMTAG_GLOBALS_STATIC
Definition: ELF.h:1135
@ STB_LOCAL
Definition: ELF.h:1318
@ STO_AARCH64_VARIANT_PCS
Definition: ELF.h:433
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
MCTargetStreamer * createAArch64AsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint, bool isVerboseAsm)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1849
MCELFStreamer * createAArch64ELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter)
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858