// FIXME: Use a PointerInt wrapper for this?
static MCSection *AbsolutePseudoSection;
- /// Name - The name of the symbol. The referred-to string data is actually
- /// held by the StringMap that lives in MCContext.
- const StringMapEntry<bool> *Name;
-
/// If a symbol has a Fragment, the section is implied, so we only need
/// one pointer.
/// FIXME: We might be able to simplify this by having the asm streamer create
/// This symbol is private extern.
mutable unsigned IsPrivateExtern : 1;
+ /// True if this symbol is named.
+ /// A named symbol will have a pointer to the name allocated in the bytes
+ /// immediately prior to the MCSymbol.
+ unsigned HasName : 1;
+
/// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
/// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
unsigned Kind : 2;
protected: // MCContext creates and uniques these.
friend class MCExpr;
friend class MCContext;
- MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
- : Name(Name), Value(nullptr), IsTemporary(isTemporary),
+
+ typedef const StringMapEntry<bool> NameEntryTy;
+ MCSymbol(SymbolKind Kind, NameEntryTy *Name, bool isTemporary)
+ : Value(nullptr), IsTemporary(isTemporary),
IsRedefinable(false), IsUsed(false), IsRegistered(false),
- IsExternal(false), IsPrivateExtern(false),
+ IsExternal(false), IsPrivateExtern(false), HasName(!!Name),
Kind(Kind) {
Offset = 0;
+ if (Name)
+ getNameEntryPtr() = Name;
}
+ // Provide custom new/delete as we will only allocate space for a name
+ // if we need one.
+ void *operator new(size_t s, NameEntryTy *Name, MCContext &Ctx);
+
private:
+
+ void operator delete(void *);
+ /// \brief Placement delete - required by std, but never called.
+ void operator delete(void*, unsigned) {
+ llvm_unreachable("Constructor throws?");
+ }
+ /// \brief Placement delete - required by std, but never called.
+ void operator delete(void*, unsigned, bool) {
+ llvm_unreachable("Constructor throws?");
+ }
+
MCSymbol(const MCSymbol &) = delete;
void operator=(const MCSymbol &) = delete;
MCSection *getSectionPtr() const {
return Section = Value->findAssociatedSection();
}
+ /// \brief Get a reference to the name field. Requires that we have a name
+ NameEntryTy *&getNameEntryPtr() {
+ assert(HasName && "Name is required");
+ NameEntryTy **Name = reinterpret_cast<NameEntryTy **>(this);
+ return *(Name - 1);
+ }
+ NameEntryTy *const &getNameEntryPtr() const {
+ assert(HasName && "Name is required");
+ NameEntryTy *const *Name = reinterpret_cast<NameEntryTy *const *>(this);
+ return *(Name - 1);
+ }
+
public:
/// getName - Get the symbol name.
- StringRef getName() const { return Name ? Name->first() : ""; }
+ StringRef getName() const {
+ if (!HasName)
+ return StringRef();
+
+ return getNameEntryPtr()->first();
+ }
bool isRegistered() const { return IsRegistered; }
void setIsRegistered(bool Value) const { IsRegistered = Value; }
}
auto NameIter = UsedNames.insert(std::make_pair(Name, true)).first;
- Sym = new (*this) MCSymbolELF(&*NameIter, /*isTemporary*/ false);
+ Sym = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false);
if (!OldSym)
OldSym = Sym;
if (MOFI) {
switch (MOFI->getObjectFileType()) {
case MCObjectFileInfo::IsCOFF:
- return new (*this) MCSymbolCOFF(Name, IsTemporary);
+ return new (Name, *this) MCSymbolCOFF(Name, IsTemporary);
case MCObjectFileInfo::IsELF:
- return new (*this) MCSymbolELF(Name, IsTemporary);
+ return new (Name, *this) MCSymbolELF(Name, IsTemporary);
case MCObjectFileInfo::IsMachO:
- return new (*this) MCSymbolMachO(Name, IsTemporary);
+ return new (Name, *this) MCSymbolMachO(Name, IsTemporary);
}
}
- return new (*this) MCSymbol(MCSymbol::SymbolKindUnset, Name, IsTemporary);
+ return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
+ IsTemporary);
}
MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix,
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
// Sentinel value for the absolute pseudo section.
MCSection *MCSymbol::AbsolutePseudoSection = reinterpret_cast<MCSection *>(1);
+void *MCSymbol::operator new(size_t s, NameEntryTy *Name, MCContext &Ctx) {
+ size_t Size = s + (Name ? sizeof(Name) : 0);
+
+ // For safety, ensure that the alignment of a pointer is enough for an
+ // MCSymbol. This also ensures we don't need padding between the name and
+ // symbol.
+ assert(alignOf<MCSymbol>() <= alignof(NameEntryTy *) &&
+ "Bad alignment of MCSymbol");
+ void *Storage = Ctx.allocate(Size, alignof(NameEntryTy *));
+ NameEntryTy **Start = static_cast<NameEntryTy**>(Storage);
+ NameEntryTy **End = Start + (Name ? 1 : 0);
+ return End;
+}
+
void MCSymbol::setVariableValue(const MCExpr *Value) {
assert(!IsUsed && "Cannot set a variable that has already been used.");
assert(Value && "Invalid variable value!");