1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

Add support for subsections to the ELF assembler. Fixes PR8717.

Differential Revision: http://llvm-reviews.chandlerc.com/D598

llvm-svn: 179725
This commit is contained in:
Peter Collingbourne 2013-04-17 21:18:16 +00:00
parent 1cb3175415
commit a0d11d0e11
30 changed files with 288 additions and 118 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;
}

View File

@ -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)

View File

@ -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) {}

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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() {

View File

@ -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.
//

View File

@ -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)) {

View File

@ -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 {

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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; }

View File

@ -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()));

37
test/MC/ELF/subsection.s Normal file
View File

@ -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

View File

@ -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) {}