Hi! did https://github.com/rustwasm/team/issues/24 get anywhere? the issue was closed, but i haven't been able to find if/where the follow-up discussion happened
It did not, but I think asm!
nowadays on nightly rust may have some support
I suspect it's quite limited though
hah indeed, there are tests in rustc that shows the proper syntax (the trick is to use "local" instead of "reg", and local.set/get to write/read them)
#[no_mangle]
pub fn inline() -> u32 {
let x = 13;
let y = 37;
let mut z = 0;
unsafe {
asm!(
"local.get {x}",
"local.get {y}",
"i32.add",
"local.set {z}",
x = in(local) x,
y = in(local) y,
z = out(local) z,
);
}
z
}
I have no idea how any of that works in llvm
I used .S web assembly in the past, works well
is the inline assembly sent as strings straight to llvm? the syntax errors in inline asm suggest so, but i'm unsure
is inline assembly a requirement?
afaik yes, it goes straight to LLVM's assembler
which afaik has not a ton of documentation
i was playing with reading from a second memory, which i do now by having a custom preprocessing pass using an updated walrus, and it works fine
(rustc's execution model in wasm makes it so that we still need to copy everything we read out from this second memory to the main memory, so it's not as interesting as i expected)
but i was wondering if this could be done without preprocessing, and i just realized today that there was inline assembly support for wasm
@Alex Crichton @fitzgen (he/him) are you interested in PRs for walrus to rely on a more recent wasmparser?
sure!
Would this give us a way to introduce collections, or at least Vec
-like buffers, whose backing store is in a different Memory, by implementing all operations that get/set contained values with inline wasm referring to the other Memory?
Yep, I do have a proof of concept implementing an io::Read
impl that can read from the second memory. That's using the walrus preprocessing, inline asm would be more straightforward tho, but they'd result in equivalent wasm code being created.
very cool!
(rustc's execution model in wasm makes it so that we still need to copy everything we read out from this second memory to the main memory, so it's not as interesting as i expected)
Can you say more about this? I'd expect to be able to load values and store them in a local in the current stack frame, but it seems like that's not the case?
Sure! My point was rather about non-primitive data structures, which need to be reconstructed in the first memory to be useful. E.g. one can't just read a Vec which elements are only backed by the second memory; the main Rust program only knows about its own memory, and will assume that pointers into the heap are referring to the first memory. That stands for "native" stdlib Vec at least. For a custom, user-land defined Vec, we could teach it to allocate in the second memory instead, and read from/write into it. The header may still live on the primary memory (stack or heap), though. Does that make sense? (and please correct me if this is wrong; I'd expect this to work like that)
it does make sense, yes. And yes, that's what I had envisioned.
We actually had extensive discussions about this all the way back at TPAC in Lyon, and concluded that it'd be hard to support this for Vec
. (This was in the context of GC, but I think largely applies to multi-memory, too.)
I could imagine there still being a lot of value in supporting good abstractions for this in custom data structures, perhaps implementing traits that also have implementations for std equivalents
I guess a more general question is, what can be directly accessed from Rust code? and where could i find this information? I know I can declare extern "C"
functions and they become imports, but what else can we explicitly do? Can we directly manipulate wasm globals from Rust code? or function tables? (and so on for every wasm concept)
afaik there's not really much documentation on this, but we're generally constrained by LLVM right now -- and this basically means that you can't manipulate or even declare arbitrary tables/globals/memories
ah, that makes sense, thanks! So it makes these wasm preprocessing transforms (as done above with walrus for using a second memory) more interesting...
It seems that I can put a static mut X: u32 = 0
declaration within an extern "C"
block, but that doesn't export a wasm global, though
Interesting: it does actually export a wasm global that contains an offset into the linear memory where the Rust static is stored
Last updated: Dec 23 2024 at 13:07 UTC