Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -1975,6 +1976,7 @@ crate::target_spec_enum! {
Nto = "nto",
NuttX = "nuttx",
OpenBsd = "openbsd",
Openvm = "openvm",
Psp = "psp",
Psx = "psx",
Qurt = "qurt",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::spec::{
Arch, Cc, LinkerFlavor, Lld, Os, 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: Arch::RiscV32,

options: TargetOptions {
os: Os::Openvm,
vendor: "unknown".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),

// 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,

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()
},
}
}
2 changes: 1 addition & 1 deletion library/panic_abort/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
8 changes: 7 additions & 1 deletion library/panic_abort/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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]
Expand Down
25 changes: 25 additions & 0 deletions library/panic_abort/src/openvm.rs
Original file line number Diff line number Diff line change
@@ -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::<String>() {
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());
}
}
1 change: 1 addition & 0 deletions library/std/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions library/std/src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
10 changes: 8 additions & 2 deletions library/std/src/sys/alloc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -107,4 +110,7 @@ cfg_select! {
target_os = "zkvm" => {
mod zkvm;
}
target_os = "openvm" => {
mod openvm;
}
}
15 changes: 15 additions & 0 deletions library/std/src/sys/alloc/openvm.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
4 changes: 4 additions & 0 deletions library/std/src/sys/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ cfg_select! {
mod zkvm;
pub use zkvm::*;
}
target_os = "openvm" => {
mod openvm;
pub use openvm::*;
}
_ => {
mod unsupported;
pub use unsupported::*;
Expand Down
94 changes: 94 additions & 0 deletions library/std/src/sys/args/openvm.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<&'static OsStr>> = 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<OsString> {
self.iter.next().map(|arg| arg.to_os_string())
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}

#[inline]
fn count(self) -> usize {
self.iter.len()
}

fn last(self) -> Option<OsString> {
self.iter.last().map(|arg| arg.to_os_string())
}

#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_by(n)
}
}

impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back().map(|arg| arg.to_os_string())
}

#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
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()
}
}
4 changes: 4 additions & 0 deletions library/std/src/sys/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ cfg_select! {
mod zkvm;
pub use zkvm::*;
}
target_os = "openvm" => {
mod openvm;
pub use openvm::*;
}
_ => {
mod unsupported;
pub use unsupported::*;
Expand Down
28 changes: 28 additions & 0 deletions library/std/src/sys/env/openvm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#[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<OsString> {
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.
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() }))
}
11 changes: 11 additions & 0 deletions library/std/src/sys/env_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/pal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down
35 changes: 35 additions & 0 deletions library/std/src/sys/pal/openvm/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! ABI definitions for symbols exported by 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)]

/// 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_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_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;
}
Loading
Loading