[WebAssembly] Handle undefined data symbols in shared libraries
When linking shared libraries, we import a mutable wasm global to represent the address of each undefined data symbol. This is a step towards supporting dynamic linking and shared libraries. Differential Revision: https://reviews.llvm.org/D59270 llvm-svn: 355988
This commit is contained in:
parent
773c391d4a
commit
d425d6b08b
|
@ -5,18 +5,18 @@
|
|||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
@data = hidden global i32 2, align 4
|
||||
@indirect_func = local_unnamed_addr global void ()* @foo, align 4
|
||||
@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4
|
||||
@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4
|
||||
|
||||
define default void @foo() {
|
||||
define default i32 @foo() {
|
||||
entry:
|
||||
; To ensure we use __stack_pointer
|
||||
%ptr = alloca i32
|
||||
%0 = load i32, i32* @data, align 4
|
||||
%1 = load i32, i32* @data_external, align 4
|
||||
%2 = load void ()*, void ()** @indirect_func, align 4
|
||||
call void %2()
|
||||
ret void
|
||||
%2 = load i32 ()*, i32 ()** @indirect_func, align 4
|
||||
call i32 %2()
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
declare void @func_external()
|
||||
|
@ -60,6 +60,15 @@ declare void @func_external()
|
|||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: GlobalType: I32
|
||||
; CHECK-NEXT: GlobalMutable: false
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: data_external
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: GlobalType: I32
|
||||
; CHECK-NEXT: GlobalMutable: true
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: func_external
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: SigIndex: 1
|
||||
|
||||
; check for elem segment initialized with __table_base global as offset
|
||||
|
||||
|
|
|
@ -331,6 +331,7 @@ static void setConfigs(opt::InputArgList &Args) {
|
|||
"--thinlto-cache-policy: invalid cache policy");
|
||||
Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);
|
||||
errorHandler().Verbose = Args.hasArg(OPT_verbose);
|
||||
LLVM_DEBUG(errorHandler().Verbose = true);
|
||||
ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
|
||||
|
||||
Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0);
|
||||
|
|
|
@ -249,6 +249,21 @@ public:
|
|||
static bool classof(const Symbol *S) {
|
||||
return S->kind() == UndefinedDataKind;
|
||||
}
|
||||
|
||||
// Undefined data symbols are imported as wasm globals so also have a global
|
||||
// index.
|
||||
uint32_t getGlobalIndex() const {
|
||||
assert(GlobalIndex != INVALID_INDEX);
|
||||
return GlobalIndex;
|
||||
}
|
||||
void setGlobalIndex(uint32_t Index) {
|
||||
assert(GlobalIndex == INVALID_INDEX);
|
||||
GlobalIndex = Index;
|
||||
}
|
||||
bool hasGlobalIndex() const { return GlobalIndex != INVALID_INDEX; }
|
||||
|
||||
protected:
|
||||
uint32_t GlobalIndex = INVALID_INDEX;
|
||||
};
|
||||
|
||||
class GlobalSymbol : public Symbol {
|
||||
|
|
|
@ -198,6 +198,9 @@ void Writer::createImportSection() {
|
|||
if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
|
||||
Import.Kind = WASM_EXTERNAL_FUNCTION;
|
||||
Import.SigIndex = lookupType(*FunctionSym->Signature);
|
||||
} else if (auto *DataSym = dyn_cast<UndefinedData>(Sym)) {
|
||||
Import.Kind = WASM_EXTERNAL_GLOBAL;
|
||||
Import.Global = {WASM_TYPE_I32, true};
|
||||
} else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
|
||||
Import.Kind = WASM_EXTERNAL_GLOBAL;
|
||||
Import.Global = *GlobalSym->getGlobalType();
|
||||
|
@ -851,14 +854,16 @@ void Writer::calculateImports() {
|
|||
for (Symbol *Sym : Symtab->getSymbols()) {
|
||||
if (!Sym->isUndefined())
|
||||
continue;
|
||||
if (isa<DataSymbol>(Sym))
|
||||
continue;
|
||||
if (Sym->isWeak() && !Config->Relocatable)
|
||||
continue;
|
||||
if (!Sym->isLive())
|
||||
continue;
|
||||
if (!Sym->IsUsedInRegularObj)
|
||||
continue;
|
||||
// In relocatable output we don't generate imports for data symbols.
|
||||
// These live only in the symbol table.
|
||||
if (Config->Relocatable && isa<DataSymbol>(Sym))
|
||||
continue;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n");
|
||||
ImportedSymbols.emplace_back(Sym);
|
||||
|
@ -866,6 +871,8 @@ void Writer::calculateImports() {
|
|||
F->setFunctionIndex(NumImportedFunctions++);
|
||||
else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
|
||||
G->setGlobalIndex(NumImportedGlobals++);
|
||||
else if (auto *D = dyn_cast<UndefinedData>(Sym))
|
||||
D->setGlobalIndex(NumImportedGlobals++);
|
||||
else
|
||||
cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue