1 //===- AArch64TargetStreamer.cpp - AArch64TargetStreamer class ------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the AArch64TargetStreamer class.
11 //===----------------------------------------------------------------------===//
13 #include "AArch64TargetStreamer.h"
14 #include "AArch64MCAsmInfo.h"
15 #include "llvm/BinaryFormat/ELF.h"
16 #include "llvm/MC/ConstantPools.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCSection.h"
19 #include "llvm/MC/MCSectionELF.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/CommandLine.h"
25 static cl::opt
<bool> MarkBTIProperty(
26 "aarch64-mark-bti-property", cl::Hidden
,
27 cl::desc("Add .note.gnu.property with BTI to assembly files"),
31 // AArch64TargetStreamer Implemenation
33 AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer
&S
)
34 : MCTargetStreamer(S
), ConstantPools(new AssemblerConstantPools()) {}
36 AArch64TargetStreamer::~AArch64TargetStreamer() = default;
38 // The constant pool handling is shared by all AArch64TargetStreamer
40 const MCExpr
*AArch64TargetStreamer::addConstantPoolEntry(const MCExpr
*Expr
,
43 return ConstantPools
->addEntry(Streamer
, Expr
, Size
, Loc
);
46 void AArch64TargetStreamer::emitCurrentConstantPool() {
47 ConstantPools
->emitForCurrentSection(Streamer
);
50 void AArch64TargetStreamer::emitConstantPools() {
51 ConstantPools
->emitAll(Streamer
);
54 // finish() - write out any non-empty assembler constant pools and
55 // write out note.gnu.properties if need.
56 void AArch64TargetStreamer::finish() {
58 emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI
);
61 void AArch64TargetStreamer::emitNoteSection(unsigned Flags
,
62 uint64_t PAuthABIPlatform
,
63 uint64_t PAuthABIVersion
) {
64 assert((PAuthABIPlatform
== uint64_t(-1)) ==
65 (PAuthABIVersion
== uint64_t(-1)));
69 if (PAuthABIPlatform
!= uint64_t(-1))
70 DescSz
+= 4 + 4 + 8 * 2;
74 MCStreamer
&OutStreamer
= getStreamer();
75 MCContext
&Context
= OutStreamer
.getContext();
76 // Emit a .note.gnu.property section with the flags.
77 MCSectionELF
*Nt
= Context
.getELFSection(".note.gnu.property", ELF::SHT_NOTE
,
79 if (Nt
->isRegistered()) {
81 Context
.reportWarning(
83 "The .note.gnu.property is not emitted because it is already present.");
86 MCSection
*Cur
= OutStreamer
.getCurrentSectionOnly();
87 OutStreamer
.switchSection(Nt
);
89 // Emit the note header.
90 OutStreamer
.emitValueToAlignment(Align(8));
91 OutStreamer
.emitIntValue(4, 4); // data size for "GNU\0"
92 OutStreamer
.emitIntValue(DescSz
, 4); // Elf_Prop array size
93 OutStreamer
.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0
, 4);
94 OutStreamer
.emitBytes(StringRef("GNU", 4)); // note name
96 // Emit the PAC/BTI properties.
98 OutStreamer
.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND
, 4);
99 OutStreamer
.emitIntValue(4, 4); // data size
100 OutStreamer
.emitIntValue(Flags
, 4); // data
101 OutStreamer
.emitIntValue(0, 4); // pad
104 // Emit the PAuth ABI compatibility info
105 if (PAuthABIPlatform
!= uint64_t(-1)) {
106 OutStreamer
.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_PAUTH
, 4);
107 OutStreamer
.emitIntValue(8 * 2, 4); // data size
108 OutStreamer
.emitIntValue(PAuthABIPlatform
, 8);
109 OutStreamer
.emitIntValue(PAuthABIVersion
, 8);
112 OutStreamer
.endSection(Nt
);
113 OutStreamer
.switchSection(Cur
);
116 void AArch64TargetStreamer::emitInst(uint32_t Inst
) {
119 // We can't just use EmitIntValue here, as that will swap the
120 // endianness on big-endian systems (instructions are always
122 for (char &C
: Buffer
) {
127 getStreamer().emitBytes(StringRef(Buffer
, 4));
131 llvm::createAArch64ObjectTargetStreamer(MCStreamer
&S
,
132 const MCSubtargetInfo
&STI
) {
133 const Triple
&TT
= STI
.getTargetTriple();
134 if (TT
.isOSBinFormatELF())
135 return new AArch64TargetELFStreamer(S
);
136 if (TT
.isOSBinFormatCOFF())
137 return new AArch64TargetWinCOFFStreamer(S
);
141 MCTargetStreamer
*llvm::createAArch64NullTargetStreamer(MCStreamer
&S
) {
142 return new AArch64TargetStreamer(S
);