/// fragment is not a data fragment.
MCDataFragment *getOrCreateDataFragment();
+ bool changeSectionImpl(const MCSection *Section, const MCExpr *Subsection);
+
public:
void visitUsedSymbol(const MCSymbol &Sym) override;
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);
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,
MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter,
const MCSubtargetInfo &STI,
- bool RelaxAll) const {
+ bool RelaxAll,
+ bool DWARFMustBeAtTheEnd) const {
MCStreamer *S;
switch (T.getObjectFormat()) {
default:
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)
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:
Triple T(getTargetTriple());
const MCSubtargetInfo &STI = *getMCSubtargetInfo();
std::unique_ptr<MCStreamer> 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 =
/// 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.
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 {
} // 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<MCSectionMachO>(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]) {
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;
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 &&
report_fatal_error("Subsection number out of range");
CurInsertionPoint =
CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection));
+ return Created;
}
void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
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);
}
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<const TargetLoweringObjectFileMachO &>(
- getObjFileLowering());
-
- // Collect the set of sections our functions will go into.
- SetVector<const MCSection *, SmallVector<const MCSection *, 8>,
- SmallPtrSet<const MCSection *, 8> > 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);
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,
+++ /dev/null
-; 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
-}
; 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 {
--- /dev/null
+; 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)
+++ /dev/null
-; 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")
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);
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);
}