Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for riscv32im-risc0-zkvm-elf #7

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,7 @@ supported_targets! {
("x86_64-unknown-none-hermitkernel", x86_64_unknown_none_hermitkernel),

("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
Expand Down
36 changes: 36 additions & 0 deletions compiler/rustc_target/src/spec/riscv32im_risc0_zkvm_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
use crate::spec::{Target, TargetOptions};

pub fn target() -> Target {
Target {
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
llvm_target: "riscv32".into(),
pointer_width: 32,
arch: "riscv32".into(),

options: TargetOptions {
os: "zkvm".into(),
vendor: "risc0".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
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 zkvm 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(),
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
eh_frame_header: false,
singlethread: true,
..Default::default()
},
}
}
1 change: 1 addition & 0 deletions library/std/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fn main() {
|| target.contains("asmjs")
|| target.contains("espidf")
|| target.contains("solid")
|| target.contains("zkvm")
{
// These platforms don't have any special requirements.
} else {
Expand Down
6 changes: 3 additions & 3 deletions library/std/src/sys/common/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::ptr;
target_arch = "asmjs",
target_arch = "wasm32",
target_arch = "hexagon",
all(target_arch = "riscv32", not(target_os = "espidf")),
all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))),
all(target_arch = "xtensa", not(target_os = "espidf")),
)))]
pub const MIN_ALIGN: usize = 8;
Expand All @@ -28,9 +28,9 @@ pub const MIN_ALIGN: usize = 8;
target_arch = "wasm64",
)))]
pub const MIN_ALIGN: usize = 16;
// The allocator on the esp-idf platform guarentees 4 byte alignment.
// The allocator on the esp-idf and zkvm platforms guarantee 4 byte alignment.
#[cfg(all(any(
all(target_arch = "riscv32", target_os = "espidf"),
all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")),
all(target_arch = "xtensa", target_os = "espidf"),
)))]
pub const MIN_ALIGN: usize = 4;
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ cfg_if::cfg_if! {
} else if #[cfg(target_family = "wasm")] {
mod wasm;
pub use self::wasm::*;
} else if #[cfg(target_os = "zkvm")] {
mod zkvm;
pub use self::zkvm::*;
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
pub use self::sgx::*;
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/zkvm/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern "Rust" {
pub(crate) fn zkvm_abi_alloc_words(nwords: usize) -> *mut u32;
pub(crate) fn zkvm_abi_write_stdout(buf: &[u8]);
pub(crate) fn zkvm_abi_write_stderr(buf: &[u8]);
}
25 changes: 25 additions & 0 deletions library/std/src/sys/zkvm/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::abi;
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::cell::UnsafeCell;

const WORD_SIZE: usize = core::mem::size_of::<u32>();

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let nwords = layout
.align_to(WORD_SIZE)
.expect("Unable to align allocation to word size")
.pad_to_align()
.size()
/ WORD_SIZE;

abi::zkvm_abi_alloc_words(nwords) as *mut u8
}

#[inline]
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
// this allocator never deallocates memory
}
}
9 changes: 9 additions & 0 deletions library/std/src/sys/zkvm/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod os {
pub const FAMILY: &str = "";
pub const OS: &str = "";
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";
}
47 changes: 47 additions & 0 deletions library/std/src/sys/zkvm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! System bindings for the risc0 zkvm platform
//!
//! This module contains the facade (aka platform-specific) implementations of
//! OS level functionality for zkvm.
//!
//! 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.

pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;
#[path = "../unsupported/io.rs"]
pub mod io;
#[path = "../unsupported/net.rs"]
pub mod net;
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../unix/os_str.rs"]
pub mod os_str;
#[path = "../unix/path.rs"]
pub mod path;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/process.rs"]
pub mod process;
pub mod stdio;
pub mod thread_local_key;
#[path = "../unsupported/time.rs"]
pub mod time;

#[path = "../unsupported/locks/mod.rs"]
pub mod locks;
#[path = "../unsupported/thread.rs"]
pub mod thread;

#[path = "../unsupported/common.rs"]
#[deny(unsafe_op_in_unsafe_fn)]
mod common;
pub use common::*;

mod abi;
64 changes: 64 additions & 0 deletions library/std/src/sys/zkvm/stdio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use super::abi;
use crate::io;

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<usize> {
Ok(0)
}
}

impl Stdout {
pub const fn new() -> Stdout {
Stdout
}
}

impl io::Write for Stdout {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unsafe { abi::zkvm_abi_write_stdout(buf) };

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<usize> {
unsafe { abi::zkvm_abi_write_stderr(buf) };

Ok(buf.len())
}

fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

pub const STDIN_BUF_SIZE: usize = 0;

pub fn is_ebadf(_err: &io::Error) -> bool {
true
}

pub fn panic_output() -> Option<impl io::Write> {
Some(Stderr::new())
}
28 changes: 28 additions & 0 deletions library/std/src/sys/zkvm/thread_local_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::alloc::{alloc, Layout};

pub type Key = usize;

#[inline]
pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
alloc(Layout::new::<*mut u8>()) as _
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
let key = key as *mut *mut u8;
*key = value;
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
let key = key as *mut *mut u8;
*key
}

#[inline]
pub unsafe fn destroy(_key: Key) {}

#[inline]
pub fn requires_synchronized_create() -> bool {
false
}
1 change: 1 addition & 0 deletions library/std/src/sys_common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub mod wtf8;
cfg_if::cfg_if! {
if #[cfg(any(target_os = "l4re",
target_os = "hermit",
target_os = "zkvm",
feature = "restricted-std",
all(target_family = "wasm", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
Expand Down
5 changes: 5 additions & 0 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,11 @@ impl Build {
if self.config.profiler_enabled(target) {
features.push_str(" profiler");
}
// Generate memcpy, etc. FIXME: Remove this once compiler-builtins
// automatically detects this target.
if target.contains("zkvm") {
features.push_str(" compiler-builtins-mem");
}
features
}

Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,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 + RISCV32 support patches)
`riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF
`riscv32im-risc0-zkvm-elf` | * | | RISC-V running on the Risc0 Zero-Knowledge Virtual Machine
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0)
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 2.6.32, MUSL)
Expand Down
1 change: 1 addition & 0 deletions src/tools/build-manifest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static TARGETS: &[&str] = &[
"powerpc64-unknown-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"riscv32i-unknown-none-elf",
"riscv32im-risc0-zkvm-elf",
"riscv32imc-unknown-none-elf",
"riscv32imac-unknown-none-elf",
"riscv32gc-unknown-linux-gnu",
Expand Down
1 change: 1 addition & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const LICENSES: &[&str] = &[
"MIT / Apache-2.0",
"Apache-2.0/MIT",
"Apache-2.0 / MIT",
"Apache-2.0",
"MIT OR Apache-2.0",
"Apache-2.0 OR MIT",
"Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/extdeps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn check(root: &Path, bad: &mut bool) {
let source = line.split_once('=').unwrap().1.trim();

// Ensure source is allowed.
if !ALLOWED_SOURCES.contains(&&*source) {
if !ALLOWED_SOURCES.contains(&&*source) && !source.contains("risc0") {
tidy_error!(bad, "invalid source: {}", source);
}
}
Expand Down