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 @@ -294,6 +294,33 @@ CC1Args.push_back("-target-feature"); CC1Args.push_back("+exception-handling"); } + + for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) { + StringRef Opt = A->getValue(0); + if (Opt.startswith("-emscripten-cxx-exceptions-allowed")) { + // '-mllvm -emscripten-cxx-exceptions-allowed' is only allowed with + // '-mllvm -enable-emscripten-cxx-exceptions' + bool EmExceptionArgExists = false; + for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) + if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") + EmExceptionArgExists = true; + if (!EmExceptionArgExists) + getDriver().Diag(diag::err_drv_argument_only_allowed_with) + << "-mllvm -emscripten-cxx-exceptions-allowed" + << "-mllvm -enable-emscripten-cxx-exceptions"; + + // Prevent functions specified in -emscripten-cxx-exceptions-allowed list + // from being inlined before reaching the wasm backend. + StringRef FuncNamesStr = Opt.split('=').second; + SmallVector FuncNames; + FuncNamesStr.split(FuncNames, ','); + for (auto Name : FuncNames) { + CC1Args.push_back("-mllvm"); + CC1Args.push_back(DriverArgs.MakeArgString("--force-attribute=" + Name + + ":noinline")); + } + } + } } ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const { 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 @@ -79,6 +79,21 @@ // RUN: | FileCheck -check-prefix=PTHREAD_NO_SIGN_EXT %s // PTHREAD_NO_SIGN_EXT: invalid argument '-pthread' not allowed with '-mno-sign-ext' +// '-mllvm -emscripten-cxx-exceptions-allowed=foo,bar' sets +// '-mllvm --force-attribute=foo:noinline -mllvm --force-attribute=bar:noinline' +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ +// RUN: --sysroot=/foo %s -mllvm -enable-emscripten-cxx-exceptions \ +// RUN: -mllvm -emscripten-cxx-exceptions-allowed=foo,bar 2>&1 \ +// RUN: | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_NOINLINE %s +// EMSCRIPTEN_EH_ALLOWED_NOINLINE: clang{{.*}}" "-cc1" {{.*}} "-mllvm" "--force-attribute=foo:noinline" "-mllvm" "--force-attribute=bar:noinline" + +// '-mllvm -emscripten-cxx-exceptions-allowed' only allowed with +// '-mllvm -enable-emscripten-cxx-exceptions' +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ +// RUN: --sysroot=/foo %s -mllvm -emscripten-cxx-exceptions-allowed 2>&1 \ +// RUN: | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_WO_ENABLE %s +// EMSCRIPTEN_EH_ALLOWED_WO_ENABLE: invalid argument '-mllvm -emscripten-cxx-exceptions-allowed' only allowed with '-mllvm -enable-emscripten-cxx-exceptions' + // '-fwasm-exceptions' sets +exception-handling // RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ // RUN: --sysroot=/foo %s -fwasm-exceptions 2>&1 \