diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2013-04-17 21:18:16 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2013-04-17 21:18:16 +0000 |
commit | df39be6cb4eb44011db3d3e86f8fe463f81ce127 (patch) | |
tree | a008e657a29cef0e9c842f58d4eebb9bd45aba2b | |
parent | 53c9def43359f9b908565b28340e461ce5463009 (diff) | |
download | external_llvm-df39be6cb4eb44011db3d3e86f8fe463f81ce127.zip external_llvm-df39be6cb4eb44011db3d3e86f8fe463f81ce127.tar.gz external_llvm-df39be6cb4eb44011db3d3e86f8fe463f81ce127.tar.bz2 |
Add support for subsections to the ELF assembler. Fixes PR8717.
Differential Revision: http://llvm-reviews.chandlerc.com/D598
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179725 91177308-0d34-0410-b5e6-96231b3b80d8
30 files changed, 288 insertions, 118 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 32df38b..38a70f0 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -82,7 +82,7 @@ private: /// @} protected: - MCFragment(FragmentType _Kind, MCSectionData *_Parent); + MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0); public: // Only for sentinel. @@ -92,6 +92,7 @@ public: FragmentType getKind() const { return Kind; } MCSectionData *getParent() const { return Parent; } + void setParent(MCSectionData *Value) { Parent = Value; } MCSymbolData *getAtom() const { return Atom; } void setAtom(MCSymbolData *Value) { Atom = Value; } @@ -132,7 +133,7 @@ class MCEncodedFragment : public MCFragment { uint8_t BundlePadding; public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD) + MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0) : MCFragment(FType, SD), BundlePadding(0) { } @@ -347,7 +348,7 @@ class MCAlignFragment : public MCFragment { public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, MCSectionData *SD) + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} @@ -388,7 +389,7 @@ class MCFillFragment : public MCFragment { public: MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, - MCSectionData *SD) + MCSectionData *SD = 0) : MCFragment(FT_Fill, SD), Value(_Value), ValueSize(_ValueSize), Size(_Size) { assert((!ValueSize || (Size % ValueSize) == 0) && @@ -421,7 +422,7 @@ class MCOrgFragment : public MCFragment { int8_t Value; public: - MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD) + MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) : MCFragment(FT_Org, SD), Offset(&_Offset), Value(_Value) {} @@ -450,7 +451,7 @@ class MCLEBFragment : public MCFragment { SmallString<8> Contents; public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD = 0) : MCFragment(FT_LEB, SD), Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } @@ -486,7 +487,7 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD) + MCSectionData *SD = 0) : MCFragment(FT_Dwarf, SD), LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -517,7 +518,7 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD) + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD = 0) : MCFragment(FT_DwarfFrame, SD), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -589,6 +590,10 @@ private: /// it. unsigned HasInstructions : 1; + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; + /// @} public: @@ -632,6 +637,8 @@ public: bool empty() const { return Fragments.empty(); } + iterator getSubsectionInsertionPoint(unsigned Subsection); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 6fb2d22..55c05b0 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -50,7 +50,8 @@ public: virtual void InitSections(); virtual void InitToTextSection(); - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index f06c49f..22a2839 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCOBJECTSTREAMER_H #define LLVM_MC_MCOBJECTSTREAMER_H +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCStreamer.h" namespace llvm { @@ -32,6 +33,7 @@ class raw_ostream; class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; MCSectionData *CurSectionData; + MCSectionData::iterator CurInsertionPoint; virtual void EmitInstToData(const MCInst &Inst) = 0; virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); @@ -56,6 +58,11 @@ protected: MCFragment *getCurrentFragment() const; + void insert(MCFragment *F) const { + CurSectionData->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSectionData); + } + /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment() const; @@ -76,7 +83,8 @@ public: virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void EmitInstruction(const MCInst &Inst); /// \brief Emit an instruction to a special fragment, because this instruction diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index e575424..de2678a 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -20,6 +20,7 @@ namespace llvm { class MCAsmInfo; + class MCExpr; class raw_ostream; /// MCSection - Instances of this class represent a uniqued identifier for a @@ -48,7 +49,8 @@ namespace llvm { SectionVariant getVariant() const { return Variant; } virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const = 0; + raw_ostream &OS, + const MCExpr *Subsection) const = 0; // Convenience routines to get label names for the beginning/end of a // section. diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 07c4714..50e33a5 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -60,7 +60,8 @@ namespace llvm { int getSelection () const { return Selection; } virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 4b8b849..5979915 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -70,7 +70,8 @@ public: const MCSymbol *getGroup() const { return Group; } void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index 898f571..b68bd85 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -175,7 +175,8 @@ public: unsigned &StubSize); // Out. virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index a069a2b..2cab481 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -37,6 +37,8 @@ namespace llvm { class raw_ostream; class formatted_raw_ostream; + typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; + /// MCStreamer - Streaming machine code generation interface. This interface /// is intended to provide a programatic interface that is very similar to the /// level that an assembler .s file provides. It has callbacks to emit bytes, @@ -86,8 +88,7 @@ namespace llvm { /// SectionStack - This is stack of current and previous section /// values saved by PushSection. - SmallVector<std::pair<const MCSection *, - const MCSection *>, 4> SectionStack; + SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; bool AutoInitSections; @@ -174,25 +175,25 @@ namespace llvm { /// getCurrentSection - Return the current section that the streamer is /// emitting code to. - const MCSection *getCurrentSection() const { + MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; - return NULL; + return MCSectionSubPair(); } /// getPreviousSection - Return the previous section that the streamer is /// emitting code to. - const MCSection *getPreviousSection() const { + MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; - return NULL; + return MCSectionSubPair(); } /// ChangeSection - Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *) = 0; + virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; /// pushSection - Save the current and previous section on the /// section stack. @@ -208,11 +209,19 @@ namespace llvm { bool PopSection() { if (SectionStack.size() <= 1) return false; - const MCSection *oldSection = SectionStack.pop_back_val().first; - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; if (oldSection != curSection) - ChangeSection(curSection); + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); return true; } @@ -220,25 +229,26 @@ namespace llvm { /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section) { + void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { assert(Section && "Cannot switch to a null section!"); - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; - if (Section != curSection) { - SectionStack.back().first = Section; - ChangeSection(Section); + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } } /// SwitchSectionNoChange - Set the current section where code is being /// emitted to @p Section. This is required to update CurSection. This /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section) { + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { assert(Section && "Cannot switch to a null section!"); - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; - if (Section != curSection) - SectionStack.back().first = Section; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); } /// Initialize the streamer. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d4a745d..2d13db2 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -135,7 +135,7 @@ const DataLayout &AsmPrinter::getDataLayout() const { /// getCurrentSection() - Return the current section we are emitting to. const MCSection *AsmPrinter::getCurrentSection() const { - return OutStreamer.getCurrentSection(); + return OutStreamer.getCurrentSection().first; } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index b35a9de..9e86785 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -124,7 +124,8 @@ public: /// @name MCStreamer Interface /// @{ - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void InitSections() { InitToTextSection(); @@ -328,9 +329,10 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); } -void MCAsmStreamer::ChangeSection(const MCSection *Section) { +void MCAsmStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); - Section->PrintSwitchToSection(MAI, OS); + Section->PrintSwitchToSection(MAI, OS, Subsection); } void MCAsmStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, @@ -637,7 +639,8 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) { void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); if (Data.empty()) return; if (Data.size() == 1) { @@ -668,7 +671,8 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, unsigned AddrSpace) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); const char *Directive = 0; switch (Size) { default: break; @@ -1363,7 +1367,8 @@ void MCAsmStreamer::EmitTCEntry(const MCSymbol &S) { } void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); // Show the encoding in a comment if we have a code emitter. if (Emitter) diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 8970e18..fb5ab28 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -214,7 +214,8 @@ MCFragment::~MCFragment() { MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)) { - Parent->getFragmentList().push_back(this); + if (Parent) + Parent->getFragmentList().push_back(this); } /* *** */ @@ -242,6 +243,36 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) A->getSectionList().push_back(this); } +MCSectionData::iterator +MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { + if (Subsection == 0 && SubsectionFragmentMap.empty()) + return end(); + + SmallVectorImpl<std::pair<unsigned, MCFragment *> >::iterator MI = + std::lower_bound(SubsectionFragmentMap.begin(), SubsectionFragmentMap.end(), + std::make_pair(Subsection, (MCFragment *)0)); + bool ExactMatch = false; + if (MI != SubsectionFragmentMap.end()) { + ExactMatch = MI->first == Subsection; + if (ExactMatch) + ++MI; + } + iterator IP; + if (MI == SubsectionFragmentMap.end()) + IP = end(); + else + IP = MI->second; + if (!ExactMatch && Subsection != 0) { + // The GNU as documentation claims that subsections have an alignment of 4, + // although this appears not to be the case. + MCFragment *F = new MCDataFragment(); + SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F)); + getFragmentList().insert(IP, F); + F->setParent(this); + } + return IP; +} + /* *** */ MCSymbolData::MCSymbolData() : Symbol(0) {} diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 549ab7f..1dff71a 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -197,6 +197,8 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // actually a DW_LNE_end_sequence. // Switch to the section to be able to create a symbol at its end. + // TODO: keep track of the last subsection so that this symbol appears in the + // correct place. MCOS->SwitchSection(Section); MCContext &context = MCOS->getContext(); @@ -787,7 +789,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection()) + if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) return; // The dwarf label's name does not have the symbol name's leading diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 7faa6f4..116f86f 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -109,14 +109,15 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { llvm_unreachable("invalid assembler flag!"); } -void MCELFStreamer::ChangeSection(const MCSection *Section) { +void MCELFStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { MCSectionData *CurSection = getCurrentSectionData(); if (CurSection && CurSection->isBundleLocked()) report_fatal_error("Unterminated .bundle_lock when changing a section"); const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup(); if (Grp) getAssembler().getOrCreateSymbolData(*Grp); - this->MCObjectStreamer::ChangeSection(Section); + this->MCObjectStreamer::ChangeSection(Section, Subsection); } void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -318,7 +319,7 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, // entry in the module's symbol table (the first being the null symbol). void MCELFStreamer::EmitFileDirective(StringRef Filename) { MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); Symbol->setAbsolute(); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); @@ -434,11 +435,13 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { // Optimize memory usage by emitting the instruction to a // MCCompactEncodedInstFragment when not in a bundle-locked group and // there are no fixups registered. - MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(SD); + MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); + insert(CEIF); CEIF->getContents().append(Code.begin(), Code.end()); return; } else { - DF = new MCDataFragment(SD); + DF = new MCDataFragment(); + insert(DF); if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { // If this is a new fragment created for a bundle-locked group, and the // group was marked as "align_to_end", set a flag in the fragment. diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 7d08d0e..e08b01b 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -122,11 +122,11 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); // isSymbolLinkerVisible uses the section. - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(*Symbol)) - new MCDataFragment(getCurrentSectionData()); + insert(new MCDataFragment()); MCObjectStreamer::EmitLabel(Symbol); diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index c872b22..659706a 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -30,13 +30,14 @@ namespace { virtual void InitSections() { } - virtual void ChangeSection(const MCSection *Section) { + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { } virtual void EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first &&"Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); } virtual void EmitDebugLabel(MCSymbol *Symbol) { EmitLabel(Symbol); diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 0d2ce83..d21ce8d 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCObjectStreamer.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" @@ -45,14 +46,15 @@ void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); CurSectionData = 0; + CurInsertionPoint = MCSectionData::iterator(); MCStreamer::reset(); } MCFragment *MCObjectStreamer::getCurrentFragment() const { assert(getCurrentSectionData() && "No current section!"); - if (!getCurrentSectionData()->empty()) - return &getCurrentSectionData()->getFragmentList().back(); + if (CurInsertionPoint != getCurrentSectionData()->getFragmentList().begin()) + return prior(CurInsertionPoint); return 0; } @@ -61,8 +63,10 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); // When bundling is enabled, we don't want to add data to a fragment that // already has instructions (see MCELFStreamer::EmitInstToData for details) - if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) - F = new MCDataFragment(getCurrentSectionData()); + if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) { + F = new MCDataFragment(); + insert(F); + } return F; } @@ -145,7 +149,7 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { return; } Value = ForceExpAbs(Value); - new MCLEBFragment(*Value, false, getCurrentSectionData()); + insert(new MCLEBFragment(*Value, false)); } void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { @@ -155,7 +159,7 @@ void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { return; } Value = ForceExpAbs(Value); - new MCLEBFragment(*Value, true, getCurrentSectionData()); + insert(new MCLEBFragment(*Value, true)); } void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, @@ -163,10 +167,20 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, report_fatal_error("This file format doesn't support weak aliases."); } -void MCObjectStreamer::ChangeSection(const MCSection *Section) { +void MCObjectStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); CurSectionData = &getAssembler().getOrCreateSectionData(*Section); + + int64_t IntSubsection = 0; + if (Subsection && + !Subsection->EvaluateAsAbsolute(IntSubsection, getAssembler())) + report_fatal_error("Cannot evaluate subsection number"); + if (IntSubsection < 0 || IntSubsection > 8192) + report_fatal_error("Subsection number out of range"); + CurInsertionPoint = + CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection)); } void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { @@ -185,7 +199,7 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { // Now that a machine instruction has been assembled into this section, make // a line entry for any .loc directive that has been seen. - MCLineEntry::Make(this, getCurrentSection()); + MCLineEntry::Make(this, getCurrentSection().first); // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); @@ -216,8 +230,8 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { // Always create a new, separate fragment here, because its size can change // during relaxation. - MCRelaxableFragment *IF = - new MCRelaxableFragment(Inst, getCurrentSectionData()); + MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); + insert(IF); SmallString<128> Code; raw_svector_ostream VecOS(Code); @@ -258,7 +272,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, return; } AddrDelta = ForceExpAbs(AddrDelta); - new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData()); + insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); } void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, @@ -270,7 +284,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, return; } AddrDelta = ForceExpAbs(AddrDelta); - new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData()); + insert(new MCDwarfCallFrameFragment(*AddrDelta)); } void MCObjectStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { @@ -284,8 +298,7 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) { if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - getCurrentSectionData()); + insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > getCurrentSectionData()->getAlignment()) @@ -302,7 +315,7 @@ bool MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { int64_t Res; if (Offset->EvaluateAsAbsolute(Res, getAssembler())) { - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + insert(new MCOrgFragment(*Offset, Value)); return false; } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 3e39a9c..8783bc0 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -602,7 +602,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - getContext().setGenDwarfSection(getStreamer().getCurrentSection()); + getContext().setGenDwarfSection(getStreamer().getCurrentSection().first); MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSym); getContext().setGenDwarfSectionStartSym(SectionStartSym); @@ -667,7 +667,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { } void AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSection()) { + if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { TokError("expected section directive before assembly directive"); Out.InitToTextSection(); } @@ -1493,7 +1493,8 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // section is the initial text section then generate a .loc directive for // the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && - getContext().getGenDwarfSection() == getStreamer().getCurrentSection()) { + getContext().getGenDwarfSection() == + getStreamer().getCurrentSection().first) { unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); @@ -2484,7 +2485,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { // Check whether we should use optimal code alignment for this .align // directive. - bool UseCodeAlign = getStreamer().getCurrentSection()->UseCodeAlign(); + bool UseCodeAlign = getStreamer().getCurrentSection().first->UseCodeAlign(); if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && ValueSize == 1 && UseCodeAlign) { getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill); diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 6d6409f..7eb8b74 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -566,10 +566,10 @@ bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { /// ParseDirectivePrevious: /// ::= .previous bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - const MCSection *PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection == NULL) + MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection.first == NULL) return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection); + getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 4c45e08..3134fc3 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -76,6 +76,7 @@ public: &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); } // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is @@ -147,9 +148,11 @@ public: bool ParseDirectiveVersion(StringRef, SMLoc); bool ParseDirectiveWeakref(StringRef, SMLoc); bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); + bool ParseDirectiveSubsection(StringRef, SMLoc); private: bool ParseSectionName(StringRef &SectionName); + bool ParseSectionArguments(bool IsPush); }; } @@ -191,12 +194,15 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in section switching directive"); - Lex(); + const MCExpr *Subsection = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } getStreamer().SwitchSection(getContext().getELFSection( - Section, Type, Flags, Kind)); + Section, Type, Flags, Kind), + Subsection); return false; } @@ -316,7 +322,7 @@ static int parseSectionFlags(StringRef flagsStr) { bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { getStreamer().PushSection(); - if (ParseDirectiveSection(s, loc)) { + if (ParseSectionArguments(/*IsPush=*/true)) { getStreamer().PopSection(); return true; } @@ -332,6 +338,10 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { // FIXME: This is a work in progress. bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + return ParseSectionArguments(/*IsPush=*/false); +} + +bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef SectionName; if (ParseSectionName(SectionName)) @@ -341,6 +351,7 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { int64_t Size = 0; StringRef GroupName; unsigned Flags = 0; + const MCExpr *Subsection = 0; // Set the defaults first. if (SectionName == ".fini" || SectionName == ".init" || @@ -352,6 +363,14 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { if (getLexer().is(AsmToken::Comma)) { Lex(); + if (IsPush && getLexer().isNot(AsmToken::String)) { + if (getParser().parseExpression(Subsection)) + return true; + if (getLexer().isNot(AsmToken::Comma)) + goto EndStmt; + Lex(); + } + if (getLexer().isNot(AsmToken::String)) return TokError("expected string in directive"); @@ -408,6 +427,7 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { } } +EndStmt: if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); @@ -444,15 +464,16 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { SectionKind Kind = computeSectionKind(Flags); getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, Flags, Kind, Size, - GroupName)); + GroupName), + Subsection); return false; } bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - const MCSection *PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection == NULL) + MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection.first == NULL) return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection); + getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } @@ -613,6 +634,20 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { return false; } +bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { + const MCExpr *Subsection = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + getStreamer().SubSection(Subsection); + return false; +} + namespace llvm { MCAsmParserExtension *createELFAsmParser() { diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index c9779e0..8ae724f 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -118,16 +118,16 @@ void MCPureStreamer::InitToTextSection() { void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); + assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(SD.getSymbol())) - new MCDataFragment(getCurrentSectionData()); + insert(new MCDataFragment()); // FIXME: This is wasteful, we don't necessarily need to create a data // fragment. Instead, we should mark the symbol as pointing into the data @@ -162,8 +162,7 @@ void MCPureStreamer::EmitValueToAlignment(unsigned ByteAlignment, // MCObjectStreamer. if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - getCurrentSectionData()); + insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > getCurrentSectionData()->getAlignment()) @@ -176,8 +175,8 @@ void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, // MCObjectStreamer. if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, - getCurrentSectionData()); + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit); + insert(F); F->setEmitNops(true); // Update the maximum alignment on the current section if necessary. @@ -187,13 +186,13 @@ void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, bool MCPureStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + insert(new MCOrgFragment(*Offset, Value)); return false; } void MCPureStreamer::EmitInstToFragment(const MCInst &Inst) { - MCRelaxableFragment *IF = - new MCRelaxableFragment(Inst, getCurrentSectionData()); + MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); + insert(IF); // Add the fixups and data. // diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp index aac9377..6cedf06 100644 --- a/lib/MC/MCSectionCOFF.cpp +++ b/lib/MC/MCSectionCOFF.cpp @@ -29,7 +29,8 @@ bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, } void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { // standard sections don't require the '.section' if (ShouldOmitSectionDirective(SectionName, MAI)) { diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 0775cfa..bf1a984 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -32,10 +33,14 @@ bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, } void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { if (ShouldOmitSectionDirective(SectionName, MAI)) { - OS << '\t' << getSectionName() << '\n'; + OS << '\t' << getSectionName(); + if (Subsection) + OS << '\t' << *Subsection; + OS << '\n'; return; } @@ -129,6 +134,9 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, if (Flags & ELF::SHF_GROUP) OS << "," << Group->getName() << ",comdat"; OS << '\n'; + + if (Subsection) + OS << "\t.subsection\t" << *Subsection << '\n'; } bool MCSectionELF::UseCodeAlign() const { diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp index fc32315..8704513 100644 --- a/lib/MC/MCSectionMachO.cpp +++ b/lib/MC/MCSectionMachO.cpp @@ -91,7 +91,8 @@ MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, } void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); // Get the section type and attributes. diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index d02e553..4839c34 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -24,8 +24,7 @@ using namespace llvm; MCStreamer::MCStreamer(StreamerKind Kind, MCContext &Ctx) : Kind(Kind), Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), CurrentW64UnwindInfo(0), LastSymbol(0), AutoInitSections(false) { - const MCSection *section = 0; - SectionStack.push_back(std::make_pair(section, section)); + SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } MCStreamer::~MCStreamer() { @@ -40,9 +39,8 @@ void MCStreamer::reset() { EmitDebugFrame = false; CurrentW64UnwindInfo = 0; LastSymbol = 0; - const MCSection *section = 0; SectionStack.clear(); - SectionStack.push_back(std::make_pair(section, section)); + SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, @@ -188,15 +186,15 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); LastSymbol = Symbol; } void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); LastSymbol = Symbol; } diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index b83577a..3b811df 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -63,14 +63,15 @@ public: ~AArch64ELFStreamer() {} - virtual void ChangeSection(const MCSection *Section) { + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { // We have to keep track of the mapping symbol state of any sections we // use. Each one should start off as EMS_None, which is provided as the // default constructor by DenseMap::lookup. - LastMappingSymbols[getPreviousSection()] = LastEMS; + LastMappingSymbols[getPreviousSection().first] = LastEMS; LastEMS = LastMappingSymbols.lookup(Section); - MCELFStreamer::ChangeSection(Section); + MCELFStreamer::ChangeSection(Section, Subsection); } /// This function is the one used to emit instruction data into the ELF @@ -129,7 +130,7 @@ private: MCELF::SetType(SD, ELF::STT_NOTYPE); MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); Symbol->setVariableValue(Value); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 52d9237..6c3d247 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -83,14 +83,15 @@ public: virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); - virtual void ChangeSection(const MCSection *Section) { + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { // We have to keep track of the mapping symbol state of any sections we // use. Each one should start off as EMS_None, which is provided as the // default constructor by DenseMap::lookup. - LastMappingSymbols[getPreviousSection()] = LastEMS; + LastMappingSymbols[getPreviousSection().first] = LastEMS; LastEMS = LastMappingSymbols.lookup(Section); - MCELFStreamer::ChangeSection(Section); + MCELFStreamer::ChangeSection(Section, Subsection); } /// This function is the one used to emit instruction data into the ELF @@ -183,7 +184,7 @@ private: MCELF::SetType(SD, ELF::STT_NOTYPE); MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); Symbol->setVariableValue(Value); diff --git a/lib/Target/NVPTX/NVPTXSection.h b/lib/Target/NVPTX/NVPTXSection.h index e166be5..e57ace9 100644 --- a/lib/Target/NVPTX/NVPTXSection.h +++ b/lib/Target/NVPTX/NVPTXSection.h @@ -32,7 +32,8 @@ public: /// Override this as NVPTX has its own way of printing switching /// to a section. virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const {} + raw_ostream &OS, + const MCExpr *Subsection) const {} /// Base address of PTX sections is zero. virtual bool isBaseAddressKnownZero() const { return true; } diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 96a9f0a..3c7cc4e 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -721,7 +721,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { return AsmPrinter::EmitFunctionEntryLabel(); // Emit an official procedure descriptor. - const MCSection *Current = OutStreamer.getCurrentSection(); + MCSectionSubPair Current = OutStreamer.getCurrentSection(); const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getReadOnly()); @@ -741,7 +741,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { 8/*size*/); // Emit a null environment pointer. OutStreamer.EmitIntValue(0, 8 /* size */); - OutStreamer.SwitchSection(Current); + OutStreamer.SwitchSection(Current.first, Current.second); MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol( ".L." + Twine(CurrentFnSym->getName())); diff --git a/test/MC/ELF/subsection.s b/test/MC/ELF/subsection.s new file mode 100644 index 0000000..d437cac --- /dev/null +++ b/test/MC/ELF/subsection.s @@ -0,0 +1,37 @@ +// RUN: llvm-mc -filetype=obj %s -o - -triple x86_64-pc-linux | llvm-objdump -s - | FileCheck %s + +// CHECK: Contents of section .text: +// CHECK-NEXT: 0000 03042502 00000003 04250100 0000ebf7 +.text 1 +add 1, %eax +jmp label +.subsection +add 2, %eax +label: + +// CHECK-NOT: Contents of section .rela.text: + +// CHECK: Contents of section .data: +// CHECK-NEXT: 0000 01030402 74657374 +.data +l0: +.byte 1 +.subsection 1+1 +l1: +.byte 2 +l2: +.subsection l2-l1 +.byte l1-l0 +.subsection 3 +.ascii "test" +.previous +.byte 4 + +// CHECK: Contents of section test: +// CHECK-NEXT: 0000 010302 +.section test +.byte 1 +.pushsection test, 1 +.byte 2 +.popsection +.byte 3 diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index ff67769..d805f49 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -743,7 +743,7 @@ namespace { AddValueSymbols(Inst.getOperand(i).getExpr()); } virtual void EmitLabel(MCSymbol *Symbol) { - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); markDefined(*Symbol); } virtual void EmitDebugLabel(MCSymbol *Symbol) { @@ -771,7 +771,8 @@ namespace { virtual void EmitBundleUnlock() {} // Noop calls. - virtual void ChangeSection(const MCSection *Section) {} + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) {} virtual void InitToTextSection() {} virtual void InitSections() {} virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} |