about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Kaneda <erik@risczero.com>2023-11-15 16:57:32 -0800
committerErik Kaneda <erik@risczero.com>2024-01-22 10:07:36 -0800
commit966b94e0a2330255e30b687f165dc4f2e8de140a (patch)
tree6746533b9ab8c22aceb0d27fb65144d166756f96
parent06fbe079014f8534eba21956d73e4be6022f0058 (diff)
downloadrust-966b94e0a2330255e30b687f165dc4f2e8de140a.tar.gz
rust-966b94e0a2330255e30b687f165dc4f2e8de140a.zip
rustc: implement support for `riscv32im_risc0_zkvm_elf`
This also adds changes in the rust test suite in order to get a few of them to
pass.

Co-authored-by: Frank Laub <flaub@risc0.com>
Co-authored-by: Urgau <3616612+Urgau@users.noreply.github.com>
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs36
-rw-r--r--library/panic_abort/src/lib.rs5
-rw-r--r--library/panic_abort/src/zkvm.rs24
-rw-r--r--library/test/src/console.rs3
-rw-r--r--library/test/src/lib.rs2
-rw-r--r--src/bootstrap/src/lib.rs9
-rw-r--r--src/tools/build-manifest/src/main.rs1
8 files changed, 79 insertions, 2 deletions
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 5d74ebebdf3..884bd23e8cc 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1597,6 +1597,7 @@ supported_targets! {
     ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
 
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
+    ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf),
     ("riscv32im-unknown-none-elf", riscv32im_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_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
new file mode 100644
index 00000000000..bf819de4133
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
@@ -0,0 +1,36 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, 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::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 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()
+        },
+    }
+}
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 8fd64279ac5..c44f23eea80 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -19,6 +19,9 @@
 #[cfg(target_os = "android")]
 mod android;
 
+#[cfg(target_os = "zkvm")]
+mod zkvm;
+
 use core::any::Any;
 use core::panic::PanicPayload;
 
@@ -34,6 +37,8 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
     // Android has the ability to attach a message as part of the abort.
     #[cfg(target_os = "android")]
     android::android_set_abort_message(_payload);
+    #[cfg(target_os = "zkvm")]
+    zkvm::zkvm_set_abort_message(_payload);
 
     abort();
 
diff --git a/library/panic_abort/src/zkvm.rs b/library/panic_abort/src/zkvm.rs
new file mode 100644
index 00000000000..a6a02abf109
--- /dev/null
+++ b/library/panic_abort/src/zkvm.rs
@@ -0,0 +1,24 @@
+use alloc::string::String;
+use core::panic::PanicPayload;
+
+// Forward the abort message to zkVM's sys_panic. This is implemented by RISC Zero's
+// platform crate which exposes system calls specifically for the zkVM.
+pub(crate) unsafe fn zkvm_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;
+    }
+
+    extern "C" {
+        fn sys_panic(msg_ptr: *const u8, len: usize) -> !;
+    }
+
+    sys_panic(msg.as_ptr(), msg.len());
+}
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index bbeb944e8b1..09aa3bfb6aa 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -323,7 +323,8 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
     // Prevent the usage of `Instant` in some cases:
     // - It's currently not supported for wasm targets.
     // - We disable it for miri because it's not available when isolation is enabled.
-    let is_instant_supported = !cfg!(target_family = "wasm") && !cfg!(miri);
+    let is_instant_supported =
+        !cfg!(target_family = "wasm") && !cfg!(target_os = "zkvm") && !cfg!(miri);
 
     let start_time = is_instant_supported.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 2e93796d981..5969d6b772c 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -540,7 +540,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_family = "wasm") || cfg!(target_os = "zkvm"))
         && !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 30824f58522..1336abf6c7a 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -90,6 +90,10 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     /* 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(&[])),
+    // #[cfg(bootstrap)] zkvm
+    (Some(Mode::Std), "target_os", Some(&["zkvm"])),
+    // #[cfg(bootstrap)] risc0
+    (Some(Mode::Std), "target_vendor", Some(&["risc0"])),
     (Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])),
     /* Extra names used by dependencies */
     // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
@@ -721,6 +725,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
     }
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9ac97236f19..1ef8cf7de3c 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -121,6 +121,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",