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