mirror of
https://github.com/eth-act/ere.git
synced 2026-04-03 03:00:17 -04:00
openvm: Guest program compilation with stock rust compiler. (#115)
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -2314,7 +2314,9 @@ dependencies = [
|
||||
name = "ere-openvm"
|
||||
version = "0.0.11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"build-utils",
|
||||
"cargo_metadata 0.19.2",
|
||||
"openvm-build",
|
||||
"openvm-circuit",
|
||||
"openvm-continuations",
|
||||
@@ -2325,6 +2327,7 @@ dependencies = [
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
"tracing",
|
||||
"zkvm-interface",
|
||||
]
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ rust-version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror.workspace = true
|
||||
cargo_metadata.workspace = true
|
||||
tracing.workspace = true
|
||||
toml.workspace = true
|
||||
|
||||
# OpenVM dependencies
|
||||
|
||||
160
crates/ere-openvm/src/compile_stock_rust.rs
Normal file
160
crates/ere-openvm/src/compile_stock_rust.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
use crate::OpenVMProgram;
|
||||
use crate::error::CompileError;
|
||||
use cargo_metadata::MetadataCommand;
|
||||
use openvm_sdk::config::{AppConfig, DEFAULT_APP_LOG_BLOWUP, DEFAULT_LEAF_LOG_BLOWUP, SdkVmConfig};
|
||||
use openvm_stark_sdk::config::FriParameters;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use tracing::info;
|
||||
|
||||
static CARGO_ENCODED_RUSTFLAGS_SEPARATOR: &str = "\x1f";
|
||||
const TARGET_TRIPLE: &str = "riscv32ima-unknown-none-elf";
|
||||
// Rust flags according to https://github.com/openvm-org/openvm/blob/v1.4.0-rc.8/crates/toolchain/build/src/lib.rs#L291
|
||||
const RUSTFLAGS: &[&str] = &[
|
||||
// Replace atomic ops with nonatomic versions since the guest is single threaded.
|
||||
"-C",
|
||||
"passes=lower-atomic",
|
||||
// Specify where to start loading the program in
|
||||
// memory. The clang linker understands the same
|
||||
// command line arguments as the GNU linker does; see
|
||||
// https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#SEC3
|
||||
// for details.
|
||||
"-C",
|
||||
"link-arg=-Ttext=0x00200800",
|
||||
// Apparently not having an entry point is only a linker warning(!), so
|
||||
// error out in this case.
|
||||
"-C",
|
||||
"link-arg=--fatal-warnings",
|
||||
"-C",
|
||||
"panic=abort",
|
||||
// https://docs.rs/getrandom/0.3.2/getrandom/index.html#opt-in-backends
|
||||
"--cfg",
|
||||
"getrandom_backend=\"custom\"",
|
||||
];
|
||||
const CARGO_ARGS: &[&str] = &[
|
||||
"build",
|
||||
"--target",
|
||||
TARGET_TRIPLE,
|
||||
"--release",
|
||||
// For bare metal we have to build core and alloc
|
||||
"-Zbuild-std=core,alloc",
|
||||
];
|
||||
|
||||
pub fn compile_openvm_program_stock_rust(
|
||||
guest_directory: &Path,
|
||||
toolchain: &String,
|
||||
) -> Result<OpenVMProgram, CompileError> {
|
||||
wrap_into_openvm_program(
|
||||
compile_program_stock_rust(guest_directory, toolchain)?,
|
||||
guest_directory,
|
||||
)
|
||||
}
|
||||
|
||||
fn compile_program_stock_rust(
|
||||
guest_directory: &Path,
|
||||
toolchain: &String,
|
||||
) -> Result<Vec<u8>, CompileError> {
|
||||
let metadata = MetadataCommand::new().current_dir(guest_directory).exec()?;
|
||||
let package = metadata
|
||||
.root_package()
|
||||
.ok_or_else(|| CompileError::MissingPackageName {
|
||||
path: guest_directory.to_path_buf(),
|
||||
})?;
|
||||
|
||||
let plus_toolchain = format!("+{}", toolchain);
|
||||
let mut cargo_args = [plus_toolchain.as_str()].to_vec();
|
||||
cargo_args.append(&mut CARGO_ARGS.to_vec());
|
||||
|
||||
let encoded_rust_flags = RUSTFLAGS.to_vec().join(CARGO_ENCODED_RUSTFLAGS_SEPARATOR);
|
||||
|
||||
let target_direcotry = guest_directory
|
||||
.join("target")
|
||||
.join(TARGET_TRIPLE)
|
||||
.join("release");
|
||||
|
||||
// Remove target directory.
|
||||
if target_direcotry.exists() {
|
||||
fs::remove_dir_all(&target_direcotry).unwrap();
|
||||
}
|
||||
|
||||
let result = Command::new("cargo")
|
||||
.current_dir(guest_directory)
|
||||
.env("CARGO_ENCODED_RUSTFLAGS", &encoded_rust_flags)
|
||||
.args(cargo_args)
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.status()
|
||||
.map_err(|source| CompileError::BuildFailure {
|
||||
source: source.into(),
|
||||
crate_path: guest_directory.to_path_buf(),
|
||||
});
|
||||
|
||||
if result.is_err() {
|
||||
return Err(result.err().unwrap());
|
||||
}
|
||||
|
||||
let elf_path = target_direcotry.join(&package.name);
|
||||
|
||||
fs::read(&elf_path).map_err(|e| CompileError::ReadFile {
|
||||
path: elf_path,
|
||||
source: e,
|
||||
})
|
||||
}
|
||||
|
||||
fn wrap_into_openvm_program(
|
||||
elf: Vec<u8>,
|
||||
guest_directory: &Path,
|
||||
) -> Result<OpenVMProgram, CompileError> {
|
||||
let app_config_path = guest_directory.join("openvm.toml");
|
||||
let app_config = if app_config_path.exists() {
|
||||
let toml = fs::read_to_string(&app_config_path).map_err(|source| {
|
||||
CompileError::ReadConfigFailed {
|
||||
source,
|
||||
path: app_config_path.to_path_buf(),
|
||||
}
|
||||
})?;
|
||||
toml::from_str(&toml).map_err(CompileError::DeserializeConfigFailed)?
|
||||
} else {
|
||||
// The default `AppConfig` copied from https://github.com/openvm-org/openvm/blob/ca36de3/crates/cli/src/default.rs#L31.
|
||||
AppConfig {
|
||||
app_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_APP_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
// By default it supports RISCV32IM with IO but no precompiles.
|
||||
app_vm_config: SdkVmConfig::builder()
|
||||
.system(Default::default())
|
||||
.rv32i(Default::default())
|
||||
.rv32m(Default::default())
|
||||
.io(Default::default())
|
||||
.build(),
|
||||
leaf_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_LEAF_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
compiler_options: Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
info!("Openvm program compiled OK - {} bytes", elf.len());
|
||||
|
||||
Ok(OpenVMProgram { elf, app_config })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::compile_stock_rust::compile_openvm_program_stock_rust;
|
||||
use test_utils::host::testing_guest_directory;
|
||||
|
||||
#[test]
|
||||
fn test_stock_compiler_impl() {
|
||||
let guest_directory = testing_guest_directory("openvm", "stock_nightly_no_std");
|
||||
let result = compile_openvm_program_stock_rust(&guest_directory, &"nightly".to_string());
|
||||
assert!(result.is_ok(), "Openvm guest program compilation failure.");
|
||||
assert!(
|
||||
!result.unwrap().elf.is_empty(),
|
||||
"ELF bytes should not be empty."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,12 @@ pub enum OpenVMError {
|
||||
pub enum CompileError {
|
||||
#[error("Failed to build guest, code: {0}")]
|
||||
BuildFailed(i32),
|
||||
#[error("`openvm` build failure for {crate_path} failed: {source}")]
|
||||
BuildFailure {
|
||||
#[source]
|
||||
source: anyhow::Error,
|
||||
crate_path: PathBuf,
|
||||
},
|
||||
#[error("Guest building skipped (OPENVM_SKIP_BUILD is set)")]
|
||||
BuildSkipped,
|
||||
#[error("Missing to find unique elf: {0}")]
|
||||
@@ -44,6 +50,16 @@ pub enum CompileError {
|
||||
ReadConfigFailed { source: io::Error, path: PathBuf },
|
||||
#[error("Failed to deserialize OpenVM's config file: {0}")]
|
||||
DeserializeConfigFailed(toml::de::Error),
|
||||
#[error("`cargo metadata` failed: {0}")]
|
||||
MetadataCommand(#[from] cargo_metadata::Error),
|
||||
#[error("Could not find `[package].name` in guest Cargo.toml at {path}")]
|
||||
MissingPackageName { path: PathBuf },
|
||||
#[error("Failed to read file at {path}: {source}")]
|
||||
ReadFile {
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use crate::compile_stock_rust::compile_openvm_program_stock_rust;
|
||||
use crate::error::{CommonError, CompileError, ExecuteError, OpenVMError, ProveError, VerifyError};
|
||||
use openvm_build::GuestOptions;
|
||||
use openvm_circuit::arch::instructions::exe::VmExe;
|
||||
@@ -27,6 +28,8 @@ use zkvm_interface::{
|
||||
ProverResourceType, PublicValues, zkVM, zkVMError,
|
||||
};
|
||||
|
||||
mod compile_stock_rust;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
mod error;
|
||||
|
||||
@@ -44,58 +47,69 @@ impl Compiler for OPENVM_TARGET {
|
||||
|
||||
type Program = OpenVMProgram;
|
||||
|
||||
// Inlining `openvm_sdk::Sdk::build` in order to get raw elf bytes.
|
||||
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error> {
|
||||
let pkg = openvm_build::get_package(guest_directory);
|
||||
let guest_opts = GuestOptions::default().with_profile("release".to_string());
|
||||
let target_dir = match openvm_build::build_guest_package(&pkg, &guest_opts, None, &None) {
|
||||
Ok(target_dir) => target_dir,
|
||||
Err(Some(code)) => return Err(CompileError::BuildFailed(code))?,
|
||||
Err(None) => return Err(CompileError::BuildSkipped)?,
|
||||
};
|
||||
|
||||
let elf_path = openvm_build::find_unique_executable(guest_directory, target_dir, &None)
|
||||
.map_err(|e| CompileError::UniqueElfNotFound(e.into()))?;
|
||||
let elf = fs::read(&elf_path).map_err(|source| CompileError::ReadElfFailed {
|
||||
source,
|
||||
path: elf_path.to_path_buf(),
|
||||
})?;
|
||||
|
||||
let app_config_path = guest_directory.join("openvm.toml");
|
||||
let app_config = if app_config_path.exists() {
|
||||
let toml = fs::read_to_string(&app_config_path).map_err(|source| {
|
||||
CompileError::ReadConfigFailed {
|
||||
source,
|
||||
path: app_config_path.to_path_buf(),
|
||||
}
|
||||
})?;
|
||||
toml::from_str(&toml).map_err(CompileError::DeserializeConfigFailed)?
|
||||
} else {
|
||||
// The default `AppConfig` copied from https://github.com/openvm-org/openvm/blob/ca36de3/crates/cli/src/default.rs#L31.
|
||||
AppConfig {
|
||||
app_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_APP_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
// By default it supports RISCV32IM with IO but no precompiles.
|
||||
app_vm_config: SdkVmConfig::builder()
|
||||
.system(Default::default())
|
||||
.rv32i(Default::default())
|
||||
.rv32m(Default::default())
|
||||
.io(Default::default())
|
||||
.build(),
|
||||
leaf_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_LEAF_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
compiler_options: Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(OpenVMProgram { elf, app_config })
|
||||
let toolchain = env::var("ERE_GUEST_TOOLCHAIN").unwrap_or_else(|_error| "openvm".into());
|
||||
match toolchain.as_str() {
|
||||
"openvm" => Ok(compile_openvm_program(guest_directory)?),
|
||||
_ => Ok(compile_openvm_program_stock_rust(
|
||||
guest_directory,
|
||||
&toolchain,
|
||||
)?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inlining `openvm_sdk::Sdk::build` in order to get raw elf bytes.
|
||||
fn compile_openvm_program(guest_directory: &Path) -> Result<OpenVMProgram, OpenVMError> {
|
||||
let pkg = openvm_build::get_package(guest_directory);
|
||||
let guest_opts = GuestOptions::default().with_profile("release".to_string());
|
||||
let target_dir = match openvm_build::build_guest_package(&pkg, &guest_opts, None, &None) {
|
||||
Ok(target_dir) => target_dir,
|
||||
Err(Some(code)) => return Err(CompileError::BuildFailed(code))?,
|
||||
Err(None) => return Err(CompileError::BuildSkipped)?,
|
||||
};
|
||||
|
||||
let elf_path = openvm_build::find_unique_executable(guest_directory, target_dir, &None)
|
||||
.map_err(|e| CompileError::UniqueElfNotFound(e.into()))?;
|
||||
let elf = fs::read(&elf_path).map_err(|source| CompileError::ReadElfFailed {
|
||||
source,
|
||||
path: elf_path.to_path_buf(),
|
||||
})?;
|
||||
|
||||
let app_config_path = guest_directory.join("openvm.toml");
|
||||
let app_config = if app_config_path.exists() {
|
||||
let toml = fs::read_to_string(&app_config_path).map_err(|source| {
|
||||
CompileError::ReadConfigFailed {
|
||||
source,
|
||||
path: app_config_path.to_path_buf(),
|
||||
}
|
||||
})?;
|
||||
toml::from_str(&toml).map_err(CompileError::DeserializeConfigFailed)?
|
||||
} else {
|
||||
// The default `AppConfig` copied from https://github.com/openvm-org/openvm/blob/ca36de3/crates/cli/src/default.rs#L31.
|
||||
AppConfig {
|
||||
app_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_APP_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
// By default it supports RISCV32IM with IO but no precompiles.
|
||||
app_vm_config: SdkVmConfig::builder()
|
||||
.system(Default::default())
|
||||
.rv32i(Default::default())
|
||||
.rv32m(Default::default())
|
||||
.io(Default::default())
|
||||
.build(),
|
||||
leaf_fri_params: FriParameters::standard_with_100_bits_conjectured_security(
|
||||
DEFAULT_LEAF_LOG_BLOWUP,
|
||||
)
|
||||
.into(),
|
||||
compiler_options: Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(OpenVMProgram { elf, app_config })
|
||||
}
|
||||
|
||||
pub struct EreOpenVM {
|
||||
app_config: AppConfig<SdkVmConfig>,
|
||||
app_exe: Arc<VmExe<F>>,
|
||||
@@ -266,6 +280,7 @@ pub fn agg_pk_path() -> PathBuf {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::compile_stock_rust::compile_openvm_program_stock_rust;
|
||||
use std::sync::OnceLock;
|
||||
use test_utils::host::{
|
||||
BasicProgramIo, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
|
||||
@@ -297,6 +312,17 @@ mod tests {
|
||||
run_zkvm_execute(&zkvm, &io);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_nightly() {
|
||||
let guest_directory = testing_guest_directory("openvm", "stock_nightly_no_std");
|
||||
let program =
|
||||
compile_openvm_program_stock_rust(&guest_directory, &"nightly".to_string()).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let result = zkvm.execute(&BasicProgramIo::empty());
|
||||
assert!(result.is_ok(), "Openvm execution failure");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
|
||||
@@ -9,6 +9,9 @@ FROM ${BASE_IMAGE_TAG}
|
||||
COPY scripts/sdk_installers/install_openvm_sdk.sh /tmp/install_openvm_sdk.sh
|
||||
RUN chmod +x /tmp/install_openvm_sdk.sh
|
||||
|
||||
# Add `rust-src` component to enable std build for nightly rust.
|
||||
RUN rustup +nightly component add rust-src
|
||||
|
||||
# Run the OpenVM SDK installation script.
|
||||
# This script installs a specific toolchain
|
||||
# and installs cargo-openvm.
|
||||
|
||||
7
tests/openvm/stock_nightly_no_std/Cargo.toml
Normal file
7
tests/openvm/stock_nightly_no_std/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "addition_no_std"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[workspace]
|
||||
25
tests/openvm/stock_nightly_no_std/src/main.rs
Normal file
25
tests/openvm/stock_nightly_no_std/src/main.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::sync::atomic::Ordering;
|
||||
use core::sync::atomic::AtomicU16;
|
||||
mod openvm_rt;
|
||||
|
||||
fn main() {
|
||||
let a: AtomicU16 = core::hint::black_box(AtomicU16::new(5));
|
||||
let b: AtomicU16 = core::hint::black_box(AtomicU16::new(7));
|
||||
|
||||
if a.load(Ordering::SeqCst) + b.load(Ordering::SeqCst) != 12 {
|
||||
panic!("Something went wrong!");
|
||||
}
|
||||
|
||||
let mut v: Vec<AtomicU16> = Vec::new();
|
||||
v.push(AtomicU16::new(5));
|
||||
v.push(AtomicU16::new(7));
|
||||
|
||||
if v[0].load(Ordering::SeqCst) + v[1].load(Ordering::SeqCst) != 12 {
|
||||
panic!("Something went wrong!");
|
||||
}
|
||||
}
|
||||
136
tests/openvm/stock_nightly_no_std/src/openvm_rt.rs
Normal file
136
tests/openvm/stock_nightly_no_std/src/openvm_rt.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
// Import user `main` function
|
||||
use crate::main;
|
||||
|
||||
// 1. Init global pointer (GP). It's used to optimize jumps by linker. Linker can change jumping from PC(Program Counter) based to GP based.
|
||||
// 2. Init stack pointer to the value STACK_TOP. It's stored in sp register.
|
||||
// 3. Call __start function defined below.
|
||||
// `__global_pointer$` is set by the linker. Its value depends on linker optimization. https://www.programmersought.com/article/77722901592/
|
||||
core::arch::global_asm!(
|
||||
r#"
|
||||
.section .text._start;
|
||||
.globl _start;
|
||||
_start:
|
||||
.option push;
|
||||
.option norelax;
|
||||
la gp, __global_pointer$;
|
||||
.option pop;
|
||||
la sp, {0}
|
||||
lw sp, 0(sp)
|
||||
call __start;
|
||||
"#,
|
||||
sym STACK_TOP
|
||||
);
|
||||
|
||||
static STACK_TOP: u32 = 0x0020_0400;
|
||||
|
||||
// 1. Call `main` user function
|
||||
// 2. Call system halt environment function. It's defined by sp1 vm.
|
||||
#[unsafe(no_mangle)]
|
||||
fn __start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
main();
|
||||
|
||||
terminate();
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// According to https://github.com/openvm-org/openvm/blob/v1.4.0-rc.8/crates/toolchain/openvm/src/process.rs
|
||||
#[inline(always)]
|
||||
fn terminate() {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
".insn 4, 0x000b"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// According to https://github.com/openvm-org/openvm/blob/v1.4.0-rc.8/crates/toolchain/openvm/src/process.rs
|
||||
#[panic_handler]
|
||||
fn panic_impl(_panic_info: &core::panic::PanicInfo) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
".insn 4, 0x10000b"
|
||||
)
|
||||
}
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
/// A simple heap allocator.
|
||||
///
|
||||
/// Allocates memory from left to right, without any deallocation.
|
||||
struct SimpleAlloc;
|
||||
|
||||
unsafe impl GlobalAlloc for SimpleAlloc {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
unsafe {
|
||||
sys_alloc_aligned(layout.size(), layout.align())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _: *mut u8, _: Layout) {}
|
||||
}
|
||||
|
||||
#[global_allocator]
|
||||
static HEAP: SimpleAlloc = SimpleAlloc;
|
||||
|
||||
pub const MAX_MEMORY: usize = 0x78000000;
|
||||
static mut HEAP_POS: usize = 0;
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
|
||||
unsafe extern "C" {
|
||||
// https://lld.llvm.org/ELF/linker_script.html#sections-command
|
||||
// `_end` is the last global variable defined by the linker. Its address is the beginning of heap data.
|
||||
unsafe static _end: u8;
|
||||
}
|
||||
|
||||
// SAFETY: Single threaded, so nothing else can touch this while we're working.
|
||||
let mut heap_pos = unsafe { HEAP_POS };
|
||||
|
||||
if heap_pos == 0 {
|
||||
heap_pos = unsafe { (&_end) as *const u8 as usize };
|
||||
}
|
||||
|
||||
let offset = heap_pos & (align - 1);
|
||||
if offset != 0 {
|
||||
heap_pos += align - offset;
|
||||
}
|
||||
|
||||
let ptr = heap_pos as *mut u8;
|
||||
let (heap_pos, overflowed) = heap_pos.overflowing_add(bytes);
|
||||
|
||||
if overflowed || MAX_MEMORY < heap_pos {
|
||||
panic!("Memory limit exceeded (0x78000000)");
|
||||
}
|
||||
|
||||
unsafe { HEAP_POS = heap_pos };
|
||||
ptr
|
||||
}
|
||||
|
||||
// Assume single-threaded.
|
||||
#[cfg(all(target_arch = "riscv32", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_acquire() -> u32
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "riscv32", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_release(_: u32)
|
||||
{}
|
||||
|
||||
// Assume single-threaded.
|
||||
#[cfg(all(target_arch = "riscv64", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_acquire() -> u64
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "riscv64", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_release(_: u64)
|
||||
{}
|
||||
Reference in New Issue
Block a user