[WebAssembly] Improve support linker synthetic symbols
This is part of larger change to add synthetic symbols for section start/end points and init/fini_array: https://reviews.llvm.org/D40760 Allows synthetic global symbols to have an explicitly set virtual address. Differential Revision: https://reviews.llvm.org/D40843 llvm-svn: 319813
This commit is contained in:
parent
a0d50ce7af
commit
4eedcfc946
|
@ -39,7 +39,8 @@ struct Configuration {
|
||||||
|
|
||||||
llvm::StringSet<> AllowUndefinedSymbols;
|
llvm::StringSet<> AllowUndefinedSymbols;
|
||||||
std::vector<llvm::StringRef> SearchPaths;
|
std::vector<llvm::StringRef> SearchPaths;
|
||||||
std::vector<std::pair<Symbol *, WasmGlobal>> SyntheticGlobals;
|
std::vector<Symbol *> SyntheticGlobals;
|
||||||
|
Symbol *StackPointerSymbol = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The only instance of Configuration struct.
|
// The only instance of Configuration struct.
|
||||||
|
|
|
@ -138,17 +138,12 @@ static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
|
||||||
// Wasm global are used in relocatable object files to model symbol imports
|
// Wasm global are used in relocatable object files to model symbol imports
|
||||||
// and exports. In the final executable the only use of wasm globals is
|
// and exports. In the final executable the only use of wasm globals is
|
||||||
// for the exlicit stack pointer (__stack_pointer).
|
// for the exlicit stack pointer (__stack_pointer).
|
||||||
static void addSyntheticGlobal(StringRef Name, int32_t Value) {
|
static Symbol* addSyntheticGlobal(StringRef Name, int32_t Value) {
|
||||||
log("injecting global: " + Name);
|
log("injecting global: " + Name);
|
||||||
Symbol *S = Symtab->addDefinedGlobal(Name);
|
Symbol *S = Symtab->addDefinedGlobal(Name);
|
||||||
S->setOutputIndex(Config->SyntheticGlobals.size());
|
S->setVirtualAddress(Value);
|
||||||
|
Config->SyntheticGlobals.emplace_back(S);
|
||||||
WasmGlobal Global;
|
return S;
|
||||||
Global.Mutable = true;
|
|
||||||
Global.Type = WASM_TYPE_I32;
|
|
||||||
Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
|
|
||||||
Global.InitExpr.Value.Int32 = Value;
|
|
||||||
Config->SyntheticGlobals.emplace_back(S, Global);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inject a new undefined symbol into the link. This will cause the link to
|
// Inject a new undefined symbol into the link. This will cause the link to
|
||||||
|
@ -285,7 +280,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||||
static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
|
static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
|
||||||
addSyntheticUndefinedFunction(Config->Entry, &Signature);
|
addSyntheticUndefinedFunction(Config->Entry, &Signature);
|
||||||
|
|
||||||
addSyntheticGlobal("__stack_pointer", 0);
|
Config->StackPointerSymbol = addSyntheticGlobal("__stack_pointer", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
createFiles(Args);
|
createFiles(Args);
|
||||||
|
|
|
@ -41,6 +41,8 @@ uint32_t Symbol::getVirtualAddress() const {
|
||||||
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
|
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
|
||||||
if (isUndefined())
|
if (isUndefined())
|
||||||
return UINT32_MAX;
|
return UINT32_MAX;
|
||||||
|
if (VirtualAddress.hasValue())
|
||||||
|
return VirtualAddress.getValue();
|
||||||
|
|
||||||
assert(Sym != nullptr);
|
assert(Sym != nullptr);
|
||||||
ObjFile *Obj = cast<ObjFile>(File);
|
ObjFile *Obj = cast<ObjFile>(File);
|
||||||
|
@ -57,6 +59,11 @@ uint32_t Symbol::getOutputIndex() const {
|
||||||
return OutputIndex.getValue();
|
return OutputIndex.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Symbol::setVirtualAddress(uint32_t Value) {
|
||||||
|
DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
|
||||||
|
VirtualAddress = Value;
|
||||||
|
}
|
||||||
|
|
||||||
void Symbol::setOutputIndex(uint32_t Index) {
|
void Symbol::setOutputIndex(uint32_t Index) {
|
||||||
DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
|
DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
|
||||||
assert(!hasOutputIndex());
|
assert(!hasOutputIndex());
|
||||||
|
|
|
@ -77,12 +77,14 @@ public:
|
||||||
uint32_t getVirtualAddress() const;
|
uint32_t getVirtualAddress() const;
|
||||||
|
|
||||||
// Returns true if an output index has been set for this symbol
|
// Returns true if an output index has been set for this symbol
|
||||||
bool hasOutputIndex() { return OutputIndex.hasValue(); }
|
bool hasOutputIndex() const { return OutputIndex.hasValue(); }
|
||||||
|
|
||||||
// Set the output index of the symbol (in the function or global index
|
// Set the output index of the symbol (in the function or global index
|
||||||
// space of the output object.
|
// space of the output object.
|
||||||
void setOutputIndex(uint32_t Index);
|
void setOutputIndex(uint32_t Index);
|
||||||
|
|
||||||
|
void setVirtualAddress(uint32_t VA);
|
||||||
|
|
||||||
void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr,
|
void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr,
|
||||||
const InputSegment *Segment = nullptr,
|
const InputSegment *Segment = nullptr,
|
||||||
const WasmSignature *Sig = nullptr);
|
const WasmSignature *Sig = nullptr);
|
||||||
|
@ -105,6 +107,7 @@ protected:
|
||||||
const WasmSymbol *Sym = nullptr;
|
const WasmSymbol *Sym = nullptr;
|
||||||
const InputSegment *Segment = nullptr;
|
const InputSegment *Segment = nullptr;
|
||||||
llvm::Optional<uint32_t> OutputIndex;
|
llvm::Optional<uint32_t> OutputIndex;
|
||||||
|
llvm::Optional<uint32_t> VirtualAddress;
|
||||||
const WasmSignature *FunctionType;
|
const WasmSignature *FunctionType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ void Writer::createImportSection() {
|
||||||
|
|
||||||
writeUleb128(OS, NumImports, "import count");
|
writeUleb128(OS, NumImports, "import count");
|
||||||
|
|
||||||
for (Symbol *Sym : FunctionImports) {
|
for (const Symbol *Sym : FunctionImports) {
|
||||||
WasmImport Import;
|
WasmImport Import;
|
||||||
Import.Module = "env";
|
Import.Module = "env";
|
||||||
Import.Field = Sym->getName();
|
Import.Field = Sym->getName();
|
||||||
|
@ -169,7 +169,7 @@ void Writer::createImportSection() {
|
||||||
writeImport(OS, Import);
|
writeImport(OS, Import);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Symbol *Sym : GlobalImports) {
|
for (const Symbol *Sym : GlobalImports) {
|
||||||
WasmImport Import;
|
WasmImport Import;
|
||||||
Import.Module = "env";
|
Import.Module = "env";
|
||||||
Import.Field = Sym->getName();
|
Import.Field = Sym->getName();
|
||||||
|
@ -221,8 +221,12 @@ void Writer::createGlobalSection() {
|
||||||
raw_ostream &OS = Section->getStream();
|
raw_ostream &OS = Section->getStream();
|
||||||
|
|
||||||
writeUleb128(OS, NumGlobals, "global count");
|
writeUleb128(OS, NumGlobals, "global count");
|
||||||
for (auto &Pair : Config->SyntheticGlobals) {
|
for (const Symbol *Sym : Config->SyntheticGlobals) {
|
||||||
WasmGlobal &Global = Pair.second;
|
WasmGlobal Global;
|
||||||
|
Global.Type = WASM_TYPE_I32;
|
||||||
|
Global.Mutable = Sym == Config->StackPointerSymbol;
|
||||||
|
Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
|
||||||
|
Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
|
||||||
writeGlobal(OS, Global);
|
writeGlobal(OS, Global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +511,7 @@ void Writer::layoutMemory() {
|
||||||
debugPrint("mem: stack size = %d\n", Config->ZStackSize);
|
debugPrint("mem: stack size = %d\n", Config->ZStackSize);
|
||||||
debugPrint("mem: stack base = %d\n", MemoryPtr);
|
debugPrint("mem: stack base = %d\n", MemoryPtr);
|
||||||
MemoryPtr += Config->ZStackSize;
|
MemoryPtr += Config->ZStackSize;
|
||||||
Config->SyntheticGlobals[0].second.InitExpr.Value.Int32 = MemoryPtr;
|
Config->StackPointerSymbol->setVirtualAddress(MemoryPtr);
|
||||||
debugPrint("mem: stack top = %d\n", MemoryPtr);
|
debugPrint("mem: stack top = %d\n", MemoryPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue