Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -1,6 +1,6 @@ ; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.o ; RUN: llc -filetype=obj %s -o %t.o -; RUN: lld -flavor wasm --emit-relocs --allow-undefined --entry '' -o %t.wasm %t.o %t.hello.o +; RUN: lld -flavor wasm --emit-relocs --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o ; RUN: obj2yaml %t.wasm | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -215,6 +215,18 @@ error("no input files"); } +static StringRef getEntry(opt::InputArgList &Args, StringRef def) { + auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); + if (!Arg) + return def; + if (Arg->getOption().getID() == OPT_no_entry) + return StringRef(); + StringRef Entry(Arg->getValue()); + if (Entry.empty()) + error("empty string invalid for entry point"); + return Entry; +} + void LinkerDriver::link(ArrayRef ArgsArr) { WasmOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); @@ -244,8 +256,8 @@ Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false); Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); Config->Relocatable = Args.hasArg(OPT_relocatable); - Config->Entry = Args.getLastArgValue(OPT_entry, - Config->Relocatable ? "" : "_start"); + Config->Entry = getEntry(Args, Config->Relocatable ? StringRef() + : StringRef("_start")); Config->ImportMemory = Args.hasArg(OPT_import_memory); Config->OutputFile = Args.getLastArgValue(OPT_o); Config->SearchPaths = args::getStrings(Args, OPT_L); @@ -285,8 +297,11 @@ } // Handle the `--undefined ` options. - for (StringRef S : args::getStrings(Args, OPT_undefined)) + for (StringRef S : args::getStrings(Args, OPT_undefined)) { + if (S.empty()) + error("empty string invalid for undefined symbol"); addSyntheticUndefinedFunction(S, nullptr); + } Config->StackPointerSymbol = addSyntheticGlobal("__stack_pointer", 0); } @@ -309,8 +324,8 @@ if (!Config->Entry.empty()) { Symbol *Sym = Symtab->find(Config->Entry); - if (!Sym->isFunction()) - fatal("entry point is not a function: " + Sym->getName()); + if (!Sym->isDefined()) + error("entry point not found: " + Config->Entry); } for (StringRef S : args::getStrings(Args, OPT_undefined)) { Symbol *Sym = Symtab->find(S); Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -66,6 +66,9 @@ def entry: S<"entry">, MetaVarName<"">, HelpText<"Name of entry point symbol">; +def no_entry: F<"no-entry">, + HelpText<"Do not output any entry point">; + def error_limit: J<"error-limit=">, HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">; Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -265,7 +265,7 @@ bool ExportMemory = !Config->Relocatable && !Config->ImportMemory; bool ExportOther = true; // ??? TODO Config->Relocatable; bool ExportHidden = Config->Relocatable; - Symbol *EntrySym = Symtab->find(Config->Entry); + Symbol *EntrySym = !Config->Entry.empty() ? Symtab->find(Config->Entry) : nullptr; bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); uint32_t NumExports = 0;