summaryrefslogtreecommitdiffstats
path: root/lib/MC/MCELFStreamer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCELFStreamer.cpp')
-rw-r--r--lib/MC/MCELFStreamer.cpp57
1 files changed, 36 insertions, 21 deletions
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 7c70540..bdc4a84 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
@@ -38,19 +39,23 @@ using namespace llvm;
MCELFStreamer::~MCELFStreamer() {
}
-void MCELFStreamer::InitSections() {
+void MCELFStreamer::InitSections(bool NoExecStack) {
// This emulates the same behavior of GNU as. This makes it easier
// to compare the output as the major sections are in the same order.
- SwitchSection(getContext().getObjectFileInfo()->getTextSection());
+ MCContext &Ctx = getContext();
+ SwitchSection(Ctx.getObjectFileInfo()->getTextSection());
EmitCodeAlignment(4);
- SwitchSection(getContext().getObjectFileInfo()->getDataSection());
+ SwitchSection(Ctx.getObjectFileInfo()->getDataSection());
EmitCodeAlignment(4);
- SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
+ SwitchSection(Ctx.getObjectFileInfo()->getBSSSection());
EmitCodeAlignment(4);
- SwitchSection(getContext().getObjectFileInfo()->getTextSection());
+ SwitchSection(Ctx.getObjectFileInfo()->getTextSection());
+
+ if (NoExecStack)
+ SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
}
void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
@@ -87,10 +92,19 @@ void MCELFStreamer::ChangeSection(const MCSection *Section,
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();
+
+ MCAssembler &Asm = getAssembler();
+ auto *SectionELF = static_cast<const MCSectionELF *>(Section);
+ const MCSymbol *Grp = SectionELF->getGroup();
if (Grp)
- getAssembler().getOrCreateSymbolData(*Grp);
+ Asm.getOrCreateSymbolData(*Grp);
+
this->MCObjectStreamer::ChangeSection(Section, Subsection);
+ MCSymbol *SectionSymbol = getContext().getOrCreateSectionSymbol(*SectionELF);
+ if (SectionSymbol->isUndefined()) {
+ EmitLabel(SectionSymbol);
+ MCELF::SetType(Asm.getSymbolData(*SectionSymbol), ELF::STT_SECTION);
+ }
}
void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
@@ -448,11 +462,13 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst,
} else {
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.
- DF->setAlignToBundleEnd(true);
- }
+ }
+ if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
+ // If this fragment is for a group marked "align_to_end", set a flag
+ // in the fragment. This can happen after the fragment has already been
+ // created if there are nested bundle_align groups and an inner one
+ // is the one marked align_to_end.
+ DF->setAlignToBundleEnd(true);
}
// We're now emitting an instruction in a bundle group, so this flag has
@@ -474,10 +490,11 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst,
void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
assert(AlignPow2 <= 30 && "Invalid bundle alignment");
MCAssembler &Assembler = getAssembler();
- if (Assembler.getBundleAlignSize() == 0 && AlignPow2 > 0)
- Assembler.setBundleAlignSize(1 << AlignPow2);
+ if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 ||
+ Assembler.getBundleAlignSize() == 1U << AlignPow2))
+ Assembler.setBundleAlignSize(1U << AlignPow2);
else
- report_fatal_error(".bundle_align_mode should be only set once per file");
+ report_fatal_error(".bundle_align_mode cannot be changed once set");
}
void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
@@ -487,12 +504,12 @@ void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
//
if (!getAssembler().isBundlingEnabled())
report_fatal_error(".bundle_lock forbidden when bundling is disabled");
- else if (SD->isBundleLocked())
- report_fatal_error("Nesting of .bundle_lock is forbidden");
+
+ if (!SD->isBundleLocked())
+ SD->setBundleGroupBeforeFirstInst(true);
SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd :
MCSectionData::BundleLocked);
- SD->setBundleGroupBeforeFirstInst(true);
}
void MCELFStreamer::EmitBundleUnlock() {
@@ -543,12 +560,10 @@ void MCELFStreamer::FinishImpl() {
MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_ostream &OS, MCCodeEmitter *CE,
- bool RelaxAll, bool NoExecStack) {
+ bool RelaxAll) {
MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
- if (NoExecStack)
- S->getAssembler().setNoExecStack(true);
return S;
}