-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Wasm globals from C code? #12793
Comments
Currently that only way to do that is using See There are plan to try expose first class WebAssembly concepts to llvm's higher levels and eventually perhaps to C/C++ as well. I believe current efforts are focused on reference types, but it seems like the tequniques could equally well be applied to other first class WebAssembly elements such as globals. Here is some of the work being done to enable ref types: https://reviews.llvm.org/D91428 @tlively is there a short route we could use to expose wasm globals? Anyway, hopefully the |
Unfortunately that will not let me do what I would want to - I really would need to have support for defining globals directly in C code. The intent is twofold: 1) allow adding globals so that even if I nuke the heap clear, the globals will still preserve the state, and 2) to enable creating "zero extra disk space overhead" TLS items without needing to implement TLS array slots etc. For solving 1) .S files would be enough, but for 2), .S files would be clumsy. It'd be amazing if we were to add support for this! :) |
Yes, this is on the roadmap for Igalia's reference types work in LLVM. Specifically, it should be implemented by their fifth milestone. I don't see a shorter route to implementing this, but they are making good progress so it shouldn't be too long. |
Just to be clear, after that work, if one is just creating globals but not using reference types for anything, one would not need to require to run in a Wasm VM that supports wasm reference types? |
Yes, that's correct :) This work forms the foundation for being able to declare WebAssembly tables, memories, and globals from C/C++ and it just so happens that their particular motivating use case needs tables (and reference types) specifically. |
I wonder if there might have been any updates/progress on LLVM side on this? It has been about 10 months since the last check-in. |
Some context: our goal is reference types in C/C++. Storage locations for reference types (C globals and locals) can't be in linear memory, so we enhanced the WebAssembly backend for LLVM IR to allow a designated non-default address space (AS 1) to indicate allocations in a WebAssembly-managed storage (globals and locals, in practice). This is how you can tell LLVM that a given allocation must be in a global or a local in LLVM -- they are allocations (global variables or allocas) in AS 1. (Locals can also be allocated as part of the backend lowering process, for some SSA variables, but that's after LLVM IR.) On the front-end, the initial idea was to have an address space qualifier to indicate a definition that should be allocated to a global -- similar in style to OpenCL's __thread, __local etc qualifiers. You need some front-end support for these values, because they carry restrictions: e.g. if you declare a global variable as being a wasm_global, you can't take its address. The front-end needs to ensure that it produces IR that we can handle, and that the user gets a sensible error otherwise. However, upstream clang saw such a generic feature as being too invasive -- see e.g. https://reviews.llvm.org/D108464#2959591. And they're right in a way -- there is only a weak argument for being able to declare globals as being wasm globals, and no argument at all for function locals. Rather, what you want is an attribute on a type, indicating that values of this type should be allocated to globals; and not all types would have this attribute. That way we hit the reference types use case -- the only real use case -- and we punt on the generic feature. So, I am refactoring my patch set. Last couple weeks have had a lot of admin on my plate but I hope to have externref/funcref wasm globals in C within 3-4 weeks. Questions very welcome, @juj and others :) |
i should mention that if there's a strong argument for e.g. |
Besides @juj's reasons above, being able to declare globals would be useful because they can be exported or imported as part of a Module's interface. For modules that are meant to be easily used without large amounts of JS glue, being able to use globals is a much better UX and more direct than having to write values into memory. |
Wouldn't the UX concerns be satisfyingly fulfilled by exposing getter and (possibly) setter functions? |
Thanks @wingo, the main carrot for us would be to be able to implement much more efficiently and conveniently TLS variables in multithreaded builds. Currently an access to a C _Thread_local int i; will currently generate an inconvenient access (i32.store16 offset=30 align=1
(local.get $0)
(i32.const 105)
)
(i32.store offset=16
(local.get $0)
(i32.load
(local.tee $1
(global.get $__tls_base)
)
)
) which could be simplified to a single Currently managing the JS object references in dictionaries outside the Wasm module has not caused much problems, though it would be interesting to be able to use externrefs in the future, if paired with the ability to make direct calls to web apis from wasm. I suppose in general case with wasm reference types, all the wasm reference type globals would be JS GC roots? I wonder how the GC would work with the heap embedding example:
How would JS track liveness of the object held by |
@juj the issue is the semantic restrictions, afaics -- what would happen if user code took the address of For the struct-containing-an-externref example, here it is clear that |
No, that does not need to be allowed. Note that our use case is not about implementing all TLS variables this way, and not even the
In general I don't think this kind of machinery is needed (for our intended use case), we would be able to annotate our interesting TLS variables manually/explicitly, and only those would ever need to become TLS globals. |
For that level of fine-grained control, perhaps it would be appropriate to use assembly files, as @sbc100 suggested in an earlier comment. I don't think we would be able to convince clang to accept a patch for a language extension motivated by a small codegen improvement like that. That being said, it would be great to see an optimization pass to turn non-address-taken thread-local variables into globals like @wingo mentioned, either at the IR level or in the WebAssembly backend. With such an optimization pass, you wouldn't need to do anything to get the codegen you want. |
I would like to define WebAssembly
global
s in C code, something likethat would then emit a
into the build. Setting and reading the variable would then emit
global.get
andglobal.set
, and taking an address&myGlobal
would then be forbidden at compile time. Is there a way to do that today, or would it be possible to add?The text was updated successfully, but these errors were encountered: