diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 724c3d7f38e..037a24f85b2 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -116,6 +116,13 @@ namespace llvm { /// file. const char *PrivateGlobalPrefix; // Defaults to "L" + /// This prefix is used for symbols that should be passed through the + /// assembler but be removed by the linker. This is 'l' on Darwin, + /// currently used for some ObjC metadata. + /// The default of "" meast that for this system a plain private symbol + /// should be used. + const char *LinkerPrivateGlobalPrefix; // Defaults to "". + /// InlineAsmStart/End - If these are nonempty, they contain a directive to /// emit before and after an inline assembly statement. const char *InlineAsmStart; // Defaults to "#APP\n" @@ -425,6 +432,14 @@ namespace llvm { const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + bool hasLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix[0] != '\0'; + } + const char *getLinkerPrivateGlobalPrefix() const { + if (hasLinkerPrivateGlobalPrefix()) + return LinkerPrivateGlobalPrefix; + return getPrivateGlobalPrefix(); + } const char *getInlineAsmStart() const { return InlineAsmStart; } diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index afb94f07bdd..b276b1f83e8 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -193,6 +193,10 @@ namespace llvm { /// @name Symbol Management /// @{ + /// CreateLinkerPrivateTempSymbol - Create and return a new linker temporary + /// symbol with a unique but unspecified name. + MCSymbol *CreateLinkerPrivateTempSymbol(); + /// CreateTempSymbol - Create and return a new assembler temporary symbol /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 37d586b8f18..9fe6da96b65 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -758,7 +758,8 @@ MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, /// Takes ownership of \p TAB and \p CE. MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + bool RelaxAll = false, + bool LabelSections = false); /// createWinCOFFStreamer - Create a machine code streamer which will /// generate Microsoft COFF format object files. diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index c78d3d574a4..966714592a6 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -41,6 +41,7 @@ MCAsmInfo::MCAsmInfo() { LabelSuffix = ":"; DebugLabelSuffix = ":"; PrivateGlobalPrefix = "L"; + LinkerPrivateGlobalPrefix = ""; InlineAsmStart = "APP"; InlineAsmEnd = "NO_APP"; Code16Directive = ".code16"; diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index fdedec1031a..73ffdc0a4bd 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -153,6 +153,13 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { return GetOrCreateSymbol(Name.toStringRef(NameSV)); } +MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() { + SmallString<128> NameSV; + raw_svector_ostream(NameSV) + << MAI->getLinkerPrivateGlobalPrefix() << "tmp" << NextUniqueID++; + return CreateSymbol(NameSV); +} + MCSymbol *MCContext::CreateTempSymbol() { SmallString<128> NameSV; raw_svector_ostream(NameSV) diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index c932c3c375a..742f7846496 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #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/MCCodeEmitter.h" @@ -31,18 +33,31 @@ namespace { class MCMachOStreamer : public MCObjectStreamer { private: + /// 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; + + /// 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; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; void EmitDataRegion(DataRegionData::KindTy Kind); void EmitDataRegionEnd(); + public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, MAB, OS, Emitter) {} + MCCodeEmitter *Emitter, bool label) + : MCObjectStreamer(Context, MAB, OS, Emitter), + LabelSections(label) {} /// @name MCStreamer Interface /// @{ + void ChangeSection(const MCSection *Sect, const MCExpr *Subsect) override; void EmitLabel(MCSymbol *Symbol) override; void EmitDebugLabel(MCSymbol *Symbol) override; void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; @@ -94,6 +109,19 @@ public: } // end anonymous namespace. +void MCMachOStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { + // Change the section normally. + MCObjectStreamer::ChangeSection(Section, Subsection); + // 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]) { + MCSymbol *Label = getContext().CreateLinkerPrivateTempSymbol(); + EmitLabel(Label); + HasSectionLabel[Section] = true; + } +} + void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { MCSymbolData &SD = @@ -425,8 +453,9 @@ void MCMachOStreamer::FinishImpl() { MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll) { - MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE); + bool RelaxAll, + bool LabelSections) { + MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, LabelSections); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S;