summaryrefslogtreecommitdiff
path: root/COFF/Symbols.h
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/Symbols.h')
-rw-r--r--COFF/Symbols.h146
1 files changed, 67 insertions, 79 deletions
diff --git a/COFF/Symbols.h b/COFF/Symbols.h
index a12ae1c01e07e..d8a030705e271 100644
--- a/COFF/Symbols.h
+++ b/COFF/Symbols.h
@@ -12,8 +12,8 @@
#include "Chunks.h"
#include "Config.h"
-#include "Memory.h"
-#include "lld/Core/LLVM.h"
+#include "lld/Common/LLVM.h"
+#include "lld/Common/Memory.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
@@ -31,12 +31,11 @@ using llvm::object::coff_symbol_generic;
class ArchiveFile;
class InputFile;
-class ObjectFile;
-struct Symbol;
+class ObjFile;
class SymbolTable;
// The base class for real symbol classes.
-class SymbolBody {
+class Symbol {
public:
enum Kind {
// The order of these is significant. We start with the regular defined
@@ -70,16 +69,16 @@ public:
// Returns the file from which this symbol was created.
InputFile *getFile();
- Symbol *symbol();
- const Symbol *symbol() const {
- return const_cast<SymbolBody *>(this)->symbol();
- }
+ // Indicates that this symbol will be included in the final image. Only valid
+ // after calling markLive.
+ bool isLive() const;
protected:
friend SymbolTable;
- explicit SymbolBody(Kind K, StringRef N = "")
+ explicit Symbol(Kind K, StringRef N = "")
: SymbolKind(K), IsExternal(true), IsCOMDAT(false),
- WrittenToSymtab(false), Name(N) {}
+ WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
+ Name(N) {}
const unsigned SymbolKind : 8;
unsigned IsExternal : 1;
@@ -92,19 +91,28 @@ public:
// symbols from being written to the symbol table more than once.
unsigned WrittenToSymtab : 1;
+ // True if this symbol was referenced by a regular (non-bitcode) object.
+ unsigned IsUsedInRegularObj : 1;
+
+ // True if we've seen both a lazy and an undefined symbol with this symbol
+ // name, which means that we have enqueued an archive member load and should
+ // not load any more archive members to resolve the same symbol.
+ unsigned PendingArchiveLoad : 1;
+
+ /// True if we've already added this symbol to the list of GC roots.
+ unsigned IsGCRoot : 1;
+
protected:
StringRef Name;
};
// The base class for any defined symbols, including absolute symbols,
// etc.
-class Defined : public SymbolBody {
+class Defined : public Symbol {
public:
- Defined(Kind K, StringRef N) : SymbolBody(K, N) {}
+ Defined(Kind K, StringRef N) : Symbol(K, N) {}
- static bool classof(const SymbolBody *S) {
- return S->kind() <= LastDefinedKind;
- }
+ static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }
// Returns the RVA (relative virtual address) of this symbol. The
// writer sets and uses RVAs.
@@ -120,12 +128,13 @@ public:
// loaded through that. For bitcode files, Sym is nullptr and the name is stored
// as a StringRef.
class DefinedCOFF : public Defined {
- friend SymbolBody;
+ friend Symbol;
+
public:
DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)
: Defined(K, N), File(F), Sym(S) {}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() <= LastDefinedCOFFKind;
}
@@ -151,16 +160,15 @@ public:
this->IsCOMDAT = IsCOMDAT;
}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedRegularKind;
}
- uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; }
- bool isCOMDAT() { return IsCOMDAT; }
- SectionChunk *getChunk() { return *Data; }
- uint32_t getValue() { return Sym->Value; }
+ uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
+ bool isCOMDAT() const { return IsCOMDAT; }
+ SectionChunk *getChunk() const { return *Data; }
+ uint32_t getValue() const { return Sym->Value; }
-private:
SectionChunk **Data;
};
@@ -173,12 +181,12 @@ public:
this->IsExternal = true;
}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedCommonKind;
}
uint64_t getRVA() { return Data->getRVA(); }
- Chunk *getChunk() { return Data; }
+ CommonChunk *getChunk() { return Data; }
private:
friend SymbolTable;
@@ -198,7 +206,7 @@ public:
DefinedAbsolute(StringRef N, uint64_t V)
: Defined(DefinedAbsoluteKind, N), VA(V) {}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedAbsoluteKind;
}
@@ -222,7 +230,7 @@ public:
explicit DefinedSynthetic(StringRef Name, Chunk *C)
: Defined(DefinedSyntheticKind, Name), C(C) {}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedSyntheticKind;
}
@@ -240,12 +248,12 @@ private:
// object file from an archive to replace itself with a defined
// symbol. If the resolver finds both Undefined and Lazy for
// the same name, it will ask the Lazy to load a file.
-class Lazy : public SymbolBody {
+class Lazy : public Symbol {
public:
Lazy(ArchiveFile *F, const Archive::Symbol S)
- : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {}
+ : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}
- static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
+ static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
ArchiveFile *File;
@@ -257,19 +265,17 @@ private:
};
// Undefined symbols.
-class Undefined : public SymbolBody {
+class Undefined : public Symbol {
public:
- explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {}
+ explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}
- static bool classof(const SymbolBody *S) {
- return S->kind() == UndefinedKind;
- }
+ static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
// An undefined symbol can have a fallback symbol which gives an
// undefined symbol a second chance if it would remain undefined.
// If it remains undefined, it'll be replaced with whatever the
// Alias pointer points to.
- SymbolBody *WeakAlias = nullptr;
+ Symbol *WeakAlias = nullptr;
// If this symbol is external weak, try to resolve it to a defined
// symbol by searching the chain of fallback symbols. Returns the symbol if
@@ -289,7 +295,7 @@ public:
: Defined(DefinedImportDataKind, N), File(F) {
}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedImportDataKind;
}
@@ -313,7 +319,7 @@ class DefinedImportThunk : public Defined {
public:
DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedImportThunkKind;
}
@@ -336,7 +342,7 @@ public:
DefinedLocalImport(StringRef N, Defined *S)
: Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
- static bool classof(const SymbolBody *S) {
+ static bool classof(const Symbol *S) {
return S->kind() == DefinedLocalImportKind;
}
@@ -393,51 +399,33 @@ inline Chunk *Defined::getChunk() {
llvm_unreachable("unknown symbol kind");
}
-// A real symbol object, SymbolBody, is usually stored within a Symbol. There's
-// always one Symbol for each symbol name. The resolver updates the SymbolBody
-// stored in the Body field of this object as it resolves symbols. Symbol also
-// holds computed properties of symbol names.
-struct Symbol {
- // True if this symbol was referenced by a regular (non-bitcode) object.
- unsigned IsUsedInRegularObj : 1;
-
- // True if we've seen both a lazy and an undefined symbol with this symbol
- // name, which means that we have enqueued an archive member load and should
- // not load any more archive members to resolve the same symbol.
- unsigned PendingArchiveLoad : 1;
-
- // This field is used to store the Symbol's SymbolBody. This instantiation of
- // AlignedCharArrayUnion gives us a struct with a char array field that is
- // large and aligned enough to store any derived class of SymbolBody.
- llvm::AlignedCharArrayUnion<
- DefinedRegular, DefinedCommon, DefinedAbsolute, DefinedSynthetic, Lazy,
- Undefined, DefinedImportData, DefinedImportThunk, DefinedLocalImport>
- Body;
-
- SymbolBody *body() {
- return reinterpret_cast<SymbolBody *>(Body.buffer);
- }
- const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); }
+// A buffer class that is large enough to hold any Symbol-derived
+// object. We allocate memory using this class and instantiate a symbol
+// using the placement new.
+union SymbolUnion {
+ alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
+ alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
+ alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)];
+ alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)];
+ alignas(Lazy) char E[sizeof(Lazy)];
+ alignas(Undefined) char F[sizeof(Undefined)];
+ alignas(DefinedImportData) char G[sizeof(DefinedImportData)];
+ alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)];
+ alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)];
};
template <typename T, typename... ArgT>
-void replaceBody(Symbol *S, ArgT &&... Arg) {
- static_assert(sizeof(T) <= sizeof(S->Body), "Body too small");
- static_assert(alignof(T) <= alignof(decltype(S->Body)),
- "Body not aligned enough");
- assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr &&
- "Not a SymbolBody");
- new (S->Body.buffer) T(std::forward<ArgT>(Arg)...);
-}
-
-inline Symbol *SymbolBody::symbol() {
- assert(isExternal());
- return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
- offsetof(Symbol, Body));
+void replaceSymbol(Symbol *S, ArgT &&... Arg) {
+ static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
+ static_assert(alignof(T) <= alignof(SymbolUnion),
+ "SymbolUnion not aligned enough");
+ assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
+ "Not a Symbol");
+ new (S) T(std::forward<ArgT>(Arg)...);
}
} // namespace coff
-std::string toString(coff::SymbolBody &B);
+std::string toString(coff::Symbol &B);
} // namespace lld
#endif