581 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file assembles .s files and emits AArch64 ELF .o object files. Different10// from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit11// regions of data and code.12//13//===----------------------------------------------------------------------===//14 15#include "AArch64ELFStreamer.h"16#include "AArch64MCTargetDesc.h"17#include "AArch64TargetStreamer.h"18#include "llvm/ADT/DenseMap.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/ADT/Twine.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/MC/MCAsmBackend.h"23#include "llvm/MC/MCAssembler.h"24#include "llvm/MC/MCCodeEmitter.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/MCELFObjectWriter.h"27#include "llvm/MC/MCELFStreamer.h"28#include "llvm/MC/MCExpr.h"29#include "llvm/MC/MCInst.h"30#include "llvm/MC/MCObjectFileInfo.h"31#include "llvm/MC/MCSectionELF.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/MCSubtargetInfo.h"34#include "llvm/MC/MCSymbolELF.h"35#include "llvm/MC/MCTargetOptions.h"36#include "llvm/MC/MCWinCOFFStreamer.h"37#include "llvm/Support/AArch64BuildAttributes.h"38#include "llvm/Support/FormattedStream.h"39#include "llvm/Support/raw_ostream.h"40 41using namespace llvm;42 43namespace {44 45class AArch64ELFStreamer;46 47class AArch64TargetAsmStreamer : public AArch64TargetStreamer {48 formatted_raw_ostream &OS;49 std::string VendorTag;50 51 void emitInst(uint32_t Inst) override;52 53 void emitDirectiveVariantPCS(MCSymbol *Symbol) override {54 OS << "\t.variant_pcs\t" << Symbol->getName() << "\n";55 }56 57 void emitDirectiveArch(StringRef Name) override {58 OS << "\t.arch\t" << Name << "\n";59 }60 61 void emitDirectiveArchExtension(StringRef Name) override {62 OS << "\t.arch_extension\t" << Name << "\n";63 }64 65 void emitARM64WinCFIAllocStack(unsigned Size) override {66 OS << "\t.seh_stackalloc\t" << Size << "\n";67 }68 void emitARM64WinCFISaveR19R20X(int Offset) override {69 OS << "\t.seh_save_r19r20_x\t" << Offset << "\n";70 }71 void emitARM64WinCFISaveFPLR(int Offset) override {72 OS << "\t.seh_save_fplr\t" << Offset << "\n";73 }74 void emitARM64WinCFISaveFPLRX(int Offset) override {75 OS << "\t.seh_save_fplr_x\t" << Offset << "\n";76 }77 void emitARM64WinCFISaveReg(unsigned Reg, int Offset) override {78 OS << "\t.seh_save_reg\tx" << Reg << ", " << Offset << "\n";79 }80 void emitARM64WinCFISaveRegX(unsigned Reg, int Offset) override {81 OS << "\t.seh_save_reg_x\tx" << Reg << ", " << Offset << "\n";82 }83 void emitARM64WinCFISaveRegP(unsigned Reg, int Offset) override {84 OS << "\t.seh_save_regp\tx" << Reg << ", " << Offset << "\n";85 }86 void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override {87 OS << "\t.seh_save_regp_x\tx" << Reg << ", " << Offset << "\n";88 }89 void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override {90 OS << "\t.seh_save_lrpair\tx" << Reg << ", " << Offset << "\n";91 }92 void emitARM64WinCFISaveFReg(unsigned Reg, int Offset) override {93 OS << "\t.seh_save_freg\td" << Reg << ", " << Offset << "\n";94 }95 void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override {96 OS << "\t.seh_save_freg_x\td" << Reg << ", " << Offset << "\n";97 }98 void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override {99 OS << "\t.seh_save_fregp\td" << Reg << ", " << Offset << "\n";100 }101 void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override {102 OS << "\t.seh_save_fregp_x\td" << Reg << ", " << Offset << "\n";103 }104 void emitARM64WinCFISetFP() override { OS << "\t.seh_set_fp\n"; }105 void emitARM64WinCFIAddFP(unsigned Size) override {106 OS << "\t.seh_add_fp\t" << Size << "\n";107 }108 void emitARM64WinCFINop() override { OS << "\t.seh_nop\n"; }109 void emitARM64WinCFISaveNext() override { OS << "\t.seh_save_next\n"; }110 void emitARM64WinCFIPrologEnd() override { OS << "\t.seh_endprologue\n"; }111 void emitARM64WinCFIEpilogStart() override { OS << "\t.seh_startepilogue\n"; }112 void emitARM64WinCFIEpilogEnd() override { OS << "\t.seh_endepilogue\n"; }113 void emitARM64WinCFITrapFrame() override { OS << "\t.seh_trap_frame\n"; }114 void emitARM64WinCFIMachineFrame() override { OS << "\t.seh_pushframe\n"; }115 void emitARM64WinCFIContext() override { OS << "\t.seh_context\n"; }116 void emitARM64WinCFIECContext() override { OS << "\t.seh_ec_context\n"; }117 void emitARM64WinCFIClearUnwoundToCall() override {118 OS << "\t.seh_clear_unwound_to_call\n";119 }120 void emitARM64WinCFIPACSignLR() override {121 OS << "\t.seh_pac_sign_lr\n";122 }123 124 void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) override {125 OS << "\t.seh_save_any_reg\tx" << Reg << ", " << Offset << "\n";126 }127 void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset) override {128 OS << "\t.seh_save_any_reg_p\tx" << Reg << ", " << Offset << "\n";129 }130 void emitARM64WinCFISaveAnyRegD(unsigned Reg, int Offset) override {131 OS << "\t.seh_save_any_reg\td" << Reg << ", " << Offset << "\n";132 }133 void emitARM64WinCFISaveAnyRegDP(unsigned Reg, int Offset) override {134 OS << "\t.seh_save_any_reg_p\td" << Reg << ", " << Offset << "\n";135 }136 void emitARM64WinCFISaveAnyRegQ(unsigned Reg, int Offset) override {137 OS << "\t.seh_save_any_reg\tq" << Reg << ", " << Offset << "\n";138 }139 void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset) override {140 OS << "\t.seh_save_any_reg_p\tq" << Reg << ", " << Offset << "\n";141 }142 void emitARM64WinCFISaveAnyRegIX(unsigned Reg, int Offset) override {143 OS << "\t.seh_save_any_reg_x\tx" << Reg << ", " << Offset << "\n";144 }145 void emitARM64WinCFISaveAnyRegIPX(unsigned Reg, int Offset) override {146 OS << "\t.seh_save_any_reg_px\tx" << Reg << ", " << Offset << "\n";147 }148 void emitARM64WinCFISaveAnyRegDX(unsigned Reg, int Offset) override {149 OS << "\t.seh_save_any_reg_x\td" << Reg << ", " << Offset << "\n";150 }151 void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override {152 OS << "\t.seh_save_any_reg_px\td" << Reg << ", " << Offset << "\n";153 }154 void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override {155 OS << "\t.seh_save_any_reg_x\tq" << Reg << ", " << Offset << "\n";156 }157 void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override {158 OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";159 }160 void emitARM64WinCFIAllocZ(int Offset) override {161 OS << "\t.seh_allocz\t" << Offset << "\n";162 }163 void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) override {164 OS << "\t.seh_save_zreg\tz" << Reg << ", " << Offset << "\n";165 }166 void emitARM64WinCFISavePReg(unsigned Reg, int Offset) override {167 OS << "\t.seh_save_preg\tp" << Reg << ", " << Offset << "\n";168 }169 170 void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value,171 std::string String) override {172 173 // AArch64 build attributes for assembly attribute form:174 // .aeabi_attribute tag, value175 if (unsigned(-1) == Value && "" == String) {176 assert(0 && "Arguments error");177 return;178 }179 180 unsigned VendorID = AArch64BuildAttributes::getVendorID(VendorName);181 182 switch (VendorID) {183 case AArch64BuildAttributes::VENDOR_UNKNOWN:184 if (unsigned(-1) != Value) {185 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value;186 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");187 }188 if ("" != String) {189 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << String;190 AArch64TargetStreamer::emitAttribute(VendorName, Tag, unsigned(-1),191 String);192 }193 break;194 // Note: AEABI_FEATURE_AND_BITS takes only unsigned values195 case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS:196 switch (Tag) {197 default: // allow emitting any attribute by number198 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value;199 // Keep the data structure consistent with the case of ELF emission200 // (important for llvm-mc asm parsing)201 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");202 break;203 case AArch64BuildAttributes::TAG_FEATURE_BTI:204 case AArch64BuildAttributes::TAG_FEATURE_GCS:205 case AArch64BuildAttributes::TAG_FEATURE_PAC:206 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value << "\t// "207 << AArch64BuildAttributes::getFeatureAndBitsTagsStr(Tag);208 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");209 break;210 }211 break;212 // Note: AEABI_PAUTHABI takes only unsigned values213 case AArch64BuildAttributes::AEABI_PAUTHABI:214 switch (Tag) {215 default: // allow emitting any attribute by number216 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value;217 // Keep the data structure consistent with the case of ELF emission218 // (important for llvm-mc asm parsing)219 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");220 break;221 case AArch64BuildAttributes::TAG_PAUTH_PLATFORM:222 case AArch64BuildAttributes::TAG_PAUTH_SCHEMA:223 OS << "\t.aeabi_attribute" << "\t" << Tag << ", " << Value << "\t// "224 << AArch64BuildAttributes::getPauthABITagsStr(Tag);225 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");226 break;227 }228 break;229 }230 OS << "\n";231 }232 233 void emitAttributesSubsection(234 StringRef SubsectionName,235 AArch64BuildAttributes::SubsectionOptional Optional,236 AArch64BuildAttributes::SubsectionType ParameterType) override {237 // The AArch64 build attributes assembly subsection header format:238 // ".aeabi_subsection name, optional, parameter type"239 // optional: required (0) optional (1)240 // parameter type: uleb128 or ULEB128 (0) ntbs or NTBS (1)241 unsigned SubsectionID = AArch64BuildAttributes::getVendorID(SubsectionName);242 243 assert((0 == Optional || 1 == Optional) &&244 AArch64BuildAttributes::getSubsectionOptionalUnknownError().data());245 assert((0 == ParameterType || 1 == ParameterType) &&246 AArch64BuildAttributes::getSubsectionTypeUnknownError().data());247 248 std::string SubsectionTag = ".aeabi_subsection";249 StringRef OptionalStr = getOptionalStr(Optional);250 StringRef ParameterStr = getTypeStr(ParameterType);251 252 switch (SubsectionID) {253 case AArch64BuildAttributes::VENDOR_UNKNOWN: {254 // Private subsection255 break;256 }257 case AArch64BuildAttributes::AEABI_PAUTHABI: {258 assert(AArch64BuildAttributes::REQUIRED == Optional &&259 "subsection .aeabi-pauthabi should be marked as "260 "required and not as optional");261 assert(AArch64BuildAttributes::ULEB128 == ParameterType &&262 "subsection .aeabi-pauthabi should be "263 "marked as uleb128 and not as ntbs");264 break;265 }266 case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS: {267 assert(AArch64BuildAttributes::OPTIONAL == Optional &&268 "subsection .aeabi_feature_and_bits should be "269 "marked as optional and not as required");270 assert(AArch64BuildAttributes::ULEB128 == ParameterType &&271 "subsection .aeabi_feature_and_bits should "272 "be marked as uleb128 and not as ntbs");273 break;274 }275 }276 OS << "\t" << SubsectionTag << "\t" << SubsectionName << ", " << OptionalStr277 << ", " << ParameterStr;278 // Keep the data structure consistent with the case of ELF emission279 // (important for llvm-mc asm parsing)280 AArch64TargetStreamer::emitAttributesSubsection(SubsectionName, Optional,281 ParameterType);282 OS << "\n";283 }284 285public:286 AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);287};288 289AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,290 formatted_raw_ostream &OS)291 : AArch64TargetStreamer(S), OS(OS) {}292 293void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {294 OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n";295}296 297/// Extend the generic ELFStreamer class so that it can emit mapping symbols at298/// the appropriate points in the object files. These symbols are defined in the299/// AArch64 ELF ABI:300/// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf301///302/// In brief: $x or $d should be emitted at the start of each contiguous region303/// of A64 code or data in a section. In practice, this emission does not rely304/// on explicit assembler directives but on inherent properties of the305/// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an306/// instruction).307///308/// As a result this system is orthogonal to the DataRegion infrastructure used309/// by MachO. Beware!310class AArch64ELFStreamer : public MCELFStreamer {311public:312 friend AArch64TargetELFStreamer;313 AArch64ELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,314 std::unique_ptr<MCObjectWriter> OW,315 std::unique_ptr<MCCodeEmitter> Emitter)316 : MCELFStreamer(Context, std::move(TAB), std::move(OW),317 std::move(Emitter)),318 LastEMS(EMS_None) {319 auto *TO = getContext().getTargetOptions();320 ImplicitMapSyms = TO && TO->ImplicitMapSyms;321 }322 323 void changeSection(MCSection *Section, uint32_t Subsection = 0) override {324 // Save the mapping symbol state for potential reuse when revisiting the325 // section. When ImplicitMapSyms is true, the initial state is326 // EMS_A64 for text sections and EMS_Data for the others.327 LastMappingSymbols[getCurrentSection().first] = LastEMS;328 auto It = LastMappingSymbols.find(Section);329 if (It != LastMappingSymbols.end())330 LastEMS = It->second;331 else if (ImplicitMapSyms)332 LastEMS = Section->isText() ? EMS_A64 : EMS_Data;333 else334 LastEMS = EMS_None;335 336 MCELFStreamer::changeSection(Section, Subsection);337 338 // Section alignment of 4 to match GNU Assembler339 if (Section->isText())340 Section->ensureMinAlignment(Align(4));341 }342 343 // Reset state between object emissions344 void reset() override {345 MCELFStreamer::reset();346 LastMappingSymbols.clear();347 LastEMS = EMS_None;348 }349 350 /// This function is the one used to emit instruction data into the ELF351 /// streamer. We override it to add the appropriate mapping symbol if352 /// necessary.353 void emitInstruction(const MCInst &Inst,354 const MCSubtargetInfo &STI) override {355 emitA64MappingSymbol();356 MCELFStreamer::emitInstruction(Inst, STI);357 }358 359 /// Emit a 32-bit value as an instruction. This is only used for the .inst360 /// directive, EmitInstruction should be used in other cases.361 void emitInst(uint32_t Inst) {362 char Buffer[4];363 364 // We can't just use EmitIntValue here, as that will emit a data mapping365 // symbol, and swap the endianness on big-endian systems (instructions are366 // always little-endian).367 for (char &C : Buffer) {368 C = uint8_t(Inst);369 Inst >>= 8;370 }371 372 emitA64MappingSymbol();373 MCELFStreamer::emitBytes(StringRef(Buffer, 4));374 }375 376 /// This is one of the functions used to emit data into an ELF section, so the377 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)378 /// if necessary.379 void emitBytes(StringRef Data) override {380 emitDataMappingSymbol();381 MCELFStreamer::emitBytes(Data);382 }383 384 /// This is one of the functions used to emit data into an ELF section, so the385 /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)386 /// if necessary.387 void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {388 emitDataMappingSymbol();389 MCELFStreamer::emitValueImpl(Value, Size, Loc);390 }391 392 void emitFill(const MCExpr &NumBytes, uint64_t FillValue,393 SMLoc Loc) override {394 emitDataMappingSymbol();395 MCObjectStreamer::emitFill(NumBytes, FillValue, Loc);396 }397 398private:399 enum ElfMappingSymbol {400 EMS_None,401 EMS_A64,402 EMS_Data403 };404 405 void emitDataMappingSymbol() {406 if (LastEMS == EMS_Data)407 return;408 emitMappingSymbol("$d");409 LastEMS = EMS_Data;410 }411 412 void emitA64MappingSymbol() {413 if (LastEMS == EMS_A64)414 return;415 emitMappingSymbol("$x");416 LastEMS = EMS_A64;417 }418 419 MCSymbol *emitMappingSymbol(StringRef Name) {420 auto *Symbol =421 static_cast<MCSymbolELF *>(getContext().createLocalSymbol(Name));422 emitLabel(Symbol);423 return Symbol;424 }425 426 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;427 ElfMappingSymbol LastEMS;428 bool ImplicitMapSyms;429};430} // end anonymous namespace431 432AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {433 return static_cast<AArch64ELFStreamer &>(Streamer);434}435 436void AArch64TargetELFStreamer::emitAttributesSubsection(437 StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional,438 AArch64BuildAttributes::SubsectionType ParameterType) {439 AArch64TargetStreamer::emitAttributesSubsection(VendorName, IsOptional,440 ParameterType);441}442 443void AArch64TargetELFStreamer::emitAttribute(StringRef VendorName, unsigned Tag,444 unsigned Value,445 std::string String) {446 if (unsigned(-1) != Value)447 AArch64TargetStreamer::emitAttribute(VendorName, Tag, Value, "");448 if ("" != String)449 AArch64TargetStreamer::emitAttribute(VendorName, Tag, unsigned(-1), String);450}451 452void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {453 getStreamer().emitInst(Inst);454}455 456void AArch64TargetELFStreamer::emitDirectiveVariantPCS(MCSymbol *Symbol) {457 getStreamer().getAssembler().registerSymbol(*Symbol);458 static_cast<MCSymbolELF *>(Symbol)->setOther(ELF::STO_AARCH64_VARIANT_PCS);459}460 461void AArch64TargetELFStreamer::finish() {462 AArch64TargetStreamer::finish();463 AArch64ELFStreamer &S = getStreamer();464 MCContext &Ctx = S.getContext();465 auto &Asm = S.getAssembler();466 467 S.emitAttributesSection(AttributeSection, ".ARM.attributes",468 ELF::SHT_AARCH64_ATTRIBUTES, AttributeSubSections);469 470 // If ImplicitMapSyms is specified, ensure that text sections end with471 // the A64 state while non-text sections end with the data state. When472 // sections are combined by the linker, the subsequent section will start with473 // the right state. The ending mapping symbol is added right after the last474 // symbol relative to the section. When a dumb linker combines (.text.0; .word475 // 0) and (.text.1; .word 0), the ending $x of .text.0 precedes the $d of476 // .text.1, even if they have the same address.477 if (S.ImplicitMapSyms) {478 auto &Syms = Asm.getSymbols();479 const size_t NumSyms = Syms.size();480 DenseMap<MCSection *, std::pair<size_t, MCSymbol *>> EndMapSym;481 for (MCSection &Sec : Asm) {482 S.switchSection(&Sec);483 if (S.LastEMS == (Sec.isText() ? AArch64ELFStreamer::EMS_Data484 : AArch64ELFStreamer::EMS_A64))485 EndMapSym.insert(486 {&Sec, {NumSyms, S.emitMappingSymbol(Sec.isText() ? "$x" : "$d")}});487 }488 if (Syms.size() != NumSyms) {489 SmallVector<const MCSymbol *, 0> NewSyms;490 Syms.truncate(NumSyms);491 // Find the last symbol index for each candidate section.492 for (auto [I, Sym] : llvm::enumerate(Syms)) {493 if (!Sym->isInSection())494 continue;495 auto It = EndMapSym.find(&Sym->getSection());496 if (It != EndMapSym.end())497 It->second.first = I;498 }499 SmallVector<size_t, 0> Idx;500 for (auto [I, Sym] : llvm::enumerate(Syms)) {501 NewSyms.push_back(Sym);502 if (!Sym->isInSection())503 continue;504 auto It = EndMapSym.find(&Sym->getSection());505 // If `Sym` is the last symbol relative to the section, add the ending506 // mapping symbol after `Sym`.507 if (It != EndMapSym.end() && I == It->second.first) {508 NewSyms.push_back(It->second.second);509 Idx.push_back(I);510 }511 }512 Syms = std::move(NewSyms);513 // F.second holds the number of symbols added before the FILE symbol.514 // Take into account the inserted mapping symbols.515 for (auto &F : S.getWriter().getFileNames())516 F.second += llvm::lower_bound(Idx, F.second) - Idx.begin();517 }518 }519 520 // The mix of execute-only and non-execute-only at link time is521 // non-execute-only. To avoid the empty implicitly created .text522 // section from making the whole .text section non-execute-only, we523 // mark it execute-only if it is empty and there is at least one524 // execute-only section in the object.525 if (any_of(Asm, [](const MCSection &Sec) {526 return static_cast<const MCSectionELF &>(Sec).getFlags() &527 ELF::SHF_AARCH64_PURECODE;528 })) {529 auto *Text =530 static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection());531 bool Empty = true;532 for (auto &F : *Text) {533 if (F.getSize()) {534 Empty = false;535 break;536 }537 }538 if (Empty)539 Text->setFlags(Text->getFlags() | ELF::SHF_AARCH64_PURECODE);540 }541 542 MCSectionELF *MemtagSec = nullptr;543 for (const MCSymbol &Symbol : Asm.symbols()) {544 auto &Sym = static_cast<const MCSymbolELF &>(Symbol);545 if (Sym.isMemtag()) {546 MemtagSec = Ctx.getELFSection(".memtag.globals.static",547 ELF::SHT_AARCH64_MEMTAG_GLOBALS_STATIC, 0);548 break;549 }550 }551 if (!MemtagSec)552 return;553 554 // switchSection registers the section symbol and invalidates symbols(). We555 // need a separate symbols() loop.556 S.switchSection(MemtagSec);557 const auto *Zero = MCConstantExpr::create(0, Ctx);558 for (const MCSymbol &Symbol : Asm.symbols()) {559 auto &Sym = static_cast<const MCSymbolELF &>(Symbol);560 if (!Sym.isMemtag())561 continue;562 auto *SRE = MCSymbolRefExpr::create(&Sym, Ctx);563 S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE);564 }565}566 567MCTargetStreamer *568llvm::createAArch64AsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,569 MCInstPrinter *InstPrint) {570 return new AArch64TargetAsmStreamer(S, OS);571}572 573MCStreamer *574llvm::createAArch64ELFStreamer(const Triple &, MCContext &Context,575 std::unique_ptr<MCAsmBackend> &&TAB,576 std::unique_ptr<MCObjectWriter> &&OW,577 std::unique_ptr<MCCodeEmitter> &&Emitter) {578 return new AArch64ELFStreamer(Context, std::move(TAB), std::move(OW),579 std::move(Emitter));580}581