LLVM 20.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"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
23#include "llvm/MC/MCAssembler.h"
25#include "llvm/MC/MCContext.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
31#include "llvm/MC/MCStreamer.h"
33#include "llvm/MC/MCSymbolELF.h"
39
40using namespace llvm;
41
42namespace {
43
44class AArch64ELFStreamer;
45
46class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
48
49 void emitInst(uint32_t Inst) override;
50
51 void emitDirectiveVariantPCS(MCSymbol *Symbol) override {
52 OS << "\t.variant_pcs\t" << Symbol->getName() << "\n";
53 }
54
55 void emitARM64WinCFIAllocStack(unsigned Size) override {
56 OS << "\t.seh_stackalloc\t" << Size << "\n";
57 }
58 void emitARM64WinCFISaveR19R20X(int Offset) override {
59 OS << "\t.seh_save_r19r20_x\t" << Offset << "\n";
60 }
61 void emitARM64WinCFISaveFPLR(int Offset) override {
62 OS << "\t.seh_save_fplr\t" << Offset << "\n";
63 }
64 void emitARM64WinCFISaveFPLRX(int Offset) override {
65 OS << "\t.seh_save_fplr_x\t" << Offset << "\n";
66 }
67 void emitARM64WinCFISaveReg(unsigned Reg, int Offset) override {
68 OS << "\t.seh_save_reg\tx" << Reg << ", " << Offset << "\n";
69 }
70 void emitARM64WinCFISaveRegX(unsigned Reg, int Offset) override {
71 OS << "\t.seh_save_reg_x\tx" << Reg << ", " << Offset << "\n";
72 }
73 void emitARM64WinCFISaveRegP(unsigned Reg, int Offset) override {
74 OS << "\t.seh_save_regp\tx" << Reg << ", " << Offset << "\n";
75 }
76 void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override {
77 OS << "\t.seh_save_regp_x\tx" << Reg << ", " << Offset << "\n";
78 }
79 void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override {
80 OS << "\t.seh_save_lrpair\tx" << Reg << ", " << Offset << "\n";
81 }
82 void emitARM64WinCFISaveFReg(unsigned Reg, int Offset) override {
83 OS << "\t.seh_save_freg\td" << Reg << ", " << Offset << "\n";
84 }
85 void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override {
86 OS << "\t.seh_save_freg_x\td" << Reg << ", " << Offset << "\n";
87 }
88 void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override {
89 OS << "\t.seh_save_fregp\td" << Reg << ", " << Offset << "\n";
90 }
91 void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override {
92 OS << "\t.seh_save_fregp_x\td" << Reg << ", " << Offset << "\n";
93 }
94 void emitARM64WinCFISetFP() override { OS << "\t.seh_set_fp\n"; }
95 void emitARM64WinCFIAddFP(unsigned Size) override {
96 OS << "\t.seh_add_fp\t" << Size << "\n";
97 }
98 void emitARM64WinCFINop() override { OS << "\t.seh_nop\n"; }
99 void emitARM64WinCFISaveNext() override { OS << "\t.seh_save_next\n"; }
100 void emitARM64WinCFIPrologEnd() override { OS << "\t.seh_endprologue\n"; }
101 void emitARM64WinCFIEpilogStart() override { OS << "\t.seh_startepilogue\n"; }
102 void emitARM64WinCFIEpilogEnd() override { OS << "\t.seh_endepilogue\n"; }
103 void emitARM64WinCFITrapFrame() override { OS << "\t.seh_trap_frame\n"; }
104 void emitARM64WinCFIMachineFrame() override { OS << "\t.seh_pushframe\n"; }
105 void emitARM64WinCFIContext() override { OS << "\t.seh_context\n"; }
106 void emitARM64WinCFIECContext() override { OS << "\t.seh_ec_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:
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 LastEMS(EMS_None) {
185 auto *TO = getContext().getTargetOptions();
186 ImplicitMapSyms = TO && TO->ImplicitMapSyms;
187 }
188
189 void changeSection(MCSection *Section, uint32_t Subsection = 0) override {
190 // Save the mapping symbol state for potential reuse when revisiting the
191 // section. When ImplicitMapSyms is true, the initial state is
192 // EMS_A64 for text sections and EMS_Data for the others.
193 LastMappingSymbols[getCurrentSection().first] = LastEMS;
194 auto It = LastMappingSymbols.find(Section);
195 if (It != LastMappingSymbols.end())
196 LastEMS = It->second;
197 else if (ImplicitMapSyms)
198 LastEMS = Section->isText() ? EMS_A64 : EMS_Data;
199 else
200 LastEMS = EMS_None;
201
202 MCELFStreamer::changeSection(Section, Subsection);
203 }
204
205 // Reset state between object emissions
206 void reset() override {
208 LastMappingSymbols.clear();
209 LastEMS = EMS_None;
210 }
211
212 /// This function is the one used to emit instruction data into the ELF
213 /// streamer. We override it to add the appropriate mapping symbol if
214 /// necessary.
215 void emitInstruction(const MCInst &Inst,
216 const MCSubtargetInfo &STI) override {
217 emitA64MappingSymbol();
219 }
220
221 /// Emit a 32-bit value as an instruction. This is only used for the .inst
222 /// directive, EmitInstruction should be used in other cases.
223 void emitInst(uint32_t Inst) {
224 char Buffer[4];
225
226 // We can't just use EmitIntValue here, as that will emit a data mapping
227 // symbol, and swap the endianness on big-endian systems (instructions are
228 // always little-endian).
229 for (char &C : Buffer) {
230 C = uint8_t(Inst);
231 Inst >>= 8;
232 }
233
234 emitA64MappingSymbol();
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 emitBytes(StringRef Data) override {
242 emitDataMappingSymbol();
244 }
245
246 /// This is one of the functions used to emit data into an ELF section, so the
247 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
248 /// if necessary.
249 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
250 emitDataMappingSymbol();
252 }
253
254 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
255 SMLoc Loc) override {
256 emitDataMappingSymbol();
257 MCObjectStreamer::emitFill(NumBytes, FillValue, Loc);
258 }
259
260private:
261 enum ElfMappingSymbol {
262 EMS_None,
263 EMS_A64,
264 EMS_Data
265 };
266
267 void emitDataMappingSymbol() {
268 if (LastEMS == EMS_Data)
269 return;
270 emitMappingSymbol("$d");
271 LastEMS = EMS_Data;
272 }
273
274 void emitA64MappingSymbol() {
275 if (LastEMS == EMS_A64)
276 return;
277 emitMappingSymbol("$x");
278 LastEMS = EMS_A64;
279 }
280
281 MCSymbol *emitMappingSymbol(StringRef Name) {
282 auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
283 emitLabel(Symbol);
284 return Symbol;
285 }
286
288 ElfMappingSymbol LastEMS;
289 bool ImplicitMapSyms;
290};
291} // end anonymous namespace
292
293AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
294 return static_cast<AArch64ELFStreamer &>(Streamer);
295}
296
297void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
298 getStreamer().emitInst(Inst);
299}
300
301void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {
302 getStreamer().getAssembler().registerSymbol(*Symbol);
303 cast<MCSymbolELF>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);
304}
305
306void AArch64TargetELFStreamer::finish() {
308 AArch64ELFStreamer &S = getStreamer();
309 MCContext &Ctx = S.getContext();
310 auto &Asm = S.getAssembler();
311
312 // If ImplicitMapSyms is specified, ensure that text sections end with
313 // the A64 state while non-text sections end with the data state. When
314 // sections are combined by the linker, the subsequent section will start with
315 // the right state. The ending mapping symbol is added right after the last
316 // symbol relative to the section. When a dumb linker combines (.text.0; .word
317 // 0) and (.text.1; .word 0), the ending $x of .text.0 precedes the $d of
318 // .text.1, even if they have the same address.
319 if (S.ImplicitMapSyms) {
320 auto &Syms = Asm.getSymbols();
321 const size_t NumSyms = Syms.size();
323 for (MCSection &Sec : Asm) {
324 S.switchSection(&Sec);
325 if (S.LastEMS == (Sec.isText() ? AArch64ELFStreamer::EMS_Data
326 : AArch64ELFStreamer::EMS_A64))
327 EndMapSym.insert(
328 {&Sec, {NumSyms, S.emitMappingSymbol(Sec.isText() ? "$x" : "$d")}});
329 }
330 if (Syms.size() != NumSyms) {
333 Syms.truncate(NumSyms);
334 // Find the last symbol index for each candidate section.
335 for (auto [I, Sym] : llvm::enumerate(Syms)) {
336 if (!Sym->isInSection())
337 continue;
338 auto It = EndMapSym.find(&Sym->getSection());
339 if (It != EndMapSym.end())
340 It->second.first = I;
341 }
343 for (auto [I, Sym] : llvm::enumerate(Syms)) {
344 NewSyms.push_back(Sym);
345 if (!Sym->isInSection())
346 continue;
347 auto It = EndMapSym.find(&Sym->getSection());
348 // If `Sym` is the last symbol relative to the section, add the ending
349 // mapping symbol after `Sym`.
350 if (It != EndMapSym.end() && I == It->second.first) {
351 NewSyms.push_back(It->second.second);
352 Idx.push_back(I);
353 }
354 }
355 Syms = std::move(NewSyms);
356 // F.second holds the number of symbols added before the FILE symbol.
357 // Take into account the inserted mapping symbols.
358 for (auto &F : S.getWriter().getFileNames())
359 F.second += llvm::lower_bound(Idx, F.second) - Idx.begin();
360 }
361 }
362
363 MCSectionELF *MemtagSec = nullptr;
364 for (const MCSymbol &Symbol : Asm.symbols()) {
365 const auto &Sym = cast<MCSymbolELF>(Symbol);
366 if (Sym.isMemtag()) {
367 MemtagSec = Ctx.getELFSection(".memtag.globals.static",
369 break;
370 }
371 }
372 if (!MemtagSec)
373 return;
374
375 // switchSection registers the section symbol and invalidates symbols(). We
376 // need a separate symbols() loop.
377 S.switchSection(MemtagSec);
378 const auto *Zero = MCConstantExpr::create(0, Ctx);
379 for (const MCSymbol &Symbol : Asm.symbols()) {
380 const auto &Sym = cast<MCSymbolELF>(Symbol);
381 if (!Sym.isMemtag())
382 continue;
384 (void)S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE, SMLoc(),
385 *Ctx.getSubtargetInfo());
386 }
387}
388
391 MCInstPrinter *InstPrint) {
392 return new AArch64TargetAsmStreamer(S, OS);
393}
394
397 std::unique_ptr<MCAsmBackend> TAB,
398 std::unique_ptr<MCObjectWriter> OW,
399 std::unique_ptr<MCCodeEmitter> Emitter) {
400 AArch64ELFStreamer *S = new AArch64ELFStreamer(
401 Context, std::move(TAB), std::move(OW), std::move(Emitter));
402 return S;
403}
dxil DXContainer Global Emitter
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
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)
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:211
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:222
Context object for machine code objects.
Definition: MCContext.h:83
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:551
const MCTargetOptions * getTargetOptions() const
Definition: MCContext.h:420
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:41
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:46
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
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:395
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
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
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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
@ STO_AARCH64_VARIANT_PCS
Definition: ELF.h:435
@ SHT_AARCH64_MEMTAG_GLOBALS_STATIC
Definition: ELF.h:1160
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)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2448
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1978
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:1873
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