#include "llvm/MC/MCSymbol.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;
/// 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 {
+ HasSectionLabel.clear();
+ MCObjectStreamer::reset();
+ }
/// @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;
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitLinkerOptions(ArrayRef<std::string> Options) override;
unsigned ByteAlignment) override;
void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, unsigned ByteAlignment = 0) override;
- virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment = 0) override;
+ void EmitTBSSSymbol(const 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
} // 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]) {
SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask);
}
-void MCMachOStreamer::EmitDebugLabel(MCSymbol *Symbol) {
- EmitLabel(Symbol);
-}
void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
if (!getAssembler().getBackend().hasDataInCodeSupport())
return;
if (!getAssembler().getBackend().hasDataInCodeSupport())
return;
std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
- assert(Regions.size() && "Mismatched .end_data_region!");
+ 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.
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;