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()
; 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
"--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);
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 {
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();
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);
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++);
}