From bb66d8f8f73b07f06f2aed2a906f3c08679ed605 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Mon, 14 Aug 2023 09:18:34 -0700 Subject: [PATCH] [clang][WebAssembly] Link crt1 even in case of -shared This allows -mexec-model=reactor -shared produces a library module with _initialize entrypoint, which is preferrable over __wasm_call_ctors. This partially reverts https://reviews.llvm.org/D153293 Discussion: https://github.com/dicej/component-linking-demo/issues/3 Reviewed By: sbc100 Differential Revision: https://reviews.llvm.org/D156205 (cherry picked from commit 989ce069a4638fd561bebc95f478ca9e45154fec) --- clang/lib/Driver/ToolChains/WebAssembly.cpp | 38 ++++++++++++++------- clang/test/Driver/wasm-toolchain.c | 12 +++---- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index 36bed3166ff3..2098a68cbc6e 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -77,31 +77,43 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); - const char *Crt1 = "crt1.o"; + bool IsCommand = true; + const char *Crt1; const char *Entry = nullptr; - // If crt1-command.o exists, it supports new-style commands, so use it. - // Otherwise, use the old crt1.o. This is a temporary transition measure. - // Once WASI libc no longer needs to support LLVM versions which lack - // support for new-style command, it can make crt1.o the same as - // crt1-command.o. And once LLVM no longer needs to support WASI libc - // versions before that, it can switch to using crt1-command.o. - if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o") - Crt1 = "crt1-command.o"; + // When -shared is specified, use the reactor exec model unless + // specified otherwise. + if (Args.hasArg(options::OPT_shared)) + IsCommand = false; if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) { StringRef CM = A->getValue(); if (CM == "command") { - // Use default values. + IsCommand = true; } else if (CM == "reactor") { - Crt1 = "crt1-reactor.o"; - Entry = "_initialize"; + IsCommand = false; } else { ToolChain.getDriver().Diag(diag::err_drv_invalid_argument_to_option) << CM << A->getOption().getName(); } } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, options::OPT_shared)) + + if (IsCommand) { + // If crt1-command.o exists, it supports new-style commands, so use it. + // Otherwise, use the old crt1.o. This is a temporary transition measure. + // Once WASI libc no longer needs to support LLVM versions which lack + // support for new-style command, it can make crt1.o the same as + // crt1-command.o. And once LLVM no longer needs to support WASI libc + // versions before that, it can switch to using crt1-command.o. + Crt1 = "crt1.o"; + if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o") + Crt1 = "crt1-command.o"; + } else { + Crt1 = "crt1-reactor.o"; + Entry = "_initialize"; + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(Crt1))); if (Entry) { CmdArgs.push_back(Args.MakeArgString("--entry")); diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c index 909d27f0f2d9..cc1ac6105ad8 100644 --- a/clang/test/Driver/wasm-toolchain.c +++ b/clang/test/Driver/wasm-toolchain.c @@ -33,19 +33,19 @@ // LINK_KNOWN: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" -// -shared should be passed through to `wasm-ld` and not include crt1.o with a known OS. +// -shared should be passed through to `wasm-ld` and include crt1-reactor.o with a known OS. -// RUN: %clang -### -shared --target=wasm32-wasi --sysroot=/foo %s 2>&1 \ +// RUN: %clang -### -shared -mexec-model=reactor --target=wasm32-wasi --sysroot=/foo %s 2>&1 \ // RUN: | FileCheck -check-prefix=LINK_KNOWN_SHARED %s // LINK_KNOWN_SHARED: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" -// LINK_KNOWN_SHARED: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi" "-shared" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" +// LINK_KNOWN_SHARED: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi" "crt1-reactor.o" "--entry" "_initialize" "-shared" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" -// -shared should be passed through to `wasm-ld` and not include crt1.o with an unknown OS. +// -shared should be passed through to `wasm-ld` and include crt1-reactor.o with an unknown OS. -// RUN: %clang -### -shared --target=wasm32-unknown-unknown --sysroot=/foo %s 2>&1 \ +// RUN: %clang -### -shared -mexec-model=reactor --target=wasm32-unknown-unknown --sysroot=/foo %s 2>&1 \ // RUN: | FileCheck -check-prefix=LINK_UNKNOWN_SHARED %s // LINK_UNKNOWN_SHARED: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" -// LINK_UNKNOWN_SHARED: wasm-ld{{.*}}" "-shared" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" +// LINK_UNKNOWN_SHARED: wasm-ld{{.*}}" "crt1-reactor.o" "--entry" "_initialize" "-shared" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" // A basic C link command-line with optimization with known OS.