/// @}
protected:
- MCFragment(FragmentType _Kind, MCSectionData *_Parent);
+ MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0);
public:
// Only for sentinel.
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; }
uint8_t BundlePadding;
public:
- MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD)
+ MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0)
: MCFragment(FType, SD), BundlePadding(0)
{
}
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) {}
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) &&
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) {}
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); }
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); }
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); }
/// 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:
bool empty() const { return Fragments.empty(); }
+ iterator getSubsectionInsertionPoint(unsigned Subsection);
+
bool isBundleLocked() const {
return BundleLockState != NotBundleLocked;
}
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);
#ifndef LLVM_MC_MCOBJECTSTREAMER_H
#define LLVM_MC_MCOBJECTSTREAMER_H
+#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCStreamer.h"
namespace llvm {
class MCObjectStreamer : public MCStreamer {
MCAssembler *Assembler;
MCSectionData *CurSectionData;
+ MCSectionData::iterator CurInsertionPoint;
virtual void EmitInstToData(const MCInst &Inst) = 0;
virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame);
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;
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
namespace llvm {
class MCAsmInfo;
+ class MCExpr;
class raw_ostream;
/// MCSection - Instances of this class represent a uniqued identifier for a
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.
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;
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;
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;
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,
/// 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;
/// 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.
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;
}
/// @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.
/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
- return OutStreamer.getCurrentSection();
+ return OutStreamer.getCurrentSection().first;
}
/// @name MCStreamer Interface
/// @{
- virtual void ChangeSection(const MCSection *Section);
+ virtual void ChangeSection(const MCSection *Section,
+ const MCExpr *Subsection);
virtual void InitSections() {
InitToTextSection();
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,
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) {
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;
}
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)
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);
}
/* *** */
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) {}
// 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();
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
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) {
// 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);
// 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.
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);
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);
//===----------------------------------------------------------------------===//
#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"
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;
}
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;
}
return;
}
Value = ForceExpAbs(Value);
- new MCLEBFragment(*Value, false, getCurrentSectionData());
+ insert(new MCLEBFragment(*Value, false));
}
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,
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) {
// 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();
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);
return;
}
AddrDelta = ForceExpAbs(AddrDelta);
- new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());
+ insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
}
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) {
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())
unsigned char Value) {
int64_t Res;
if (Offset->EvaluateAsAbsolute(Res, getAssembler())) {
- new MCOrgFragment(*Offset, Value, getCurrentSectionData());
+ insert(new MCOrgFragment(*Offset, Value));
return false;
}
// 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);
}
void AsmParser::checkForValidSection() {
- if (!ParsingInlineAsm && !getStreamer().getCurrentSection()) {
+ if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) {
TokError("expected section directive before assembly directive");
Out.InitToTextSection();
}
// 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);
// 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);
/// 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;
}
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
addDirectiveHandler<
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
}
// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
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);
};
}
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;
}
bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
getStreamer().PushSection();
- if (ParseDirectiveSection(s, loc)) {
+ if (ParseSectionArguments(/*IsPush=*/true)) {
getStreamer().PopSection();
return true;
}
// 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))
int64_t Size = 0;
StringRef GroupName;
unsigned Flags = 0;
+ const MCExpr *Subsection = 0;
// Set the defaults first.
if (SectionName == ".fini" || SectionName == ".init" ||
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");
}
}
+EndStmt:
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
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;
}
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() {
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
// 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())
// 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.
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.
//
}
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)) {
#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"
}
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;
}
if (Flags & ELF::SHF_GROUP)
OS << "," << Group->getName() << ",comdat";
OS << '\n';
+
+ if (Subsection)
+ OS << "\t.subsection\t" << *Subsection << '\n';
}
bool MCSectionELF::UseCodeAlign() const {
}
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.
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() {
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,
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;
}
~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
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);
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
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);
/// 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; }
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());
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()));
--- /dev/null
+// 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
AddValueSymbols(Inst.getOperand(i).getExpr());
}
virtual void EmitLabel(MCSymbol *Symbol) {
- Symbol->setSection(*getCurrentSection());
+ Symbol->setSection(*getCurrentSection().first);
markDefined(*Symbol);
}
virtual void EmitDebugLabel(MCSymbol *Symbol) {
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) {}