[WebAssembly] WASIP3 Library Call Thread Context Support#175800
Conversation
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
alexcrichton
left a comment
There was a problem hiding this comment.
Two higher-ish level thoughts on this:
- Would it be possible to decouple the selection of how things work internally from the target name and "wasip3" suffix? These options will, I believe, be useful for experimenting on other wasm targets (e.g. even
wasm32-wasip2) and it would be useful to have knobs to turn without faking/forcing a target. My thinking is that the default behavior forwasm32-wasip3is still the same, exactly as-is in this PR, but the knobs could be further refined if so desired for power users. Effectively there'd be per-target defaults for the knobs, but the knobs could be manually overridden if needed. - What happens if objects of one ABI are mixed with objects of another ABI? For example if I were to link code compiled for
wasm32-wasip2with code forwasm32-wasip3, what would happen? Ideally I'd expect a linker-level error to be emitted with some long enough string that could be googled but probably wouldn't be descriptive in its own right. My main worry is less mixing targets and more mixing versions of LLVM by accident and ensuring that things don't silently link and then get weirdly corrupted at runtime.
|
@llvm/pr-subscribers-lld-wasm @llvm/pr-subscribers-lld Author: Sy Brand (TartanLlama) Changes(Currently in draft, as this will evolve alongside other toolchain component updates) The WebAssembly Component Model has added support for cooperative multithreading. This has been implemented in the Wasmtime engine and is part of the wider project of WASI preview 3, which is currently tracked here. These changes will require updating the way that Patch is 55.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175800.diff 22 Files Affected:
diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp
index daaefd9a1267c..1905b838e52a1 100644
--- a/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -410,7 +410,8 @@ void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
// Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
// or __STDCPP_THREADS__ if we will eventually end up stripping atomics
// because they are unsupported.
- if (!HasAtomics || !HasBulkMemory) {
+ if (getTriple().getOSName() != "wasip3" &&
+ (!HasAtomics || !HasBulkMemory)) {
Opts.POSIXThreads = false;
Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
Opts.ThreadsafeStatics = false;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index b5fa5760a46a0..efeadcc6556de 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -30,13 +30,14 @@ using namespace llvm::opt;
std::string WebAssembly::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const {
- return (TargetTriple.getArchName() + "-" +
- TargetTriple.getOSAndEnvironmentName()).str();
+ return (TargetTriple.getArchName() + "-" +
+ TargetTriple.getOSAndEnvironmentName())
+ .str();
}
std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
const ToolChain &ToolChain = getToolChain();
- if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
StringRef UseLinker = A->getValue();
if (!UseLinker.empty()) {
if (llvm::sys::path::is_absolute(UseLinker) &&
@@ -79,6 +80,10 @@ static bool WantsPthread(const llvm::Triple &Triple, const ArgList &Args) {
return WantsPthread;
}
+static bool WantsSharedMemory(const llvm::Triple &Triple, const ArgList &Args) {
+ return WantsPthread(Triple, Args) && !TargetBuildsComponents(Triple);
+}
+
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -90,10 +95,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back("-m");
+ std::string arch;
if (ToolChain.getTriple().isArch64Bit())
- CmdArgs.push_back("wasm64");
+ arch = "wasm64";
else
- CmdArgs.push_back("wasm32");
+ arch = "wasm32";
+ if (ToolChain.getTriple().getOSName() == "wasip3")
+ arch += "-wasip3";
+ CmdArgs.push_back(Args.MakeArgString(arch));
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -160,7 +169,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (WantsPthread(ToolChain.getTriple(), Args))
+ if (WantsSharedMemory(ToolChain.getTriple(), Args))
CmdArgs.push_back("--shared-memory");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -233,9 +242,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// Given a base library directory, append path components to form the
/// LTO directory.
static std::string AppendLTOLibDir(const std::string &Dir) {
- // The version allows the path to be keyed to the specific version of
- // LLVM in used, as the bitcode format is not stable.
- return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
+ // The version allows the path to be keyed to the specific version of
+ // LLVM in used, as the bitcode format is not stable.
+ return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
}
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
@@ -508,7 +517,8 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (getTriple().getOS() != llvm::Triple::UnknownOS) {
const std::string MultiarchTriple =
getMultiarchTriple(D, getTriple(), D.SysRoot);
- addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include/" + MultiarchTriple);
+ addSystemInclude(DriverArgs, CC1Args,
+ D.SysRoot + "/include/" + MultiarchTriple);
}
addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
}
@@ -637,5 +647,6 @@ void WebAssembly::addLibStdCXXIncludePaths(
// Second add the generic one.
addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
// Third the backward one.
- addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
+ addSystemInclude(DriverArgs, CC1Args,
+ LibPath + "/c++/" + Version + "/backward");
}
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 31e08e4e248a4..d291a42da200f 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -35,6 +35,7 @@ class Symbol;
class DefinedData;
class GlobalSymbol;
class DefinedFunction;
+class UndefinedFunction;
class DefinedGlobal;
class UndefinedGlobal;
class TableSymbol;
@@ -50,6 +51,8 @@ enum class BuildIdKind { None, Fast, Sha1, Hexstring, Uuid };
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Config {
+ bool isMultithreaded() const { return sharedMemory || isWasip3; }
+
bool allowMultipleDefinition;
bool bsymbolic;
bool checkFeatures;
@@ -71,6 +74,7 @@ struct Config {
bool importTable;
bool importUndefined;
std::optional<bool> is64;
+ bool isWasip3;
bool mergeDataSegments;
bool noinhibitExec;
bool pie;
@@ -252,6 +256,14 @@ struct Ctx {
// Used as an address space for function pointers, with each function that
// is used as a function pointer being allocated a slot.
TableSymbol *indirectFunctionTable;
+
+ // __wasm_component_model_builtin_context_set_1
+ // Function used to set TLS base in component model modules.
+ UndefinedFunction *contextSet1;
+
+ // __wasm_component_model_builtin_context_get_1
+ // Function used to get TLS base in component model modules.
+ UndefinedFunction *contextGet1;
};
WasmSym sym;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index b1e36f2ecff74..6eaacd7288f22 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -656,15 +656,16 @@ static void readConfigs(opt::InputArgList &args) {
ctx.arg.exportDynamic =
args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, ctx.arg.shared);
- // Parse wasm32/64.
+ // Parse wasm32/64 and maybe -wasip3.
if (auto *arg = args.getLastArg(OPT_m)) {
StringRef s = arg->getValue();
- if (s == "wasm32")
+ if (s.starts_with("wasm32"))
ctx.arg.is64 = false;
- else if (s == "wasm64")
+ else if (s.starts_with("wasm64"))
ctx.arg.is64 = true;
else
error("invalid target architecture: " + s);
+ ctx.arg.isWasip3 = s.ends_with("-wasip3");
}
// --threads= takes a positive integer and provides the default value for
@@ -827,6 +828,10 @@ static void checkOptions(opt::InputArgList &args) {
if (ctx.arg.tableBase)
error("--table-base may not be used with -shared/-pie");
}
+
+ if (ctx.arg.sharedMemory && ctx.arg.isWasip3) {
+ error("--shared-memory is incompatible with the wasip3 target");
+ }
}
static const char *getReproduceOption(opt::InputArgList &args) {
@@ -885,7 +890,7 @@ static void writeWhyExtract() {
// Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker
static void demoteLazySymbols() {
for (Symbol *sym : symtab->symbols()) {
- if (auto* s = dyn_cast<LazySymbol>(sym)) {
+ if (auto *s = dyn_cast<LazySymbol>(sym)) {
if (s->signature) {
LLVM_DEBUG(llvm::dbgs()
<< "demoting lazy func: " << s->getName() << "\n");
@@ -906,6 +911,18 @@ createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
return sym;
}
+static UndefinedFunction *
+createUndefinedFunction(StringRef name, std::optional<StringRef> importName,
+ std::optional<StringRef> importModule,
+ WasmSignature *signature) {
+ auto *sym = cast<UndefinedFunction>(symtab->addUndefinedFunction(
+ name, importName, importModule, WASM_SYMBOL_UNDEFINED, nullptr, signature,
+ true));
+ ctx.arg.allowUndefinedSymbols.insert(sym->getName());
+ sym->isUsedInRegularObj = true;
+ return sym;
+}
+
static InputGlobal *createGlobal(StringRef name, bool isMutable) {
llvm::wasm::WasmGlobal wasmGlobal;
bool is64 = ctx.arg.is64.value_or(false);
@@ -946,11 +963,13 @@ static void createSyntheticSymbols() {
bool is64 = ctx.arg.is64.value_or(false);
+ auto stack_pointer_name =
+ ctx.arg.isWasip3 ? "__init_stack_pointer" : "__stack_pointer";
if (ctx.isPic) {
ctx.sym.stackPointer =
- createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
- ? &mutableGlobalTypeI64
- : &mutableGlobalTypeI32);
+ createUndefinedGlobal(stack_pointer_name, ctx.arg.is64.value_or(false)
+ ? &mutableGlobalTypeI64
+ : &mutableGlobalTypeI32);
// For PIC code, we import two global variables (__memory_base and
// __table_base) from the environment and use these as the offset at
// which to load our static data and function table.
@@ -963,14 +982,15 @@ static void createSyntheticSymbols() {
ctx.sym.tableBase->markLive();
} else {
// For non-PIC code
- ctx.sym.stackPointer = createGlobalVariable("__stack_pointer", true);
+ ctx.sym.stackPointer = createGlobalVariable(stack_pointer_name, true);
ctx.sym.stackPointer->markLive();
}
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
// TLS symbols are all hidden/dso-local
- ctx.sym.tlsBase =
- createGlobalVariable("__tls_base", true, WASM_SYMBOL_VISIBILITY_HIDDEN);
+ auto tls_base_name = ctx.arg.isWasip3 ? "__init_tls_base" : "__tls_base";
+ ctx.sym.tlsBase = createGlobalVariable(tls_base_name, true,
+ WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsSize = createGlobalVariable("__tls_size", false,
WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false,
@@ -979,6 +999,21 @@ static void createSyntheticSymbols() {
"__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
"__wasm_init_tls"));
+ if (ctx.arg.isWasip3) {
+ ctx.sym.tlsBase->markLive();
+ ctx.sym.tlsSize->markLive();
+ ctx.sym.tlsAlign->markLive();
+ static WasmSignature contextSet1Signature{{}, {ValType::I32}};
+ ctx.sym.contextSet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_set_1", "[context-set-1]",
+ "$root", &contextSet1Signature);
+ ctx.sym.contextSet1->markLive();
+ static WasmSignature contextGet1Signature{{ValType::I32}, {}};
+ ctx.sym.contextGet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_get_1", "[context-get-1]",
+ "$root", &contextGet1Signature);
+ ctx.sym.contextGet1->markLive();
+ }
}
}
@@ -1017,7 +1052,7 @@ static void createOptionalSymbols() {
//
// __tls_size and __tls_align are not needed in this case since they are only
// needed for __wasm_init_tls (which we do not create in this case).
- if (!ctx.arg.sharedMemory)
+ if (!ctx.arg.sharedMemory && !ctx.arg.isWasip3)
ctx.sym.tlsBase = createOptionalGlobal("__tls_base", false);
}
@@ -1026,15 +1061,15 @@ static void processStubLibrariesPreLTO() {
for (auto &stub_file : ctx.stubFiles) {
LLVM_DEBUG(llvm::dbgs()
<< "processing stub file: " << stub_file->getName() << "\n");
- for (auto [name, deps]: stub_file->symbolDependencies) {
- auto* sym = symtab->find(name);
+ for (auto [name, deps] : stub_file->symbolDependencies) {
+ auto *sym = symtab->find(name);
// If the symbol is not present at all (yet), or if it is present but
// undefined, then mark the dependent symbols as used by a regular
// object so they will be preserved and exported by the LTO process.
if (!sym || sym->isUndefined()) {
for (const auto dep : deps) {
- auto* needed = symtab->find(dep);
- if (needed ) {
+ auto *needed = symtab->find(dep);
+ if (needed) {
needed->isUsedInRegularObj = true;
// Like with handleLibcall we have to extract any LTO archive
// members that might need to be exported due to stub library
diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index a3f87ea3d69c0..cb597fdeffcf3 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -33,7 +33,7 @@ static bool requiresGOTAccess(const Symbol *sym) {
return true;
}
-static bool allowUndefined(const Symbol* sym) {
+static bool allowUndefined(const Symbol *sym) {
// Symbols that are explicitly imported are always allowed to be undefined at
// link time.
if (sym->isImported())
@@ -125,7 +125,7 @@ void scanRelocations(InputChunk *chunk) {
// In single-threaded builds TLS is lowered away and TLS data can be
// merged with normal data and allowing TLS relocation in non-TLS
// segments.
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
if (!sym->isTLS()) {
error(toString(file) + ": relocation " +
relocTypeToString(reloc.Type) +
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index f2040441e6257..97a9871a06308 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -95,7 +95,7 @@ WasmSymbolType Symbol::getWasmType() const {
}
const WasmSignature *Symbol::getSignature() const {
- if (auto* f = dyn_cast<FunctionSymbol>(this))
+ if (auto *f = dyn_cast<FunctionSymbol>(this))
return f->signature;
if (auto *t = dyn_cast<TagSymbol>(this))
return t->signature;
@@ -223,9 +223,7 @@ bool Symbol::isExportedExplicit() const {
return forceExport || flags & WASM_SYMBOL_EXPORTED;
}
-bool Symbol::isNoStrip() const {
- return flags & WASM_SYMBOL_NO_STRIP;
-}
+bool Symbol::isNoStrip() const { return flags & WASM_SYMBOL_NO_STRIP; }
uint32_t FunctionSymbol::getFunctionIndex() const {
if (const auto *u = dyn_cast<UndefinedFunction>(this))
@@ -413,7 +411,7 @@ void LazySymbol::setWeak() {
flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
}
-void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
+void printTraceSymbolUndefined(StringRef name, const InputFile *file) {
message(toString(file) + ": reference to " + name);
}
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index ede6ac4da77b3..023c690c14354 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -466,8 +466,7 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) {
void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
assert(!ctx.arg.extendedConst);
bool is64 = ctx.arg.is64.value_or(false);
- unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
- : WASM_OPCODE_I32_ADD;
+ unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
for (const Symbol *sym : internalGotSymbols) {
if (TLS != sym->isTLS())
@@ -477,7 +476,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
// Get __memory_base
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
if (sym->isTLS())
- writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");
+ writeGetTLSBase(ctx, os);
else
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");
@@ -520,9 +519,9 @@ void GlobalSection::writeBody() {
// the correct runtime value during `__wasm_apply_global_relocs`.
if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())
mutable_ = true;
- // With multi-theadeding any TLS globals must be mutable since they get
+ // With multi-threading any TLS globals must be mutable since they get
// set during `__wasm_apply_global_tls_relocs`
- if (ctx.arg.sharedMemory && sym->isTLS())
+ if (ctx.arg.isMultithreaded() && sym->isTLS())
mutable_ = true;
}
WasmGlobalType type{itype, mutable_};
@@ -559,10 +558,11 @@ void GlobalSection::writeBody() {
} else {
WasmInitExpr initExpr;
if (auto *d = dyn_cast<DefinedData>(sym))
- // In the sharedMemory case TLS globals are set during
- // `__wasm_apply_global_tls_relocs`, but in the non-shared case
+ // In the multi-threaded case, TLS globals are set during
+ // `__wasm_apply_global_tls_relocs`, but in the non-multi-threaded case
// we know the absolute value at link time.
- initExpr = intConst(d->getVA(/*absolute=*/!ctx.arg.sharedMemory), is64);
+ initExpr =
+ intConst(d->getVA(/*absolute=*/!ctx.arg.isMultithreaded()), is64);
else if (auto *f = dyn_cast<FunctionSymbol>(sym))
initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);
else {
@@ -646,7 +646,7 @@ void ElemSection::writeBody() {
uint32_t tableIndex = ctx.arg.tableBase;
for (const FunctionSymbol *sym : indirectFunctions) {
assert(sym->getTableIndex() == tableIndex);
- (void) tableIndex;
+ (void)tableIndex;
writeUleb128(os, sym->getFunctionIndex(), "function index");
++tableIndex;
}
@@ -663,7 +663,7 @@ void DataCountSection::writeBody() {
}
bool DataCountSection::isNeeded() const {
- return numSegments && ctx.arg.sharedMemory;
+ return numSegments && ctx.arg.isMultithreaded();
}
void LinkingSection::writeBody() {
@@ -992,4 +992,4 @@ void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {
memcpy(hashPlaceholderPtr, buf.data(), hashSize);
}
-} // namespace wasm::lld
+} // namespace lld::wasm
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index dfd856f2faee6..50d6449ca79a9 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -311,7 +311,8 @@ void Writer::writeBuildId() {
}
static void setGlobalPtr(DefinedGlobal *g, uint64_t memoryPtr) {
- LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr << "\n");
+ LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr
+ << "\n");
g->global->setPointerValue(memoryPtr);
}
@@ -358,7 +359,8 @@ void Writer::layoutMemory() {
placeStack();
if (ctx.arg.globalBase) {
if (ctx.arg.globalBase < memoryPtr) {
- error("--global-base cannot be less than stack size when --stack-first is used");
+ error("--global-base cannot be less than stack size when --stack-first "
+ "is used");
return;
}
memoryPtr = ctx.arg.globalBase;
@@ -382,6 +384,7 @@ void Writer::layoutMemory() {
for (OutputSegment *seg : segments) {
out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment);
memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment);
+
seg->startVA = memoryPtr;
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
memoryPtr, seg->size, seg->alignment));
@@ -1029,7 +1032,7 @@ static StringRef getOutputDataSegmentName(const InputChunk &seg) {
OutputSegment *Writer::createOutputSegment(StringRef name) {
LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
OutputSegment *s = make<OutputSegment>(name);
- if (ctx.arg.sharedMemory)
+ if (ctx.arg.isMultithreaded())
s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
if (!ctx.arg.relocatable && name.starts_with(".bss"))
s->isBss = true;
@@ -1163,14 +1166,14 @@ void Writer::createSyntheticInitFunctions() {
"__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
ctx.sym.initMemory->mark...
[truncated]
|
|
@llvm/pr-subscribers-llvm-mc Author: Sy Brand (TartanLlama) Changes(Currently in draft, as this will evolve alongside other toolchain component updates) The WebAssembly Component Model has added support for cooperative multithreading. This has been implemented in the Wasmtime engine and is part of the wider project of WASI preview 3, which is currently tracked here. These changes will require updating the way that Patch is 55.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175800.diff 22 Files Affected:
diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp
index daaefd9a1267c..1905b838e52a1 100644
--- a/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -410,7 +410,8 @@ void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
// Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
// or __STDCPP_THREADS__ if we will eventually end up stripping atomics
// because they are unsupported.
- if (!HasAtomics || !HasBulkMemory) {
+ if (getTriple().getOSName() != "wasip3" &&
+ (!HasAtomics || !HasBulkMemory)) {
Opts.POSIXThreads = false;
Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
Opts.ThreadsafeStatics = false;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index b5fa5760a46a0..efeadcc6556de 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -30,13 +30,14 @@ using namespace llvm::opt;
std::string WebAssembly::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const {
- return (TargetTriple.getArchName() + "-" +
- TargetTriple.getOSAndEnvironmentName()).str();
+ return (TargetTriple.getArchName() + "-" +
+ TargetTriple.getOSAndEnvironmentName())
+ .str();
}
std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
const ToolChain &ToolChain = getToolChain();
- if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
StringRef UseLinker = A->getValue();
if (!UseLinker.empty()) {
if (llvm::sys::path::is_absolute(UseLinker) &&
@@ -79,6 +80,10 @@ static bool WantsPthread(const llvm::Triple &Triple, const ArgList &Args) {
return WantsPthread;
}
+static bool WantsSharedMemory(const llvm::Triple &Triple, const ArgList &Args) {
+ return WantsPthread(Triple, Args) && !TargetBuildsComponents(Triple);
+}
+
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -90,10 +95,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back("-m");
+ std::string arch;
if (ToolChain.getTriple().isArch64Bit())
- CmdArgs.push_back("wasm64");
+ arch = "wasm64";
else
- CmdArgs.push_back("wasm32");
+ arch = "wasm32";
+ if (ToolChain.getTriple().getOSName() == "wasip3")
+ arch += "-wasip3";
+ CmdArgs.push_back(Args.MakeArgString(arch));
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -160,7 +169,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (WantsPthread(ToolChain.getTriple(), Args))
+ if (WantsSharedMemory(ToolChain.getTriple(), Args))
CmdArgs.push_back("--shared-memory");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -233,9 +242,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// Given a base library directory, append path components to form the
/// LTO directory.
static std::string AppendLTOLibDir(const std::string &Dir) {
- // The version allows the path to be keyed to the specific version of
- // LLVM in used, as the bitcode format is not stable.
- return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
+ // The version allows the path to be keyed to the specific version of
+ // LLVM in used, as the bitcode format is not stable.
+ return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
}
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
@@ -508,7 +517,8 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (getTriple().getOS() != llvm::Triple::UnknownOS) {
const std::string MultiarchTriple =
getMultiarchTriple(D, getTriple(), D.SysRoot);
- addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include/" + MultiarchTriple);
+ addSystemInclude(DriverArgs, CC1Args,
+ D.SysRoot + "/include/" + MultiarchTriple);
}
addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
}
@@ -637,5 +647,6 @@ void WebAssembly::addLibStdCXXIncludePaths(
// Second add the generic one.
addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
// Third the backward one.
- addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
+ addSystemInclude(DriverArgs, CC1Args,
+ LibPath + "/c++/" + Version + "/backward");
}
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 31e08e4e248a4..d291a42da200f 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -35,6 +35,7 @@ class Symbol;
class DefinedData;
class GlobalSymbol;
class DefinedFunction;
+class UndefinedFunction;
class DefinedGlobal;
class UndefinedGlobal;
class TableSymbol;
@@ -50,6 +51,8 @@ enum class BuildIdKind { None, Fast, Sha1, Hexstring, Uuid };
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Config {
+ bool isMultithreaded() const { return sharedMemory || isWasip3; }
+
bool allowMultipleDefinition;
bool bsymbolic;
bool checkFeatures;
@@ -71,6 +74,7 @@ struct Config {
bool importTable;
bool importUndefined;
std::optional<bool> is64;
+ bool isWasip3;
bool mergeDataSegments;
bool noinhibitExec;
bool pie;
@@ -252,6 +256,14 @@ struct Ctx {
// Used as an address space for function pointers, with each function that
// is used as a function pointer being allocated a slot.
TableSymbol *indirectFunctionTable;
+
+ // __wasm_component_model_builtin_context_set_1
+ // Function used to set TLS base in component model modules.
+ UndefinedFunction *contextSet1;
+
+ // __wasm_component_model_builtin_context_get_1
+ // Function used to get TLS base in component model modules.
+ UndefinedFunction *contextGet1;
};
WasmSym sym;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index b1e36f2ecff74..6eaacd7288f22 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -656,15 +656,16 @@ static void readConfigs(opt::InputArgList &args) {
ctx.arg.exportDynamic =
args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, ctx.arg.shared);
- // Parse wasm32/64.
+ // Parse wasm32/64 and maybe -wasip3.
if (auto *arg = args.getLastArg(OPT_m)) {
StringRef s = arg->getValue();
- if (s == "wasm32")
+ if (s.starts_with("wasm32"))
ctx.arg.is64 = false;
- else if (s == "wasm64")
+ else if (s.starts_with("wasm64"))
ctx.arg.is64 = true;
else
error("invalid target architecture: " + s);
+ ctx.arg.isWasip3 = s.ends_with("-wasip3");
}
// --threads= takes a positive integer and provides the default value for
@@ -827,6 +828,10 @@ static void checkOptions(opt::InputArgList &args) {
if (ctx.arg.tableBase)
error("--table-base may not be used with -shared/-pie");
}
+
+ if (ctx.arg.sharedMemory && ctx.arg.isWasip3) {
+ error("--shared-memory is incompatible with the wasip3 target");
+ }
}
static const char *getReproduceOption(opt::InputArgList &args) {
@@ -885,7 +890,7 @@ static void writeWhyExtract() {
// Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker
static void demoteLazySymbols() {
for (Symbol *sym : symtab->symbols()) {
- if (auto* s = dyn_cast<LazySymbol>(sym)) {
+ if (auto *s = dyn_cast<LazySymbol>(sym)) {
if (s->signature) {
LLVM_DEBUG(llvm::dbgs()
<< "demoting lazy func: " << s->getName() << "\n");
@@ -906,6 +911,18 @@ createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
return sym;
}
+static UndefinedFunction *
+createUndefinedFunction(StringRef name, std::optional<StringRef> importName,
+ std::optional<StringRef> importModule,
+ WasmSignature *signature) {
+ auto *sym = cast<UndefinedFunction>(symtab->addUndefinedFunction(
+ name, importName, importModule, WASM_SYMBOL_UNDEFINED, nullptr, signature,
+ true));
+ ctx.arg.allowUndefinedSymbols.insert(sym->getName());
+ sym->isUsedInRegularObj = true;
+ return sym;
+}
+
static InputGlobal *createGlobal(StringRef name, bool isMutable) {
llvm::wasm::WasmGlobal wasmGlobal;
bool is64 = ctx.arg.is64.value_or(false);
@@ -946,11 +963,13 @@ static void createSyntheticSymbols() {
bool is64 = ctx.arg.is64.value_or(false);
+ auto stack_pointer_name =
+ ctx.arg.isWasip3 ? "__init_stack_pointer" : "__stack_pointer";
if (ctx.isPic) {
ctx.sym.stackPointer =
- createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
- ? &mutableGlobalTypeI64
- : &mutableGlobalTypeI32);
+ createUndefinedGlobal(stack_pointer_name, ctx.arg.is64.value_or(false)
+ ? &mutableGlobalTypeI64
+ : &mutableGlobalTypeI32);
// For PIC code, we import two global variables (__memory_base and
// __table_base) from the environment and use these as the offset at
// which to load our static data and function table.
@@ -963,14 +982,15 @@ static void createSyntheticSymbols() {
ctx.sym.tableBase->markLive();
} else {
// For non-PIC code
- ctx.sym.stackPointer = createGlobalVariable("__stack_pointer", true);
+ ctx.sym.stackPointer = createGlobalVariable(stack_pointer_name, true);
ctx.sym.stackPointer->markLive();
}
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
// TLS symbols are all hidden/dso-local
- ctx.sym.tlsBase =
- createGlobalVariable("__tls_base", true, WASM_SYMBOL_VISIBILITY_HIDDEN);
+ auto tls_base_name = ctx.arg.isWasip3 ? "__init_tls_base" : "__tls_base";
+ ctx.sym.tlsBase = createGlobalVariable(tls_base_name, true,
+ WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsSize = createGlobalVariable("__tls_size", false,
WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false,
@@ -979,6 +999,21 @@ static void createSyntheticSymbols() {
"__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
"__wasm_init_tls"));
+ if (ctx.arg.isWasip3) {
+ ctx.sym.tlsBase->markLive();
+ ctx.sym.tlsSize->markLive();
+ ctx.sym.tlsAlign->markLive();
+ static WasmSignature contextSet1Signature{{}, {ValType::I32}};
+ ctx.sym.contextSet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_set_1", "[context-set-1]",
+ "$root", &contextSet1Signature);
+ ctx.sym.contextSet1->markLive();
+ static WasmSignature contextGet1Signature{{ValType::I32}, {}};
+ ctx.sym.contextGet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_get_1", "[context-get-1]",
+ "$root", &contextGet1Signature);
+ ctx.sym.contextGet1->markLive();
+ }
}
}
@@ -1017,7 +1052,7 @@ static void createOptionalSymbols() {
//
// __tls_size and __tls_align are not needed in this case since they are only
// needed for __wasm_init_tls (which we do not create in this case).
- if (!ctx.arg.sharedMemory)
+ if (!ctx.arg.sharedMemory && !ctx.arg.isWasip3)
ctx.sym.tlsBase = createOptionalGlobal("__tls_base", false);
}
@@ -1026,15 +1061,15 @@ static void processStubLibrariesPreLTO() {
for (auto &stub_file : ctx.stubFiles) {
LLVM_DEBUG(llvm::dbgs()
<< "processing stub file: " << stub_file->getName() << "\n");
- for (auto [name, deps]: stub_file->symbolDependencies) {
- auto* sym = symtab->find(name);
+ for (auto [name, deps] : stub_file->symbolDependencies) {
+ auto *sym = symtab->find(name);
// If the symbol is not present at all (yet), or if it is present but
// undefined, then mark the dependent symbols as used by a regular
// object so they will be preserved and exported by the LTO process.
if (!sym || sym->isUndefined()) {
for (const auto dep : deps) {
- auto* needed = symtab->find(dep);
- if (needed ) {
+ auto *needed = symtab->find(dep);
+ if (needed) {
needed->isUsedInRegularObj = true;
// Like with handleLibcall we have to extract any LTO archive
// members that might need to be exported due to stub library
diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index a3f87ea3d69c0..cb597fdeffcf3 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -33,7 +33,7 @@ static bool requiresGOTAccess(const Symbol *sym) {
return true;
}
-static bool allowUndefined(const Symbol* sym) {
+static bool allowUndefined(const Symbol *sym) {
// Symbols that are explicitly imported are always allowed to be undefined at
// link time.
if (sym->isImported())
@@ -125,7 +125,7 @@ void scanRelocations(InputChunk *chunk) {
// In single-threaded builds TLS is lowered away and TLS data can be
// merged with normal data and allowing TLS relocation in non-TLS
// segments.
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
if (!sym->isTLS()) {
error(toString(file) + ": relocation " +
relocTypeToString(reloc.Type) +
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index f2040441e6257..97a9871a06308 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -95,7 +95,7 @@ WasmSymbolType Symbol::getWasmType() const {
}
const WasmSignature *Symbol::getSignature() const {
- if (auto* f = dyn_cast<FunctionSymbol>(this))
+ if (auto *f = dyn_cast<FunctionSymbol>(this))
return f->signature;
if (auto *t = dyn_cast<TagSymbol>(this))
return t->signature;
@@ -223,9 +223,7 @@ bool Symbol::isExportedExplicit() const {
return forceExport || flags & WASM_SYMBOL_EXPORTED;
}
-bool Symbol::isNoStrip() const {
- return flags & WASM_SYMBOL_NO_STRIP;
-}
+bool Symbol::isNoStrip() const { return flags & WASM_SYMBOL_NO_STRIP; }
uint32_t FunctionSymbol::getFunctionIndex() const {
if (const auto *u = dyn_cast<UndefinedFunction>(this))
@@ -413,7 +411,7 @@ void LazySymbol::setWeak() {
flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
}
-void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
+void printTraceSymbolUndefined(StringRef name, const InputFile *file) {
message(toString(file) + ": reference to " + name);
}
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index ede6ac4da77b3..023c690c14354 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -466,8 +466,7 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) {
void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
assert(!ctx.arg.extendedConst);
bool is64 = ctx.arg.is64.value_or(false);
- unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
- : WASM_OPCODE_I32_ADD;
+ unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
for (const Symbol *sym : internalGotSymbols) {
if (TLS != sym->isTLS())
@@ -477,7 +476,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
// Get __memory_base
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
if (sym->isTLS())
- writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");
+ writeGetTLSBase(ctx, os);
else
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");
@@ -520,9 +519,9 @@ void GlobalSection::writeBody() {
// the correct runtime value during `__wasm_apply_global_relocs`.
if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())
mutable_ = true;
- // With multi-theadeding any TLS globals must be mutable since they get
+ // With multi-threading any TLS globals must be mutable since they get
// set during `__wasm_apply_global_tls_relocs`
- if (ctx.arg.sharedMemory && sym->isTLS())
+ if (ctx.arg.isMultithreaded() && sym->isTLS())
mutable_ = true;
}
WasmGlobalType type{itype, mutable_};
@@ -559,10 +558,11 @@ void GlobalSection::writeBody() {
} else {
WasmInitExpr initExpr;
if (auto *d = dyn_cast<DefinedData>(sym))
- // In the sharedMemory case TLS globals are set during
- // `__wasm_apply_global_tls_relocs`, but in the non-shared case
+ // In the multi-threaded case, TLS globals are set during
+ // `__wasm_apply_global_tls_relocs`, but in the non-multi-threaded case
// we know the absolute value at link time.
- initExpr = intConst(d->getVA(/*absolute=*/!ctx.arg.sharedMemory), is64);
+ initExpr =
+ intConst(d->getVA(/*absolute=*/!ctx.arg.isMultithreaded()), is64);
else if (auto *f = dyn_cast<FunctionSymbol>(sym))
initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);
else {
@@ -646,7 +646,7 @@ void ElemSection::writeBody() {
uint32_t tableIndex = ctx.arg.tableBase;
for (const FunctionSymbol *sym : indirectFunctions) {
assert(sym->getTableIndex() == tableIndex);
- (void) tableIndex;
+ (void)tableIndex;
writeUleb128(os, sym->getFunctionIndex(), "function index");
++tableIndex;
}
@@ -663,7 +663,7 @@ void DataCountSection::writeBody() {
}
bool DataCountSection::isNeeded() const {
- return numSegments && ctx.arg.sharedMemory;
+ return numSegments && ctx.arg.isMultithreaded();
}
void LinkingSection::writeBody() {
@@ -992,4 +992,4 @@ void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {
memcpy(hashPlaceholderPtr, buf.data(), hashSize);
}
-} // namespace wasm::lld
+} // namespace lld::wasm
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index dfd856f2faee6..50d6449ca79a9 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -311,7 +311,8 @@ void Writer::writeBuildId() {
}
static void setGlobalPtr(DefinedGlobal *g, uint64_t memoryPtr) {
- LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr << "\n");
+ LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr
+ << "\n");
g->global->setPointerValue(memoryPtr);
}
@@ -358,7 +359,8 @@ void Writer::layoutMemory() {
placeStack();
if (ctx.arg.globalBase) {
if (ctx.arg.globalBase < memoryPtr) {
- error("--global-base cannot be less than stack size when --stack-first is used");
+ error("--global-base cannot be less than stack size when --stack-first "
+ "is used");
return;
}
memoryPtr = ctx.arg.globalBase;
@@ -382,6 +384,7 @@ void Writer::layoutMemory() {
for (OutputSegment *seg : segments) {
out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment);
memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment);
+
seg->startVA = memoryPtr;
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
memoryPtr, seg->size, seg->alignment));
@@ -1029,7 +1032,7 @@ static StringRef getOutputDataSegmentName(const InputChunk &seg) {
OutputSegment *Writer::createOutputSegment(StringRef name) {
LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
OutputSegment *s = make<OutputSegment>(name);
- if (ctx.arg.sharedMemory)
+ if (ctx.arg.isMultithreaded())
s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
if (!ctx.arg.relocatable && name.starts_with(".bss"))
s->isBss = true;
@@ -1163,14 +1166,14 @@ void Writer::createSyntheticInitFunctions() {
"__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
ctx.sym.initMemory->mark...
[truncated]
|
|
@llvm/pr-subscribers-backend-webassembly Author: Sy Brand (TartanLlama) Changes(Currently in draft, as this will evolve alongside other toolchain component updates) The WebAssembly Component Model has added support for cooperative multithreading. This has been implemented in the Wasmtime engine and is part of the wider project of WASI preview 3, which is currently tracked here. These changes will require updating the way that Patch is 55.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175800.diff 22 Files Affected:
diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp
index daaefd9a1267c..1905b838e52a1 100644
--- a/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -410,7 +410,8 @@ void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
// Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
// or __STDCPP_THREADS__ if we will eventually end up stripping atomics
// because they are unsupported.
- if (!HasAtomics || !HasBulkMemory) {
+ if (getTriple().getOSName() != "wasip3" &&
+ (!HasAtomics || !HasBulkMemory)) {
Opts.POSIXThreads = false;
Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
Opts.ThreadsafeStatics = false;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index b5fa5760a46a0..efeadcc6556de 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -30,13 +30,14 @@ using namespace llvm::opt;
std::string WebAssembly::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const {
- return (TargetTriple.getArchName() + "-" +
- TargetTriple.getOSAndEnvironmentName()).str();
+ return (TargetTriple.getArchName() + "-" +
+ TargetTriple.getOSAndEnvironmentName())
+ .str();
}
std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
const ToolChain &ToolChain = getToolChain();
- if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
StringRef UseLinker = A->getValue();
if (!UseLinker.empty()) {
if (llvm::sys::path::is_absolute(UseLinker) &&
@@ -79,6 +80,10 @@ static bool WantsPthread(const llvm::Triple &Triple, const ArgList &Args) {
return WantsPthread;
}
+static bool WantsSharedMemory(const llvm::Triple &Triple, const ArgList &Args) {
+ return WantsPthread(Triple, Args) && !TargetBuildsComponents(Triple);
+}
+
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -90,10 +95,14 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back("-m");
+ std::string arch;
if (ToolChain.getTriple().isArch64Bit())
- CmdArgs.push_back("wasm64");
+ arch = "wasm64";
else
- CmdArgs.push_back("wasm32");
+ arch = "wasm32";
+ if (ToolChain.getTriple().getOSName() == "wasip3")
+ arch += "-wasip3";
+ CmdArgs.push_back(Args.MakeArgString(arch));
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -160,7 +169,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (WantsPthread(ToolChain.getTriple(), Args))
+ if (WantsSharedMemory(ToolChain.getTriple(), Args))
CmdArgs.push_back("--shared-memory");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -233,9 +242,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// Given a base library directory, append path components to form the
/// LTO directory.
static std::string AppendLTOLibDir(const std::string &Dir) {
- // The version allows the path to be keyed to the specific version of
- // LLVM in used, as the bitcode format is not stable.
- return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
+ // The version allows the path to be keyed to the specific version of
+ // LLVM in used, as the bitcode format is not stable.
+ return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
}
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
@@ -508,7 +517,8 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (getTriple().getOS() != llvm::Triple::UnknownOS) {
const std::string MultiarchTriple =
getMultiarchTriple(D, getTriple(), D.SysRoot);
- addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include/" + MultiarchTriple);
+ addSystemInclude(DriverArgs, CC1Args,
+ D.SysRoot + "/include/" + MultiarchTriple);
}
addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
}
@@ -637,5 +647,6 @@ void WebAssembly::addLibStdCXXIncludePaths(
// Second add the generic one.
addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
// Third the backward one.
- addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
+ addSystemInclude(DriverArgs, CC1Args,
+ LibPath + "/c++/" + Version + "/backward");
}
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 31e08e4e248a4..d291a42da200f 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -35,6 +35,7 @@ class Symbol;
class DefinedData;
class GlobalSymbol;
class DefinedFunction;
+class UndefinedFunction;
class DefinedGlobal;
class UndefinedGlobal;
class TableSymbol;
@@ -50,6 +51,8 @@ enum class BuildIdKind { None, Fast, Sha1, Hexstring, Uuid };
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Config {
+ bool isMultithreaded() const { return sharedMemory || isWasip3; }
+
bool allowMultipleDefinition;
bool bsymbolic;
bool checkFeatures;
@@ -71,6 +74,7 @@ struct Config {
bool importTable;
bool importUndefined;
std::optional<bool> is64;
+ bool isWasip3;
bool mergeDataSegments;
bool noinhibitExec;
bool pie;
@@ -252,6 +256,14 @@ struct Ctx {
// Used as an address space for function pointers, with each function that
// is used as a function pointer being allocated a slot.
TableSymbol *indirectFunctionTable;
+
+ // __wasm_component_model_builtin_context_set_1
+ // Function used to set TLS base in component model modules.
+ UndefinedFunction *contextSet1;
+
+ // __wasm_component_model_builtin_context_get_1
+ // Function used to get TLS base in component model modules.
+ UndefinedFunction *contextGet1;
};
WasmSym sym;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index b1e36f2ecff74..6eaacd7288f22 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -656,15 +656,16 @@ static void readConfigs(opt::InputArgList &args) {
ctx.arg.exportDynamic =
args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, ctx.arg.shared);
- // Parse wasm32/64.
+ // Parse wasm32/64 and maybe -wasip3.
if (auto *arg = args.getLastArg(OPT_m)) {
StringRef s = arg->getValue();
- if (s == "wasm32")
+ if (s.starts_with("wasm32"))
ctx.arg.is64 = false;
- else if (s == "wasm64")
+ else if (s.starts_with("wasm64"))
ctx.arg.is64 = true;
else
error("invalid target architecture: " + s);
+ ctx.arg.isWasip3 = s.ends_with("-wasip3");
}
// --threads= takes a positive integer and provides the default value for
@@ -827,6 +828,10 @@ static void checkOptions(opt::InputArgList &args) {
if (ctx.arg.tableBase)
error("--table-base may not be used with -shared/-pie");
}
+
+ if (ctx.arg.sharedMemory && ctx.arg.isWasip3) {
+ error("--shared-memory is incompatible with the wasip3 target");
+ }
}
static const char *getReproduceOption(opt::InputArgList &args) {
@@ -885,7 +890,7 @@ static void writeWhyExtract() {
// Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker
static void demoteLazySymbols() {
for (Symbol *sym : symtab->symbols()) {
- if (auto* s = dyn_cast<LazySymbol>(sym)) {
+ if (auto *s = dyn_cast<LazySymbol>(sym)) {
if (s->signature) {
LLVM_DEBUG(llvm::dbgs()
<< "demoting lazy func: " << s->getName() << "\n");
@@ -906,6 +911,18 @@ createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
return sym;
}
+static UndefinedFunction *
+createUndefinedFunction(StringRef name, std::optional<StringRef> importName,
+ std::optional<StringRef> importModule,
+ WasmSignature *signature) {
+ auto *sym = cast<UndefinedFunction>(symtab->addUndefinedFunction(
+ name, importName, importModule, WASM_SYMBOL_UNDEFINED, nullptr, signature,
+ true));
+ ctx.arg.allowUndefinedSymbols.insert(sym->getName());
+ sym->isUsedInRegularObj = true;
+ return sym;
+}
+
static InputGlobal *createGlobal(StringRef name, bool isMutable) {
llvm::wasm::WasmGlobal wasmGlobal;
bool is64 = ctx.arg.is64.value_or(false);
@@ -946,11 +963,13 @@ static void createSyntheticSymbols() {
bool is64 = ctx.arg.is64.value_or(false);
+ auto stack_pointer_name =
+ ctx.arg.isWasip3 ? "__init_stack_pointer" : "__stack_pointer";
if (ctx.isPic) {
ctx.sym.stackPointer =
- createUndefinedGlobal("__stack_pointer", ctx.arg.is64.value_or(false)
- ? &mutableGlobalTypeI64
- : &mutableGlobalTypeI32);
+ createUndefinedGlobal(stack_pointer_name, ctx.arg.is64.value_or(false)
+ ? &mutableGlobalTypeI64
+ : &mutableGlobalTypeI32);
// For PIC code, we import two global variables (__memory_base and
// __table_base) from the environment and use these as the offset at
// which to load our static data and function table.
@@ -963,14 +982,15 @@ static void createSyntheticSymbols() {
ctx.sym.tableBase->markLive();
} else {
// For non-PIC code
- ctx.sym.stackPointer = createGlobalVariable("__stack_pointer", true);
+ ctx.sym.stackPointer = createGlobalVariable(stack_pointer_name, true);
ctx.sym.stackPointer->markLive();
}
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
// TLS symbols are all hidden/dso-local
- ctx.sym.tlsBase =
- createGlobalVariable("__tls_base", true, WASM_SYMBOL_VISIBILITY_HIDDEN);
+ auto tls_base_name = ctx.arg.isWasip3 ? "__init_tls_base" : "__tls_base";
+ ctx.sym.tlsBase = createGlobalVariable(tls_base_name, true,
+ WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsSize = createGlobalVariable("__tls_size", false,
WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false,
@@ -979,6 +999,21 @@ static void createSyntheticSymbols() {
"__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
"__wasm_init_tls"));
+ if (ctx.arg.isWasip3) {
+ ctx.sym.tlsBase->markLive();
+ ctx.sym.tlsSize->markLive();
+ ctx.sym.tlsAlign->markLive();
+ static WasmSignature contextSet1Signature{{}, {ValType::I32}};
+ ctx.sym.contextSet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_set_1", "[context-set-1]",
+ "$root", &contextSet1Signature);
+ ctx.sym.contextSet1->markLive();
+ static WasmSignature contextGet1Signature{{ValType::I32}, {}};
+ ctx.sym.contextGet1 = createUndefinedFunction(
+ "__wasm_component_model_builtin_context_get_1", "[context-get-1]",
+ "$root", &contextGet1Signature);
+ ctx.sym.contextGet1->markLive();
+ }
}
}
@@ -1017,7 +1052,7 @@ static void createOptionalSymbols() {
//
// __tls_size and __tls_align are not needed in this case since they are only
// needed for __wasm_init_tls (which we do not create in this case).
- if (!ctx.arg.sharedMemory)
+ if (!ctx.arg.sharedMemory && !ctx.arg.isWasip3)
ctx.sym.tlsBase = createOptionalGlobal("__tls_base", false);
}
@@ -1026,15 +1061,15 @@ static void processStubLibrariesPreLTO() {
for (auto &stub_file : ctx.stubFiles) {
LLVM_DEBUG(llvm::dbgs()
<< "processing stub file: " << stub_file->getName() << "\n");
- for (auto [name, deps]: stub_file->symbolDependencies) {
- auto* sym = symtab->find(name);
+ for (auto [name, deps] : stub_file->symbolDependencies) {
+ auto *sym = symtab->find(name);
// If the symbol is not present at all (yet), or if it is present but
// undefined, then mark the dependent symbols as used by a regular
// object so they will be preserved and exported by the LTO process.
if (!sym || sym->isUndefined()) {
for (const auto dep : deps) {
- auto* needed = symtab->find(dep);
- if (needed ) {
+ auto *needed = symtab->find(dep);
+ if (needed) {
needed->isUsedInRegularObj = true;
// Like with handleLibcall we have to extract any LTO archive
// members that might need to be exported due to stub library
diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index a3f87ea3d69c0..cb597fdeffcf3 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -33,7 +33,7 @@ static bool requiresGOTAccess(const Symbol *sym) {
return true;
}
-static bool allowUndefined(const Symbol* sym) {
+static bool allowUndefined(const Symbol *sym) {
// Symbols that are explicitly imported are always allowed to be undefined at
// link time.
if (sym->isImported())
@@ -125,7 +125,7 @@ void scanRelocations(InputChunk *chunk) {
// In single-threaded builds TLS is lowered away and TLS data can be
// merged with normal data and allowing TLS relocation in non-TLS
// segments.
- if (ctx.arg.sharedMemory) {
+ if (ctx.arg.isMultithreaded()) {
if (!sym->isTLS()) {
error(toString(file) + ": relocation " +
relocTypeToString(reloc.Type) +
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index f2040441e6257..97a9871a06308 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -95,7 +95,7 @@ WasmSymbolType Symbol::getWasmType() const {
}
const WasmSignature *Symbol::getSignature() const {
- if (auto* f = dyn_cast<FunctionSymbol>(this))
+ if (auto *f = dyn_cast<FunctionSymbol>(this))
return f->signature;
if (auto *t = dyn_cast<TagSymbol>(this))
return t->signature;
@@ -223,9 +223,7 @@ bool Symbol::isExportedExplicit() const {
return forceExport || flags & WASM_SYMBOL_EXPORTED;
}
-bool Symbol::isNoStrip() const {
- return flags & WASM_SYMBOL_NO_STRIP;
-}
+bool Symbol::isNoStrip() const { return flags & WASM_SYMBOL_NO_STRIP; }
uint32_t FunctionSymbol::getFunctionIndex() const {
if (const auto *u = dyn_cast<UndefinedFunction>(this))
@@ -413,7 +411,7 @@ void LazySymbol::setWeak() {
flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
}
-void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
+void printTraceSymbolUndefined(StringRef name, const InputFile *file) {
message(toString(file) + ": reference to " + name);
}
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index ede6ac4da77b3..023c690c14354 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -466,8 +466,7 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) {
void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
assert(!ctx.arg.extendedConst);
bool is64 = ctx.arg.is64.value_or(false);
- unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
- : WASM_OPCODE_I32_ADD;
+ unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
for (const Symbol *sym : internalGotSymbols) {
if (TLS != sym->isTLS())
@@ -477,7 +476,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
// Get __memory_base
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
if (sym->isTLS())
- writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");
+ writeGetTLSBase(ctx, os);
else
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");
@@ -520,9 +519,9 @@ void GlobalSection::writeBody() {
// the correct runtime value during `__wasm_apply_global_relocs`.
if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())
mutable_ = true;
- // With multi-theadeding any TLS globals must be mutable since they get
+ // With multi-threading any TLS globals must be mutable since they get
// set during `__wasm_apply_global_tls_relocs`
- if (ctx.arg.sharedMemory && sym->isTLS())
+ if (ctx.arg.isMultithreaded() && sym->isTLS())
mutable_ = true;
}
WasmGlobalType type{itype, mutable_};
@@ -559,10 +558,11 @@ void GlobalSection::writeBody() {
} else {
WasmInitExpr initExpr;
if (auto *d = dyn_cast<DefinedData>(sym))
- // In the sharedMemory case TLS globals are set during
- // `__wasm_apply_global_tls_relocs`, but in the non-shared case
+ // In the multi-threaded case, TLS globals are set during
+ // `__wasm_apply_global_tls_relocs`, but in the non-multi-threaded case
// we know the absolute value at link time.
- initExpr = intConst(d->getVA(/*absolute=*/!ctx.arg.sharedMemory), is64);
+ initExpr =
+ intConst(d->getVA(/*absolute=*/!ctx.arg.isMultithreaded()), is64);
else if (auto *f = dyn_cast<FunctionSymbol>(sym))
initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);
else {
@@ -646,7 +646,7 @@ void ElemSection::writeBody() {
uint32_t tableIndex = ctx.arg.tableBase;
for (const FunctionSymbol *sym : indirectFunctions) {
assert(sym->getTableIndex() == tableIndex);
- (void) tableIndex;
+ (void)tableIndex;
writeUleb128(os, sym->getFunctionIndex(), "function index");
++tableIndex;
}
@@ -663,7 +663,7 @@ void DataCountSection::writeBody() {
}
bool DataCountSection::isNeeded() const {
- return numSegments && ctx.arg.sharedMemory;
+ return numSegments && ctx.arg.isMultithreaded();
}
void LinkingSection::writeBody() {
@@ -992,4 +992,4 @@ void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {
memcpy(hashPlaceholderPtr, buf.data(), hashSize);
}
-} // namespace wasm::lld
+} // namespace lld::wasm
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index dfd856f2faee6..50d6449ca79a9 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -311,7 +311,8 @@ void Writer::writeBuildId() {
}
static void setGlobalPtr(DefinedGlobal *g, uint64_t memoryPtr) {
- LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr << "\n");
+ LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr
+ << "\n");
g->global->setPointerValue(memoryPtr);
}
@@ -358,7 +359,8 @@ void Writer::layoutMemory() {
placeStack();
if (ctx.arg.globalBase) {
if (ctx.arg.globalBase < memoryPtr) {
- error("--global-base cannot be less than stack size when --stack-first is used");
+ error("--global-base cannot be less than stack size when --stack-first "
+ "is used");
return;
}
memoryPtr = ctx.arg.globalBase;
@@ -382,6 +384,7 @@ void Writer::layoutMemory() {
for (OutputSegment *seg : segments) {
out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment);
memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment);
+
seg->startVA = memoryPtr;
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
memoryPtr, seg->size, seg->alignment));
@@ -1029,7 +1032,7 @@ static StringRef getOutputDataSegmentName(const InputChunk &seg) {
OutputSegment *Writer::createOutputSegment(StringRef name) {
LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
OutputSegment *s = make<OutputSegment>(name);
- if (ctx.arg.sharedMemory)
+ if (ctx.arg.isMultithreaded())
s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
if (!ctx.arg.relocatable && name.starts_with(".bss"))
s->isBss = true;
@@ -1163,14 +1166,14 @@ void Writer::createSyntheticInitFunctions() {
"__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
ctx.sym.initMemory->mark...
[truncated]
|
|
@alexcrichton I've factored out the WASIP3 changes into feature flags and linker options like |
|
@alexcrichton I've made it so that if you try to link an object file compiled with/without the |
|
I'll progressively add tests to this, but the core functionality is ready for review |
sbc100
left a comment
There was a problem hiding this comment.
LGTM % a couple last nits.
| // info is present so we can allocate a local for DWARF to reference. | ||
| bool NeedsSPForDebug = | ||
| MF.getFunction().getSubprogram() && | ||
| MF.getSubtarget<WebAssemblySubtarget>().hasLibcallThreadContext(); |
There was a problem hiding this comment.
Is there a test that covers this part of the change?
| IntPtrType = SignedLong; | ||
| } | ||
| if (T.getOS() == llvm::Triple::WASIp3) | ||
| HasLibcallThreadContext = true; |
There was a problem hiding this comment.
This logic seems to be repeated in WebAssemblySubtarget.cpp. Is the expected/unavoidable?
There was a problem hiding this comment.
I think this is expected, because both Clang and LLVM need to default the behaviour based on the triple
|
thanks for sticking with this! Don't forget to update the commit message with the final description, and maybe also note that the feature/define that we are adding will eventually go away once the library code has migrated to having the ABI and OS be synonymous. |
|
@dschuff thanks, I've updated the PR description |
| static bool WantsLibcallThreadContext(const llvm::Triple &Triple, | ||
| const ArgList &Args) { | ||
| return Triple.getOS() == llvm::Triple::WASIp3; | ||
| } |
There was a problem hiding this comment.
Do we need this function or can use the HasLibcallThreadContext from clang/lib/Basic/Targets/WebAssembly.h ?
There was a problem hiding this comment.
I think the driver toolchain file doesn't have access to that
|
lgtm % CI failures. They don't look related at all.. perhaps you could try rebasing to see if they are transient? |
|
I'm not sure whats going on with the CI, do the failures look like they could be possibly related to this change? |
|
The failure is a compile failure building the ASan runtime (which is not a wasm build) so I don't think it could plausibly be related. |
|
We can let the currently in-progress tests run, but if they fail again I'll just merge manually. |
|
@TartanLlama Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
The [WebAssembly Component Model](https://component-model.bytecodealliance.org/) has added support for [cooperative multithreading](WebAssembly/component-model#557). This has been implemented in the [Wasmtime engine](bytecodealliance/wasmtime#11751) and is part of the wider project of [WASI preview 3](https://wasi.dev/roadmap#upcoming-wasi-03-releases), which is currently tracked [here](https://github.com/orgs/bytecodealliance/projects/16). These changes require updating the way that `__stack_pointer` and `__tls_base` work purely for a new `wasm32-wasip3` target; other targets will not be touched. Specifically, rather than using a Wasm global for tracking the stack pointer and TLS base, the new [`context.get/set`](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#-canon-contextget) component model builtin functions will be used (the intention being that runtimes will need to aggressively optimize these calls into single load/stores). For justification on this choice rather than switching out the global at context-switch boundaries, see [this comment](WebAssembly/wasi-libc#691 (comment)) and [this comment](WebAssembly/wasi-libc#691 (comment)). This PR adds support for using library calls instead of globals for holding the stack pointer and TLS base. When used, this thread context ABI emits calls to `__wasm_{get,set}_{stack_pointer,tls_base}` when needed. These functions can then be implemented in `libc`. This is enabled only for the WASIp3 target. There is a temporary macro define for `__wasm_libcall_thread_context__` which can be removed once `wasi-libc` has fully migrated to the new ABI for the WASIp3 target.
The WebAssembly Component Model has added support for cooperative multithreading. This has been implemented in the Wasmtime engine and is part of the wider project of WASI preview 3, which is currently tracked here.
These changes require updating the way that
__stack_pointerand__tls_basework purely for a newwasm32-wasip3target; other targets will not be touched. Specifically, rather than using a Wasm global for tracking the stack pointer and TLS base, the newcontext.get/setcomponent model builtin functions will be used (the intention being that runtimes will need to aggressively optimize these calls into single load/stores). For justification on this choice rather than switching out the global at context-switch boundaries, see this comment and this comment.This PR adds support for using library calls instead of globals for holding the stack pointer and TLS base. When used, this thread context ABI emits calls to
__wasm_{get,set}_{stack_pointer,tls_base}when needed. These functions can then be implemented inlibc. This is enabled only for the WASIp3 target.There is a temporary macro define for
__wasm_libcall_thread_context__which can be removed oncewasi-libchas fully migrated to the new ABI for the WASIp3 target.