aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2013-04-17 21:18:16 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2013-04-17 21:18:16 +0000
commitdf39be6cb4eb44011db3d3e86f8fe463f81ce127 (patch)
treea008e657a29cef0e9c842f58d4eebb9bd45aba2b
parent53c9def43359f9b908565b28340e461ce5463009 (diff)
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
-rw-r--r--include/llvm/MC/MCAssembler.h23
-rw-r--r--include/llvm/MC/MCELFStreamer.h3
-rw-r--r--include/llvm/MC/MCObjectStreamer.h10
-rw-r--r--include/llvm/MC/MCSection.h4
-rw-r--r--include/llvm/MC/MCSectionCOFF.h3
-rw-r--r--include/llvm/MC/MCSectionELF.h3
-rw-r--r--include/llvm/MC/MCSectionMachO.h3
-rw-r--r--include/llvm/MC/MCStreamer.h48
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp2
-rw-r--r--lib/MC/MCAsmStreamer.cpp17
-rw-r--r--lib/MC/MCAssembler.cpp33
-rw-r--r--lib/MC/MCDwarf.cpp4
-rw-r--r--lib/MC/MCELFStreamer.cpp13
-rw-r--r--lib/MC/MCMachOStreamer.cpp4
-rw-r--r--lib/MC/MCNullStreamer.cpp7
-rw-r--r--lib/MC/MCObjectStreamer.cpp43
-rw-r--r--lib/MC/MCParser/AsmParser.cpp9
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp6
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp53
-rw-r--r--lib/MC/MCPureStreamer.cpp19
-rw-r--r--lib/MC/MCSectionCOFF.cpp3
-rw-r--r--lib/MC/MCSectionELF.cpp12
-rw-r--r--lib/MC/MCSectionMachO.cpp3
-rw-r--r--lib/MC/MCStreamer.cpp14
-rw-r--r--lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp9
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp9
-rw-r--r--lib/Target/NVPTX/NVPTXSection.h3
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp4
-rw-r--r--test/MC/ELF/subsection.s37
-rw-r--r--tools/lto/LTOModule.cpp5
30 files changed, 288 insertions, 118 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 32df38b2b9..38a70f0adf 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 6fb2d22be2..55c05b0363 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 f06c49ff08..22a2839869 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 e5754249e9..de2678adad 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 07c47144cb..50e33a5b04 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 4b8b849c79..59799158ad 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 898f571490..b68bd85968 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 a069a2b0ca..2cab481c3d 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 d4a745d985..2d13db2c9c 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 b35a9de1fc..9e867859da 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 8970e18a2c..fb5ab28bcf 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 549ab7ff21..1dff71a495 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 7faa6f411b..116f86feb8 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 7d08d0ecd5..e08b01b7ae 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 c872b2203f..659706a1d8 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 0d2ce83a8a..d21ce8d1a1 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) {