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/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -10,6 +10,7 @@ #ifndef LLD_WASM_CONFIG_H #define LLD_WASM_CONFIG_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/Wasm.h" @@ -34,7 +35,7 @@ uint32_t InitialMemory; uint32_t MaxMemory; uint32_t ZStackSize; - llvm::StringRef Entry; + llvm::Optional Entry; llvm::StringRef OutputFile; llvm::StringRef Sysroot; Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -219,6 +219,16 @@ error("no input files"); } +static Optional getEntry(opt::InputArgList &Args, + Optional def) { + auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); + if (!Arg) + return def; + if (Arg->getOption().getID() == OPT_no_entry) + return Optional(); + return Optional(Arg->getValue()); +} + void LinkerDriver::link(ArrayRef ArgsArr) { WasmOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); @@ -248,8 +258,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 ? Optional() + : Optional(StringRef("_start"))); Config->ImportMemory = Args.hasArg(OPT_import_memory); Config->OutputFile = Args.getLastArgValue(OPT_o); Config->SearchPaths = args::getStrings(Args, OPT_L); @@ -276,20 +286,25 @@ if (!Args.hasArg(OPT_INPUT)) error("no input files"); - if (Config->Relocatable && !Config->Entry.empty()) + if (Config->Relocatable && Config->Entry) error("entry point specified for relocatable output file"); if (Config->Relocatable && Args.hasArg(OPT_undefined)) error("undefined symbols specified for relocatable output file"); if (!Config->Relocatable) { - if (!Config->Entry.empty()) { + if (Config->Entry) { + if (Config->Entry.getValue().empty()) + error("empty string invalid for entry point"); static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; - addSyntheticUndefinedFunction(Config->Entry, &Signature); + addSyntheticUndefinedFunction(Config->Entry.getValue(), &Signature); } // 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); + } addSyntheticGlobal("__stack_pointer", 0); } @@ -310,10 +325,10 @@ return; } - if (!Config->Entry.empty()) { - Symbol *Sym = Symtab->find(Config->Entry); - if (!Sym->isFunction()) - fatal("entry point is not a function: " + Sym->getName()); + if (Config->Entry) { + Symbol *Sym = Symtab->find(Config->Entry.getValue()); + if (!Sym->isDefined()) + error("entry point not found: " + Config->Entry.getValue()); } for (StringRef S : args::getStrings(Args, OPT_undefined)) { Symbol *Sym = Symtab->find(S); Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -68,6 +68,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 @@ -261,7 +261,8 @@ 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 ? Symtab->find(Config->Entry.getValue()) + : nullptr; bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); uint32_t NumExports = 0; @@ -304,7 +305,7 @@ if (ExportEntry) { WasmExport EntryExport; - EntryExport.Name = Config->Entry; + EntryExport.Name = Config->Entry.getValue(); EntryExport.Kind = WASM_EXTERNAL_FUNCTION; EntryExport.Index = EntrySym->getOutputIndex(); writeExport(OS, EntryExport); @@ -334,10 +335,10 @@ } void Writer::createStartSection() { - if (Config->Entry.empty()) + if (!Config->Entry) return; - const Symbol *Sym = Symtab->find(Config->Entry); + const Symbol *Sym = Symtab->find(Config->Entry.getValue()); assert(Sym && Sym->isDefined() && Sym->isFunction()); SyntheticSection *Section = createSyntheticSection(WASM_SEC_START);