Comments (11)
So I tweaked the macro so I can specify the repr per S* type and gave the S1 a repr(transparent) and now everything works. Would that be a sufficient solution that I could PR (or maybe you guys do the change real quick) or is there a better solution?
from wasmer.
The RefCell is not necessary, this results in a much smaller file:
fn main() {
let binary = [
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60, 0x00, 0x00, 0x60,
0x00, 0x01, 0x7C, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01,
0x05, 0x03, 0x01, 0x00, 0x11, 0x06, 0x19, 0x03, 0x7F, 0x01, 0x41, 0x80, 0x80, 0xC0, 0x00,
0x0B, 0x7F, 0x00, 0x41, 0x90, 0x80, 0xC0, 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x90, 0x80, 0xC0,
0x00, 0x0B, 0x07, 0x4D, 0x05, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x19,
0x5F, 0x5F, 0x69, 0x6E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5F, 0x66, 0x75, 0x6E, 0x63,
0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x01, 0x00, 0x0B, 0x5F, 0x5F,
0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x01, 0x0A, 0x5F, 0x5F, 0x64,
0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x02, 0x09, 0x67, 0x61, 0x6D, 0x65, 0x5F,
0x74, 0x69, 0x6D, 0x65, 0x00, 0x01, 0x0A, 0x42, 0x02, 0x02, 0x00, 0x0B, 0x3D, 0x00, 0x02,
0x40, 0x41, 0x00, 0x29, 0x03, 0x80, 0x80, 0x40, 0x42, 0x01, 0x52, 0x0D, 0x00, 0x41, 0x00,
0x2B, 0x03, 0x88, 0x80, 0x40, 0x0F, 0x0B, 0x41, 0x00, 0x42, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0xD0, 0xB7, 0xC0, 0x00, 0x37, 0x03, 0x88, 0x80, 0x40, 0x41, 0x00, 0x42, 0x01, 0x37,
0x03, 0x80, 0x80, 0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6F, 0x40, 0x0B, 0x0B,
0x19, 0x01, 0x00, 0x41, 0x80, 0x80, 0xC0, 0x00, 0x0B, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x04, 0x6E,
0x61, 0x6D, 0x65, 0x01, 0x1F, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F,
0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x01, 0x09, 0x67, 0x61, 0x6D,
0x65, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x02, 0x05, 0x02, 0x00, 0x00, 0x01, 0x00,
];
let import_object = wasmer_runtime::imports! {};
let instance = wasmer_runtime::instantiate(&binary, &import_object).unwrap();
if let Ok(func) = instance.func::<(), f64>("game_time") {
let ret_val = func.call().unwrap();
println!("{} {:#016x}", ret_val, ret_val.to_bits());
}
}
WAST:
(module
(type $t0 (func))
(type $t1 (func (result f64)))
(func $__wasm_call_ctors (type $t0))
(func $game_time (type $t1) (result f64)
block $B0
i32.const 0
i64.load offset=1048576
i64.const 1
i64.ne
br_if $B0
i32.const 0
f64.load offset=1048584
return
end
i32.const 0
i64.const 4643000109586448384
i64.store offset=1048584
i32.const 0
i64.const 1
i64.store offset=1048576
f64.const 0x1.f4p+7 (;=250;))
(table $__indirect_function_table 1 1 anyfunc)
(memory $memory 17)
(global $g0 (mut i32) (i32.const 1048576))
(global $__heap_base i32 (i32.const 1048592))
(global $__data_end i32 (i32.const 1048592))
(export "memory" (memory 0))
(export "__indirect_function_table" (table 0))
(export "__heap_base" (global 1))
(export "__data_end" (global 2))
(export "game_time" (func $game_time))
(data (i32.const 1048576) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"))
Source:
use std::cell::RefCell;
struct Context {
val: f64,
}
fn build_context() -> Context {
Context {
val: 250.0,
}
}
thread_local! {
static CONTEXT: Context = build_context();
}
#[no_mangle]
pub extern "C" fn game_time() -> f64 {
CONTEXT.with(|ctx| {
ctx.val
})
}
from wasmer.
It seems like global variables don't work at all actually (if they are sufficiently uninlinable) as shown here:
(module
(type $t0 (func))
(type $t1 (func (result f64)))
(func $__wasm_call_ctors (type $t0))
(func $mutate (type $t0)
i32.const 0
i64.const 4636737291354636288
i64.store offset=1048576)
(func $game_time (type $t1) (result f64)
i32.const 0
f64.load offset=1048576)
(table $__indirect_function_table 1 1 anyfunc)
(memory $memory 17)
(global $g0 (mut i32) (i32.const 1048576))
(global $__heap_base i32 (i32.const 1048584))
(global $__data_end i32 (i32.const 1048584))
(export "memory" (memory 0))
(export "__indirect_function_table" (table 0))
(export "__heap_base" (global 1))
(export "__data_end" (global 2))
(export "mutate" (func $mutate))
(export "game_time" (func $game_time))
(data (i32.const 1048576) "\00\00\00\00\00@o@"))
Neither calling mutate nor skipping it produce the correct value, suggesting that it is indeed an ABI problem, because even if it would store / load from an incorrect address, at least mutate
would write to the same location as the game_time
function is loading from, and yet it still doesn't return the correct value.
from wasmer.
Thanks for the super detailed examples, we'll take a look on it soon!
from wasmer.
Ah, I figured out the problem. It's the assumption that c structs with a single element have the same ABI as the single element itself, but that isn't always the case. So the S1<f64> WasmExternType impl destructures the S1 by derefencing from a pointer, storing the value in XMM0. However the JIT'ed code already has the f64 residing in the XMM0 register, which now gets overwritten by garbage:
from wasmer.
@CryZe Looks like you're using visual studio to debug Rust! I personally have not got this to work correctly. This is unrelated to the issue, but could you point me to resources on how you got visual studio configured for rust? How you're attaching the debugger?
In addition to learning how to do that, I want to reproduce and visual the problem the same way you have.
from wasmer.
I did not really set up much. It works straight out of the box. You just need to make sure you use the msvc target and then you open the actual .exe file as a project (not as a file) in Visual Studio. After the "project" is opened you want to open the main.rs and put a breakpoint in there. Then you can start the project and it should hit the breakpoint. From there I added the disassembly and register view (which you can find under debugging -> views (or something, mine is german)). And then I right clicked the register view to show the SSE registers.
from wasmer.
Wow that is totally unintuitive, but that works. Do you manually open the source files with the "Open" button, or have you found a way to load the source into the solution explorer? As it is now, I only have the wasmer.exe shown in solution explorer.
from wasmer.
I actually usually use the Visual Studio Debugger in VS Code where I also have direct access to all my source files and stuff. However for this, VS Code's debugger is missing the disassembly and register view, which was necessary here. So I switched to Visual Studio instead. So since this is such a temporary occurance I just manually stepped through the calls which auto opened the files, and didn't bother with properly setting up any solution or anything. But I guess you could theoretically add the folders to the solution and then save it as a proper solution? I really don't know though.
from wasmer.
I also was able to replicate this on Godbolt right now, where #[repr(C)] struct F(f64) and f64 behave differently when targeting windows (not linux though): https://rust.godbolt.org/z/pNibCT
from wasmer.
That seems like a good solution to me! Make a pr!
from wasmer.
Related Issues (20)
- Replace BinaryPackage::uses with PackageId
- Fix wasmer_api::query::fetch_webc_package
- `backend_api`: fix fetch_webc_package HOT 1
- Improve deploy flow by automatically authing the user if in interactive mode
- Remove webc v1 support
- webc v3: Use the webc-volume timestamps in the webc virtual-fs filesystem implementation
- wasmer app create: Fails with custom path
- wasmer app create: --no-wait is not respected HOT 1
- wasmer run python/python -- --version should be instant
- Fix timestamps in Pirita and Wasmer
- We should not compute the hash of wasm modules inside of WebC
- Add Integration tests for all parts of the wasmer deploy + publish flow
- Improve codebase - deploy flow (unnamed packages)
- Fix ``wasmer publish`` not bumping versions for named packages
- Prompt user login for anonymous user when using `wasmer deploy`, `wasmer publish`
- new `wasmer publish` flow
- Add support for tagging a package release with a named package version
- Add support for pushing package releases and tagging them HOT 1
- Support partial `[package]` section in `wasmer.toml` HOT 1
- Mistakenly computing hash of a pre-compiled artifact
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wasmer.