summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-10-05 12:07:05 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-10-05 12:07:05 +0000
commite3a20f57d927e422874a8e7730bb7590515b586d (patch)
treec173b7c07c1267489d17715ee156ee7a8412a78c /llvm/lib/MC
parentee4e08ba94e2ee04ad7ad0e0e396147be417c79f (diff)
downloadbcm5719-llvm-e3a20f57d927e422874a8e7730bb7590515b586d.tar.gz
bcm5719-llvm-e3a20f57d927e422874a8e7730bb7590515b586d.zip
Fix pr24486.
This extends the work done in r233995 so that now getFragment (in addition to getSection) also works for variable symbols. With that the existing logic to decide if a-b can be computed works even if a or b are variables. Given that, the expression evaluation can avoid expanding variables as aggressively and that in turn lets the relocation code see the original variable. In order for this to work with the asm streamer, there is now a dummy fragment per section. It is used to assign a section to a symbol when no other fragment exists. This patch is a joint work by Maxim Ostapenko andy myself. llvm-svn: 249303
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/ELFObjectWriter.cpp3
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp4
-rw-r--r--llvm/lib/MC/MCAssembler.cpp16
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp10
-rw-r--r--llvm/lib/MC/MCExpr.cpp45
-rw-r--r--llvm/lib/MC/MCMachOStreamer.cpp7
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp4
-rw-r--r--llvm/lib/MC/MCObjectWriter.cpp10
-rw-r--r--llvm/lib/MC/MCSection.cpp2
-rw-r--r--llvm/lib/MC/MCStreamer.cpp9
-rw-r--r--llvm/lib/MC/MCSymbol.cpp5
-rw-r--r--llvm/lib/MC/MachObjectWriter.cpp12
-rw-r--r--llvm/lib/MC/WinCOFFStreamer.cpp2
13 files changed, 72 insertions, 57 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 16f299c8fd8..f1acc1d75fb 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -447,9 +447,6 @@ void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
uint32_t StringIndex, ELFSymbolData &MSD,
const MCAsmLayout &Layout) {
const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
- assert((!Symbol.getFragment() ||
- (Symbol.getFragment()->getParent() == &Symbol.getSection())) &&
- "The symbol's section doesn't match the fragment's symbol");
const MCSymbolELF *Base =
cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 7a30075bac9..f9dbd5ad3f0 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -575,7 +575,7 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
if (Symbol)
- AssignSection(Symbol, Section);
+ AssignFragment(Symbol, &Section->getDummyFragment());
// Note: a .zerofill directive does not switch sections.
OS << ".zerofill ";
@@ -599,7 +599,7 @@ void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
// e.g. _a.
void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
- AssignSection(Symbol, Section);
+ AssignFragment(Symbol, &Section->getDummyFragment());
assert(Symbol && "Symbol shouldn't be NULL!");
// Instead of using the Section we'll just use the shortcut.
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d93bf44928d..143d284897f 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -277,7 +277,7 @@ MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
: Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
Offset(~UINT64_C(0)) {
- if (Parent)
+ if (Parent && !isDummy())
Parent->getFragmentList().push_back(this);
}
@@ -319,6 +319,9 @@ void MCFragment::destroy() {
case FT_SafeSEH:
delete cast<MCSafeSEHFragment>(this);
return;
+ case FT_Dummy:
+ delete cast<MCDummyFragment>(this);
+ return;
}
}
@@ -411,7 +414,7 @@ const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const {
return &S;
// Absolute and undefined symbols have no defining atom.
- if (!S.getFragment())
+ if (!S.isInSection())
return nullptr;
// Non-linker visible symbols in sections which can't be atomized have no
@@ -547,6 +550,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
return cast<MCDwarfLineAddrFragment>(F).getContents().size();
case MCFragment::FT_DwarfFrame:
return cast<MCDwarfCallFrameFragment>(F).getContents().size();
+ case MCFragment::FT_Dummy:
+ llvm_unreachable("Should not have been added");
}
llvm_unreachable("invalid fragment kind");
@@ -780,6 +785,8 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
OW->writeBytes(CF.getContents());
break;
}
+ case MCFragment::FT_Dummy:
+ llvm_unreachable("Should not have been added");
}
assert(OW->getStream().tell() - Start == FragmentSize &&
@@ -1147,6 +1154,9 @@ void MCFragment::dump() {
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break;
+ case MCFragment::FT_Dummy:
+ OS << "MCDummyFragment";
+ break;
}
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
@@ -1245,6 +1255,8 @@ void MCFragment::dump() {
OS << " Sym:" << F->getSymbol();
break;
}
+ case MCFragment::FT_Dummy:
+ break;
}
OS << ">";
}
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index f0b3ec699fe..fc4f8a6281b 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -111,7 +111,7 @@ void MCELFStreamer::EmitLabel(MCSymbol *S) {
MCObjectStreamer::EmitLabel(Symbol);
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(Symbol->getSection());
+ static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
if (Section.getFlags() & ELF::SHF_TLS)
Symbol->setType(ELF::STT_TLS);
}
@@ -311,11 +311,6 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
Symbol->setType(ELF::STT_OBJECT);
if (Symbol->getBinding() == ELF::STB_LOCAL) {
- MCSection *Section = getAssembler().getContext().getELFSection(
- ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
-
- AssignSection(Symbol, Section);
-
struct LocalCommon L = {Symbol, Size, ByteAlignment};
LocalCommons.push_back(L);
} else {
@@ -630,7 +625,8 @@ void MCELFStreamer::Flush() {
const MCSymbol &Symbol = *i->Symbol;
uint64_t Size = i->Size;
unsigned ByteAlignment = i->ByteAlignment;
- MCSection &Section = Symbol.getSection();
+ MCSection &Section = *getAssembler().getContext().getELFSection(
+ ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
getAssembler().registerSection(Section);
new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &Section);
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 042fd1c72a2..916e505c4b9 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -477,7 +477,8 @@ static void AttemptToFoldSymbolOffsetDifference(
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
return;
- if (SA.getFragment() == SB.getFragment()) {
+ if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
+ !SB.isVariable()) {
Addend += (SA.getOffset() - SB.getOffset());
// Pointers to Thumb symbols need to have their low-bit set to allow
@@ -606,7 +607,7 @@ bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const {
true);
}
-static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm, bool InSet) {
+static bool canExpand(const MCSymbol &Sym, bool InSet) {
const MCExpr *Expr = Sym.getVariableValue();
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
if (Inner) {
@@ -616,9 +617,7 @@ static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm, bool InSet) {
if (InSet)
return true;
- if (!Asm)
- return false;
- return !Asm->getWriter().isWeak(Sym);
+ return !Sym.isInSection();
}
bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
@@ -643,7 +642,7 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
// Evaluate recursively if this is a variable.
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
- canExpand(Sym, Asm, InSet)) {
+ canExpand(Sym, InSet)) {
bool IsMachO = SRE->hasSubsectionsViaSymbols();
if (Sym.getVariableValue()->evaluateAsRelocatableImpl(
Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) {
@@ -775,45 +774,41 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
llvm_unreachable("Invalid assembly expression kind!");
}
-MCSection *MCExpr::findAssociatedSection() const {
+MCFragment *MCExpr::findAssociatedFragment() const {
switch (getKind()) {
case Target:
// We never look through target specific expressions.
- return cast<MCTargetExpr>(this)->findAssociatedSection();
+ return cast<MCTargetExpr>(this)->findAssociatedFragment();
case Constant:
- return MCSymbol::AbsolutePseudoSection;
+ return MCSymbol::AbsolutePseudoFragment;
case SymbolRef: {
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
const MCSymbol &Sym = SRE->getSymbol();
-
- if (Sym.isDefined())
- return &Sym.getSection();
-
- return nullptr;
+ return Sym.getFragment();
}
case Unary:
- return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedSection();
+ return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment();
case Binary: {
const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
- MCSection *LHS_S = BE->getLHS()->findAssociatedSection();
- MCSection *RHS_S = BE->getRHS()->findAssociatedSection();
+ MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment();
+ MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment();
- // If either section is absolute, return the other.
- if (LHS_S == MCSymbol::AbsolutePseudoSection)
- return RHS_S;
- if (RHS_S == MCSymbol::AbsolutePseudoSection)
- return LHS_S;
+ // If either is absolute, return the other.
+ if (LHS_F == MCSymbol::AbsolutePseudoFragment)
+ return RHS_F;
+ if (RHS_F == MCSymbol::AbsolutePseudoFragment)
+ return LHS_F;
// Not always correct, but probably the best we can do without more context.
if (BE->getOpcode() == MCBinaryExpr::Sub)
- return MCSymbol::AbsolutePseudoSection;
+ return MCSymbol::AbsolutePseudoFragment;
- // Otherwise, return the first non-null section.
- return LHS_S ? LHS_S : RHS_S;
+ // Otherwise, return the first non-null fragment.
+ return LHS_F ? LHS_F : RHS_F;
}
}
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 0f65d51bb73..50ee08fa1f9 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -180,8 +180,6 @@ void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
- // isSymbolLinkerVisible uses the section.
- AssignSection(Symbol, getCurrentSection().first);
// We have to create a new fragment if this is an atom defining symbol,
// fragments cannot span atoms.
if (getAssembler().isSymbolLinkerVisible(*Symbol))
@@ -415,8 +413,6 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
if (ByteAlignment != 1)
new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section);
- AssignSection(Symbol, Section);
-
MCFragment *F = new MCFillFragment(0, 0, Size, Section);
Symbol->setFragment(F);
@@ -460,7 +456,8 @@ void MCMachOStreamer::FinishImpl() {
// defining symbols.
DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
for (const MCSymbol &Symbol : getAssembler().symbols()) {
- if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.getFragment()) {
+ if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() &&
+ !Symbol.isVariable()) {
// An atom defining symbol should never be internal to a fragment.
assert(Symbol.getOffset() == 0 &&
"Invalid offset in atom defining symbol!");
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index caee5da47a0..992b2cfe359 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -58,7 +58,8 @@ void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
// If not assigned to the same (valid) fragment, fallback.
- if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment()) {
+ if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
+ Hi->isVariable() || Lo->isVariable()) {
MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
return;
}
@@ -155,7 +156,6 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
MCStreamer::EmitLabel(Symbol);
getAssembler().registerSymbol(*Symbol);
- assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
// If there is a current fragment, mark the symbol as pointing into it.
// Otherwise queue the label and set its fragment pointer when we emit the
diff --git a/llvm/lib/MC/MCObjectWriter.cpp b/llvm/lib/MC/MCObjectWriter.cpp
index 34790340873..e84f74ae81d 100644
--- a/llvm/lib/MC/MCObjectWriter.cpp
+++ b/llvm/lib/MC/MCObjectWriter.cpp
@@ -33,8 +33,14 @@ bool MCObjectWriter::isSymbolRefDifferenceFullyResolved(
if (!SA.getFragment() || !SB.getFragment())
return false;
- return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, *SB.getFragment(),
- InSet, false);
+ return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, SB, InSet);
+}
+
+bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
+ const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
+ bool InSet) const {
+ return isSymbolRefDifferenceFullyResolvedImpl(Asm, A, *B.getFragment(), InSet,
+ false);
}
bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 9152f2b42a4..e0d29bbd660 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -21,7 +21,7 @@ using namespace llvm;
MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
- IsRegistered(false), Variant(V), Kind(K) {}
+ IsRegistered(false), DummyFragment(this), Variant(V), Kind(K) {}
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
if (!End)
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index d6b44a0297d..5d7685177b2 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -188,9 +188,9 @@ void MCStreamer::InitSections(bool NoExecStack) {
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
}
-void MCStreamer::AssignSection(MCSymbol *Symbol, MCSection *Section) {
- assert(Section);
- Symbol->setSection(*Section);
+void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
+ assert(Fragment);
+ Symbol->setFragment(Fragment);
// As we emit symbols into a section, track the order so that they can
// be sorted upon later. Zero is reserved to mean 'unemitted'.
@@ -200,7 +200,8 @@ void MCStreamer::AssignSection(MCSymbol *Symbol, MCSection *Section) {
void MCStreamer::EmitLabel(MCSymbol *Symbol) {
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
assert(getCurrentSection().first && "Cannot emit before setting section!");
- AssignSection(Symbol, getCurrentSection().first);
+ assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
+ Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());
MCTargetStreamer *TS = getTargetStreamer();
if (TS)
diff --git a/llvm/lib/MC/MCSymbol.cpp b/llvm/lib/MC/MCSymbol.cpp
index 125380a9d14..c7d6213bc19 100644
--- a/llvm/lib/MC/MCSymbol.cpp
+++ b/llvm/lib/MC/MCSymbol.cpp
@@ -16,8 +16,9 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-// Sentinel value for the absolute pseudo section.
-MCSection *MCSymbol::AbsolutePseudoSection = reinterpret_cast<MCSection *>(1);
+// Sentinel value for the absolute pseudo fragment.
+MCFragment *MCSymbol::AbsolutePseudoFragment =
+ reinterpret_cast<MCFragment *>(4);
void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name,
MCContext &Ctx) {
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 94d71f1116d..d5184f1d9a4 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -626,6 +626,18 @@ void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
}
bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
+ const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
+ bool InSet) const {
+ // FIXME: We don't handle things like
+ // foo = .
+ // creating atoms.
+ if (A.isVariable() || B.isVariable())
+ return false;
+ return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B,
+ InSet);
+}
+
+bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
bool InSet, bool IsPCRel) const {
if (InSet)
diff --git a/llvm/lib/MC/WinCOFFStreamer.cpp b/llvm/lib/MC/WinCOFFStreamer.cpp
index 40c242ce866..02814fa7d28 100644
--- a/llvm/lib/MC/WinCOFFStreamer.cpp
+++ b/llvm/lib/MC/WinCOFFStreamer.cpp
@@ -245,8 +245,6 @@ void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
getAssembler().registerSymbol(*Symbol);
Symbol->setExternal(false);
- AssignSection(Symbol, Section);
-
if (ByteAlignment != 1)
new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
ByteAlignment, Section);
OpenPOWER on IntegriCloud