Skip to content

Commit

Permalink
Initial RISC-V support (#1718)
Browse files Browse the repository at this point in the history
* Fix message dispatch for riscv

* Fix error handlers for riscv

* Fix allocator for riscv

* Fix ext for riscv

* Remove not needed manifest keys (they are already removed from the template)

* Add no_main to all examples

* Fix CI

* Fix multisig doc test

* Update linking to latest supported toolchain

* fmt

* fmt

* fmt

* Fix mess caused by rustfmt

* Combine no_std and no_main

* Update .gitlab-ci.yml

Co-authored-by: Andrew Jones <ascjones@gmail.com>

* Remove not needed block

---------

Co-authored-by: Andrew Jones <ascjones@gmail.com>
  • Loading branch information
athei and ascjones committed Mar 28, 2023
1 parent b436933 commit 6fb975d
Show file tree
Hide file tree
Showing 73 changed files with 1,206 additions and 825 deletions.
23 changes: 12 additions & 11 deletions .gitlab-ci.yml
Expand Up @@ -39,10 +39,12 @@ variables:
# this fix not yet in stable: https://github.com/rust-lang/rust-clippy/issues/8895.
# Remove the following line again as soon as `clippy` on stable succeeds again.
CLIPPY_ALLOWED: "clippy::extra_unused_lifetimes"
# This is a target that does not have a standard library in contrast to Wasm. We compile against
# this target to make sure that we don't pull in `std` by accident (through dependencies).
# See https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-2.
NO_STD_TARGET: "aarch64-unknown-none"
# We plan to fully support RISC-V as a bytecode for contracts soon.
# RISC-V does not have a standard library in contrast to Wasm. Compiling against
# this target also makes sure that we don't pull in `std` by accident (through dependencies).
# RISC-V is a modular archtitecture. We might switch to a different flavor with more features
# later. For example, `riscv32imc-unknown-none-elf`.
RISCV_TARGET: "riscv32i-unknown-none-elf"

workflow:
rules:
Expand Down Expand Up @@ -209,16 +211,15 @@ check-wasm:
cargo check --verbose --no-default-features --target wasm32-unknown-unknown --manifest-path ./crates/${crate}/Cargo.toml;
done

# We just check on a target which doesn't have `std` to make sure that we don't pull in `std` by accident
check-no-std:
check-riscv:
stage: check
<<: *docker-env
<<: *test-refs
variables:
RUSTC_BOOTSTRAP: "1"
script:
- for crate in ${ALSO_WASM_CRATES}; do
cargo check --verbose --no-default-features --target $NO_STD_TARGET -Zbuild-std="core,alloc" --manifest-path ./crates/${crate}/Cargo.toml;
cargo check --verbose --no-default-features --target $RISCV_TARGET -Zbuild-std="core,alloc" --manifest-path ./crates/${crate}/Cargo.toml;
done

dylint:
Expand Down Expand Up @@ -426,8 +427,8 @@ examples-contract-build:
done
- cargo +stable contract build --manifest-path ./integration-tests/set_code_hash/updated_incrementer/Cargo.toml

# We only check a few basic contracts here, no need to check them all.
examples-no-std-check:
# TODO: Use cargo contract as soon as it has RISC-V support
examples-contract-build-riscv:
stage: examples
<<: *docker-env
<<: *test-refs
Expand All @@ -442,15 +443,15 @@ examples-no-std-check:
# - upgradeable-contracts
# This uses dlmalloc which is only supported on select targets.
# - custom_allocator
# Pulls in sp-std which needlessly requires atomic pointers.
# Pulls in sp-std which needlessly requires atomic pointers (TODO: Fix sp-std and enable this example)
# - call-runtime
- for example in integration-tests/*/; do
if [ "$example" = "integration-tests/lang-err-integration-tests/" ]; then continue; fi;
if [ "$example" = "integration-tests/upgradeable-contracts/" ]; then continue; fi;
if [ "$example" = "integration-tests/custom_allocator/" ]; then continue; fi;
if [ "$example" = "integration-tests/call-runtime/" ]; then continue; fi;
pushd $example &&
cargo +stable check --no-default-features --target $NO_STD_TARGET -Zbuild-std="core,alloc" &&
cargo +stable build --no-default-features --target $RISCV_TARGET -Zbuild-std="core,alloc" &&
popd;
done

Expand Down
45 changes: 41 additions & 4 deletions crates/allocator/src/bump.rs
Expand Up @@ -68,13 +68,21 @@ struct InnerAlloc {
impl InnerAlloc {
const fn new() -> Self {
Self {
next: 0,
upper_limit: 0,
next: Self::heap_start(),
upper_limit: Self::heap_end(),
}
}

cfg_if::cfg_if! {
if #[cfg(test)] {
const fn heap_start() -> usize {
0
}

const fn heap_end() -> usize {
0
}

/// Request a `pages` number of page sized sections of Wasm memory. Each page is `64KiB` in size.
///
/// Returns `None` if a page is not available.
Expand All @@ -85,13 +93,29 @@ impl InnerAlloc {
Some(self.upper_limit)
}
} else if #[cfg(feature = "std")] {
const fn heap_start() -> usize {
0
}

const fn heap_end() -> usize {
0
}

fn request_pages(&mut self, _pages: usize) -> Option<usize> {
unreachable!(
"This branch is only used to keep the compiler happy when building tests, and
should never actually be called outside of a test run."
)
}
} else if #[cfg(target_arch = "wasm32")] {
const fn heap_start() -> usize {
0
}

const fn heap_end() -> usize {
0
}

/// Request a `pages` number of pages of Wasm memory. Each page is `64KiB` in size.
///
/// Returns `None` if a page is not available.
Expand All @@ -103,11 +127,24 @@ impl InnerAlloc {

prev_page.checked_mul(PAGE_SIZE)
}
} else {
/// On other architectures growing memory probably doesn't make sense.
} else if #[cfg(target_arch = "riscv32")] {
const fn heap_start() -> usize {
// Placeholder value until we specified our riscv VM
0x7000_0000
}

const fn heap_end() -> usize {
// Placeholder value until we specified our riscv VM
// Let's just assume a cool megabyte of mem for now
0x7000_0400
}

fn request_pages(&mut self, _pages: usize) -> Option<usize> {
// On riscv the memory can't be grown
None
}
} else {
core::compile_error!("ink! only supports wasm32 and riscv32");
}
}

Expand Down
31 changes: 0 additions & 31 deletions crates/allocator/src/handlers.rs

This file was deleted.

4 changes: 0 additions & 4 deletions crates/allocator/src/lib.rs
Expand Up @@ -23,17 +23,13 @@
html_favicon_url = "https://use.ink/crate-docs/favicon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))]

#[cfg(not(any(feature = "std", feature = "no-allocator")))]
#[global_allocator]
static mut ALLOC: bump::BumpAllocator = bump::BumpAllocator {};

mod bump;

#[cfg(not(feature = "std"))]
mod handlers;

#[cfg(all(test, feature = "std", feature = "ink-fuzz-tests",))]
#[macro_use(quickcheck)]
extern crate quickcheck_macros;
1 change: 1 addition & 0 deletions crates/env/Cargo.toml
Expand Up @@ -3,6 +3,7 @@ name = "ink_env"
version = "4.1.0"
authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
edition = "2021"
rust-version = "1.68"

license = "Apache-2.0"
readme = "README.md"
Expand Down

1 comment on commit 6fb975d

@Polkadot-Forum
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on Polkadot Forum. There might be relevant details there:

https://forum.polkadot.network/t/ebpf-contracts-hackathon/1084/12

Please sign in to comment.