mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +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:
parent
1cb3175415
commit
a0d11d0e11
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -214,6 +214,7 @@ MCFragment::~MCFragment() {
|
||||
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
|
||||
: Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0))
|
||||
{
|
||||
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) {}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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)) {
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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
37
test/MC/ELF/subsection.s
Normal 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
|
@ -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) {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user