brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.3 KiB · 917dbdf Raw
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