LLVM 17.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"
31#include "llvm/MC/MCSection.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 emitARM64WinCFIClearUnwoundToCall() override {
108 OS << "\t.seh_clear_unwound_to_call\n";
109 }
110 void emitARM64WinCFIPACSignLR() override {
111 OS << "\t.seh_pac_sign_lr\n";
112 }
113
114 void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) override {
115 OS << "\t.seh_save_any_reg\tx" << Reg << ", " << Offset << "\n";
116 }
117 void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset) override {
118 OS << "\t.seh_save_any_reg_p\tx" << Reg << ", " << Offset << "\n";
119 }
120 void emitARM64WinCFISaveAnyRegD(unsigned Reg, int Offset) override {
121 OS << "\t.seh_save_any_reg\td" << Reg << ", " << Offset << "\n";
122 }
123 void emitARM64WinCFISaveAnyRegDP(unsigned Reg, int Offset) override {
124 OS << "\t.seh_save_any_reg_p\td" << Reg << ", " << Offset << "\n";
125 }
126 void emitARM64WinCFISaveAnyRegQ(unsigned Reg, int Offset) override {
127 OS << "\t.seh_save_any_reg\tq" << Reg << ", " << Offset << "\n";
128 }
129 void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset) override {
130 OS << "\t.seh_save_any_reg_p\tq" << Reg << ", " << Offset << "\n";
131 }
132 void emitARM64WinCFISaveAnyRegIX(unsigned Reg, int Offset) override {
133 OS << "\t.seh_save_any_reg_x\tx" << Reg << ", " << Offset << "\n";
134 }
135 void emitARM64WinCFISaveAnyRegIPX(unsigned Reg, int Offset) override {
136 OS << "\t.seh_save_any_reg_px\tx" << Reg << ", " << Offset << "\n";
137 }
138 void emitARM64WinCFISaveAnyRegDX(unsigned Reg, int Offset) override {
139 OS << "\t.seh_save_any_reg_x\td" << Reg << ", " << Offset << "\n";
140 }
141 void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override {
142 OS << "\t.seh_save_any_reg_px\td" << Reg << ", " << Offset << "\n";
143 }
144 void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override {
145 OS << "\t.seh_save_any_reg_x\tq" << Reg << ", " << Offset << "\n";
146 }
147 void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override {
148 OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
149 }
150
151public:
152 AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
153};
154
155AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
157 : AArch64TargetStreamer(S), OS(OS) {}
158
159void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
160 OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";
161}
162
163/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
164/// the appropriate points in the object files. These symbols are defined in the
165/// AArch64 ELF ABI:
166/// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf
167///
168/// In brief: $x or $d should be emitted at the start of each contiguous region
169/// of A64 code or data in a section. In practice, this emission does not rely
170/// on explicit assembler directives but on inherent properties of the
171/// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an
172/// instruction).
173///
174/// As a result this system is orthogonal to the DataRegion infrastructure used
175/// by MachO. Beware!
176class AArch64ELFStreamer : public MCELFStreamer {
177public:
178 AArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
179 std::unique_ptr<MCObjectWriter> OW,
180 std::unique_ptr<MCCodeEmitter> Emitter)
181 : MCELFStreamer(Context, std::move(TAB), std::move(OW),
182 std::move(Emitter)),
183 MappingSymbolCounter(0), LastEMS(EMS_None) {}
184
185 void changeSection(MCSection *Section, const MCExpr *Subsection) override {
186 // We have to keep track of the mapping symbol state of any sections we
187 // use. Each one should start off as EMS_None, which is provided as the
188 // default constructor by DenseMap::lookup.
189 LastMappingSymbols[getPreviousSection().first] = LastEMS;
190 LastEMS = LastMappingSymbols.lookup(Section);
191
192 MCELFStreamer::changeSection(Section, Subsection);
193 }
194
195 // Reset state between object emissions
196 void reset() override {
197 MappingSymbolCounter = 0;
199 LastMappingSymbols.clear();
200 LastEMS = EMS_None;
201 }
202
203 /// This function is the one used to emit instruction data into the ELF
204 /// streamer. We override it to add the appropriate mapping symbol if
205 /// necessary.
206 void emitInstruction(const MCInst &Inst,
207 const MCSubtargetInfo &STI) override {
208 emitA64MappingSymbol();
210 }
211
212 /// Emit a 32-bit value as an instruction. This is only used for the .inst
213 /// directive, EmitInstruction should be used in other cases.
214 void emitInst(uint32_t Inst) {
215 char Buffer[4];
216
217 // We can't just use EmitIntValue here, as that will emit a data mapping
218 // symbol, and swap the endianness on big-endian systems (instructions are
219 // always little-endian).
220 for (char &C : Buffer) {
221 C = uint8_t(Inst);
222 Inst >>= 8;
223 }
224
225 emitA64MappingSymbol();
227 }
228
229 /// This is one of the functions used to emit data into an ELF section, so the
230 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
231 /// if necessary.
232 void emitBytes(StringRef Data) override {
233 emitDataMappingSymbol();
235 }
236
237 /// This is one of the functions used to emit data into an ELF section, so the
238 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
239 /// if necessary.
240 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
241 emitDataMappingSymbol();
243 }
244
245 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
246 SMLoc Loc) override {
247 emitDataMappingSymbol();
248 MCObjectStreamer::emitFill(NumBytes, FillValue, Loc);
249 }
250private:
251 enum ElfMappingSymbol {
252 EMS_None,
253 EMS_A64,
254 EMS_Data
255 };
256
257 void emitDataMappingSymbol() {
258 if (LastEMS == EMS_Data)
259 return;
260 emitMappingSymbol("$d");
261 LastEMS = EMS_Data;
262 }
263
264 void emitA64MappingSymbol() {
265 if (LastEMS == EMS_A64)
266 return;
267 emitMappingSymbol("$x");
268 LastEMS = EMS_A64;
269 }
270
271 void emitMappingSymbol(StringRef Name) {
272 auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
273 Name + "." + Twine(MappingSymbolCounter++)));
274 emitLabel(Symbol);
275 Symbol->setType(ELF::STT_NOTYPE);
276 Symbol->setBinding(ELF::STB_LOCAL);
277 Symbol->setExternal(false);
278 }
279
280 int64_t MappingSymbolCounter;
281
283 ElfMappingSymbol LastEMS;
284};
285
286} // end anonymous namespace
287
288AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
289 return static_cast<AArch64ELFStreamer &>(Streamer);
290}
291
292void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
293 getStreamer().emitInst(Inst);
294}
295
296void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {
297 getStreamer().getAssembler().registerSymbol(*Symbol);
298 cast<MCSymbolELF>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);
299}
300
303 MCInstPrinter *InstPrint,
304 bool isVerboseAsm) {
305 return new AArch64TargetAsmStreamer(S, OS);
306}
307
309 MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
310 std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
311 bool RelaxAll) {
312 AArch64ELFStreamer *S = new AArch64ELFStreamer(
313 Context, std::move(TAB), std::move(OW), std::move(Emitter));
314 if (RelaxAll)
315 S->getAssembler().setRelaxAll(true);
316 return S;
317}
dxil DXContainer Global Emitter
This file defines the DenseMap class.
std::string Name
uint64_t Size
LLVMContext & Context
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)
Context object for machine code objects.
Definition: MCContext.h:76
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 changeSection(MCSection *Section, const MCExpr *Subsection) override
Update streamer for a new active section.
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:35
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:44
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.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
Streaming machine code generation interface.
Definition: MCStreamer.h:212
MCSectionSubPair getPreviousSection() const
Return the previous section that the streamer is emitting code to.
Definition: MCStreamer.h:396
MCContext & getContext() const
Definition: MCStreamer.h:297
Generic base class for all target subtargets.
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:93
MCStreamer & Streamer
Definition: MCStreamer.h:95
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:404
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
@ STO_AARCH64_VARIANT_PCS
Definition: ELF.h:429
@ STB_LOCAL
Definition: ELF.h:1241
@ STT_NOTYPE
Definition: ELF.h:1253
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:406
MCELFStreamer * createAArch64ELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter, bool RelaxAll)
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:1946
Definition: BitVector.h:858