diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3035,6 +3035,12 @@ .. option:: -munimplemented-simd128, -mno-unimplemented-simd128 +.. option:: -mexec-model= + +Select between "command" and "reactor" executable models. Commands have a main +function which scopes the lifetime of the program. Reactors are activated and +remain active until explicitly terminated. + X86 --- .. option:: -m3dnow, -mno-3dnow diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -151,6 +151,10 @@ Group, DocName<"PowerPC">; def m_wasm_Features_Group : OptionGroup<"">, Group, DocName<"WebAssembly">; +// The features added by this group will not be added to target features. +// These are explicitly handled. +def m_wasm_Features_Driver_Group : OptionGroup<"">, + Group, DocName<"WebAssembly Driver">; def m_x86_Features_Group : OptionGroup<"">, Group, Flags<[CoreOption]>, DocName<"X86">; def m_riscv_Features_Group : OptionGroup<"">, @@ -2416,6 +2420,9 @@ def mno_tail_call : Flag<["-"], "mno-tail-call">, Group; def mreference_types : Flag<["-"], "mreference-types">, Group; def mno_reference_types : Flag<["-"], "mno-reference-types">, Group; +def mexec_model_EQ : Joined<["-"], "mexec-model=">, Group, + Values<"command,reactor">, + HelpText<"Execution model (WebAssembly only)">; def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">, Flags<[HelpHidden]>, diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -69,8 +69,26 @@ Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); + const char *Crt1 = "crt1.o"; + const char *Entry = NULL; + if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) { + StringRef CM = A->getValue(); + if (CM == "command") { + // Use default values. + } else if (CM == "reactor") { + Crt1 = "crt1-reactor.o"; + Entry = "_initialize"; + } else { + ToolChain.getDriver().Diag(diag::err_drv_invalid_argument_to_option) + << CM << A->getOption().getName(); + } + } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(Crt1))); + if (Entry) { + CmdArgs.push_back(Args.MakeArgString("--entry")); + CmdArgs.push_back(Args.MakeArgString(Entry)); + } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c --- a/clang/test/Driver/wasm-toolchain.c +++ b/clang/test/Driver/wasm-toolchain.c @@ -107,3 +107,14 @@ // RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 2>&1 | FileCheck -check-prefix=CHECK-ASAN-EMSCRIPTEN %s // CHECK-ASAN-EMSCRIPTEN: "-fsanitize=address" // CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping" + +// Basic exec-model tests. + +// RUN: %clang %s -### -no-canonical-prefixes -target wasm32-unknown-unknown -mexec-model=command 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-COMMAND %s +// CHECK-COMMAND: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// CHECK-COMMAND: wasm-ld{{.*}}" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// RUN: %clang %s -### -no-canonical-prefixes -target wasm32-unknown-unknown -mexec-model=reactor 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-REACTOR %s +// CHECK-REACTOR: wasm-ld{{.*}}" {{.*}} "--entry" "_initialize" {{.*}}