X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCMachOStreamer.cpp;h=6f36001037835f1209463424ed8526e0a55f6b81;hb=3f45c27d19f4315437d493ed3c9429b57e2cc59c;hp=9f813fdc49e5bb13db3947dff3c3fc7bbe472466;hpb=0f5fa6955199cc7e0964524d73c8a9820d8f78c1;p=oota-llvm.git diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 9f813fdc49e..03868b00fb8 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===// +//===-- MCMachOStreamer.cpp - MachO Streamer ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,205 +8,290 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" - +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbolMachO.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; namespace { -class MCMachOStreamer : public MCStreamer { - /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest - /// 16 bits of the implementation defined flags. - enum SymbolFlags { // See . - SF_DescFlagsMask = 0xFFFF, - - // Reference type flags. - SF_ReferenceTypeMask = 0x0007, - SF_ReferenceTypeUndefinedNonLazy = 0x0000, - SF_ReferenceTypeUndefinedLazy = 0x0001, - SF_ReferenceTypeDefined = 0x0002, - SF_ReferenceTypePrivateDefined = 0x0003, - SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, - SF_ReferenceTypePrivateUndefinedLazy = 0x0005, - - // Other 'desc' flags. - SF_NoDeadStrip = 0x0020, - SF_WeakReference = 0x0040, - SF_WeakDefinition = 0x0080 - }; - +class MCMachOStreamer : public MCObjectStreamer { private: - MCAssembler Assembler; - - MCCodeEmitter *Emitter; + /// LabelSections - true if each section change should emit a linker local + /// label for use in relocations for assembler local references. Obviates the + /// need for local relocations. False by default. + bool LabelSections; - MCSectionData *CurSectionData; + bool DWARFMustBeAtTheEnd; + bool CreatedADWARFSection; - DenseMap SectionMap; - - DenseMap SymbolMap; - -private: - MCFragment *getCurrentFragment() const { - assert(CurSectionData && "No current section!"); - - if (!CurSectionData->empty()) - return &CurSectionData->getFragmentList().back(); - - return 0; - } + /// HasSectionLabel - map of which sections have already had a non-local + /// label emitted to them. Used so we don't emit extraneous linker local + /// labels in the middle of the section. + DenseMap HasSectionLabel; - MCSectionData &getSectionData(const MCSection &Section) { - MCSectionData *&Entry = SectionMap[&Section]; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; - if (!Entry) - Entry = new MCSectionData(Section, &Assembler); - - return *Entry; - } - - MCSymbolData &getSymbolData(MCSymbol &Symbol) { - MCSymbolData *&Entry = SymbolMap[&Symbol]; - - if (!Entry) - Entry = new MCSymbolData(Symbol, 0, 0, &Assembler); - - return *Entry; - } + void EmitDataRegion(DataRegionData::KindTy Kind); + void EmitDataRegionEnd(); public: - MCMachOStreamer(MCContext &Context, raw_ostream &_OS, MCCodeEmitter *_Emitter) - : MCStreamer(Context), Assembler(_OS), Emitter(_Emitter), - CurSectionData(0) {} - ~MCMachOStreamer() {} - - const MCValue &AddValueSymbols(const MCValue &Value) { - if (Value.getSymA()) - getSymbolData(*const_cast(Value.getSymA())); - if (Value.getSymB()) - getSymbolData(*const_cast(Value.getSymB())); - return Value; + MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool DWARFMustBeAtTheEnd, bool label) + : MCObjectStreamer(Context, MAB, OS, Emitter), LabelSections(label), + DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd), CreatedADWARFSection(false) {} + + /// state management + void reset() override { + HasSectionLabel.clear(); + MCObjectStreamer::reset(); } /// @name MCStreamer Interface /// @{ - virtual void SwitchSection(const MCSection *Section); - - virtual void EmitLabel(MCSymbol *Symbol); - - virtual void EmitAssemblerFlag(AssemblerFlag Flag); - - virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value, - bool MakeAbsolute = false); - - virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); + void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitLinkerOptions(ArrayRef Options) override; + void EmitDataRegion(MCDataRegionType Kind) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) override; + void EmitThumbFunc(MCSymbol *Func) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void BeginCOFFSymbolDef(const MCSymbol *Symbol) override { + llvm_unreachable("macho doesn't support this directive"); + } + void EmitCOFFSymbolStorageClass(int StorageClass) override { + llvm_unreachable("macho doesn't support this directive"); + } + void EmitCOFFSymbolType(int Type) override { + llvm_unreachable("macho doesn't support this directive"); + } + void EndCOFFSymbolDef() override { + llvm_unreachable("macho doesn't support this directive"); + } + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; + + void EmitFileDirective(StringRef Filename) override { + // FIXME: Just ignore the .file; it isn't important enough to fail the + // entire assembly. + + // report_fatal_error("unsupported directive: '.file'"); + } - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + void EmitIdent(StringRef IdentString) override { + llvm_unreachable("macho doesn't support this directive"); + } - virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value); + void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override { + getAssembler().getLOHContainer().addDirective(Kind, Args); + } - virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, - unsigned Pow2Alignment); + void FinishImpl() override; +}; - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - unsigned Size = 0, unsigned Pow2Alignment = 0); +} // end anonymous namespace. - virtual void EmitBytes(const StringRef &Data); +static bool canGoAfterDWARF(const MCSectionMachO &MSec) { + // These sections are created by the assembler itself after the end of + // the .s file. + StringRef SegName = MSec.getSegmentName(); + StringRef SecName = MSec.getSectionName(); - virtual void EmitValue(const MCValue &Value, unsigned Size); + if (SegName == "__LD" && SecName == "__compact_unwind") + return true; - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0); + if (SegName == "__IMPORT") { + if (SecName == "__jump_table") + return true; - virtual void EmitValueToOffset(const MCValue &Offset, - unsigned char Value = 0); + if (SecName == "__pointers") + return true; + } - virtual void EmitInstruction(const MCInst &Inst); + if (SegName == "__TEXT" && SecName == "__eh_frame") + return true; - virtual void Finish(); + if (SegName == "__DATA" && SecName == "__nl_symbol_ptr") + return true; - /// @} -}; - -} // end anonymous namespace. + return false; +} -void MCMachOStreamer::SwitchSection(const MCSection *Section) { - assert(Section && "Cannot switch to a null section!"); - - // If already in this section, then this is a noop. - if (Section == CurSection) return; +void MCMachOStreamer::ChangeSection(MCSection *Section, + const MCExpr *Subsection) { + // Change the section normally. + bool Created = MCObjectStreamer::changeSectionImpl(Section, Subsection); + const MCSectionMachO &MSec = *cast(Section); + StringRef SegName = MSec.getSegmentName(); + if (SegName == "__DWARF") + CreatedADWARFSection = true; + else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec)) + assert(!CreatedADWARFSection && "Creating regular section after DWARF"); + + // Output a linker-local symbol so we don't need section-relative local + // relocations. The linker hates us when we do that. + if (LabelSections && !HasSectionLabel[Section] && + !Section->getBeginSymbol()) { + MCSymbol *Label = getContext().createLinkerPrivateTempSymbol(); + Section->setBeginSymbol(Label); + HasSectionLabel[Section] = true; + } +} - CurSection = Section; - CurSectionData = &getSectionData(*Section); +void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol) { + getAssembler().registerSymbol(*Symbol); + if (Symbol->isExternal()) + EmitSymbolAttribute(EHSymbol, MCSA_Global); + if (cast(Symbol)->isWeakDefinition()) + EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); + if (Symbol->isPrivateExtern()) + EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); } void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - // FIXME: We should also use offsets into Fill fragments. - MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); - if (!F) - F = new MCDataFragment(CurSectionData); + // We have to create a new fragment if this is an atom defining symbol, + // fragments cannot span atoms. + if (getAssembler().isSymbolLinkerVisible(*Symbol)) + insert(new MCDataFragment()); - MCSymbolData &SD = getSymbolData(*Symbol); - assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); - SD.setFragment(F); - SD.setOffset(F->getContents().size()); + MCObjectStreamer::EmitLabel(Symbol); + + // This causes the reference type flag to be cleared. Darwin 'as' was "trying" + // to clear the weak reference and weak definition bits too, but the + // implementation was buggy. For now we just try to match 'as', for + // diffability. + // + // FIXME: Cleanup this code, these bits should be emitted based on semantic + // properties, not on the order of definition, etc. + cast(Symbol)->clearReferenceType(); +} + +void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { + if (!getAssembler().getBackend().hasDataInCodeSupport()) + return; + // Create a temporary label to mark the start of the data region. + MCSymbol *Start = getContext().createTempSymbol(); + EmitLabel(Start); + // Record the region for the object writer to use. + DataRegionData Data = { Kind, Start, nullptr }; + std::vector &Regions = getAssembler().getDataRegions(); + Regions.push_back(Data); +} - // This causes the reference type and weak reference flags to be cleared. - SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask)); - - Symbol->setSection(*CurSection); +void MCMachOStreamer::EmitDataRegionEnd() { + if (!getAssembler().getBackend().hasDataInCodeSupport()) + return; + std::vector &Regions = getAssembler().getDataRegions(); + assert(!Regions.empty() && "Mismatched .end_data_region!"); + DataRegionData &Data = Regions.back(); + assert(!Data.End && "Mismatched .end_data_region!"); + // Create a temporary label to mark the end of the data region. + Data.End = getContext().createTempSymbol(); + EmitLabel(Data.End); } -void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { +void MCMachOStreamer::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) { - default: - llvm_unreachable("FIXME: Not yet implemented!"); + 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; + } +} - case SubsectionsViaSymbols: - Assembler.setSubsectionsViaSymbols(true); - break; +void MCMachOStreamer::EmitLinkerOptions(ArrayRef Options) { + getAssembler().getLinkerOptions().push_back(Options); +} + +void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { + switch (Kind) { + case MCDR_DataRegion: + EmitDataRegion(DataRegionData::Data); + return; + case MCDR_DataRegionJT8: + EmitDataRegion(DataRegionData::JumpTable8); + return; + case MCDR_DataRegionJT16: + EmitDataRegion(DataRegionData::JumpTable16); + return; + case MCDR_DataRegionJT32: + EmitDataRegion(DataRegionData::JumpTable32); + return; + case MCDR_DataRegionEnd: + EmitDataRegionEnd(); + return; } } -void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, - const MCValue &Value, - bool MakeAbsolute) { - // Only absolute symbols can be redefined. - assert((Symbol->isUndefined() || Symbol->isAbsolute()) && - "Cannot define a symbol twice!"); +void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) { + getAssembler().setVersionMinInfo(Kind, Major, Minor, Update); +} - llvm_unreachable("FIXME: Not yet implemented!"); +void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { + // Remember that the function is a thumb function. Fixup and relocation + // values will need adjusted. + getAssembler().setIsThumbFunc(Symbol); + cast(Symbol)->setThumbFunc(); } -void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - SymbolAttr Attribute) { +bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym, + MCSymbolAttr Attribute) { + MCSymbolMachO *Symbol = cast(Sym); + // Indirect symbols are handled differently, to match how 'as' handles // them. This makes writing matching .o files easier. - if (Attribute == MCStreamer::IndirectSymbol) { + if (Attribute == MCSA_IndirectSymbol) { // Note that we intentionally cannot use the symbol data here; this is // important for matching the string table that 'as' generates. IndirectSymbolData ISD; ISD.Symbol = Symbol; - ISD.SectionData = CurSectionData; - Assembler.getIndirectSymbols().push_back(ISD); - return; + ISD.Section = getCurrentSectionOnly(); + getAssembler().getIndirectSymbols().push_back(ISD); + return true; } // Adding a symbol attribute always introduces the symbol, note that an - // important side effect of calling getSymbolData here is to register the - // symbol with the assembler. - MCSymbolData &SD = getSymbolData(*Symbol); + // 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 @@ -215,122 +300,202 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, // In the future it might be worth trying to make these operations more well // defined. switch (Attribute) { - case MCStreamer::IndirectSymbol: - case MCStreamer::Hidden: - case MCStreamer::Internal: - case MCStreamer::Protected: - case MCStreamer::Weak: - assert(0 && "Invalid symbol attribute for Mach-O!"); + case MCSA_Invalid: + case MCSA_ELF_TypeFunction: + case MCSA_ELF_TypeIndFunction: + case MCSA_ELF_TypeObject: + case MCSA_ELF_TypeTLS: + case MCSA_ELF_TypeCommon: + case MCSA_ELF_TypeNoType: + case MCSA_ELF_TypeGnuUniqueObject: + case MCSA_Hidden: + case MCSA_IndirectSymbol: + case MCSA_Internal: + case MCSA_Protected: + case MCSA_Weak: + case MCSA_Local: + return false; + + case MCSA_Global: + Symbol->setExternal(true); + // This effectively clears the undefined lazy bit, in Darwin 'as', although + // it isn't very consistent because it implements this as part of symbol + // lookup. + // + // FIXME: Cleanup this code, these bits should be emitted based on semantic + // properties, not on the order of definition, etc. + Symbol->setReferenceTypeUndefinedLazy(false); break; - case MCStreamer::Global: - getSymbolData(*Symbol).setExternal(true); - break; - - case MCStreamer::LazyReference: + case MCSA_LazyReference: // FIXME: This requires -dynamic. - SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + Symbol->setNoDeadStrip(); if (Symbol->isUndefined()) - SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); + Symbol->setReferenceTypeUndefinedLazy(true); break; // Since .reference sets the no dead strip bit, it is equivalent to // .no_dead_strip in practice. - case MCStreamer::Reference: - case MCStreamer::NoDeadStrip: - SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + case MCSA_Reference: + case MCSA_NoDeadStrip: + Symbol->setNoDeadStrip(); break; - case MCStreamer::PrivateExtern: - SD.setExternal(true); - SD.setPrivateExtern(true); + case MCSA_SymbolResolver: + Symbol->setSymbolResolver(); break; - case MCStreamer::WeakReference: + case MCSA_PrivateExtern: + Symbol->setExternal(true); + Symbol->setPrivateExtern(true); + break; + + case MCSA_WeakReference: // FIXME: This requires -dynamic. if (Symbol->isUndefined()) - SD.setFlags(SD.getFlags() | SF_WeakReference); + Symbol->setWeakReference(); break; - case MCStreamer::WeakDefinition: + case MCSA_WeakDefinition: // FIXME: 'as' enforces that this is defined and global. The manual claims // it has to be in a coalesced section, but this isn't enforced. - SD.setFlags(SD.getFlags() | SF_WeakDefinition); + Symbol->setWeakDefinition(); + break; + + case MCSA_WeakDefAutoPrivate: + Symbol->setWeakDefinition(); + Symbol->setWeakReference(); break; } + + return true; } void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { // Encode the 'desc' value into the lowest implementation defined bits. - assert(DescValue == (DescValue & SF_DescFlagsMask) && - "Invalid .desc value!"); - getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); + getAssembler().registerSymbol(*Symbol); + cast(Symbol)->setDesc(DescValue); } -void MCMachOStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { - llvm_unreachable("FIXME: Not yet implemented!"); -} +void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); -void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, - unsigned Pow2Alignment) { - llvm_unreachable("FIXME: Not yet implemented!"); + getAssembler().registerSymbol(*Symbol); + Symbol->setExternal(true); + Symbol->setCommon(Size, ByteAlignment); } -void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - unsigned Size, unsigned Pow2Alignment) { - llvm_unreachable("FIXME: Not yet implemented!"); +void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + // '.lcomm' is equivalent to '.zerofill'. + return EmitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(), + Symbol, Size, ByteAlignment); } -void MCMachOStreamer::EmitBytes(const StringRef &Data) { - MCDataFragment *DF = dyn_cast_or_null(getCurrentFragment()); - if (!DF) - DF = new MCDataFragment(CurSectionData); - DF->getContents().append(Data.begin(), Data.end()); -} +void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + getAssembler().registerSection(*Section); -void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) { - new MCFillFragment(AddValueSymbols(Value), Size, 1, CurSectionData); -} + // The symbol may not be present, which only creates the section. + if (!Symbol) + return; -void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value, unsigned ValueSize, - unsigned MaxBytesToEmit) { - if (MaxBytesToEmit == 0) - MaxBytesToEmit = ByteAlignment; - new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - CurSectionData); - - // Update the maximum alignment on the current section if necessary. - if (ByteAlignment > CurSectionData->getAlignment()) - CurSectionData->setAlignment(ByteAlignment); -} + // On darwin all virtual sections have zerofill type. + assert(Section->isVirtualSection() && "Section does not have zerofill type!"); + + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + getAssembler().registerSymbol(*Symbol); -void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset, - unsigned char Value) { - new MCOrgFragment(AddValueSymbols(Offset), Value, CurSectionData); + // Emit an align fragment if necessary. + if (ByteAlignment != 1) + new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section); + + MCFragment *F = new MCFillFragment(0, 0, Size, Section); + Symbol->setFragment(F); + + // Update the maximum alignment on the zero fill section if necessary. + if (ByteAlignment > Section->getAlignment()) + Section->setAlignment(ByteAlignment); } -void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { - // Scan for values. - for (unsigned i = 0; i != Inst.getNumOperands(); ++i) - if (Inst.getOperand(i).isMCValue()) - AddValueSymbols(Inst.getOperand(i).getMCValue()); +// This should always be called with the thread local bss section. Like the +// .zerofill directive this doesn't actually switch sections on us. +void MCMachOStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + EmitZerofill(Section, Symbol, Size, ByteAlignment); + return; +} - if (!Emitter) - llvm_unreachable("no code emitter available!"); +void MCMachOStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCDataFragment *DF = getOrCreateDataFragment(); - // FIXME: Relocations! + SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - Emitter->EncodeInstruction(Inst, VecOS); - EmitBytes(VecOS.str()); + getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); + + // Add the fixups and data. + for (MCFixup &Fixup : Fixups) { + Fixup.setOffset(Fixup.getOffset() + DF->getContents().size()); + DF->getFixups().push_back(Fixup); + } + DF->getContents().append(Code.begin(), Code.end()); } -void MCMachOStreamer::Finish() { - Assembler.Finish(); +void MCMachOStreamer::FinishImpl() { + EmitFrames(&getAssembler().getBackend()); + + // We have to set the fragment atom associations so we can relax properly for + // Mach-O. + + // First, scan the symbol table to build a lookup table from fragments to + // defining symbols. + DenseMap DefiningSymbolMap; + for (const MCSymbol &Symbol : getAssembler().symbols()) { + if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() && + !Symbol.isVariable()) { + // An atom defining symbol should never be internal to a fragment. + assert(Symbol.getOffset() == 0 && + "Invalid offset in atom defining symbol!"); + DefiningSymbolMap[Symbol.getFragment()] = &Symbol; + } + } + + // Set the fragment atom associations by tracking the last seen atom defining + // symbol. + for (MCSection &Sec : getAssembler()) { + const MCSymbol *CurrentAtom = nullptr; + for (MCFragment &Frag : Sec) { + if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag)) + CurrentAtom = Symbol; + Frag.setAtom(CurrentAtom); + } + } + + this->MCObjectStreamer::FinishImpl(); } -MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS, - MCCodeEmitter *CE) { - return new MCMachOStreamer(Context, OS, CE); +MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool DWARFMustBeAtTheEnd, + bool LabelSections) { + MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, + DWARFMustBeAtTheEnd, LabelSections); + const Triple &TT = Context.getObjectFileInfo()->getTargetTriple(); + if (TT.isOSDarwin()) { + unsigned Major, Minor, Update; + TT.getOSVersion(Major, Minor, Update); + // If there is a version specified, Major will be non-zero. + if (Major) + S->EmitVersionMin((TT.isMacOSX() ? + MCVM_OSXVersionMin : MCVM_IOSVersionMin), + Major, Minor, Update); + } + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; }