Index: test/wasm/undefined.ll =================================================================== --- test/wasm/undefined.ll +++ test/wasm/undefined.ll @@ -2,25 +2,44 @@ ; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o ; Fails due to undefined 'foo' and also 'baz' -; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s -; CHECK: error: {{.*}}.o: undefined symbol: foo -; CHECK: error: undefined symbol: baz +; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR +; CHECK-ERROR: error: {{.*}}.o: undefined symbol: foo +; CHECK-ERROR: error: {{.*}}.o: undefined symbol: bar +; CHECK-ERROR: error: undefined symbol: baz ; Succeeds if we pass a file containing 'foo' as --allow-undefined-file. ; RUN: echo 'foo' > %t.txt +; RUN: echo 'bar' >> %t.txt ; RUN: wasm-ld --allow-undefined-file=%t.txt -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s ; Succeeds even if a missing symbol is added via --export ; RUN: wasm-ld --allow-undefined --export=xxx -o %t.wasm %t.o target triple = "wasm32-unknown-unknown" -; Takes the address of the external foo() resulting in undefined external -@bar = hidden local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 4 +; Takes the address of the external function foo() +@addr_func = local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 4 + +; Take the address of the external_data +@addr_data = local_unnamed_addr global i32* @bar, align 4 declare i32 @foo() #0 +@bar = external global i32 -define hidden void @_start() local_unnamed_addr #0 { +define void @_start() local_unnamed_addr #0 { entry: ret void } + +; CHECK: - Type: IMPORT +; CHECK-NEXT: Imports: +; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: foo +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: SigIndex: 0 +; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: bar +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: GlobalType: I32 +; CHECK-NEXT: GlobalMutable: false Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -89,6 +89,11 @@ uint32_t getOutputSymbolIndex() const; void setOutputSymbolIndex(uint32_t Index); + // Get/set the global index + uint32_t getGlobalIndex() const; + void setGlobalIndex(uint32_t Index); + bool hasGlobalIndex() const; + WasmSymbolType getWasmType() const; protected: @@ -101,6 +106,7 @@ uint32_t Flags; InputFile *File; uint32_t OutputSymbolIndex = INVALID_INDEX; + uint32_t GlobalIndex = INVALID_INDEX; bool Referenced = false; }; @@ -232,11 +238,6 @@ const WasmGlobalType *getGlobalType() const { return GlobalType; } - // Get/set the global index - uint32_t getGlobalIndex() const; - void setGlobalIndex(uint32_t Index); - bool hasGlobalIndex() const; - protected: GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, const WasmGlobalType *GlobalType) @@ -245,7 +246,6 @@ // Explicit function type, needed for undefined or synthetic functions only. // For regular defined globals this information comes from the InputChunk. const WasmGlobalType *GlobalType; - uint32_t GlobalIndex = INVALID_INDEX; }; class DefinedGlobal : public GlobalSymbol { Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -76,6 +76,25 @@ OutputSymbolIndex = Index; } +uint32_t Symbol::getGlobalIndex() const { + if (auto *F = dyn_cast(this)) + return F->Global->getGlobalIndex(); + assert(GlobalIndex != INVALID_INDEX); + return GlobalIndex; +} + +void Symbol::setGlobalIndex(uint32_t Index) { + DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n"); + assert(GlobalIndex == INVALID_INDEX); + GlobalIndex = Index; +} + +bool Symbol::hasGlobalIndex() const { + if (auto *F = dyn_cast(this)) + return F->Global->hasGlobalIndex(); + return GlobalIndex != INVALID_INDEX; +} + bool Symbol::isWeak() const { return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; } @@ -171,25 +190,6 @@ return Segment->OutputSeg->Index; } -uint32_t GlobalSymbol::getGlobalIndex() const { - if (auto *F = dyn_cast(this)) - return F->Global->getGlobalIndex(); - assert(GlobalIndex != INVALID_INDEX); - return GlobalIndex; -} - -void GlobalSymbol::setGlobalIndex(uint32_t Index) { - DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n"); - assert(GlobalIndex == INVALID_INDEX); - GlobalIndex = Index; -} - -bool GlobalSymbol::hasGlobalIndex() const { - if (auto *F = dyn_cast(this)) - return F->Global->hasGlobalIndex(); - return GlobalIndex != INVALID_INDEX; -} - DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, InputGlobal *Global) : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -176,10 +176,13 @@ if (auto *FunctionSym = dyn_cast(Sym)) { Import.Kind = WASM_EXTERNAL_FUNCTION; Import.SigIndex = lookupType(*FunctionSym->getFunctionType()); - } else { - auto *GlobalSym = cast(Sym); + } else if (auto *GlobalSym = dyn_cast(Sym)) { Import.Kind = WASM_EXTERNAL_GLOBAL; Import.Global = *GlobalSym->getGlobalType(); + } else { + assert(isa(Sym)); + Import.Kind = WASM_EXTERNAL_GLOBAL; + Import.Global = {WASM_TYPE_I32, false}; } writeImport(OS, Import); } @@ -709,7 +712,9 @@ for (Symbol *Sym : Symtab->getSymbols()) { if (!Sym->isUndefined()) continue; - if (isa(Sym)) + // For data symbols we don't use imports in the relocatable output, instead + // these are in the explict symbol table. + if (isa(Sym) && Config->Relocatable) continue; if (Sym->isWeak() && !Config->Relocatable) continue; @@ -720,8 +725,10 @@ ImportedSymbols.emplace_back(Sym); if (auto *F = dyn_cast(Sym)) F->setFunctionIndex(NumImportedFunctions++); + else if (auto *G = dyn_cast(Sym)) + G->setGlobalIndex(NumImportedGlobals++); else - cast(Sym)->setGlobalIndex(NumImportedGlobals++); + cast(Sym)->setGlobalIndex(NumImportedGlobals++); } }