rvtime
A RISC-V compiler with a wasmtime-like interface.
Load a statically linked RV64IMAC ELF, compile it to native code with Cranelift, call its exported functions from Rust, and let it call back into the host.
let engine = new?;
let module = from_file?;
let mut store = new;
let mut linker = new;
// The guest reaches this with `ecall` and `a7 == 1`.
linker.func_wrap?;
let instance = linker.instantiate?;
let add = instance.?;
assert_eq!;
Documentation
- Guide and design notes — how it works and why, with worked examples.
- API reference — generated from the source.
The design chapters cover the parts most likely to surprise: why a direct call on RISC-V is encoded as an indirect jump, why registers cross calls by ABI, and why guest memory is confined rather than bounds-checked.
Status
Working end to end: ELF loading, RV64IMAC decoding, control-flow analysis, Cranelift codegen, guest memory with a committed heap and guard pages, host calls, traps, interruption, a compiled-code cache, and a guest-side SDK.
CI runs the suite on Linux/x86_64 and macOS/arm64, in debug and release. Windows is not supported — memory and traps are POSIX.
Guests must be linked with --emit-relocs; that is the first thing to check
when one fails to load. See
Getting Started, and
Limitations for what is not
done yet.
Building
Rust 2024 edition. No RISC-V toolchain needed — the fixtures are committed as prebuilt ELFs alongside their disassembly, which is also why CI can run the whole suite without one. To regenerate them:
Contributing
Every test lives in tests/; there are no in-file test modules. The decoder is
checked differentially against llvm-objdump over whole .text sections, and
the fixtures together cover 122 distinct mnemonics.
Examples under crates/rvtime/examples/ are documentation: the book includes
them by reference and CI runs them, so they cannot drift from the API.
License
Licensed under the Apache License, Version 2.0.