Skip to content

Commit

Permalink
Merge pull request #3 from risc0/nils/from-upstream-nightly-2022-06-13
Browse files Browse the repository at this point in the history
Add rust standard library support for zkvm to upstream's nightly-2022-06-13
  • Loading branch information
shkoo authored Jul 27, 2022
2 parents 546c826 + 13dd9c8 commit d5e0226
Show file tree
Hide file tree
Showing 17 changed files with 247 additions and 5 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3277,6 +3277,14 @@ dependencies = [
"winapi",
]

[[package]]
name = "risc0-zkvm-platform"
version = "0.10.0"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]

[[package]]
name = "rls"
version = "1.41.0"
Expand Down Expand Up @@ -5016,6 +5024,7 @@ dependencies = [
"panic_unwind",
"profiler_builtins",
"rand 0.7.3",
"risc0-zkvm-platform",
"rustc-demangle",
"std_detect",
"unwind",
Expand Down
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 @@ -981,6 +981,7 @@ supported_targets! {

("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
("riscv32im-unknown-none-elf", riscv32im_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()
},
}
}
3 changes: 3 additions & 0 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ hermit-abi = { version = "0.2.0", features = ['rustc-dep-of-std'] }
[target.wasm32-wasi.dependencies]
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }

[target.'cfg(target_os = "zkvm")'.dependencies]
risc0-zkvm-platform = { git = "https://github.com/risc0/risc0", default-features = false, features = ['rustc-dep-of-std'] }

[features]
backtrace = [
"gimli-symbolize",
Expand Down
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 guarantees 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
36 changes: 36 additions & 0 deletions library/std/src/sys/zkvm/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::cell::UnsafeCell;
use risc0_zkvm_platform::{memory, WORD_SIZE};

struct BumpPointerAlloc {
head: UnsafeCell<usize>,
end: usize,
}
// SAFETY: single threaded environment
unsafe impl Sync for BumpPointerAlloc {}

static mut HEAP: BumpPointerAlloc =
BumpPointerAlloc { head: UnsafeCell::new(memory::HEAP.start()), end: memory::HEAP.end() };

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let head = HEAP.head.get();

// move start up to the next alignment boundary
let alloc_start = (*head + WORD_SIZE) & !(WORD_SIZE - 1);
let alloc_end = alloc_start.checked_add(layout.size()).unwrap();
if alloc_end > HEAP.end {
panic!("out of heap");
} else {
*head = alloc_end;
alloc_start 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";
}
45 changes: 45 additions & 0 deletions library/std/src/sys/zkvm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! 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::*;
63 changes: 63 additions & 0 deletions library/std/src/sys/zkvm/stdio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::io;

use risc0_zkvm_platform::io::{host_sendrecv, SENDRECV_CHANNEL_STDERR, SENDRECV_CHANNEL_STDOUT};

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> {
host_sendrecv(SENDRECV_CHANNEL_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> {
host_sendrecv(SENDRECV_CHANNEL_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 @@ -40,6 +40,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
7 changes: 6 additions & 1 deletion src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx"])),
(Some(Mode::Std), "target_os", Some(&["watchos"])),
(Some(Mode::Std), "target_os", Some(&["watchos", "zkvm"])),
(
Some(Mode::Std),
"target_arch",
Expand Down Expand Up @@ -761,6 +761,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 @@ -274,6 +274,7 @@ target | std | host | notes
`powerpc64le-unknown-linux-musl` | ? | |
`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)
`riscv32im-risc0-zkvm-elf` | * | | Risc-V running on the Risc0 Zero-Knowledge Virtual Machine
`riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA)
[`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA)
`riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/check-cfg/well-known-values.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | #[cfg(target_os = "linuz")]
| help: did you mean: `"linux"`
|
= note: `#[warn(unexpected_cfgs)]` on by default
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, windows, xous
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, windows, xous, zkvm

warning: unexpected `cfg` condition value
--> $DIR/well-known-values.rs:14:7
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",
"riscv32im-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"riscv32imac-unknown-none-elf",
Expand Down

0 comments on commit d5e0226

Please sign in to comment.