|  | //===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file assembles .s files and emits ELF .o object files. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/MC/MCELFStreamer.h" | 
|  | #include "llvm/ADT/SmallString.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/BinaryFormat/ELF.h" | 
|  | #include "llvm/MC/MCAsmBackend.h" | 
|  | #include "llvm/MC/MCAsmInfo.h" | 
|  | #include "llvm/MC/MCAssembler.h" | 
|  | #include "llvm/MC/MCCodeEmitter.h" | 
|  | #include "llvm/MC/MCContext.h" | 
|  | #include "llvm/MC/MCExpr.h" | 
|  | #include "llvm/MC/MCFixup.h" | 
|  | #include "llvm/MC/MCFragment.h" | 
|  | #include "llvm/MC/MCObjectFileInfo.h" | 
|  | #include "llvm/MC/MCObjectWriter.h" | 
|  | #include "llvm/MC/MCSection.h" | 
|  | #include "llvm/MC/MCSectionELF.h" | 
|  | #include "llvm/MC/MCStreamer.h" | 
|  | #include "llvm/MC/MCSymbol.h" | 
|  | #include "llvm/MC/MCSymbolELF.h" | 
|  | #include "llvm/Support/Casting.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include "llvm/Support/TargetRegistry.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include <cassert> | 
|  | #include <cstdint> | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | MCELFStreamer::MCELFStreamer(MCContext &Context, | 
|  | std::unique_ptr<MCAsmBackend> TAB, | 
|  | std::unique_ptr<MCObjectWriter> OW, | 
|  | std::unique_ptr<MCCodeEmitter> Emitter) | 
|  | : MCObjectStreamer(Context, std::move(TAB), std::move(OW), | 
|  | std::move(Emitter)) {} | 
|  |  | 
|  | bool MCELFStreamer::isBundleLocked() const { | 
|  | return getCurrentSectionOnly()->isBundleLocked(); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::mergeFragment(MCDataFragment *DF, | 
|  | MCDataFragment *EF) { | 
|  | MCAssembler &Assembler = getAssembler(); | 
|  |  | 
|  | if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { | 
|  | uint64_t FSize = EF->getContents().size(); | 
|  |  | 
|  | if (FSize > Assembler.getBundleAlignSize()) | 
|  | report_fatal_error("Fragment can't be larger than a bundle size"); | 
|  |  | 
|  | uint64_t RequiredBundlePadding = computeBundlePadding( | 
|  | Assembler, EF, DF->getContents().size(), FSize); | 
|  |  | 
|  | if (RequiredBundlePadding > UINT8_MAX) | 
|  | report_fatal_error("Padding cannot exceed 255 bytes"); | 
|  |  | 
|  | if (RequiredBundlePadding > 0) { | 
|  | SmallString<256> Code; | 
|  | raw_svector_ostream VecOS(Code); | 
|  | EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); | 
|  | Assembler.writeFragmentPadding(VecOS, *EF, FSize); | 
|  |  | 
|  | DF->getContents().append(Code.begin(), Code.end()); | 
|  | } | 
|  | } | 
|  |  | 
|  | flushPendingLabels(DF, DF->getContents().size()); | 
|  |  | 
|  | for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { | 
|  | EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() + | 
|  | DF->getContents().size()); | 
|  | DF->getFixups().push_back(EF->getFixups()[i]); | 
|  | } | 
|  | if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) | 
|  | DF->setHasInstructions(*EF->getSubtargetInfo()); | 
|  | DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::InitSections(bool NoExecStack) { | 
|  | MCContext &Ctx = getContext(); | 
|  | SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); | 
|  | EmitCodeAlignment(4); | 
|  |  | 
|  | if (NoExecStack) | 
|  | SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { | 
|  | auto *Symbol = cast<MCSymbolELF>(S); | 
|  | MCObjectStreamer::EmitLabel(Symbol, Loc); | 
|  |  | 
|  | const MCSectionELF &Section = | 
|  | static_cast<const MCSectionELF &>(*getCurrentSectionOnly()); | 
|  | if (Section.getFlags() & ELF::SHF_TLS) | 
|  | Symbol->setType(ELF::STT_TLS); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) { | 
|  | auto *Symbol = cast<MCSymbolELF>(S); | 
|  | MCObjectStreamer::EmitLabel(Symbol, Loc, F); | 
|  |  | 
|  | const MCSectionELF &Section = | 
|  | static_cast<const MCSectionELF &>(*getCurrentSectionOnly()); | 
|  | if (Section.getFlags() & ELF::SHF_TLS) | 
|  | Symbol->setType(ELF::STT_TLS); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { | 
|  | // Let the target do whatever target specific stuff it needs to do. | 
|  | getAssembler().getBackend().handleAssemblerFlag(Flag); | 
|  | // Do any generic stuff we need to do. | 
|  | switch (Flag) { | 
|  | case MCAF_SyntaxUnified: return; // no-op here. | 
|  | case MCAF_Code16: return; // Change parsing mode; no-op here. | 
|  | case MCAF_Code32: return; // Change parsing mode; no-op here. | 
|  | case MCAF_Code64: return; // Change parsing mode; no-op here. | 
|  | case MCAF_SubsectionsViaSymbols: | 
|  | getAssembler().setSubsectionsViaSymbols(true); | 
|  | return; | 
|  | } | 
|  |  | 
|  | llvm_unreachable("invalid assembler flag!"); | 
|  | } | 
|  |  | 
|  | // If bundle alignment is used and there are any instructions in the section, it | 
|  | // needs to be aligned to at least the bundle size. | 
|  | static void setSectionAlignmentForBundling(const MCAssembler &Assembler, | 
|  | MCSection *Section) { | 
|  | if (Section && Assembler.isBundlingEnabled() && Section->hasInstructions() && | 
|  | Section->getAlignment() < Assembler.getBundleAlignSize()) | 
|  | Section->setAlignment(Assembler.getBundleAlignSize()); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::ChangeSection(MCSection *Section, | 
|  | const MCExpr *Subsection) { | 
|  | MCSection *CurSection = getCurrentSectionOnly(); | 
|  | if (CurSection && isBundleLocked()) | 
|  | report_fatal_error("Unterminated .bundle_lock when changing a section"); | 
|  |  | 
|  | MCAssembler &Asm = getAssembler(); | 
|  | // Ensure the previous section gets aligned if necessary. | 
|  | setSectionAlignmentForBundling(Asm, CurSection); | 
|  | auto *SectionELF = static_cast<const MCSectionELF *>(Section); | 
|  | const MCSymbol *Grp = SectionELF->getGroup(); | 
|  | if (Grp) | 
|  | Asm.registerSymbol(*Grp); | 
|  |  | 
|  | changeSectionImpl(Section, Subsection); | 
|  | Asm.registerSymbol(*Section->getBeginSymbol()); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  | const MCExpr *Value = MCSymbolRefExpr::create( | 
|  | Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); | 
|  | Alias->setVariableValue(Value); | 
|  | } | 
|  |  | 
|  | // When GNU as encounters more than one .type declaration for an object it seems | 
|  | // to use a mechanism similar to the one below to decide which type is actually | 
|  | // used in the object file.  The greater of T1 and T2 is selected based on the | 
|  | // following ordering: | 
|  | //  STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else | 
|  | // If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user | 
|  | // provided type). | 
|  | static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { | 
|  | for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC, | 
|  | ELF::STT_GNU_IFUNC, ELF::STT_TLS}) { | 
|  | if (T1 == Type) | 
|  | return T2; | 
|  | if (T2 == Type) | 
|  | return T1; | 
|  | } | 
|  |  | 
|  | return T2; | 
|  | } | 
|  |  | 
|  | bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { | 
|  | auto *Symbol = cast<MCSymbolELF>(S); | 
|  |  | 
|  | // Adding a symbol attribute always introduces the symbol, note that an | 
|  | // important side effect of calling registerSymbol here is to register | 
|  | // the symbol with the assembler. | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  |  | 
|  | // The implementation of symbol attributes is designed to match 'as', but it | 
|  | // leaves much to desired. It doesn't really make sense to arbitrarily add and | 
|  | // remove flags, but 'as' allows this (in particular, see .desc). | 
|  | // | 
|  | // In the future it might be worth trying to make these operations more well | 
|  | // defined. | 
|  | switch (Attribute) { | 
|  | case MCSA_LazyReference: | 
|  | case MCSA_Reference: | 
|  | case MCSA_SymbolResolver: | 
|  | case MCSA_PrivateExtern: | 
|  | case MCSA_WeakDefinition: | 
|  | case MCSA_WeakDefAutoPrivate: | 
|  | case MCSA_Invalid: | 
|  | case MCSA_IndirectSymbol: | 
|  | return false; | 
|  |  | 
|  | case MCSA_NoDeadStrip: | 
|  | // Ignore for now. | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeGnuUniqueObject: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); | 
|  | Symbol->setBinding(ELF::STB_GNU_UNIQUE); | 
|  | Symbol->setExternal(true); | 
|  | break; | 
|  |  | 
|  | case MCSA_Global: | 
|  | Symbol->setBinding(ELF::STB_GLOBAL); | 
|  | Symbol->setExternal(true); | 
|  | break; | 
|  |  | 
|  | case MCSA_WeakReference: | 
|  | case MCSA_Weak: | 
|  | Symbol->setBinding(ELF::STB_WEAK); | 
|  | Symbol->setExternal(true); | 
|  | break; | 
|  |  | 
|  | case MCSA_Local: | 
|  | Symbol->setBinding(ELF::STB_LOCAL); | 
|  | Symbol->setExternal(false); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeFunction: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC)); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeIndFunction: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC)); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeObject: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeTLS: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS)); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeCommon: | 
|  | // TODO: Emit these as a common symbol. | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); | 
|  | break; | 
|  |  | 
|  | case MCSA_ELF_TypeNoType: | 
|  | Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE)); | 
|  | break; | 
|  |  | 
|  | case MCSA_Protected: | 
|  | Symbol->setVisibility(ELF::STV_PROTECTED); | 
|  | break; | 
|  |  | 
|  | case MCSA_Hidden: | 
|  | Symbol->setVisibility(ELF::STV_HIDDEN); | 
|  | break; | 
|  |  | 
|  | case MCSA_Internal: | 
|  | Symbol->setVisibility(ELF::STV_INTERNAL); | 
|  | break; | 
|  |  | 
|  | case MCSA_AltEntry: | 
|  | llvm_unreachable("ELF doesn't support the .alt_entry attribute"); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, | 
|  | unsigned ByteAlignment) { | 
|  | auto *Symbol = cast<MCSymbolELF>(S); | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  |  | 
|  | if (!Symbol->isBindingSet()) { | 
|  | Symbol->setBinding(ELF::STB_GLOBAL); | 
|  | Symbol->setExternal(true); | 
|  | } | 
|  |  | 
|  | Symbol->setType(ELF::STT_OBJECT); | 
|  |  | 
|  | if (Symbol->getBinding() == ELF::STB_LOCAL) { | 
|  | MCSection &Section = *getAssembler().getContext().getELFSection( | 
|  | ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); | 
|  | MCSectionSubPair P = getCurrentSection(); | 
|  | SwitchSection(&Section); | 
|  |  | 
|  | EmitValueToAlignment(ByteAlignment, 0, 1, 0); | 
|  | EmitLabel(Symbol); | 
|  | EmitZeros(Size); | 
|  |  | 
|  | // Update the maximum alignment of the section if necessary. | 
|  | if (ByteAlignment > Section.getAlignment()) | 
|  | Section.setAlignment(ByteAlignment); | 
|  |  | 
|  | SwitchSection(P.first, P.second); | 
|  | } else { | 
|  | if(Symbol->declareCommon(Size, ByteAlignment)) | 
|  | report_fatal_error("Symbol: " + Symbol->getName() + | 
|  | " redeclared as different type"); | 
|  | } | 
|  |  | 
|  | cast<MCSymbolELF>(Symbol) | 
|  | ->setSize(MCConstantExpr::create(Size, getContext())); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { | 
|  | cast<MCSymbolELF>(Symbol)->setSize(Value); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::emitELFSymverDirective(StringRef AliasName, | 
|  | const MCSymbol *Aliasee) { | 
|  | getAssembler().Symvers.push_back({AliasName, Aliasee}); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, | 
|  | unsigned ByteAlignment) { | 
|  | auto *Symbol = cast<MCSymbolELF>(S); | 
|  | // FIXME: Should this be caught and done earlier? | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  | Symbol->setBinding(ELF::STB_LOCAL); | 
|  | Symbol->setExternal(false); | 
|  | EmitCommonSymbol(Symbol, Size, ByteAlignment); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, | 
|  | SMLoc Loc) { | 
|  | if (isBundleLocked()) | 
|  | report_fatal_error("Emitting values inside a locked bundle is forbidden"); | 
|  | fixSymbolsInTLSFixups(Value); | 
|  | MCObjectStreamer::EmitValueImpl(Value, Size, Loc); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, | 
|  | int64_t Value, | 
|  | unsigned ValueSize, | 
|  | unsigned MaxBytesToEmit) { | 
|  | if (isBundleLocked()) | 
|  | report_fatal_error("Emitting values inside a locked bundle is forbidden"); | 
|  | MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, | 
|  | ValueSize, MaxBytesToEmit); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, | 
|  | const MCSymbolRefExpr *To, | 
|  | uint64_t Count) { | 
|  | getAssembler().CGProfile.push_back({From, To, Count}); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitIdent(StringRef IdentString) { | 
|  | MCSection *Comment = getAssembler().getContext().getELFSection( | 
|  | ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); | 
|  | PushSection(); | 
|  | SwitchSection(Comment); | 
|  | if (!SeenIdent) { | 
|  | EmitIntValue(0, 1); | 
|  | SeenIdent = true; | 
|  | } | 
|  | EmitBytes(IdentString); | 
|  | EmitIntValue(0, 1); | 
|  | PopSection(); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { | 
|  | switch (expr->getKind()) { | 
|  | case MCExpr::Target: | 
|  | cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler()); | 
|  | break; | 
|  | case MCExpr::Constant: | 
|  | break; | 
|  |  | 
|  | case MCExpr::Binary: { | 
|  | const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); | 
|  | fixSymbolsInTLSFixups(be->getLHS()); | 
|  | fixSymbolsInTLSFixups(be->getRHS()); | 
|  | break; | 
|  | } | 
|  |  | 
|  | case MCExpr::SymbolRef: { | 
|  | const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); | 
|  | switch (symRef.getKind()) { | 
|  | default: | 
|  | return; | 
|  | case MCSymbolRefExpr::VK_GOTTPOFF: | 
|  | case MCSymbolRefExpr::VK_INDNTPOFF: | 
|  | case MCSymbolRefExpr::VK_NTPOFF: | 
|  | case MCSymbolRefExpr::VK_GOTNTPOFF: | 
|  | case MCSymbolRefExpr::VK_TLSGD: | 
|  | case MCSymbolRefExpr::VK_TLSLD: | 
|  | case MCSymbolRefExpr::VK_TLSLDM: | 
|  | case MCSymbolRefExpr::VK_TPOFF: | 
|  | case MCSymbolRefExpr::VK_TPREL: | 
|  | case MCSymbolRefExpr::VK_DTPOFF: | 
|  | case MCSymbolRefExpr::VK_DTPREL: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPMOD: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGH: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: | 
|  | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: | 
|  | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TPREL: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_TLS: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_TLSGD: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: | 
|  | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: | 
|  | case MCSymbolRefExpr::VK_PPC_TLSLD: | 
|  | break; | 
|  | } | 
|  | getAssembler().registerSymbol(symRef.getSymbol()); | 
|  | cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS); | 
|  | break; | 
|  | } | 
|  |  | 
|  | case MCExpr::Unary: | 
|  | fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) { | 
|  | const MCSymbol *S = &SRE->getSymbol(); | 
|  | if (S->isTemporary()) { | 
|  | if (!S->isInSection()) { | 
|  | getContext().reportError( | 
|  | SRE->getLoc(), Twine("Reference to undefined temporary symbol ") + | 
|  | "`" + S->getName() + "`"); | 
|  | return; | 
|  | } | 
|  | S = S->getSection().getBeginSymbol(); | 
|  | S->setUsedInReloc(); | 
|  | SRE = | 
|  | MCSymbolRefExpr::create(S, SRE->getKind(), getContext(), SRE->getLoc()); | 
|  | return; | 
|  | } | 
|  | // Not a temporary, referece it as a weak undefined. | 
|  | bool Created; | 
|  | getAssembler().registerSymbol(*S, &Created); | 
|  | if (Created) { | 
|  | cast<MCSymbolELF>(S)->setBinding(ELF::STB_WEAK); | 
|  | cast<MCSymbolELF>(S)->setExternal(true); | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::finalizeCGProfile() { | 
|  | for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) { | 
|  | finalizeCGProfileEntry(E.From); | 
|  | finalizeCGProfileEntry(E.To); | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, | 
|  | const MCSubtargetInfo &STI) { | 
|  | this->MCObjectStreamer::EmitInstToFragment(Inst, STI); | 
|  | MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); | 
|  |  | 
|  | for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) | 
|  | fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); | 
|  | } | 
|  |  | 
|  | // A fragment can only have one Subtarget, and when bundling is enabled we | 
|  | // sometimes need to use the same fragment. We give an error if there | 
|  | // are conflicting Subtargets. | 
|  | static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI, | 
|  | const MCSubtargetInfo *NewSTI) { | 
|  | if (OldSTI && NewSTI && OldSTI != NewSTI) | 
|  | report_fatal_error("A Bundle can only have one Subtarget."); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitInstToData(const MCInst &Inst, | 
|  | const MCSubtargetInfo &STI) { | 
|  | MCAssembler &Assembler = getAssembler(); | 
|  | SmallVector<MCFixup, 4> Fixups; | 
|  | SmallString<256> Code; | 
|  | raw_svector_ostream VecOS(Code); | 
|  | Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); | 
|  |  | 
|  | for (unsigned i = 0, e = Fixups.size(); i != e; ++i) | 
|  | fixSymbolsInTLSFixups(Fixups[i].getValue()); | 
|  |  | 
|  | // There are several possibilities here: | 
|  | // | 
|  | // If bundling is disabled, append the encoded instruction to the current data | 
|  | // fragment (or create a new such fragment if the current fragment is not a | 
|  | // data fragment, or the Subtarget has changed). | 
|  | // | 
|  | // If bundling is enabled: | 
|  | // - If we're not in a bundle-locked group, emit the instruction into a | 
|  | //   fragment of its own. If there are no fixups registered for the | 
|  | //   instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a | 
|  | //   MCDataFragment. | 
|  | // - If we're in a bundle-locked group, append the instruction to the current | 
|  | //   data fragment because we want all the instructions in a group to get into | 
|  | //   the same fragment. Be careful not to do that for the first instruction in | 
|  | //   the group, though. | 
|  | MCDataFragment *DF; | 
|  |  | 
|  | if (Assembler.isBundlingEnabled()) { | 
|  | MCSection &Sec = *getCurrentSectionOnly(); | 
|  | if (Assembler.getRelaxAll() && isBundleLocked()) { | 
|  | // If the -mc-relax-all flag is used and we are bundle-locked, we re-use | 
|  | // the current bundle group. | 
|  | DF = BundleGroups.back(); | 
|  | CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); | 
|  | } | 
|  | else if (Assembler.getRelaxAll() && !isBundleLocked()) | 
|  | // When not in a bundle-locked group and the -mc-relax-all flag is used, | 
|  | // we create a new temporary fragment which will be later merged into | 
|  | // the current fragment. | 
|  | DF = new MCDataFragment(); | 
|  | else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) { | 
|  | // If we are bundle-locked, we re-use the current fragment. | 
|  | // The bundle-locking directive ensures this is a new data fragment. | 
|  | DF = cast<MCDataFragment>(getCurrentFragment()); | 
|  | CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); | 
|  | } | 
|  | else if (!isBundleLocked() && Fixups.size() == 0) { | 
|  | // Optimize memory usage by emitting the instruction to a | 
|  | // MCCompactEncodedInstFragment when not in a bundle-locked group and | 
|  | // there are no fixups registered. | 
|  | MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); | 
|  | insert(CEIF); | 
|  | CEIF->getContents().append(Code.begin(), Code.end()); | 
|  | CEIF->setHasInstructions(STI); | 
|  | return; | 
|  | } else { | 
|  | DF = new MCDataFragment(); | 
|  | insert(DF); | 
|  | } | 
|  | if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) { | 
|  | // If this fragment is for a group marked "align_to_end", set a flag | 
|  | // in the fragment. This can happen after the fragment has already been | 
|  | // created if there are nested bundle_align groups and an inner one | 
|  | // is the one marked align_to_end. | 
|  | DF->setAlignToBundleEnd(true); | 
|  | } | 
|  |  | 
|  | // We're now emitting an instruction in a bundle group, so this flag has | 
|  | // to be turned off. | 
|  | Sec.setBundleGroupBeforeFirstInst(false); | 
|  | } else { | 
|  | DF = getOrCreateDataFragment(&STI); | 
|  | } | 
|  |  | 
|  | // Add the fixups and data. | 
|  | for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { | 
|  | Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); | 
|  | DF->getFixups().push_back(Fixups[i]); | 
|  | } | 
|  | DF->setHasInstructions(STI); | 
|  | DF->getContents().append(Code.begin(), Code.end()); | 
|  |  | 
|  | if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { | 
|  | if (!isBundleLocked()) { | 
|  | mergeFragment(getOrCreateDataFragment(&STI), DF); | 
|  | delete DF; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { | 
|  | assert(AlignPow2 <= 30 && "Invalid bundle alignment"); | 
|  | MCAssembler &Assembler = getAssembler(); | 
|  | if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || | 
|  | Assembler.getBundleAlignSize() == 1U << AlignPow2)) | 
|  | Assembler.setBundleAlignSize(1U << AlignPow2); | 
|  | else | 
|  | report_fatal_error(".bundle_align_mode cannot be changed once set"); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { | 
|  | MCSection &Sec = *getCurrentSectionOnly(); | 
|  |  | 
|  | // Sanity checks | 
|  | // | 
|  | if (!getAssembler().isBundlingEnabled()) | 
|  | report_fatal_error(".bundle_lock forbidden when bundling is disabled"); | 
|  |  | 
|  | if (!isBundleLocked()) | 
|  | Sec.setBundleGroupBeforeFirstInst(true); | 
|  |  | 
|  | if (getAssembler().getRelaxAll() && !isBundleLocked()) { | 
|  | // TODO: drop the lock state and set directly in the fragment | 
|  | MCDataFragment *DF = new MCDataFragment(); | 
|  | BundleGroups.push_back(DF); | 
|  | } | 
|  |  | 
|  | Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd | 
|  | : MCSection::BundleLocked); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitBundleUnlock() { | 
|  | MCSection &Sec = *getCurrentSectionOnly(); | 
|  |  | 
|  | // Sanity checks | 
|  | if (!getAssembler().isBundlingEnabled()) | 
|  | report_fatal_error(".bundle_unlock forbidden when bundling is disabled"); | 
|  | else if (!isBundleLocked()) | 
|  | report_fatal_error(".bundle_unlock without matching lock"); | 
|  | else if (Sec.isBundleGroupBeforeFirstInst()) | 
|  | report_fatal_error("Empty bundle-locked group is forbidden"); | 
|  |  | 
|  | // When the -mc-relax-all flag is used, we emit instructions to fragments | 
|  | // stored on a stack. When the bundle unlock is emitted, we pop a fragment | 
|  | // from the stack a merge it to the one below. | 
|  | if (getAssembler().getRelaxAll()) { | 
|  | assert(!BundleGroups.empty() && "There are no bundle groups"); | 
|  | MCDataFragment *DF = BundleGroups.back(); | 
|  |  | 
|  | // FIXME: Use BundleGroups to track the lock state instead. | 
|  | Sec.setBundleLockState(MCSection::NotBundleLocked); | 
|  |  | 
|  | // FIXME: Use more separate fragments for nested groups. | 
|  | if (!isBundleLocked()) { | 
|  | mergeFragment(getOrCreateDataFragment(DF->getSubtargetInfo()), DF); | 
|  | BundleGroups.pop_back(); | 
|  | delete DF; | 
|  | } | 
|  |  | 
|  | if (Sec.getBundleLockState() != MCSection::BundleLockedAlignToEnd) | 
|  | getOrCreateDataFragment()->setAlignToBundleEnd(false); | 
|  | } else | 
|  | Sec.setBundleLockState(MCSection::NotBundleLocked); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::FinishImpl() { | 
|  | // Ensure the last section gets aligned if necessary. | 
|  | MCSection *CurSection = getCurrentSectionOnly(); | 
|  | setSectionAlignmentForBundling(getAssembler(), CurSection); | 
|  |  | 
|  | finalizeCGProfile(); | 
|  | EmitFrames(nullptr); | 
|  |  | 
|  | this->MCObjectStreamer::FinishImpl(); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { | 
|  | llvm_unreachable("Generic ELF doesn't support this directive"); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { | 
|  | llvm_unreachable("ELF doesn't support this directive"); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, | 
|  | uint64_t Size, unsigned ByteAlignment, | 
|  | SMLoc Loc) { | 
|  | llvm_unreachable("ELF doesn't support this directive"); | 
|  | } | 
|  |  | 
|  | void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, | 
|  | uint64_t Size, unsigned ByteAlignment) { | 
|  | llvm_unreachable("ELF doesn't support this directive"); | 
|  | } | 
|  |  | 
|  | MCStreamer *llvm::createELFStreamer(MCContext &Context, | 
|  | std::unique_ptr<MCAsmBackend> &&MAB, | 
|  | std::unique_ptr<MCObjectWriter> &&OW, | 
|  | std::unique_ptr<MCCodeEmitter> &&CE, | 
|  | bool RelaxAll) { | 
|  | MCELFStreamer *S = | 
|  | new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); | 
|  | if (RelaxAll) | 
|  | S->getAssembler().setRelaxAll(true); | 
|  | return S; | 
|  | } |