diff --git a/lld/docs/WebAssembly.rst b/lld/docs/WebAssembly.rst --- a/lld/docs/WebAssembly.rst +++ b/lld/docs/WebAssembly.rst @@ -72,7 +72,8 @@ .. option:: --allow-undefined Allow undefined symbols in linked binary. This is the legacy - flag which corresponds to ``--unresolved-symbols=import-functions``. + flag which corresponds to ``--unresolve-symbols=ignore`` + + --import-undefined-symbols``. .. option:: --unresolved-symbols= @@ -91,16 +92,17 @@ this is trivial. For direct function calls, the linker will generate a trapping stub function in place of the undefined function. - import-functions: - - Generate WebAssembly imports for any undefined functions. Undefined data - symbols are resolved to zero as in ``ignore-all``. This corresponds to - the legacy ``--allow-undefined`` flag. - .. option:: --import-memory Import memory from the environment. +.. option:: --import-undefined + + Generate WebAssembly imports for undefined symbols, where possible. For + example, for function symbols this is always possible, but in general this + is not possible for undefined data symbols. Undefined data symbols will + still be reported as normal (in accordance with ``--unresolved-symbols``). + .. option:: --initial-memory= Initial size of the linear memory. Default: static data size. diff --git a/lld/test/wasm/unresolved-symbols.s b/lld/test/wasm/unresolved-symbols.s --- a/lld/test/wasm/unresolved-symbols.s +++ b/lld/test/wasm/unresolved-symbols.s @@ -1,9 +1,9 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t1.o -## Check that %t1.o contains undefined symbol undef. +## Check that %t1.o contains undefined symbol undef_func. # RUN: not wasm-ld %t1.o -o /dev/null 2>&1 | \ # RUN: FileCheck -check-prefix=ERRUND %s -# ERRUND: error: {{.*}}1.o: undefined symbol: undef +# ERRUND: error: {{.*}}1.o: undefined symbol: undef_func ## report-all is the default one. Check that we get the same error # RUN: not wasm-ld %t1.o -o /dev/null --unresolved-symbols=report-all 2>&1 | \ @@ -52,19 +52,25 @@ # IGNORE-NEXT: - Index: 3 # IGNORE-NEXT: Name: get_func_addr -## import-functions should not produce errors and should resolve in -# imports for the missing functions but not the missing data symbols. -# `--allow-undefined` should behave exactly the same. -# RUN: wasm-ld %t1.o -o %t3.wasm --unresolved-symbols=import-functions +## --import-undefined should handle unresolved funtions symbols +# by importing them but still report errors/warning for missing data symbols. +# `--allow-undefined` should behave like `--import-undefined` + +# `--unresolve-symbols=ignore` +# RUN: wasm-ld %t1.o -o %t3.wasm --import-undefined --unresolved-symbols=ignore-all # RUN: obj2yaml %t3.wasm | FileCheck -check-prefix=IMPORT %s # IMPORT: - Type: IMPORT # IMPORT-NEXT: Imports: # IMPORT-NEXT: - Module: env -# IMPORT-NEXT: Field: undef +# IMPORT-NEXT: Field: undef_func # IMPORT-NEXT: Kind: FUNCTION # IMPORT-NEXT: SigIndex: 0 # IMPORT-NEXT: - Type: FUNCTION +## Check that --import-undefined reports unresolved data symbols. +# RUN: not wasm-ld %t1.o -o %t3.wasm --import-undefined --unresolved-symbols=report-all 2>&1 | FileCheck -check-prefix=IMPORTUNDEFINED %s +# IMPORTUNDEFINED-NOT: error: {{.*}}1.o: undefined symbol: undef_func +# IMPORTUNDEFINED: error: {{.*}}1.o: undefined symbol: undef_data + ## Do not report undefines if linking relocatable. # RUN: wasm-ld -r %t1.o -o %t4.wasm --unresolved-symbols=report-all # RUN: llvm-readobj %t4.wasm > /dev/null 2>&1 @@ -72,7 +78,7 @@ .globl _start _start: .functype _start () -> () - call undef + call undef_func call get_data_addr call get_func_addr end_function @@ -87,8 +93,8 @@ .globl get_func_addr get_func_addr: .functype get_func_addr () -> (i32) - i32.const undef + i32.const undef_func return end_function -.functype undef () -> () +.functype undef_func () -> () diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -18,10 +18,7 @@ namespace wasm { // For --unresolved-symbols. -// The `ImportFuncs` mode is an additional mode that corresponds to the -// --allow-undefined flag which turns undefined functions in imports -// as opposed ed to Ignore or Warn which turn them into unreachables. -enum class UnresolvedPolicy { ReportError, Warn, Ignore, ImportFuncs }; +enum class UnresolvedPolicy { ReportError, Warn, Ignore }; // This struct contains the global configuration for the linker. // Most fields are direct mapping from the command line options @@ -43,6 +40,7 @@ bool importMemory; bool sharedMemory; bool importTable; + bool importUndefined; llvm::Optional is64; bool mergeDataSegments; bool pie; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -344,18 +344,11 @@ StringRef s = arg->getValue(); if (s == "ignore-all") return UnresolvedPolicy::Ignore; - if (s == "import-functions") - return UnresolvedPolicy::ImportFuncs; if (s == "report-all") return errorOrWarn; error("unknown --unresolved-symbols value: " + s); } - // Legacy --allow-undefined flag which is equivalent to - // --unresolve-symbols=ignore-all - if (args.hasArg(OPT_allow_undefined)) - return UnresolvedPolicy::ImportFuncs; - return errorOrWarn; } @@ -378,6 +371,7 @@ config->importMemory = args.hasArg(OPT_import_memory); config->sharedMemory = args.hasArg(OPT_shared_memory); config->importTable = args.hasArg(OPT_import_table); + config->importUndefined = args.hasArg(OPT_import_undefined); config->ltoo = args::getInteger(args, OPT_lto_O, 2); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoNewPassManager = @@ -453,6 +447,13 @@ config->features->push_back(std::string(s)); } + // Legacy --allow-undefined flag which is equivalent to + // --unresolve-symbols=ignore + --import-undefined-symbols + if (args.hasArg(OPT_allow_undefined)) { + config->importUndefined = true; + config->unresolvedSymbols = UnresolvedPolicy::Ignore; + } + if (args.hasArg(OPT_print_map)) config->mapFile = "-"; } @@ -481,7 +482,8 @@ if (config->shared) { config->importMemory = true; - config->unresolvedSymbols = UnresolvedPolicy::ImportFuncs; + config->importUndefined = true; + config->unresolvedSymbols = UnresolvedPolicy::Ignore; } } diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -141,7 +141,11 @@ // The follow flags are unique to wasm def allow_undefined: F<"allow-undefined">, - HelpText<"Allow undefined symbols in linked binary">; + HelpText<"Allow undefined symbols in linked binary. This options is equivelant " + "to --import-undefined and --unresolved-symbols=ignore-all">; + +def import_undefined: F<"import-undefined">, + HelpText<"Turn undefined symbols into imports where possible">; def allow_undefined_file: J<"allow-undefined-file=">, HelpText<"Allow symbols listed in to be undefined in linked binary">; diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp --- a/lld/wasm/Relocations.cpp +++ b/lld/wasm/Relocations.cpp @@ -35,7 +35,7 @@ // Undefined functions and globals with explicit import name are allowed to be // undefined at link time. if (auto *f = dyn_cast(sym)) - if (f->importName) + if (f->importName || config->importUndefined) return true; if (auto *g = dyn_cast(sym)) if (g->importName) @@ -56,20 +56,20 @@ warn(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); break; case UnresolvedPolicy::Ignore: - if (auto *f = dyn_cast(sym)) { - if (!f->stubFunction) { - LLVM_DEBUG(dbgs() - << "ignoring undefined symbol: " + toString(*sym) + "\n"); - f->stubFunction = symtab->createUndefinedStub(*f->getSignature()); - f->stubFunction->markLive(); - // Mark the function itself as a stub which prevents it from being - // assigned a table entry. - f->isStub = true; + LLVM_DEBUG(dbgs() << "ignoring undefined symbol: " + toString(*sym) + + "\n"); + if (!config->importUndefined) { + if (auto *f = dyn_cast(sym)) { + if (!f->stubFunction) { + f->stubFunction = symtab->createUndefinedStub(*f->getSignature()); + f->stubFunction->markLive(); + // Mark the function itself as a stub which prevents it from being + // assigned a table entry. + f->isStub = true; + } } } break; - case UnresolvedPolicy::ImportFuncs: - break; } } } diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -558,8 +558,7 @@ if (isa(sym)) return false; - if ((config->isPic || config->relocatable) || - config->unresolvedSymbols == UnresolvedPolicy::ImportFuncs) + if (config->isPic || config->relocatable || config->importUndefined) return true; if (config->allowUndefinedSymbols.count(sym->getName()) != 0) return true;