From 20614c8b82f6c39071df6f6c4597a50447a0651c Mon Sep 17 00:00:00 2001 From: Arayi Date: Fri, 31 Oct 2025 13:22:47 -0400 Subject: [PATCH 1/7] add riscv32im-unknown-openvm-elf tier 3 target --- compiler/rustc_target/src/spec/mod.rs | 1 + .../targets/riscv32im_unknown_openvm_elf.rs | 44 +++++++++ library/panic_abort/Cargo.toml | 2 +- library/panic_abort/src/lib.rs | 8 +- library/panic_abort/src/openvm.rs | 25 +++++ library/std/build.rs | 1 + library/std/src/random.rs | 1 + library/std/src/sys/alloc/mod.rs | 10 +- library/std/src/sys/alloc/openvm.rs | 15 +++ library/std/src/sys/args/mod.rs | 4 + library/std/src/sys/args/openvm.rs | 94 +++++++++++++++++++ library/std/src/sys/env/mod.rs | 4 + library/std/src/sys/env/openvm.rs | 32 +++++++ library/std/src/sys/env_consts.rs | 11 +++ library/std/src/sys/pal/mod.rs | 4 + library/std/src/sys/pal/openvm/abi.rs | 38 ++++++++ library/std/src/sys/pal/openvm/mod.rs | 49 ++++++++++ library/std/src/sys/random/mod.rs | 4 + library/std/src/sys/random/openvm.rs | 21 +++++ library/std/src/sys/stdio/mod.rs | 4 + library/std/src/sys/stdio/openvm.rs | 72 ++++++++++++++ library/std/src/sys/thread_local/mod.rs | 2 + library/test/src/console.rs | 6 +- library/test/src/lib.rs | 2 +- src/bootstrap/src/lib.rs | 4 +- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../riscv32im-unknown-openvm-elf.md | 75 +++++++++++++++ src/tools/miri/src/shims/alloc.rs | 2 +- tests/assembly-llvm/targets/targets-elf.rs | 3 + 30 files changed, 530 insertions(+), 10 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs create mode 100644 library/panic_abort/src/openvm.rs create mode 100644 library/std/src/sys/alloc/openvm.rs create mode 100644 library/std/src/sys/args/openvm.rs create mode 100644 library/std/src/sys/env/openvm.rs create mode 100644 library/std/src/sys/pal/openvm/abi.rs create mode 100644 library/std/src/sys/pal/openvm/mod.rs create mode 100644 library/std/src/sys/random/openvm.rs create mode 100644 library/std/src/sys/stdio/openvm.rs create mode 100644 src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c76e345bb7b64..bf1badf0ec5f6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1671,6 +1671,7 @@ supported_targets! { ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), + ("riscv32im-unknown-openvm-elf", riscv32im_unknown_openvm_elf), ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), ("riscv32imc-esp-espidf", riscv32imc_esp_espidf), diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs new file mode 100644 index 0000000000000..7409715398478 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs @@ -0,0 +1,44 @@ +use crate::spec::{ + Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), + llvm_target: "riscv32".into(), + metadata: TargetMetadata { + description: Some("OpenVM zero-knowledge Virtual Machine (RV32IM ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + os: "openvm".into(), + vendor: "unknown".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + + // Some crates (*cough* crossbeam) assume you have 64 bit + // atomics if the target name is not in a hardcoded list. + // Since OpenVM is singlethreaded and all operations are + // atomic, I guess we can just say we support 64-bit + // atomics. + max_atomic_width: Some(64), + atomic_cas: true, + + features: "+m".into(), + llvm_abiname: "ilp32".into(), + executables: true, + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + singlethread: true, + ..Default::default() + }, + } +} diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index ecf043ac7071c..781b791ba16dd 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -17,5 +17,5 @@ core = { path = "../rustc-std-workspace-core", package = "rustc-std-workspace-co [target.'cfg(target_os = "android")'.dependencies] libc = { version = "0.2", default-features = false } -[target.'cfg(any(target_os = "android", target_os = "zkvm"))'.dependencies] +[target.'cfg(any(target_os = "android", target_os = "zkvm", target_os = "openvm"))'.dependencies] alloc = { path = "../alloc" } diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index d1706b6525295..ecf89e82846bb 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -19,6 +19,9 @@ mod android; #[cfg(target_os = "zkvm")] mod zkvm; +#[cfg(target_os = "openvm")] +mod openvm; + use core::any::Any; use core::panic::PanicPayload; @@ -40,7 +43,10 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { unsafe { zkvm::zkvm_set_abort_message(_payload); } - + #[cfg(target_os = "openvm")] + unsafe { + openvm::openvm_set_abort_message(_payload); + } unsafe extern "Rust" { // This is defined in std::rt. #[rustc_std_internal_symbol] diff --git a/library/panic_abort/src/openvm.rs b/library/panic_abort/src/openvm.rs new file mode 100644 index 0000000000000..01d93ef59d9b2 --- /dev/null +++ b/library/panic_abort/src/openvm.rs @@ -0,0 +1,25 @@ +use alloc::string::String; +use core::panic::PanicPayload; + +// Forward the abort message to OpenVM's sys_panic. +pub(crate) unsafe fn openvm_set_abort_message(payload: &mut dyn PanicPayload) { + let payload = payload.get(); + let msg = match payload.downcast_ref::<&'static str>() { + Some(msg) => msg.as_bytes(), + None => match payload.downcast_ref::() { + Some(msg) => msg.as_bytes(), + None => &[], + }, + }; + if msg.is_empty() { + return; + } + + unsafe extern "C" { + fn sys_panic(msg_ptr: *const u8, len: usize) -> !; + } + + unsafe { + sys_panic(msg.as_ptr(), msg.len()); + } +} diff --git a/library/std/build.rs b/library/std/build.rs index bee28e88491d0..42f60d0119f74 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -54,6 +54,7 @@ fn main() { || target_os == "nuttx" || target_os == "cygwin" || target_os == "vexos" + || target_os == "openvm" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/random.rs b/library/std/src/random.rs index 3994c5cfaf6f4..c14d8cb353c65 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -45,6 +45,7 @@ use crate::sys::random as sys; /// VxWorks | `randABytes` after waiting for `randSecure` to become ready /// WASI | [`random_get`](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-random_getbuf-pointeru8-buf_len-size---result-errno) /// ZKVM | `sys_rand` +/// OpenVM | `sys_rand` /// /// Note that the sources used might change over time. /// diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs index f2f1d1c7feceb..828545e73b601 100644 --- a/library/std/src/sys/alloc/mod.rs +++ b/library/std/src/sys/alloc/mod.rs @@ -7,10 +7,13 @@ use crate::ptr; // add fast paths for low alignment values. #[allow(dead_code)] const MIN_ALIGN: usize = if cfg!(any( - all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")), + all( + target_arch = "riscv32", + any(target_os = "espidf", target_os = "zkvm", target_os = "openvm") + ), all(target_arch = "xtensa", target_os = "espidf"), )) { - // The allocator on the esp-idf and zkvm platforms guarantees 4 byte alignment. + // The allocator on the esp-idf, zkvm, and openvm platforms guarantees 4 byte alignment. 4 } else if cfg!(any( target_arch = "x86", @@ -107,4 +110,7 @@ cfg_select! { target_os = "zkvm" => { mod zkvm; } + target_os = "openvm" => { + mod openvm; + } } diff --git a/library/std/src/sys/alloc/openvm.rs b/library/std/src/sys/alloc/openvm.rs new file mode 100644 index 0000000000000..a600cfa2220dd --- /dev/null +++ b/library/std/src/sys/alloc/openvm.rs @@ -0,0 +1,15 @@ +use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::sys::pal::abi; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + unsafe { abi::sys_alloc_aligned(layout.size(), layout.align()) } + } + + #[inline] + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + // this allocator never deallocates memory + } +} diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs index 5424d40a15883..3c4c43a490b43 100644 --- a/library/std/src/sys/args/mod.rs +++ b/library/std/src/sys/args/mod.rs @@ -53,6 +53,10 @@ cfg_select! { mod zkvm; pub use zkvm::*; } + target_os = "openvm" => { + mod openvm; + pub use openvm::*; + } _ => { mod unsupported; pub use unsupported::*; diff --git a/library/std/src/sys/args/openvm.rs b/library/std/src/sys/args/openvm.rs new file mode 100644 index 0000000000000..d26bf1eaff91f --- /dev/null +++ b/library/std/src/sys/args/openvm.rs @@ -0,0 +1,94 @@ +use crate::ffi::{OsStr, OsString}; +use crate::num::NonZero; +use crate::sync::OnceLock; +use crate::sys::pal::{WORD_SIZE, abi}; +use crate::{fmt, ptr, slice}; + +pub fn args() -> Args { + Args { iter: ARGS.get_or_init(|| get_args()).iter() } +} + +fn get_args() -> Vec<&'static OsStr> { + let argc = unsafe { abi::sys_argc() }; + let mut args = Vec::with_capacity(argc); + + for i in 0..argc { + // Get the size of the argument then the data. + let arg_len = unsafe { abi::sys_argv(ptr::null_mut(), 0, i) }; + + let arg_len_words = (arg_len + WORD_SIZE - 1) / WORD_SIZE; + let words = unsafe { abi::sys_alloc_words(arg_len_words) }; + + let arg_len2 = unsafe { abi::sys_argv(words, arg_len_words, i) }; + debug_assert_eq!(arg_len, arg_len2); + + let arg_bytes = unsafe { slice::from_raw_parts(words.cast(), arg_len) }; + args.push(unsafe { OsStr::from_encoded_bytes_unchecked(arg_bytes) }); + } + args +} + +static ARGS: OnceLock> = OnceLock::new(); + +pub struct Args { + iter: slice::Iter<'static, &'static OsStr>, +} + +impl !Send for Args {} +impl !Sync for Args {} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) + } +} + +impl Iterator for Args { + type Item = OsString; + + fn next(&mut self) -> Option { + self.iter.next().map(|arg| arg.to_os_string()) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.iter.len() + } + + fn last(self) -> Option { + self.iter.last().map(|arg| arg.to_os_string()) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.iter.advance_by(n) + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|arg| arg.to_os_string()) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.iter.advance_back_by(n) + } +} + +impl ExactSizeIterator for Args { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } + + #[inline] + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} diff --git a/library/std/src/sys/env/mod.rs b/library/std/src/sys/env/mod.rs index 89856516b6dce..039dfe7afa92e 100644 --- a/library/std/src/sys/env/mod.rs +++ b/library/std/src/sys/env/mod.rs @@ -55,6 +55,10 @@ cfg_select! { mod zkvm; pub use zkvm::*; } + target_os = "openvm" => { + mod openvm; + pub use openvm::*; + } _ => { mod unsupported; pub use unsupported::*; diff --git a/library/std/src/sys/env/openvm.rs b/library/std/src/sys/env/openvm.rs new file mode 100644 index 0000000000000..2eb7005ba1289 --- /dev/null +++ b/library/std/src/sys/env/openvm.rs @@ -0,0 +1,32 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_env; +pub use unsupported_env::{Env, env, setenv, unsetenv}; + +use crate::ffi::{OsStr, OsString}; +use crate::sys::os_str; +use crate::sys::pal::{WORD_SIZE, abi}; +use crate::sys_common::FromInner; + +pub fn getenv(varname: &OsStr) -> Option { + let varname = varname.as_encoded_bytes(); + let nbytes = + unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) }; + if nbytes == usize::MAX { + return None; + } + + let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE; + let words = unsafe { abi::sys_alloc_words(nwords) }; + + let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) }; + debug_assert_eq!(nbytes, nbytes2); + + // Convert to OsString. + // + // FIXME: We can probably get rid of the extra copy here if we + // reimplement "os_str" instead of just using the generic unix + // "os_str". + let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) }; + Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() })) +} diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs index 573f540483b1a..26de0527604c7 100644 --- a/library/std/src/sys/env_consts.rs +++ b/library/std/src/sys/env_consts.rs @@ -411,6 +411,17 @@ pub mod os { pub const EXE_EXTENSION: &str = "elf"; } +#[cfg(target_os = "openvm")] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = "openvm"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".elf"; + pub const DLL_EXTENSION: &str = "elf"; + pub const EXE_SUFFIX: &str = ".elf"; + pub const EXE_EXTENSION: &str = "elf"; +} + // The fallback when none of the other gates match. #[else] pub mod os { diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index e11df38a8ee68..5275ad10340c8 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -85,6 +85,10 @@ cfg_select! { mod zkvm; pub use self::zkvm::*; } + target_os = "openvm" => { + mod openvm; + pub use self::openvm::*; + } _ => { mod unsupported; pub use self::unsupported::*; diff --git a/library/std/src/sys/pal/openvm/abi.rs b/library/std/src/sys/pal/openvm/abi.rs new file mode 100644 index 0000000000000..f47eb27e3a4c6 --- /dev/null +++ b/library/std/src/sys/pal/openvm/abi.rs @@ -0,0 +1,38 @@ +//! ABI definitions for symbols exported by OpenVM. + +// Included here so we don't have to depend on OpenVM + +#![allow(dead_code)] +pub const DIGEST_WORDS: usize = 8; + +/// Standard IO file descriptors for use with sys_read and sys_write. +pub mod fileno { + pub const STDIN: u32 = 0; + pub const STDOUT: u32 = 1; + pub const STDERR: u32 = 2; + pub const JOURNAL: u32 = 3; +} + +unsafe extern "C" { + // Wrappers around syscalls provided by OpenVM: + pub fn sys_halt(); + pub fn sys_output(output_id: u32, output_value: u32); + pub fn sys_rand(recv_buf: *mut u32, words: usize); + pub fn sys_panic(msg_ptr: *const u8, len: usize) -> !; + pub fn sys_log(msg_ptr: *const u8, len: usize); + pub fn sys_cycle_count() -> usize; + pub fn sys_read(fd: u32, recv_buf: *mut u8, nrequested: usize) -> usize; + pub fn sys_write(fd: u32, write_buf: *const u8, nbytes: usize); + pub fn sys_getenv( + recv_buf: *mut u32, + words: usize, + varname: *const u8, + varname_len: usize, + ) -> usize; + pub fn sys_argc() -> usize; + pub fn sys_argv(out_words: *mut u32, out_nwords: usize, arg_index: usize) -> usize; + + // Allocate memory from global HEAP. + pub fn sys_alloc_words(nwords: usize) -> *mut u32; + pub fn sys_alloc_aligned(nwords: usize, align: usize) -> *mut u8; +} diff --git a/library/std/src/sys/pal/openvm/mod.rs b/library/std/src/sys/pal/openvm/mod.rs new file mode 100644 index 0000000000000..bc128d8564e09 --- /dev/null +++ b/library/std/src/sys/pal/openvm/mod.rs @@ -0,0 +1,49 @@ +//! System bindings for the OpenVM platform +//! +//! This module contains the facade (aka platform-specific) implementations of +//! OS level functionality for OpenVM. +//! +//! This is all super highly experimental and not actually intended for +//! wide/production use yet, it's still all in the experimental category. This +//! will likely change over time. +#![forbid(unsafe_op_in_unsafe_fn)] + +pub const WORD_SIZE: usize = size_of::(); + +pub mod abi; +#[path = "../unsupported/os.rs"] +pub mod os; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/time.rs"] +pub mod time; + +use crate::io as std_io; + +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {} + +// SAFETY: must be called only once during runtime cleanup. +// NOTE: this is not guaranteed to run, for example when the program aborts. +pub unsafe fn cleanup() {} + +pub fn unsupported() -> std_io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> std_io::Error { + std_io::Error::UNSUPPORTED_PLATFORM +} + +pub fn is_interrupted(_code: i32) -> bool { + false +} + +pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { + crate::io::ErrorKind::Uncategorized +} + +pub fn abort_internal() -> ! { + core::intrinsics::abort(); +} diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index 91f72d0738790..116d12a5276c4 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -102,6 +102,10 @@ cfg_select! { mod zkvm; pub use zkvm::fill_bytes; } + target_os = "openvm" => { + mod openvm; + pub use openvm::fill_bytes; + } any( all(target_family = "wasm", target_os = "unknown"), target_os = "xous", diff --git a/library/std/src/sys/random/openvm.rs b/library/std/src/sys/random/openvm.rs new file mode 100644 index 0000000000000..3011942f6b26b --- /dev/null +++ b/library/std/src/sys/random/openvm.rs @@ -0,0 +1,21 @@ +use crate::sys::pal::abi; + +pub fn fill_bytes(bytes: &mut [u8]) { + let (pre, words, post) = unsafe { bytes.align_to_mut::() }; + if !words.is_empty() { + unsafe { + abi::sys_rand(words.as_mut_ptr(), words.len()); + } + } + + let mut buf = [0u32; 2]; + let len = (pre.len() + post.len() + size_of::() - 1) / size_of::(); + if len != 0 { + unsafe { abi::sys_rand(buf.as_mut_ptr(), len) }; + } + + let buf = buf.map(u32::to_ne_bytes); + let buf = buf.as_flattened(); + pre.copy_from_slice(&buf[..pre.len()]); + post.copy_from_slice(&buf[pre.len()..pre.len() + post.len()]); +} diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs index d51ea9ad726b5..b3fbcc77b55e5 100644 --- a/library/std/src/sys/stdio/mod.rs +++ b/library/std/src/sys/stdio/mod.rs @@ -53,6 +53,10 @@ cfg_select! { mod zkvm; pub use zkvm::*; } + target_os = "openvm" => { + mod openvm; + pub use openvm::*; + } _ => { mod unsupported; pub use unsupported::*; diff --git a/library/std/src/sys/stdio/openvm.rs b/library/std/src/sys/stdio/openvm.rs new file mode 100644 index 0000000000000..f31c6c26e87cd --- /dev/null +++ b/library/std/src/sys/stdio/openvm.rs @@ -0,0 +1,72 @@ +use crate::io::{self, BorrowedCursor}; +use crate::sys::pal::abi::{self, fileno}; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +impl Stdin { + pub const fn new() -> Stdin { + Stdin + } +} + +impl io::Read for Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + Ok(unsafe { abi::sys_read(fileno::STDIN, buf.as_mut_ptr(), buf.len()) }) + } + + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + unsafe { + let n = abi::sys_read(fileno::STDIN, buf.as_mut().as_mut_ptr().cast(), buf.capacity()); + buf.advance_unchecked(n); + } + Ok(()) + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { abi::sys_write(fileno::STDOUT, buf.as_ptr(), buf.len()) } + + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub const fn new() -> Stderr { + Stderr + } +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { abi::sys_write(fileno::STDERR, buf.as_ptr(), buf.len()) } + + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub const STDIN_BUF_SIZE: usize = crate::sys::io::DEFAULT_BUF_SIZE; + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} + +pub fn panic_output() -> Option { + Some(Stderr::new()) +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index e88011aa22dad..ca30fc8bfe236 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -28,6 +28,7 @@ cfg_select! { all(target_family = "wasm", not(target_feature = "atomics")), target_os = "uefi", target_os = "zkvm", + target_os = "openvm", target_os = "trusty", target_os = "vexos", ) => { @@ -98,6 +99,7 @@ pub(crate) mod guard { )), target_os = "uefi", target_os = "zkvm", + target_os = "openvm", target_os = "trusty", target_os = "vexos", ) => { diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 13b2b3d502c81..6ab0c4c5e707f 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -320,8 +320,10 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu // Prevent the usage of `Instant` in some cases: // - It's currently not supported for wasm targets without Emscripten nor WASI. // - It's currently not supported for zkvm targets. - let is_instant_unsupported = - (cfg!(target_family = "wasm") && cfg!(target_os = "unknown")) || cfg!(target_os = "zkvm"); + // - It's currently not supported for openvm targets. + let is_instant_unsupported = (cfg!(target_family = "wasm") && cfg!(target_os = "unknown")) + || cfg!(target_os = "zkvm") + || cfg!(target_os = "openvm"); let start_time = (!is_instant_unsupported).then(Instant::now); run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index d554807bbde70..4915fc33dd32a 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -580,7 +580,7 @@ pub fn run_test( // Emscripten can catch panics but other wasm targets cannot let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No - && (cfg!(target_family = "wasm") || cfg!(target_os = "zkvm")) + && (cfg!(target_family = "wasm") || cfg!(target_os = "zkvm") || cfg!(target_os = "openvm")) && !cfg!(target_os = "emscripten"); if force_ignore || desc.ignore || ignore_because_no_process_support { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index a31eb0c1c8012..c459be9431a28 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -841,8 +841,8 @@ impl Build { features.insert("profiler"); } - // If zkvm target, generate memcpy, etc. - if target.contains("zkvm") { + // If zkvm or openvm target, generate memcpy, etc. + if target.contains("zkvm") || target.contains("openvm") { features.insert("compiler-builtins-mem"); } diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 832b5a69d47c4..65a2c77058404 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -111,6 +111,7 @@ - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md) - [riscv32i\*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md) + - [riscv32im-unknown-openvm-elf](platform-support/riscv32im-unknown-openvm-elf.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d772702df76e2..ce49249ee185f 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -380,6 +380,7 @@ target | std | host | notes `riscv32gc-unknown-linux-gnu` | ✓ | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | ? | | RISC-V Linux (kernel 5.4, musl 1.2.5) [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA) +[`riscv32im-unknown-openvm-elf`](platform-support/riscv32im-unknown-openvm-elf.md) | ? | | OpenVM zero-knowledge Virtual Machine (RV32IM ISA) [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA) [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md new file mode 100644 index 0000000000000..c58478e7d7b44 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md @@ -0,0 +1,75 @@ +# `riscv32im-unknown-openvm-elf` + +**Tier: 3** + +OpenVm's Zero Knowledge Virtual Machine (zkVM) implementing the RV32IM instruction set. + +## Target maintainers + +## Background + +This target is an execution environment to produce a proof of execution of +a RISC-V ELF binary and any output that the developer of the binary wishes to +display publicly. In order to do this, the target will execute the ELF to +generate a receipt containing the output of the computation along with a +cryptographic seal. This receipt can be verified to ensure the integrity of the +computation and its result. This target is implemented as software only; it has +no hardware implementation. + +We have a cargo extension called [cargo-openvm] that allow users to generate +project templates, install tools for improved user experience, build the binary +using a docker environment and test programs. + +## Requirements + +The target only supports cross compilation and no host tools. The target +supports `alloc` with a default allocator and has experimental support for +`std`. The target expects the binaries to be in ELF. + +The target's execution environment is single threaded, non-preemptive, and does +not support any privileged instructions, nor unaligned accesses. At the time of +writing the VM has 192 MB of memory and text/data, heap, and stack need to be +with in the address range `0x400` - `0x0C000000`. The binaries themselves expect +no operating system and can be thought of as running on bare-metal. The target +does not use `#[target_feature(...)]` or `-C target-feature=` values. + +Calling `extern "C"` on the target uses the C calling convention outlined in the +[RISC-V specification]. + +## Building for the zkVM + +Programs for the zkVM could be built by adding it to the `target` list in +`bootstrap.toml`. However, we recommend building programs in our starter template +generated by the [cargo-openvm] utility and the [openvm-build] crate. This +crate calls `rustc` with `-C "link-arg=-Ttext=` so that it maps the text in the +appropriate location as well as generating variables that represent the ELF and +a unique ID associated with the ELF. The starter template provides developers +with system calls that are useful to zero knowledge computing such as writing to +the public output, hashing using sha256, and multiply big integers. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above). We do not recommend using `build-std` as we have +run into issues building core in the past on our starter template. An alternate +solution is to download the risc0 tool chain by running `cargo risczero install`. + +## Testing + +Note: the target is implemented as a software emulator called the zkVM and there +is no hardware implementation of the target. + +The most practical way to test the target program is to use our starter template +that can be generated by using the `cargo risczero new` command. The template +generates a sample "host" and "guest" code. The guest code compiled to the +target (which is RV32IM) whereas the "host" code is compiled to run on the +programmer's machine running either a Linux distribution or macOS. The host +program is responsible for running the guest binary on the zkVM and retrieving +its public output. + +The target currently does not support running the Rust test suite. + +[RISC-V specification]: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf +[cargo-openvm]: https://docs.openvm.dev/book/getting-started/introduction +[openvm-build]: https://docs.openvm.dev/book/getting-started/introduction diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index 94649dde47361..60bc19d574db0 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -21,7 +21,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // be kept in sync. let os = &this.tcx.sess.target.os; let max_fundamental_align = match &this.tcx.sess.target.arch { - Arch::RiscV32 if matches!(os, Os::EspIdf | Os::Zkvm) => 4, + Arch::RiscV32 if matches!(os, Os::EspIdf | Os::Zkvm | Os::Openvm) => 4, Arch::Xtensa if matches!(os, Os::EspIdf) => 4, Arch::X86 | Arch::Arm diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 324c7fc9da4ee..7913ec97e202b 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -457,6 +457,9 @@ //@ revisions: riscv32im_unknown_none_elf //@ [riscv32im_unknown_none_elf] compile-flags: --target riscv32im-unknown-none-elf //@ [riscv32im_unknown_none_elf] needs-llvm-components: riscv +//@ revisions: riscv32im_unknown_openvm_elf +//@ [riscv32im_unknown_openvm_elf] compile-flags: --target riscv32im-unknown-openvm-elf +//@ [riscv32im_unknown_openvm_elf] needs-llvm-components: riscv //@ revisions: riscv32ima_unknown_none_elf //@ [riscv32ima_unknown_none_elf] compile-flags: --target riscv32ima-unknown-none-elf //@ [riscv32ima_unknown_none_elf] needs-llvm-components: riscv From 0bd4f94fd4913a2cc0d2c760e6e15915dad4a214 Mon Sep 17 00:00:00 2001 From: Arayi Date: Sun, 16 Nov 2025 19:46:27 -0500 Subject: [PATCH 2/7] update platform doc --- .../riscv32im-unknown-openvm-elf.md | 84 ++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md index c58478e7d7b44..33cfd77b75fb0 100644 --- a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md @@ -2,74 +2,64 @@ **Tier: 3** -OpenVm's Zero Knowledge Virtual Machine (zkVM) implementing the RV32IM instruction set. +OpenVM's zero-knowledge Virtual Machine (zkVM) implementing the RV32IM instruction set. ## Target maintainers -## Background +[@jonathanpwang](https://github.com/jonathanpwang) +[@yi-sun](https://github.com/yi-sun) -This target is an execution environment to produce a proof of execution of -a RISC-V ELF binary and any output that the developer of the binary wishes to -display publicly. In order to do this, the target will execute the ELF to -generate a receipt containing the output of the computation along with a -cryptographic seal. This receipt can be verified to ensure the integrity of the -computation and its result. This target is implemented as software only; it has -no hardware implementation. +## Background -We have a cargo extension called [cargo-openvm] that allow users to generate -project templates, install tools for improved user experience, build the binary -using a docker environment and test programs. +This target is an execution environment to produce a verifiable proof of execution of +an RV32IM RISC‑V ELF binary and any output that the developer wishes to make public. +The VM executes the ELF and emits artifacts that can be verified to ensure the integrity +of the computation and its results. This target is implemented in software only; there is +no hardware implementation. See the [OpenVM Book] for architecture and usage. ## Requirements -The target only supports cross compilation and no host tools. The target -supports `alloc` with a default allocator and has experimental support for -`std`. The target expects the binaries to be in ELF. - -The target's execution environment is single threaded, non-preemptive, and does -not support any privileged instructions, nor unaligned accesses. At the time of -writing the VM has 192 MB of memory and text/data, heap, and stack need to be -with in the address range `0x400` - `0x0C000000`. The binaries themselves expect -no operating system and can be thought of as running on bare-metal. The target -does not use `#[target_feature(...)]` or `-C target-feature=` values. +The target only supports cross-compilation (no host tools). It supports `alloc` with a +default allocator; availability of `std` depends on the OpenVM environment and is not +guaranteed. Binaries are expected to be ELF. -Calling `extern "C"` on the target uses the C calling convention outlined in the -[RISC-V specification]. +The execution environment is single-threaded, non-preemptive, and does not support +privileged instructions. The binaries expect no operating system and can be thought +of as running on bare-metal. The target does not use `#[target_feature(...)]` or +`-C target-feature=` values. Calling `extern "C"` uses the C calling convention outlined +in the [RISC-V specification]. ## Building for the zkVM -Programs for the zkVM could be built by adding it to the `target` list in -`bootstrap.toml`. However, we recommend building programs in our starter template -generated by the [cargo-openvm] utility and the [openvm-build] crate. This -crate calls `rustc` with `-C "link-arg=-Ttext=` so that it maps the text in the -appropriate location as well as generating variables that represent the ELF and -a unique ID associated with the ELF. The starter template provides developers -with system calls that are useful to zero knowledge computing such as writing to -the public output, hashing using sha256, and multiply big integers. +You can add this target to the `target` list in `bootstrap.toml` to build with the compiler. +However, most users should follow the tooling and starter templates in the [OpenVM Book], +which provide a streamlined developer experience for building, linking, and packaging +OpenVM guests. ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you will either need to build Rust with the target enabled (see -"Building the target" above). We do not recommend using `build-std` as we have -run into issues building core in the past on our starter template. An alternate -solution is to download the risc0 tool chain by running `cargo risczero install`. +this target, either build Rust with the target enabled (see "Building for the zkVM" above) +or use the toolchain and instructions provided in the [OpenVM Book]. ## Testing -Note: the target is implemented as a software emulator called the zkVM and there -is no hardware implementation of the target. +Note: this target is implemented as a software zkVM; there is no hardware implementation. -The most practical way to test the target program is to use our starter template -that can be generated by using the `cargo risczero new` command. The template -generates a sample "host" and "guest" code. The guest code compiled to the -target (which is RV32IM) whereas the "host" code is compiled to run on the -programmer's machine running either a Linux distribution or macOS. The host -program is responsible for running the guest binary on the zkVM and retrieving -its public output. +The most practical way to test programs is to use the OpenVM host runner and starter +templates described in the [OpenVM Book]. Typically, a "host" program runs on your +development machine (Linux or macOS) and invokes the OpenVM to execute the "guest" +binary compiled for this target, retrieving any public output. The target currently does not support running the Rust test suite. +## Cross-compilation toolchains and C code + +Compatible C code can be built for this target on any compiler that has a RV32IM +target. On clang and ld.lld linker, it can be generated using the +`-march=rv32im`, `-mabi=ilp32` with llvm features flag `features=+m` and llvm +target `riscv32-unknown-none`. + [RISC-V specification]: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf -[cargo-openvm]: https://docs.openvm.dev/book/getting-started/introduction -[openvm-build]: https://docs.openvm.dev/book/getting-started/introduction +[OpenVM]: https://openvm.dev/ +[OpenVM Book]: https://docs.openvm.dev/book/getting-started/introduction From 5b5e1092252ed90d7d822c110673e3af7f068c84 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:39:00 -0800 Subject: [PATCH 3/7] feat(docs): update target docs (#2) --- .../riscv32im-unknown-openvm-elf.md | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md index 33cfd77b75fb0..997a161b4dda8 100644 --- a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md @@ -2,7 +2,7 @@ **Tier: 3** -OpenVM's zero-knowledge Virtual Machine (zkVM) implementing the RV32IM instruction set. +Target for [OpenVM](https://github.com/openvm-org/openvm/) virtual machines with the RV32IM ISA and custom RISC-V extensions defined through OpenVM's extension framework. ## Target maintainers @@ -11,45 +11,50 @@ OpenVM's zero-knowledge Virtual Machine (zkVM) implementing the RV32IM instructi ## Background -This target is an execution environment to produce a verifiable proof of execution of -an RV32IM RISC‑V ELF binary and any output that the developer wishes to make public. -The VM executes the ELF and emits artifacts that can be verified to ensure the integrity -of the computation and its results. This target is implemented in software only; there is -no hardware implementation. See the [OpenVM Book] for architecture and usage. +This target is an execution environment to produce a verifiable cryptographic proof of execution of +a RISC‑V ELF binary and any output that the developer wishes to make public. +The execution environment is implemented as a virtual machine in software only. The target is not intended for bare metal hardware. The virtual machine may be extended to support custom RISC-V instruction sets, which may be invoked from Rust via the `asm!` macro. See the [OpenVM Book] for further documentation on the architecture and usage. + +We provide a cargo extension called [cargo-openvm] that provides tools for cross-compilation, execution, and generating cryptographic proofs of execution. ## Requirements -The target only supports cross-compilation (no host tools). It supports `alloc` with a -default allocator; availability of `std` depends on the OpenVM environment and is not -guaranteed. Binaries are expected to be ELF. +The target supports cross-compilation from any host and does not support host tools. It supports `alloc` with a +default allocator. Partial support for the Rust `std` library is provided using custom RISC-V instructions and requires the `openvm` crate with the `"std"` feature enabled. Further details and limitations of `std` support are documented [here](https://docs.openvm.dev/book/writing-apps/writing-a-program#rust-std-library-support). -The execution environment is single-threaded, non-preemptive, and does not support -privileged instructions. The binaries expect no operating system and can be thought +The target's execution environment is single-threaded, non-preemptive, and does not support +privileged instructions. At present, unaligned accesses are not supported and will result in execution traps. The binaries expect no operating system and can be thought of as running on bare-metal. The target does not use `#[target_feature(...)]` or -`-C target-feature=` values. Calling `extern "C"` uses the C calling convention outlined +`-C target-feature=` values. + +Binaries are expected to be ELF. + +Calling `extern "C"` uses the C calling convention outlined in the [RISC-V specification]. -## Building for the zkVM +## Building the target +The target can be built by enabling it for a `rustc` build. -You can add this target to the `target` list in `bootstrap.toml` to build with the compiler. -However, most users should follow the tooling and starter templates in the [OpenVM Book], -which provide a streamlined developer experience for building, linking, and packaging -OpenVM guests. +```toml +[build] +target = ["riscv32im-unknown-openvm-elf"] +``` ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, either build Rust with the target enabled (see "Building for the zkVM" above) -or use the toolchain and instructions provided in the [OpenVM Book]. +this target, you will need to do one of the following: +- Build Rust with the target enabled (see "Building the target" above) +- Build your own copy of `core` by passing args `-Zbuild-std=alloc,core,proc_macro,panic_abort,std -Zbuild-std-features=compiler-builtins-mem` +- Use `cargo openvm build` provided by the cargo extension [cargo-openvm]. + +The `cargo-openvm` utility is a command-line interface that calls `cargo` with the `build-std` flags above together with `rustc` flags `-C passes=lower-atomic -C link-arg=-Ttext=` to map text to the appropriate location. The text start (presently `0x0020_0800`) must be set to start above the stack top, and heap begins right after the text. The utility also includes the `rustc` flag `--cfg getrandom_backend="custom"` to enable a custom backend for the `getrandom` crate. ## Testing -Note: this target is implemented as a software zkVM; there is no hardware implementation. +Note: this target is implemented as a software virtual machine; there is no hardware implementation. -The most practical way to test programs is to use the OpenVM host runner and starter -templates described in the [OpenVM Book]. Typically, a "host" program runs on your -development machine (Linux or macOS) and invokes the OpenVM to execute the "guest" -binary compiled for this target, retrieving any public output. +Guest programs cross-compiled to the target must be run on the host inside OpenVM virtual machines, which are software emulators. The most practical way to do this is via either the [cargo-openvm] command-line interface or the [OpenVM SDK]. The target currently does not support running the Rust test suite. @@ -61,5 +66,7 @@ target. On clang and ld.lld linker, it can be generated using the target `riscv32-unknown-none`. [RISC-V specification]: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf -[OpenVM]: https://openvm.dev/ -[OpenVM Book]: https://docs.openvm.dev/book/getting-started/introduction +[OpenVM]: https://github.com/openvm-org/openvm/ +[OpenVM Book]: https://docs.openvm.dev/book/ +[OpenVM SDK]: https://docs.openvm.dev/book/advanced-usage/sdk +[cargo-openvm]: https://docs.openvm.dev/book/getting-started/install From 31e7b80e1e675c100688603ba8c1df1d28943efa Mon Sep 17 00:00:00 2001 From: Arayi Date: Mon, 8 Dec 2025 01:40:05 -0500 Subject: [PATCH 4/7] reviewer comments --- .../src/spec/targets/riscv32im_unknown_openvm_elf.rs | 8 +++----- library/std/src/sys/env/openvm.rs | 4 ---- library/std/src/sys/pal/openvm/abi.rs | 7 ++----- library/std/src/sys/random/openvm.rs | 2 +- .../src/platform-support/riscv32im-unknown-openvm-elf.md | 4 ++-- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs index 7409715398478..64ef4eefd6176 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs @@ -22,11 +22,9 @@ pub(crate) fn target() -> Target { linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), - // Some crates (*cough* crossbeam) assume you have 64 bit - // atomics if the target name is not in a hardcoded list. - // Since OpenVM is singlethreaded and all operations are - // atomic, I guess we can just say we support 64-bit - // atomics. + // We set atomic_width to 64 for compatibility with crates such as crossbeam, + // but this should never be triggered since compilation should always lower + // atomics and be single-threaded. max_atomic_width: Some(64), atomic_cas: true, diff --git a/library/std/src/sys/env/openvm.rs b/library/std/src/sys/env/openvm.rs index 2eb7005ba1289..93813c184a289 100644 --- a/library/std/src/sys/env/openvm.rs +++ b/library/std/src/sys/env/openvm.rs @@ -23,10 +23,6 @@ pub fn getenv(varname: &OsStr) -> Option { debug_assert_eq!(nbytes, nbytes2); // Convert to OsString. - // - // FIXME: We can probably get rid of the extra copy here if we - // reimplement "os_str" instead of just using the generic unix - // "os_str". let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) }; Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() })) } diff --git a/library/std/src/sys/pal/openvm/abi.rs b/library/std/src/sys/pal/openvm/abi.rs index f47eb27e3a4c6..491fdb3c17897 100644 --- a/library/std/src/sys/pal/openvm/abi.rs +++ b/library/std/src/sys/pal/openvm/abi.rs @@ -1,9 +1,8 @@ //! ABI definitions for symbols exported by OpenVM. -// Included here so we don't have to depend on OpenVM - +// We provide the ABI so that the OpenVM-specific implementations can be provided +// by linking the openvm crate without introducing the crate as a dependency here #![allow(dead_code)] -pub const DIGEST_WORDS: usize = 8; /// Standard IO file descriptors for use with sys_read and sys_write. pub mod fileno { @@ -16,11 +15,9 @@ pub mod fileno { unsafe extern "C" { // Wrappers around syscalls provided by OpenVM: pub fn sys_halt(); - pub fn sys_output(output_id: u32, output_value: u32); pub fn sys_rand(recv_buf: *mut u32, words: usize); pub fn sys_panic(msg_ptr: *const u8, len: usize) -> !; pub fn sys_log(msg_ptr: *const u8, len: usize); - pub fn sys_cycle_count() -> usize; pub fn sys_read(fd: u32, recv_buf: *mut u8, nrequested: usize) -> usize; pub fn sys_write(fd: u32, write_buf: *const u8, nbytes: usize); pub fn sys_getenv( diff --git a/library/std/src/sys/random/openvm.rs b/library/std/src/sys/random/openvm.rs index 3011942f6b26b..4e8bef8265707 100644 --- a/library/std/src/sys/random/openvm.rs +++ b/library/std/src/sys/random/openvm.rs @@ -9,7 +9,7 @@ pub fn fill_bytes(bytes: &mut [u8]) { } let mut buf = [0u32; 2]; - let len = (pre.len() + post.len() + size_of::() - 1) / size_of::(); + let len = (pre.len() + post.len()).div_ceil(size_of::()); if len != 0 { unsafe { abi::sys_rand(buf.as_mut_ptr(), len) }; } diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md index 997a161b4dda8..8b5c1cf80304a 100644 --- a/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-openvm-elf.md @@ -20,12 +20,12 @@ We provide a cargo extension called [cargo-openvm] that provides tools for cross ## Requirements The target supports cross-compilation from any host and does not support host tools. It supports `alloc` with a -default allocator. Partial support for the Rust `std` library is provided using custom RISC-V instructions and requires the `openvm` crate with the `"std"` feature enabled. Further details and limitations of `std` support are documented [here](https://docs.openvm.dev/book/writing-apps/writing-a-program#rust-std-library-support). +default allocator. Partial support for the Rust `std` library is provided using custom RISC-V instructions and requires the `openvm` crate with the `"std"` feature enabled. Further details and limitations of `std` support are documented [here](https://docs.openvm.dev/book/writing-apps/writing-a-program#rust-std-library-support). The target's execution environment is single-threaded, non-preemptive, and does not support privileged instructions. At present, unaligned accesses are not supported and will result in execution traps. The binaries expect no operating system and can be thought of as running on bare-metal. The target does not use `#[target_feature(...)]` or -`-C target-feature=` values. +`-C target-feature=` values. Binaries are expected to be ELF. From 512959b46a5974ba1d69414af6832a1abb3ad1fe Mon Sep 17 00:00:00 2001 From: Arayi Date: Mon, 8 Dec 2025 20:40:34 -0500 Subject: [PATCH 5/7] rebase fixes --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/targets/riscv32im_unknown_openvm_elf.rs | 7 ++++--- library/std/src/sys/stdio/openvm.rs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index bf1badf0ec5f6..6bb75fbdca98a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1996,6 +1996,7 @@ crate::target_spec_enum! { Windows = "windows", Xous = "xous", Zkvm = "zkvm", + Openvm = "openvm", Unknown = "unknown", } other_variant = Other; diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs index 64ef4eefd6176..b6296ae937c47 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_openvm_elf.rs @@ -1,5 +1,6 @@ use crate::spec::{ - Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, + Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata, + TargetOptions, }; pub(crate) fn target() -> Target { @@ -13,10 +14,10 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 32, - arch: "riscv32".into(), + arch: Arch::RiscV32, options: TargetOptions { - os: "openvm".into(), + os: Os::Openvm, vendor: "unknown".into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), diff --git a/library/std/src/sys/stdio/openvm.rs b/library/std/src/sys/stdio/openvm.rs index f31c6c26e87cd..84496ac937363 100644 --- a/library/std/src/sys/stdio/openvm.rs +++ b/library/std/src/sys/stdio/openvm.rs @@ -19,7 +19,7 @@ impl io::Read for Stdin { fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { unsafe { let n = abi::sys_read(fileno::STDIN, buf.as_mut().as_mut_ptr().cast(), buf.capacity()); - buf.advance_unchecked(n); + buf.advance(n); } Ok(()) } From d6a46ad70f6841ae8eada6f8392a9c84ba57b002 Mon Sep 17 00:00:00 2001 From: Arayi Date: Tue, 9 Dec 2025 01:57:17 -0500 Subject: [PATCH 6/7] Fix test stderr --- compiler/rustc_target/src/spec/mod.rs | 2 +- tests/ui/check-cfg/cfg-crate-features.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6bb75fbdca98a..a99227c55e3da 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1976,6 +1976,7 @@ crate::target_spec_enum! { Nto = "nto", NuttX = "nuttx", OpenBsd = "openbsd", + Openvm = "openvm", Psp = "psp", Psx = "psx", Qurt = "qurt", @@ -1996,7 +1997,6 @@ crate::target_spec_enum! { Windows = "windows", Xous = "xous", Zkvm = "zkvm", - Openvm = "openvm", Unknown = "unknown", } other_variant = Other; diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index 242883995488e..db095227d9cae 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, and `solid_asp3` and 14 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `openvm`, `psp`, `psx`, `qurt`, `redox`, `rtems`, and `solaris` and 14 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index efa0a7f4af9ac..ed69f06ba8909 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `openvm`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `openvm`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 28 warnings emitted From b8f847e7469b9bca408ec01a72a81ed65400fc2f Mon Sep 17 00:00:00 2001 From: Arayi Date: Wed, 10 Dec 2025 13:03:25 -0500 Subject: [PATCH 7/7] fix cfg-crate-features.stderr --- tests/ui/check-cfg/cfg-crate-features.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index db095227d9cae..aeb4096486854 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `openvm`, `psp`, `psx`, `qurt`, `redox`, `rtems`, and `solaris` and 14 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `openvm`, `psp`, `psx`, `qurt`, `redox`, `rtems`, and `solaris` and 15 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default