diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 100029f3aae..24200724c62 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -85,6 +85,8 @@ protected: /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment(); + bool changeSectionImpl(const MCSection *Section, const MCExpr *Subsection); + public: void visitUsedSymbol(const MCSymbol &Sym) override; diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index bad1e5146b1..26134e4eecb 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -65,7 +65,8 @@ namespace llvm { bool RelaxAll); MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool LabelSections = false); + bool RelaxAll, bool DWARFMustBeAtTheEnd, + bool LabelSections = false); MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); @@ -138,11 +139,9 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, bool RelaxAll); - typedef MCStreamer *(*MachOStreamerCtorTy)(MCContext &Ctx, - MCAsmBackend &TAB, - raw_ostream &OS, - MCCodeEmitter *Emitter, - bool RelaxAll); + typedef MCStreamer *(*MachOStreamerCtorTy)( + MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter, bool RelaxAll, bool DWARFMustBeAtTheEnd); typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, @@ -444,7 +443,8 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI, - bool RelaxAll) const { + bool RelaxAll, + bool DWARFMustBeAtTheEnd) const { MCStreamer *S; switch (T.getObjectFormat()) { default: @@ -455,9 +455,11 @@ namespace llvm { break; case Triple::MachO: if (MachOStreamerCtorFn) - S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll); + S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); else - S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll); + S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); break; case Triple::ELF: if (ELFStreamerCtorFn) diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index f463f70d3e6..0fb0c46ddb1 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -202,7 +202,8 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, Triple T(getTargetTriple()); AsmStreamer.reset(getTarget().createMCObjectStreamer( - T, *Context, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll)); + T, *Context, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll, + /*DWARFMustBeAtTheEnd*/ true)); break; } case CGFT_Null: @@ -253,7 +254,8 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, Triple T(getTargetTriple()); const MCSubtargetInfo &STI = *getMCSubtargetInfo(); std::unique_ptr AsmStreamer(getTarget().createMCObjectStreamer( - T, *Ctx, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll)); + T, *Ctx, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll, + /*DWARFMustBeAtTheEnd*/ true)); // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. FunctionPass *Printer = diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 6246ed01ab7..d5c7101d0d5 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -40,6 +40,9 @@ private: /// need for local relocations. False by default. bool LabelSections; + bool DWARFMustBeAtTheEnd; + bool CreatedADWARFSection; + /// 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. @@ -52,9 +55,9 @@ private: public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *Emitter, bool label) - : MCObjectStreamer(Context, MAB, OS, Emitter), - LabelSections(label) {} + MCCodeEmitter *Emitter, bool DWARFMustBeAtTheEnd, bool label) + : MCObjectStreamer(Context, MAB, OS, Emitter), LabelSections(label), + DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd), CreatedADWARFSection(false) {} /// state management void reset() override { @@ -120,10 +123,43 @@ public: } // end anonymous namespace. +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(); + + if (SegName == "__LD" && SecName == "__compact_unwind") + return true; + + if (SegName == "__IMPORT") { + if (SecName == "__jump_table") + return true; + + if (SecName == "__pointers") + return true; + } + + if (SegName == "__TEXT" && SecName == "__eh_frame") + return true; + + if (SegName == "__DATA" && SecName == "__nl_symbol_ptr") + return true; + + return false; +} + void MCMachOStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { // Change the section normally. - MCObjectStreamer::ChangeSection(Section, Subsection); + 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]) { @@ -456,9 +492,10 @@ void MCMachOStreamer::FinishImpl() { MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, + bool RelaxAll, bool DWARFMustBeAtTheEnd, bool LabelSections) { - MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, LabelSections); + MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, + DWARFMustBeAtTheEnd, LabelSections); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S; diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 5b6b6b5facf..6aa2de36db6 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -182,10 +182,16 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, void MCObjectStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { + changeSectionImpl(Section, Subsection); +} + +bool MCObjectStreamer::changeSectionImpl(const MCSection *Section, + const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); flushPendingLabels(nullptr); - CurSectionData = &getAssembler().getOrCreateSectionData(*Section); + bool Created; + CurSectionData = &getAssembler().getOrCreateSectionData(*Section, &Created); int64_t IntSubsection = 0; if (Subsection && @@ -195,6 +201,7 @@ void MCObjectStreamer::ChangeSection(const MCSection *Section, report_fatal_error("Subsection number out of range"); CurInsertionPoint = CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection)); + return Created; } void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp index 1a72b79a291..38b399d5da4 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -131,8 +131,10 @@ static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx, static MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll) { + bool RelaxAll, + bool DWARFMustBeAtTheEnd) { return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd, /*LabelSections*/ true); } diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index e3c9dcbf72b..971e10df8b9 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -435,65 +435,6 @@ void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { Triple TT(TM.getTargetTriple()); - if (TT.isOSBinFormatMachO()) { - Reloc::Model RelocM = TM.getRelocationModel(); - if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { - // Declare all the text sections up front (before the DWARF sections - // emitted by AsmPrinter::doInitialization) so the assembler will keep - // them together at the beginning of the object file. This helps - // avoid out-of-range branches that are due a fundamental limitation of - // the way symbol offsets are encoded with the current Darwin ARM - // relocations. - const TargetLoweringObjectFileMachO &TLOFMacho = - static_cast( - getObjFileLowering()); - - // Collect the set of sections our functions will go into. - SetVector, - SmallPtrSet > TextSections; - // Default text section comes first. - TextSections.insert(TLOFMacho.getTextSection()); - // Now any user defined text sections from function attributes. - for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F) - if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) - TextSections.insert(TLOFMacho.SectionForGlobal(F, *Mang, TM)); - // Now the coalescable sections. - TextSections.insert(TLOFMacho.getTextCoalSection()); - TextSections.insert(TLOFMacho.getConstTextCoalSection()); - - // Emit the sections in the .s file header to fix the order. - for (unsigned i = 0, e = TextSections.size(); i != e; ++i) - OutStreamer.SwitchSection(TextSections[i]); - - if (RelocM == Reloc::DynamicNoPIC) { - const MCSection *sect = - OutContext.getMachOSection("__TEXT", "__symbol_stub4", - MachO::S_SYMBOL_STUBS, - 12, SectionKind::getText()); - OutStreamer.SwitchSection(sect); - } else { - const MCSection *sect = - OutContext.getMachOSection("__TEXT", "__picsymbolstub4", - MachO::S_SYMBOL_STUBS, - 16, SectionKind::getText()); - OutStreamer.SwitchSection(sect); - } - const MCSection *StaticInitSect = - OutContext.getMachOSection("__TEXT", "__StaticInit", - MachO::S_REGULAR | - MachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - OutStreamer.SwitchSection(StaticInitSect); - } - - // Compiling with debug info should not affect the code - // generation. Ensure the cstring section comes before the - // optional __DWARF secion. Otherwise, PC-relative loads would - // have to use different instruction sequences at "-g" in order to - // reach global data in the same object file. - OutStreamer.SwitchSection(getObjFileLowering().getCStringSection()); - } - // Use unified assembler syntax. OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index 9f75491911c..82dac5c4357 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -307,9 +307,9 @@ static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx, static MCStreamer *createARMMachOStreamer(MCContext &Ctx, MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *Emitter, - bool RelaxAll) { - return createMachOStreamer(Ctx, MAB, OS, Emitter, false); + MCCodeEmitter *Emitter, bool RelaxAll, + bool DWARFMustBeAtTheEnd) { + return createMachOStreamer(Ctx, MAB, OS, Emitter, false, DWARFMustBeAtTheEnd); } static MCInstPrinter *createARMMCInstPrinter(const Target &T, diff --git a/test/CodeGen/ARM/darwin-section-order.ll b/test/CodeGen/ARM/darwin-section-order.ll deleted file mode 100644 index 701028c0a53..00000000000 --- a/test/CodeGen/ARM/darwin-section-order.ll +++ /dev/null @@ -1,21 +0,0 @@ -; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s - -; CHECK: .section __TEXT,__text,regular,pure_instructions -; CHECK: .section __TEXT,myprecious -; CHECK: .section __TEXT,__textcoal_nt,coalesced,pure_instructions -; CHECK: .section __TEXT,__const_coal,coalesced -; CHECK: .section __TEXT,__picsymbolstub4,symbol_stubs,none,16 -; CHECK: .section __TEXT,__StaticInit,regular,pure_instructions - - -define void @normal() nounwind readnone { -; CHECK: .section __TEXT,__text,regular,pure_instructions -; CHECK: _normal: - ret void -} - -define void @special() nounwind readnone section "__TEXT,myprecious" { -; CHECK: .section __TEXT,myprecious -; CHECK: _special: - ret void -} diff --git a/test/CodeGen/ARM/none-macho.ll b/test/CodeGen/ARM/none-macho.ll index 23555b3d22c..733ba4ba2d2 100644 --- a/test/CodeGen/ARM/none-macho.ll +++ b/test/CodeGen/ARM/none-macho.ll @@ -2,11 +2,6 @@ ; RUN: llc -mtriple=thumbv7m-none-macho -O0 %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s ; RUN: llc -mtriple=thumbv7m-none-macho -filetype=obj %s -o /dev/null - ; Bare-metal should probably "declare" segments just like normal MachO -; CHECK: __picsymbolstub4 -; CHECK: __StaticInit -; CHECK: __text - @var = external global i32 define i32 @test_litpool() minsize { diff --git a/test/DebugInfo/ARM/header.ll b/test/DebugInfo/ARM/header.ll new file mode 100644 index 00000000000..d9dd611e127 --- /dev/null +++ b/test/DebugInfo/ARM/header.ll @@ -0,0 +1,30 @@ +; RUN: llc -mtriple armv7-apple-darwin < %s | FileCheck %s + +; Test that we don't pollute the start of the file with debug sections. +; This is particularly important on ARM MachO as a change in section order can +; cause a change the relaxation of the instructions used. + +; CHECK: .section __TEXT,__text,regular,pure_instructions +; CHECK-NEXT: .syntax unified +; CHECK-NEXT: .globl _f +; CHECK-NEXT: .align 2 +; CHECK-NEXT: _f: @ @f + +; CHECK: .section __DWARF,__debug_str,regular,debug + +define void @f() { + ret void, !dbg !9 +} +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} + +!0 = !MDCompileUnit(language: DW_LANG_C99, file: !1, producer: "foo", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) +!1 = !MDFile(filename: "/foo/test.c", directory: "/foo") +!2 = !{} +!3 = !{!4} +!4 = !MDSubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @f, variables: !2) +!5 = !MDSubroutineType(types: !6) +!6 = !{null} +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !MDLocation(line: 1, column: 15, scope: !4) diff --git a/test/DebugInfo/ARM/sectionorder.ll b/test/DebugInfo/ARM/sectionorder.ll deleted file mode 100644 index e6e067a1b58..00000000000 --- a/test/DebugInfo/ARM/sectionorder.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: llc -filetype=asm %s -o - | FileCheck %s - -; Verifies that the DWARF* sections come _after_ the __TEXT sections. -; rdar://problem/15623193 - -; CHECK: .section __TEXT,__text, -; CHECK-NOT: __DWARF,__debug -; CHECK: .section __TEXT,__cstring,cstring_literals -target triple = "thumbv7-apple-ios" - -!llvm.module.flags = !{!3, !4} -!llvm.dbg.cu = !{!0} - -!0 = !MDCompileUnit(language: DW_LANG_C99, producer: "LLVM", isOptimized: true, file: !5, enums: !1, retainedTypes: !1, subprograms: !1, globals: !1) -!1 = !{} -!3 = !{i32 2, !"Dwarf Version", i32 2} -!4 = !{i32 1, !"Debug Info Version", i32 3} -!5 = !MDFile(filename: "test.c", directory: "/Volumes/Data/radar/15623193") diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index 4326be45137..c9c05cd54ac 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -511,7 +511,8 @@ bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) { return error(Twine(OutputFilename) + ": " + EC.message(), Context); MS = TheTarget->createMCObjectStreamer(TheTriple, *MC, *MAB, *OutFile, MCE, - *MSTI, false); + *MSTI, false, + /*DWARFMustBeAtTheEnd*/ false); if (!MS) return error("no object streamer for target " + TripleName, Context); diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index eb0df78c48d..4f9b6fc99e3 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -472,7 +472,8 @@ int main(int argc, char **argv) { MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, FOS, CE, - *STI, RelaxAll)); + *STI, RelaxAll, + /*DWARFMustBeAtTheEnd*/ false)); if (NoExecStack) Str->InitSections(true); }