forked from OSchip/llvm-project
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
This commit is contained in:
parent
ee4e08ba94
commit
e3a20f57d9
|
@ -52,7 +52,8 @@ public:
|
||||||
FT_Dwarf,
|
FT_Dwarf,
|
||||||
FT_DwarfFrame,
|
FT_DwarfFrame,
|
||||||
FT_LEB,
|
FT_LEB,
|
||||||
FT_SafeSEH
|
FT_SafeSEH,
|
||||||
|
FT_Dummy
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -136,9 +137,19 @@ public:
|
||||||
/// and only some fragments have a meaningful implementation.
|
/// and only some fragments have a meaningful implementation.
|
||||||
void setBundlePadding(uint8_t N) { BundlePadding = N; }
|
void setBundlePadding(uint8_t N) { BundlePadding = N; }
|
||||||
|
|
||||||
|
/// \brief Return true if given frgment has FT_Dummy type.
|
||||||
|
bool isDummy() const { return Kind == FT_Dummy; }
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MCDummyFragment : public MCFragment {
|
||||||
|
public:
|
||||||
|
explicit MCDummyFragment(MCSection *Sec)
|
||||||
|
: MCFragment(FT_Dummy, false, 0, Sec){};
|
||||||
|
static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
|
||||||
|
};
|
||||||
|
|
||||||
/// Interface implemented by fragments that contain encoded instructions and/or
|
/// Interface implemented by fragments that contain encoded instructions and/or
|
||||||
/// data.
|
/// data.
|
||||||
///
|
///
|
||||||
|
|
|
@ -20,6 +20,7 @@ class MCAsmLayout;
|
||||||
class MCAssembler;
|
class MCAssembler;
|
||||||
class MCContext;
|
class MCContext;
|
||||||
class MCFixup;
|
class MCFixup;
|
||||||
|
class MCFragment;
|
||||||
class MCSection;
|
class MCSection;
|
||||||
class MCStreamer;
|
class MCStreamer;
|
||||||
class MCSymbol;
|
class MCSymbol;
|
||||||
|
@ -115,7 +116,7 @@ public:
|
||||||
/// currently defined as the absolute section for constants, or
|
/// currently defined as the absolute section for constants, or
|
||||||
/// otherwise the section associated with the first defined symbol in the
|
/// otherwise the section associated with the first defined symbol in the
|
||||||
/// expression.
|
/// expression.
|
||||||
MCSection *findAssociatedSection() const;
|
MCFragment *findAssociatedFragment() const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
@ -556,7 +557,7 @@ public:
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const = 0;
|
const MCFixup *Fixup) const = 0;
|
||||||
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
|
virtual void visitUsedExpr(MCStreamer& Streamer) const = 0;
|
||||||
virtual MCSection *findAssociatedSection() const = 0;
|
virtual MCFragment *findAssociatedFragment() const = 0;
|
||||||
|
|
||||||
virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0;
|
virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,11 @@ public:
|
||||||
void executePostLayoutBinding(MCAssembler &Asm,
|
void executePostLayoutBinding(MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout) override;
|
const MCAsmLayout &Layout) override;
|
||||||
|
|
||||||
|
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||||
|
const MCSymbol &A,
|
||||||
|
const MCSymbol &B,
|
||||||
|
bool InSet) const override;
|
||||||
|
|
||||||
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||||
const MCSymbol &SymA,
|
const MCSymbol &SymA,
|
||||||
const MCFragment &FB, bool InSet,
|
const MCFragment &FB, bool InSet,
|
||||||
|
|
|
@ -92,6 +92,11 @@ public:
|
||||||
const MCSymbolRefExpr *B,
|
const MCSymbolRefExpr *B,
|
||||||
bool InSet) const;
|
bool InSet) const;
|
||||||
|
|
||||||
|
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||||
|
const MCSymbol &A,
|
||||||
|
const MCSymbol &B,
|
||||||
|
bool InSet) const;
|
||||||
|
|
||||||
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||||
const MCSymbol &SymA,
|
const MCSymbol &SymA,
|
||||||
const MCFragment &FB,
|
const MCFragment &FB,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/ilist.h"
|
#include "llvm/ADT/ilist.h"
|
||||||
#include "llvm/ADT/ilist_node.h"
|
#include "llvm/ADT/ilist_node.h"
|
||||||
|
#include "llvm/MC/MCAssembler.h"
|
||||||
#include "llvm/MC/SectionKind.h"
|
#include "llvm/MC/SectionKind.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
|
||||||
|
@ -92,6 +93,8 @@ private:
|
||||||
|
|
||||||
unsigned IsRegistered : 1;
|
unsigned IsRegistered : 1;
|
||||||
|
|
||||||
|
MCDummyFragment DummyFragment;
|
||||||
|
|
||||||
FragmentListType Fragments;
|
FragmentListType Fragments;
|
||||||
|
|
||||||
/// Mapping from subsection number to insertion point for subsection numbers
|
/// Mapping from subsection number to insertion point for subsection numbers
|
||||||
|
@ -152,6 +155,9 @@ public:
|
||||||
return const_cast<MCSection *>(this)->getFragmentList();
|
return const_cast<MCSection *>(this)->getFragmentList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
|
||||||
|
MCDummyFragment &getDummyFragment() { return DummyFragment; }
|
||||||
|
|
||||||
MCSection::iterator begin();
|
MCSection::iterator begin();
|
||||||
MCSection::const_iterator begin() const {
|
MCSection::const_iterator begin() const {
|
||||||
return const_cast<MCSection *>(this)->begin();
|
return const_cast<MCSection *>(this)->begin();
|
||||||
|
|
|
@ -358,7 +358,7 @@ public:
|
||||||
///
|
///
|
||||||
/// Each emitted symbol will be tracked in the ordering table,
|
/// Each emitted symbol will be tracked in the ordering table,
|
||||||
/// so we can sort on them later.
|
/// so we can sort on them later.
|
||||||
void AssignSection(MCSymbol *Symbol, MCSection *Section);
|
void AssignFragment(MCSymbol *Symbol, MCFragment *Fragment);
|
||||||
|
|
||||||
/// \brief Emit a label for \p Symbol into the current section.
|
/// \brief Emit a label for \p Symbol into the current section.
|
||||||
///
|
///
|
||||||
|
|
|
@ -56,19 +56,17 @@ protected:
|
||||||
SymContentsCommon,
|
SymContentsCommon,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special sentinal value for the absolute pseudo section.
|
// Special sentinal value for the absolute pseudo fragment.
|
||||||
//
|
static MCFragment *AbsolutePseudoFragment;
|
||||||
// FIXME: Use a PointerInt wrapper for this?
|
|
||||||
static MCSection *AbsolutePseudoSection;
|
|
||||||
|
|
||||||
/// If a symbol has a Fragment, the section is implied, so we only need
|
/// If a symbol has a Fragment, the section is implied, so we only need
|
||||||
/// one pointer.
|
/// one pointer.
|
||||||
|
/// The special AbsolutePseudoFragment value is for absolute symbols.
|
||||||
|
/// If this is a variable symbol, this caches the variable value's fragment.
|
||||||
/// FIXME: We might be able to simplify this by having the asm streamer create
|
/// FIXME: We might be able to simplify this by having the asm streamer create
|
||||||
/// dummy fragments.
|
/// dummy fragments.
|
||||||
/// If this is a section, then it gives the symbol is defined in. This is null
|
/// If this is a section, then it gives the symbol is defined in. This is null
|
||||||
/// for undefined symbols, and the special AbsolutePseudoSection value for
|
/// for undefined symbols.
|
||||||
/// absolute symbols. If this is a variable symbol, this caches the variable
|
|
||||||
/// value's section.
|
|
||||||
///
|
///
|
||||||
/// If this is a fragment, then it gives the fragment this symbol's value is
|
/// If this is a fragment, then it gives the fragment this symbol's value is
|
||||||
/// relative to, if any.
|
/// relative to, if any.
|
||||||
|
@ -76,8 +74,7 @@ protected:
|
||||||
/// For the 'HasName' integer, this is true if this symbol is named.
|
/// For the 'HasName' integer, this is true if this symbol is named.
|
||||||
/// A named symbol will have a pointer to the name allocated in the bytes
|
/// A named symbol will have a pointer to the name allocated in the bytes
|
||||||
/// immediately prior to the MCSymbol.
|
/// immediately prior to the MCSymbol.
|
||||||
mutable PointerIntPair<PointerUnion<MCSection *, MCFragment *>, 1>
|
mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName;
|
||||||
SectionOrFragmentAndHasName;
|
|
||||||
|
|
||||||
/// IsTemporary - True if this is an assembler temporary label, which
|
/// IsTemporary - True if this is an assembler temporary label, which
|
||||||
/// typically does not survive in the .o file's symbol table. Usually
|
/// typically does not survive in the .o file's symbol table. Usually
|
||||||
|
@ -155,7 +152,7 @@ protected: // MCContext creates and uniques these.
|
||||||
Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
|
Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
|
||||||
CommonAlignLog2(0), Flags(0) {
|
CommonAlignLog2(0), Flags(0) {
|
||||||
Offset = 0;
|
Offset = 0;
|
||||||
SectionOrFragmentAndHasName.setInt(!!Name);
|
FragmentAndHasName.setInt(!!Name);
|
||||||
if (Name)
|
if (Name)
|
||||||
getNameEntryPtr() = Name;
|
getNameEntryPtr() = Name;
|
||||||
}
|
}
|
||||||
|
@ -180,19 +177,16 @@ private:
|
||||||
MCSymbol(const MCSymbol &) = delete;
|
MCSymbol(const MCSymbol &) = delete;
|
||||||
void operator=(const MCSymbol &) = delete;
|
void operator=(const MCSymbol &) = delete;
|
||||||
MCSection *getSectionPtr(bool SetUsed = true) const {
|
MCSection *getSectionPtr(bool SetUsed = true) const {
|
||||||
if (MCFragment *F = getFragment())
|
if (MCFragment *F = getFragment(SetUsed)) {
|
||||||
|
assert(F != AbsolutePseudoFragment);
|
||||||
return F->getParent();
|
return F->getParent();
|
||||||
const auto &SectionOrFragment = SectionOrFragmentAndHasName.getPointer();
|
}
|
||||||
assert(!SectionOrFragment.is<MCFragment *>() && "Section or null expected");
|
return nullptr;
|
||||||
MCSection *Section = SectionOrFragment.dyn_cast<MCSection *>();
|
|
||||||
if (Section || !isVariable())
|
|
||||||
return Section;
|
|
||||||
return Section = getVariableValue(SetUsed)->findAssociatedSection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get a reference to the name field. Requires that we have a name
|
/// \brief Get a reference to the name field. Requires that we have a name
|
||||||
const StringMapEntry<bool> *&getNameEntryPtr() {
|
const StringMapEntry<bool> *&getNameEntryPtr() {
|
||||||
assert(SectionOrFragmentAndHasName.getInt() && "Name is required");
|
assert(FragmentAndHasName.getInt() && "Name is required");
|
||||||
NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
|
NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
|
||||||
return (*(Name - 1)).NameEntry;
|
return (*(Name - 1)).NameEntry;
|
||||||
}
|
}
|
||||||
|
@ -203,7 +197,7 @@ private:
|
||||||
public:
|
public:
|
||||||
/// getName - Get the symbol name.
|
/// getName - Get the symbol name.
|
||||||
StringRef getName() const {
|
StringRef getName() const {
|
||||||
if (!SectionOrFragmentAndHasName.getInt())
|
if (!FragmentAndHasName.getInt())
|
||||||
return StringRef();
|
return StringRef();
|
||||||
|
|
||||||
return getNameEntryPtr()->first();
|
return getNameEntryPtr()->first();
|
||||||
|
@ -249,7 +243,7 @@ public:
|
||||||
///
|
///
|
||||||
/// Defined symbols are either absolute or in some section.
|
/// Defined symbols are either absolute or in some section.
|
||||||
bool isDefined(bool SetUsed = true) const {
|
bool isDefined(bool SetUsed = true) const {
|
||||||
return getSectionPtr(SetUsed) != nullptr;
|
return getFragment(SetUsed) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isInSection - Check if this symbol is defined in some section (i.e., it
|
/// isInSection - Check if this symbol is defined in some section (i.e., it
|
||||||
|
@ -263,7 +257,7 @@ public:
|
||||||
|
|
||||||
/// isAbsolute - Check if this is an absolute symbol.
|
/// isAbsolute - Check if this is an absolute symbol.
|
||||||
bool isAbsolute(bool SetUsed = true) const {
|
bool isAbsolute(bool SetUsed = true) const {
|
||||||
return getSectionPtr(SetUsed) == AbsolutePseudoSection;
|
return getFragment(SetUsed) == AbsolutePseudoFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the section associated with a defined, non-absolute symbol.
|
/// Get the section associated with a defined, non-absolute symbol.
|
||||||
|
@ -272,19 +266,14 @@ public:
|
||||||
return *getSectionPtr(SetUsed);
|
return *getSectionPtr(SetUsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark the symbol as defined in the section \p S.
|
/// Mark the symbol as defined in the fragment \p F.
|
||||||
void setSection(MCSection &S) {
|
void setFragment(MCFragment *F) const {
|
||||||
assert(!isVariable() && "Cannot set section of variable");
|
assert(!isVariable() && "Cannot set fragment of variable");
|
||||||
assert(!SectionOrFragmentAndHasName.getPointer().is<MCFragment *>() &&
|
FragmentAndHasName.setPointer(F);
|
||||||
"Section or null expected");
|
|
||||||
SectionOrFragmentAndHasName.setPointer(&S);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark the symbol as undefined.
|
/// Mark the symbol as undefined.
|
||||||
void setUndefined() {
|
void setUndefined() { FragmentAndHasName.setPointer(nullptr); }
|
||||||
SectionOrFragmentAndHasName.setPointer(
|
|
||||||
PointerUnion<MCSection *, MCFragment *>());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isELF() const { return Kind == SymbolKindELF; }
|
bool isELF() const { return Kind == SymbolKindELF; }
|
||||||
|
|
||||||
|
@ -385,11 +374,13 @@ public:
|
||||||
return SymbolContents == SymContentsCommon;
|
return SymbolContents == SymContentsCommon;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCFragment *getFragment() const {
|
MCFragment *getFragment(bool SetUsed = true) const {
|
||||||
return SectionOrFragmentAndHasName.getPointer().dyn_cast<MCFragment *>();
|
MCFragment *Fragment = FragmentAndHasName.getPointer();
|
||||||
}
|
if (Fragment || !isVariable())
|
||||||
void setFragment(MCFragment *Value) const {
|
return Fragment;
|
||||||
SectionOrFragmentAndHasName.setPointer(Value);
|
Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
|
||||||
|
FragmentAndHasName.setPointer(Fragment);
|
||||||
|
return Fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isExternal() const { return IsExternal; }
|
bool isExternal() const { return IsExternal; }
|
||||||
|
|
|
@ -447,9 +447,6 @@ void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer,
|
||||||
uint32_t StringIndex, ELFSymbolData &MSD,
|
uint32_t StringIndex, ELFSymbolData &MSD,
|
||||||
const MCAsmLayout &Layout) {
|
const MCAsmLayout &Layout) {
|
||||||
const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
|
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 =
|
const MCSymbolELF *Base =
|
||||||
cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
|
cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
|
||||||
|
|
||||||
|
|
|
@ -575,7 +575,7 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
||||||
uint64_t Size, unsigned ByteAlignment) {
|
uint64_t Size, unsigned ByteAlignment) {
|
||||||
if (Symbol)
|
if (Symbol)
|
||||||
AssignSection(Symbol, Section);
|
AssignFragment(Symbol, &Section->getDummyFragment());
|
||||||
|
|
||||||
// Note: a .zerofill directive does not switch sections.
|
// Note: a .zerofill directive does not switch sections.
|
||||||
OS << ".zerofill ";
|
OS << ".zerofill ";
|
||||||
|
@ -599,7 +599,7 @@ void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
||||||
// e.g. _a.
|
// e.g. _a.
|
||||||
void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
|
void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
|
||||||
uint64_t Size, unsigned ByteAlignment) {
|
uint64_t Size, unsigned ByteAlignment) {
|
||||||
AssignSection(Symbol, Section);
|
AssignFragment(Symbol, &Section->getDummyFragment());
|
||||||
|
|
||||||
assert(Symbol && "Symbol shouldn't be NULL!");
|
assert(Symbol && "Symbol shouldn't be NULL!");
|
||||||
// Instead of using the Section we'll just use the shortcut.
|
// Instead of using the Section we'll just use the shortcut.
|
||||||
|
|
|
@ -277,7 +277,7 @@ MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
|
||||||
: Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
|
: Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
|
||||||
BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
|
BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
|
||||||
Offset(~UINT64_C(0)) {
|
Offset(~UINT64_C(0)) {
|
||||||
if (Parent)
|
if (Parent && !isDummy())
|
||||||
Parent->getFragmentList().push_back(this);
|
Parent->getFragmentList().push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +319,9 @@ void MCFragment::destroy() {
|
||||||
case FT_SafeSEH:
|
case FT_SafeSEH:
|
||||||
delete cast<MCSafeSEHFragment>(this);
|
delete cast<MCSafeSEHFragment>(this);
|
||||||
return;
|
return;
|
||||||
|
case FT_Dummy:
|
||||||
|
delete cast<MCDummyFragment>(this);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +414,7 @@ const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const {
|
||||||
return &S;
|
return &S;
|
||||||
|
|
||||||
// Absolute and undefined symbols have no defining atom.
|
// Absolute and undefined symbols have no defining atom.
|
||||||
if (!S.getFragment())
|
if (!S.isInSection())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Non-linker visible symbols in sections which can't be atomized have no
|
// 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();
|
return cast<MCDwarfLineAddrFragment>(F).getContents().size();
|
||||||
case MCFragment::FT_DwarfFrame:
|
case MCFragment::FT_DwarfFrame:
|
||||||
return cast<MCDwarfCallFrameFragment>(F).getContents().size();
|
return cast<MCDwarfCallFrameFragment>(F).getContents().size();
|
||||||
|
case MCFragment::FT_Dummy:
|
||||||
|
llvm_unreachable("Should not have been added");
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("invalid fragment kind");
|
llvm_unreachable("invalid fragment kind");
|
||||||
|
@ -780,6 +785,8 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||||
OW->writeBytes(CF.getContents());
|
OW->writeBytes(CF.getContents());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MCFragment::FT_Dummy:
|
||||||
|
llvm_unreachable("Should not have been added");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(OW->getStream().tell() - Start == FragmentSize &&
|
assert(OW->getStream().tell() - Start == FragmentSize &&
|
||||||
|
@ -1147,6 +1154,9 @@ void MCFragment::dump() {
|
||||||
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
|
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
|
||||||
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
|
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
|
||||||
case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break;
|
case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break;
|
||||||
|
case MCFragment::FT_Dummy:
|
||||||
|
OS << "MCDummyFragment";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
|
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
|
||||||
|
@ -1245,6 +1255,8 @@ void MCFragment::dump() {
|
||||||
OS << " Sym:" << F->getSymbol();
|
OS << " Sym:" << F->getSymbol();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MCFragment::FT_Dummy:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
OS << ">";
|
OS << ">";
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ void MCELFStreamer::EmitLabel(MCSymbol *S) {
|
||||||
MCObjectStreamer::EmitLabel(Symbol);
|
MCObjectStreamer::EmitLabel(Symbol);
|
||||||
|
|
||||||
const MCSectionELF &Section =
|
const MCSectionELF &Section =
|
||||||
static_cast<const MCSectionELF&>(Symbol->getSection());
|
static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
|
||||||
if (Section.getFlags() & ELF::SHF_TLS)
|
if (Section.getFlags() & ELF::SHF_TLS)
|
||||||
Symbol->setType(ELF::STT_TLS);
|
Symbol->setType(ELF::STT_TLS);
|
||||||
}
|
}
|
||||||
|
@ -311,11 +311,6 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
|
||||||
Symbol->setType(ELF::STT_OBJECT);
|
Symbol->setType(ELF::STT_OBJECT);
|
||||||
|
|
||||||
if (Symbol->getBinding() == ELF::STB_LOCAL) {
|
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};
|
struct LocalCommon L = {Symbol, Size, ByteAlignment};
|
||||||
LocalCommons.push_back(L);
|
LocalCommons.push_back(L);
|
||||||
} else {
|
} else {
|
||||||
|
@ -630,7 +625,8 @@ void MCELFStreamer::Flush() {
|
||||||
const MCSymbol &Symbol = *i->Symbol;
|
const MCSymbol &Symbol = *i->Symbol;
|
||||||
uint64_t Size = i->Size;
|
uint64_t Size = i->Size;
|
||||||
unsigned ByteAlignment = i->ByteAlignment;
|
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);
|
getAssembler().registerSection(Section);
|
||||||
new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &Section);
|
new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &Section);
|
||||||
|
|
|
@ -477,7 +477,8 @@ static void AttemptToFoldSymbolOffsetDifference(
|
||||||
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
|
if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SA.getFragment() == SB.getFragment()) {
|
if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
|
||||||
|
!SB.isVariable()) {
|
||||||
Addend += (SA.getOffset() - SB.getOffset());
|
Addend += (SA.getOffset() - SB.getOffset());
|
||||||
|
|
||||||
// Pointers to Thumb symbols need to have their low-bit set to allow
|
// 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);
|
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 MCExpr *Expr = Sym.getVariableValue();
|
||||||
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
|
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||||
if (Inner) {
|
if (Inner) {
|
||||||
|
@ -616,9 +617,7 @@ static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm, bool InSet) {
|
||||||
|
|
||||||
if (InSet)
|
if (InSet)
|
||||||
return true;
|
return true;
|
||||||
if (!Asm)
|
return !Sym.isInSection();
|
||||||
return false;
|
|
||||||
return !Asm->getWriter().isWeak(Sym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
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.
|
// Evaluate recursively if this is a variable.
|
||||||
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
|
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
|
||||||
canExpand(Sym, Asm, InSet)) {
|
canExpand(Sym, InSet)) {
|
||||||
bool IsMachO = SRE->hasSubsectionsViaSymbols();
|
bool IsMachO = SRE->hasSubsectionsViaSymbols();
|
||||||
if (Sym.getVariableValue()->evaluateAsRelocatableImpl(
|
if (Sym.getVariableValue()->evaluateAsRelocatableImpl(
|
||||||
Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) {
|
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!");
|
llvm_unreachable("Invalid assembly expression kind!");
|
||||||
}
|
}
|
||||||
|
|
||||||
MCSection *MCExpr::findAssociatedSection() const {
|
MCFragment *MCExpr::findAssociatedFragment() const {
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
case Target:
|
case Target:
|
||||||
// We never look through target specific expressions.
|
// We never look through target specific expressions.
|
||||||
return cast<MCTargetExpr>(this)->findAssociatedSection();
|
return cast<MCTargetExpr>(this)->findAssociatedFragment();
|
||||||
|
|
||||||
case Constant:
|
case Constant:
|
||||||
return MCSymbol::AbsolutePseudoSection;
|
return MCSymbol::AbsolutePseudoFragment;
|
||||||
|
|
||||||
case SymbolRef: {
|
case SymbolRef: {
|
||||||
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
|
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
|
||||||
const MCSymbol &Sym = SRE->getSymbol();
|
const MCSymbol &Sym = SRE->getSymbol();
|
||||||
|
return Sym.getFragment();
|
||||||
if (Sym.isDefined())
|
|
||||||
return &Sym.getSection();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case Unary:
|
case Unary:
|
||||||
return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedSection();
|
return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment();
|
||||||
|
|
||||||
case Binary: {
|
case Binary: {
|
||||||
const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
|
||||||
MCSection *LHS_S = BE->getLHS()->findAssociatedSection();
|
MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment();
|
||||||
MCSection *RHS_S = BE->getRHS()->findAssociatedSection();
|
MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment();
|
||||||
|
|
||||||
// If either section is absolute, return the other.
|
// If either is absolute, return the other.
|
||||||
if (LHS_S == MCSymbol::AbsolutePseudoSection)
|
if (LHS_F == MCSymbol::AbsolutePseudoFragment)
|
||||||
return RHS_S;
|
return RHS_F;
|
||||||
if (RHS_S == MCSymbol::AbsolutePseudoSection)
|
if (RHS_F == MCSymbol::AbsolutePseudoFragment)
|
||||||
return LHS_S;
|
return LHS_F;
|
||||||
|
|
||||||
// Not always correct, but probably the best we can do without more context.
|
// Not always correct, but probably the best we can do without more context.
|
||||||
if (BE->getOpcode() == MCBinaryExpr::Sub)
|
if (BE->getOpcode() == MCBinaryExpr::Sub)
|
||||||
return MCSymbol::AbsolutePseudoSection;
|
return MCSymbol::AbsolutePseudoFragment;
|
||||||
|
|
||||||
// Otherwise, return the first non-null section.
|
// Otherwise, return the first non-null fragment.
|
||||||
return LHS_S ? LHS_S : RHS_S;
|
return LHS_F ? LHS_F : RHS_F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,8 +180,6 @@ void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
|
||||||
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
|
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
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,
|
// We have to create a new fragment if this is an atom defining symbol,
|
||||||
// fragments cannot span atoms.
|
// fragments cannot span atoms.
|
||||||
if (getAssembler().isSymbolLinkerVisible(*Symbol))
|
if (getAssembler().isSymbolLinkerVisible(*Symbol))
|
||||||
|
@ -415,8 +413,6 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
|
||||||
if (ByteAlignment != 1)
|
if (ByteAlignment != 1)
|
||||||
new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section);
|
new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section);
|
||||||
|
|
||||||
AssignSection(Symbol, Section);
|
|
||||||
|
|
||||||
MCFragment *F = new MCFillFragment(0, 0, Size, Section);
|
MCFragment *F = new MCFillFragment(0, 0, Size, Section);
|
||||||
Symbol->setFragment(F);
|
Symbol->setFragment(F);
|
||||||
|
|
||||||
|
@ -460,7 +456,8 @@ void MCMachOStreamer::FinishImpl() {
|
||||||
// defining symbols.
|
// defining symbols.
|
||||||
DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
|
DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
|
||||||
for (const MCSymbol &Symbol : getAssembler().symbols()) {
|
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.
|
// An atom defining symbol should never be internal to a fragment.
|
||||||
assert(Symbol.getOffset() == 0 &&
|
assert(Symbol.getOffset() == 0 &&
|
||||||
"Invalid offset in atom defining symbol!");
|
"Invalid offset in atom defining symbol!");
|
||||||
|
|
|
@ -58,7 +58,8 @@ void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
|
||||||
const MCSymbol *Lo,
|
const MCSymbol *Lo,
|
||||||
unsigned Size) {
|
unsigned Size) {
|
||||||
// If not assigned to the same (valid) fragment, fallback.
|
// 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);
|
MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +156,6 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
MCStreamer::EmitLabel(Symbol);
|
MCStreamer::EmitLabel(Symbol);
|
||||||
|
|
||||||
getAssembler().registerSymbol(*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.
|
// 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
|
// Otherwise queue the label and set its fragment pointer when we emit the
|
||||||
|
|
|
@ -33,8 +33,14 @@ bool MCObjectWriter::isSymbolRefDifferenceFullyResolved(
|
||||||
if (!SA.getFragment() || !SB.getFragment())
|
if (!SA.getFragment() || !SB.getFragment())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, *SB.getFragment(),
|
return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, SB, InSet);
|
||||||
InSet, false);
|
}
|
||||||
|
|
||||||
|
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(
|
bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
|
||||||
|
|
|
@ -21,7 +21,7 @@ using namespace llvm;
|
||||||
|
|
||||||
MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
|
MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
|
||||||
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
|
: 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) {
|
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
|
||||||
if (!End)
|
if (!End)
|
||||||
|
|
|
@ -188,9 +188,9 @@ void MCStreamer::InitSections(bool NoExecStack) {
|
||||||
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
|
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCStreamer::AssignSection(MCSymbol *Symbol, MCSection *Section) {
|
void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
|
||||||
assert(Section);
|
assert(Fragment);
|
||||||
Symbol->setSection(*Section);
|
Symbol->setFragment(Fragment);
|
||||||
|
|
||||||
// As we emit symbols into a section, track the order so that they can
|
// As we emit symbols into a section, track the order so that they can
|
||||||
// be sorted upon later. Zero is reserved to mean 'unemitted'.
|
// 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) {
|
void MCStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
|
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
|
||||||
assert(getCurrentSection().first && "Cannot emit before setting section!");
|
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();
|
MCTargetStreamer *TS = getTargetStreamer();
|
||||||
if (TS)
|
if (TS)
|
||||||
|
|
|
@ -16,8 +16,9 @@
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// Sentinel value for the absolute pseudo section.
|
// Sentinel value for the absolute pseudo fragment.
|
||||||
MCSection *MCSymbol::AbsolutePseudoSection = reinterpret_cast<MCSection *>(1);
|
MCFragment *MCSymbol::AbsolutePseudoFragment =
|
||||||
|
reinterpret_cast<MCFragment *>(4);
|
||||||
|
|
||||||
void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name,
|
void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name,
|
||||||
MCContext &Ctx) {
|
MCContext &Ctx) {
|
||||||
|
|
|
@ -625,6 +625,18 @@ void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
||||||
bindIndirectSymbols(Asm);
|
bindIndirectSymbols(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(
|
bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
|
||||||
const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
|
const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
|
||||||
bool InSet, bool IsPCRel) const {
|
bool InSet, bool IsPCRel) const {
|
||||||
|
|
|
@ -245,8 +245,6 @@ void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
getAssembler().registerSymbol(*Symbol);
|
getAssembler().registerSymbol(*Symbol);
|
||||||
Symbol->setExternal(false);
|
Symbol->setExternal(false);
|
||||||
|
|
||||||
AssignSection(Symbol, Section);
|
|
||||||
|
|
||||||
if (ByteAlignment != 1)
|
if (ByteAlignment != 1)
|
||||||
new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
|
new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
|
||||||
ByteAlignment, Section);
|
ByteAlignment, Section);
|
||||||
|
|
|
@ -85,7 +85,7 @@ void AArch64MCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||||
Streamer.visitUsedExpr(*getSubExpr());
|
Streamer.visitUsedExpr(*getSubExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
MCSection *AArch64MCExpr::findAssociatedSection() const {
|
MCFragment *AArch64MCExpr::findAssociatedFragment() const {
|
||||||
llvm_unreachable("FIXME: what goes here?");
|
llvm_unreachable("FIXME: what goes here?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ public:
|
||||||
|
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||||
|
|
||||||
MCSection *findAssociatedSection() const override;
|
MCFragment *findAssociatedFragment() const override;
|
||||||
|
|
||||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const override;
|
const MCFixup *Fixup) const override;
|
||||||
|
|
|
@ -63,8 +63,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||||
MCSection *findAssociatedSection() const override {
|
MCFragment *findAssociatedFragment() const override {
|
||||||
return getSubExpr()->findAssociatedSection();
|
return getSubExpr()->findAssociatedFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are no TLS ARMMCExprs at the moment.
|
// There are no TLS ARMMCExprs at the moment.
|
||||||
|
|
|
@ -114,7 +114,7 @@ void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
|
||||||
MCSection *Section = getAssembler().getContext().getELFSection(
|
MCSection *Section = getAssembler().getContext().getELFSection(
|
||||||
SectionName, ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
|
SectionName, ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
|
||||||
SwitchSection(Section);
|
SwitchSection(Section);
|
||||||
AssignSection(Symbol, Section);
|
AssignFragment(Symbol, getCurrentFragment());
|
||||||
|
|
||||||
MCELFStreamer::EmitCommonSymbol(Symbol, Size, ByteAlignment);
|
MCELFStreamer::EmitCommonSymbol(Symbol, Size, ByteAlignment);
|
||||||
SwitchSection(CrntSection);
|
SwitchSection(CrntSection);
|
||||||
|
|
|
@ -51,8 +51,8 @@ public:
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const override;
|
const MCFixup *Fixup) const override;
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||||
MCSection *findAssociatedSection() const override {
|
MCFragment *findAssociatedFragment() const override {
|
||||||
return getSubExpr()->findAssociatedSection();
|
return getSubExpr()->findAssociatedFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are no TLS MipsMCExprs at the moment.
|
// There are no TLS MipsMCExprs at the moment.
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override {};
|
void visitUsedExpr(MCStreamer &Streamer) const override {};
|
||||||
MCSection *findAssociatedSection() const override { return nullptr; }
|
MCFragment *findAssociatedFragment() const override { return nullptr; }
|
||||||
|
|
||||||
// There are no TLS NVPTXMCExprs at the moment.
|
// There are no TLS NVPTXMCExprs at the moment.
|
||||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||||
|
@ -110,7 +110,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override {};
|
void visitUsedExpr(MCStreamer &Streamer) const override {};
|
||||||
MCSection *findAssociatedSection() const override { return nullptr; }
|
MCFragment *findAssociatedFragment() const override { return nullptr; }
|
||||||
|
|
||||||
// There are no TLS NVPTXMCExprs at the moment.
|
// There are no TLS NVPTXMCExprs at the moment.
|
||||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||||
|
|
|
@ -82,8 +82,8 @@ public:
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const override;
|
const MCFixup *Fixup) const override;
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||||
MCSection *findAssociatedSection() const override {
|
MCFragment *findAssociatedFragment() const override {
|
||||||
return getSubExpr()->findAssociatedSection();
|
return getSubExpr()->findAssociatedFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are no TLS PPCMCExprs at the moment.
|
// There are no TLS PPCMCExprs at the moment.
|
||||||
|
|
|
@ -90,8 +90,8 @@ public:
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const override;
|
const MCFixup *Fixup) const override;
|
||||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||||
MCSection *findAssociatedSection() const override {
|
MCFragment *findAssociatedFragment() const override {
|
||||||
return getSubExpr()->findAssociatedSection();
|
return getSubExpr()->findAssociatedFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
||||||
|
|
|
@ -21,9 +21,9 @@ weak_aliased_to_external = external2
|
||||||
.long weak_aliased_to_external
|
.long weak_aliased_to_external
|
||||||
|
|
||||||
// CHECK: Relocations [
|
// CHECK: Relocations [
|
||||||
// CHECK: 0x0 IMAGE_REL_I386_DIR32 local1
|
// CHECK: 0x0 IMAGE_REL_I386_DIR32 external_aliased_to_local
|
||||||
// CHECK: 0x4 IMAGE_REL_I386_DIR32 external1
|
// CHECK: 0x4 IMAGE_REL_I386_DIR32 external1
|
||||||
// CHECK: 0x8 IMAGE_REL_I386_DIR32 local2
|
// CHECK: 0x8 IMAGE_REL_I386_DIR32 global_aliased_to_local
|
||||||
// CHECK: 0xC IMAGE_REL_I386_DIR32 external2
|
// CHECK: 0xC IMAGE_REL_I386_DIR32 external2
|
||||||
// CHECK: ]
|
// CHECK: ]
|
||||||
// CHECK: Symbols [
|
// CHECK: Symbols [
|
||||||
|
|
|
@ -55,6 +55,11 @@ bar:
|
||||||
.quad pr23272_2 - pr23272
|
.quad pr23272_2 - pr23272
|
||||||
.quad pr23272_3 - pr23272
|
.quad pr23272_3 - pr23272
|
||||||
|
|
||||||
|
.global pr24486
|
||||||
|
pr24486:
|
||||||
|
pr24486_alias = pr24486
|
||||||
|
.long pr24486_alias
|
||||||
|
|
||||||
.code16
|
.code16
|
||||||
call pr23771
|
call pr23771
|
||||||
|
|
||||||
|
@ -94,6 +99,7 @@ bar:
|
||||||
// CHECK-NEXT: 0xD4 R_X86_64_SIZE32 blah 0xFFFFFFFFFFFFFFE0
|
// CHECK-NEXT: 0xD4 R_X86_64_SIZE32 blah 0xFFFFFFFFFFFFFFE0
|
||||||
// CHECK-NEXT: 0xD8 R_X86_64_GOTPCREL foo 0x0
|
// CHECK-NEXT: 0xD8 R_X86_64_GOTPCREL foo 0x0
|
||||||
// CHECK-NEXT: 0xDC R_X86_64_PLT32 foo 0x0
|
// CHECK-NEXT: 0xDC R_X86_64_PLT32 foo 0x0
|
||||||
// CHECK-NEXT: 0xF1 R_X86_64_PC16 pr23771 0xFFFFFFFFFFFFFFFE
|
// CHECK-NEXT: 0xF0 R_X86_64_32 .text 0xF0
|
||||||
|
// CHECK-NEXT: 0xF5 R_X86_64_PC16 pr23771 0xFFFFFFFFFFFFFFFE
|
||||||
// CHECK-NEXT: ]
|
// CHECK-NEXT: ]
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
Loading…
Reference in New Issue