Exposing globals to host application in WASM?

I'm converting a native driver into web assembly just to see if I can do it (because if so it would make things a lot easier for me). The driver requires a base address for the device, and then I can calculate register offsets. What is the safest way of exposing a global variable to the host that can then be updated to recompute register offsets?

A #[no_mangle] static will be exported from the WASM module:

#[no_mangle]
pub static mut BASE_ADDR: usize = 0;
(module
  (table (;0;) 1 1 funcref)
  (memory (;0;) 17)
  (global (;0;) (mut i32) (i32.const 1048576))
  (global (;1;) i32 (i32.const 1048576))
  (global (;2;) i32 (i32.const 1048580))
  (global (;3;) i32 (i32.const 1048580))
  (export "memory" (memory 0))
  (export "BASE_ADDR" (global 1))
  (export "__data_end" (global 2))
  (export "__heap_base" (global 3)))

Okay, but what if I want to do that safely without static mut? Can I just do a regular pub static or would Rust not export it then? Basically, I'm trying to do this:

#[no_mangle]
pub static mut BASE_ADDR: u64 = 0x00;
static REG1: u64 = BASE_ADDR + 0x04;

Such that when BASE_ADDR is updated, REG1 is recomputed as well.

An immutable static can't depend on the value of a mutable static.

Thanks. One last question about WASM: is there a way I can force-generate a trap without doing an illegal op? For instance, if I use WASM in an environment where I need to monitor for interrupts, is there a way I can "pause" the execution of a WASM module? Or do no WASM interpreter libraries allow that kind of thing?

You can use core::arch::wasm32::unreachable - Rust to generate a trap instruction. You could also potentially export a function that could be used for that from the host into the module.

It depends on your runtime. I use wasmer and they've got a wasmer::raise_user_trap() function which, when called from a host function, will raise a trap and abort the WebAssembly call.

You can later call RuntimeError::downcast() to extract the underlying error, giving you a way to differentiate between different the traps you may raise. I don't think you can use it as a mechanism for pausing execution though, the stack frames are probably thrown away and not resumable.