diff --git a/crates/builtins/Cargo.toml b/crates/builtins/Cargo.toml index c4f1223..d8b3e8b 100644 --- a/crates/builtins/Cargo.toml +++ b/crates/builtins/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" build = "build.rs" +[features] +riscv-64 = [] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/builtins/build.rs b/crates/builtins/build.rs index dabea2e..0030e84 100644 --- a/crates/builtins/build.rs +++ b/crates/builtins/build.rs @@ -1,7 +1,11 @@ use std::{env, fs, io::Read, path::Path, process::Command}; +#[cfg(not(feature = "riscv-64"))] +pub const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv32.a"; +#[cfg(feature = "riscv-64")] +pub const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv64.a"; + fn main() { - let lib = "libclang_rt.builtins-riscv32.a"; let mut llvm_lib_dir = String::new(); Command::new("llvm-config") @@ -15,19 +19,22 @@ fn main() { let mut lib_path = std::path::PathBuf::from(llvm_lib_dir.trim()) .join("linux") - .join(lib); + .join(BUILTINS_ARCHIVE_FILE); if !lib_path.exists() { - lib_path = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join(lib); + lib_path = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) + .join(BUILTINS_ARCHIVE_FILE); } - let archive = fs::read(lib_path).expect("clang builtins for riscv32 not found"); + let archive = fs::read(lib_path).expect("clang builtins not found"); let out_dir = env::var_os("OUT_DIR").expect("has OUT_DIR"); - let archive_path = Path::new(&out_dir).join(lib); + let archive_path = Path::new(&out_dir).join(BUILTINS_ARCHIVE_FILE); let len = archive.len(); std::fs::write(archive_path, &archive).expect("can write to OUT_DIR"); let src_path = Path::new(&out_dir).join("compiler_rt.rs"); - let src = format!("pub static COMPILER_RT: &[u8; {len}] = include_bytes!(\"{lib}\");"); + let src = format!( + "pub static COMPILER_RT: &[u8; {len}] = include_bytes!(\"{BUILTINS_ARCHIVE_FILE}\");" + ); fs::write(src_path, src).expect("can write to OUT_DIR"); println!("cargo:rerun-if-changed=build.rs"); diff --git a/crates/builtins/libclang_rt.builtins-riscv32.a b/crates/builtins/libclang_rt.builtins-riscv32.a index e9ee15d..f13a884 100644 Binary files a/crates/builtins/libclang_rt.builtins-riscv32.a and b/crates/builtins/libclang_rt.builtins-riscv32.a differ diff --git a/crates/builtins/libclang_rt.builtins-riscv64.a b/crates/builtins/libclang_rt.builtins-riscv64.a new file mode 100644 index 0000000..57a7d97 Binary files /dev/null and b/crates/builtins/libclang_rt.builtins-riscv64.a differ diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 7634ae4..401ac58 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -12,6 +12,9 @@ description = "Shared constants of the revive compiler" [lib] doctest = false +[features] +riscv-64 = [] + [dependencies] anyhow = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/common/src/byte_length.rs b/crates/common/src/byte_length.rs index 08c3714..e452ca2 100644 --- a/crates/common/src/byte_length.rs +++ b/crates/common/src/byte_length.rs @@ -7,7 +7,10 @@ pub const BYTE_LENGTH_BYTE: usize = 1; pub const BYTE_LENGTH_X32: usize = 4; /// Native stack alignment size in bytes +#[cfg(not(feautre = "riscv-64"))] pub const BYTE_LENGTH_STACK_ALIGN: usize = 4; +#[cfg(feautre = "riscv-64")] +pub const BYTE_LENGTH_STACK_ALIGN: usize = 8; /// The x86_64 word byte-length. pub const BYTE_LENGTH_X64: usize = 8; diff --git a/crates/integration/codesize.json b/crates/integration/codesize.json index bb6ef56..9cedb4e 100644 --- a/crates/integration/codesize.json +++ b/crates/integration/codesize.json @@ -1,10 +1,10 @@ { "Baseline": 934, "Computation": 4360, - "DivisionArithmetics": 39448, - "ERC20": 46624, + "DivisionArithmetics": 39824, + "ERC20": 46471, "Events": 1749, "FibonacciIterative": 2973, "Flipper": 3563, - "SHA1": 32709 + "SHA1": 32543 } \ No newline at end of file diff --git a/crates/linker/Cargo.toml b/crates/linker/Cargo.toml index 2574b2a..9d30aaf 100644 --- a/crates/linker/Cargo.toml +++ b/crates/linker/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +riscv-64 = [] + [dependencies] inkwell = { workspace = true } tempfile = { workspace = true } diff --git a/crates/linker/src/lib.rs b/crates/linker/src/lib.rs index 6d1302e..27994fd 100644 --- a/crates/linker/src/lib.rs +++ b/crates/linker/src/lib.rs @@ -8,6 +8,16 @@ SECTIONS { .text : { KEEP(*(.text.polkavm_export)) *(.text .text.*) } }"#; +#[cfg(not(feature = "riscv-64"))] +const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv32.a"; +#[cfg(feature = "riscv-64")] +const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv64.a"; + +#[cfg(not(feature = "riscv-64"))] +const BUILTINS_LIB_NAME: &str = "clang_rt.builtins-riscv32"; +#[cfg(feature = "riscv-64")] +const BUILTINS_LIB_NAME: &str = "clang_rt.builtins-riscv64"; + fn invoke_lld(cmd_args: &[&str]) -> bool { let c_strings = cmd_args .iter() @@ -32,7 +42,7 @@ pub fn link>(input: T) -> anyhow::Result> { let output_path = dir.path().join("out.so"); let object_path = dir.path().join("out.o"); let linker_script_path = dir.path().join("linker.ld"); - let compiler_rt_path = dir.path().join("libclang_rt.builtins-riscv32.a"); + let compiler_rt_path = dir.path().join(BUILTINS_ARCHIVE_FILE); fs::write(&object_path, input).map_err(|msg| anyhow::anyhow!("{msg} {object_path:?}"))?; @@ -57,7 +67,7 @@ pub fn link>(input: T) -> anyhow::Result> { "--library-path", dir.path().to_str().expect("should be utf8"), "--library", - "clang_rt.builtins-riscv32", + BUILTINS_LIB_NAME, linker_script_path.to_str().expect("should be utf8"), object_path.to_str().expect("should be utf8"), "-o", diff --git a/crates/llvm-context/Cargo.toml b/crates/llvm-context/Cargo.toml index 413dc82..f50c238 100644 --- a/crates/llvm-context/Cargo.toml +++ b/crates/llvm-context/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [features] riscv-zbb = [] +riscv-64 = [] [dependencies] anyhow = { workspace = true } diff --git a/crates/llvm-context/src/polkavm/const/mod.rs b/crates/llvm-context/src/polkavm/const/mod.rs index 9cc454f..1351ab6 100644 --- a/crates/llvm-context/src/polkavm/const/mod.rs +++ b/crates/llvm-context/src/polkavm/const/mod.rs @@ -10,7 +10,10 @@ pub const LLVM_VERSION: semver::Version = semver::Version::new(18, 1, 4); pub const ZKEVM_VERSION: semver::Version = semver::Version::new(1, 3, 2); /// The register width sized type +#[cfg(not(feature = "riscv-64"))] pub static XLEN: usize = revive_common::BIT_LENGTH_X32; +#[cfg(feature = "riscv-64")] +pub static XLEN: usize = revive_common::BIT_LENGTH_X64; /// The heap memory pointer pointer global variable name. pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer"; diff --git a/crates/llvm-context/src/target_machine/mod.rs b/crates/llvm-context/src/target_machine/mod.rs index a877978..ab62569 100644 --- a/crates/llvm-context/src/target_machine/mod.rs +++ b/crates/llvm-context/src/target_machine/mod.rs @@ -20,10 +20,22 @@ pub struct TargetMachine { impl TargetMachine { /// The LLVM target name. + #[cfg(not(feature = "riscv-64"))] pub const VM_TARGET_NAME: &'static str = "riscv32"; + #[cfg(feature = "riscv-64")] + pub const VM_TARGET_NAME: &'static str = "riscv64"; /// The LLVM target triple. + #[cfg(not(feature = "riscv-64"))] pub const VM_TARGET_TRIPLE: &'static str = "riscv32-unknown-unknown-elf"; + #[cfg(feature = "riscv-64")] + pub const VM_TARGET_TRIPLE: &'static str = "riscv64-unknown-unknown-elf"; + + /// The LLVM target cpu + #[cfg(not(feature = "riscv-64"))] + pub const VM_TARGET_CPU: &'static str = "generic-rv32"; + #[cfg(feature = "riscv-64")] + pub const VM_TARGET_CPU: &'static str = "generic-rv64"; /// LLVM target features. #[cfg(feature = "riscv-zbb")] @@ -38,7 +50,7 @@ impl TargetMachine { .ok_or_else(|| anyhow::anyhow!("LLVM target machine `{}` not found", target.name()))? .create_target_machine( &inkwell::targets::TargetTriple::create(target.triple()), - "generic-rv32", + Self::VM_TARGET_CPU, Self::VM_FEATURES, optimizer_settings.level_back_end, inkwell::targets::RelocMode::PIC, diff --git a/crates/llvm-context/src/target_machine/target.rs b/crates/llvm-context/src/target_machine/target.rs index ffb4acf..91a029e 100644 --- a/crates/llvm-context/src/target_machine/target.rs +++ b/crates/llvm-context/src/target_machine/target.rs @@ -13,14 +13,20 @@ impl Target { /// Returns the target name. pub fn name(&self) -> &str { match self { + #[cfg(not(feature = "riscv-64"))] Self::PVM => "riscv32", + #[cfg(feature = "riscv-64")] + Self::PVM => "riscv64", } } /// Returns the target triple. pub fn triple(&self) -> &str { match self { + #[cfg(not(feature = "riscv-64"))] Self::PVM => "riscv32-unknown-unknown-elf", + #[cfg(feature = "riscv-64")] + Self::PVM => "riscv64-unknown-unknown-elf", } } @@ -37,7 +43,10 @@ impl FromStr for Target { fn from_str(string: &str) -> Result { match string { + #[cfg(not(feature = "riscv-64"))] "riscv32" => Ok(Self::PVM), + #[cfg(feature = "riscv-64")] + "riscv64" => Ok(Self::PVM), _ => Err(anyhow::anyhow!( "Unknown target `{}`. Supported targets: {:?}", string, @@ -50,7 +59,10 @@ impl FromStr for Target { impl std::fmt::Display for Target { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + #[cfg(not(feature = "riscv-64"))] Target::PVM => write!(f, "riscv32"), + #[cfg(feature = "riscv-64")] + Target::PVM => write!(f, "riscv64"), } } } diff --git a/crates/pallet-contracts-pvm-llapi/Cargo.toml b/crates/pallet-contracts-pvm-llapi/Cargo.toml index d80beb7..5b06be3 100644 --- a/crates/pallet-contracts-pvm-llapi/Cargo.toml +++ b/crates/pallet-contracts-pvm-llapi/Cargo.toml @@ -3,6 +3,9 @@ name = "pallet-contracts-pvm-llapi" version = "0.1.0" edition = "2021" +[features] +riscv-64 = [] + [dependencies] anyhow = { workspace = true } inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-0"] } \ No newline at end of file diff --git a/crates/pallet-contracts-pvm-llapi/build.rs b/crates/pallet-contracts-pvm-llapi/build.rs index 110e7f0..6a17ac7 100644 --- a/crates/pallet-contracts-pvm-llapi/build.rs +++ b/crates/pallet-contracts-pvm-llapi/build.rs @@ -1,13 +1,33 @@ use std::{env, fs, path::Path, process::Command}; +#[cfg(not(feature = "riscv-64"))] +const TARGET_TRIPLE_FLAG: &str = "-triple=riscv32-unknown-unknown-elf"; +#[cfg(feature = "riscv-64")] +const TARGET_TRIPLE_FLAG: &str = "-triple=riscv64-unknown-unknown-elf"; + +#[cfg(not(feature = "riscv-64"))] +const TARGET_FLAG: &str = "--target=riscv32"; +#[cfg(feature = "riscv-64")] +const TARGET_FLAG: &str = "--target=riscv64"; + +#[cfg(not(feature = "riscv-64"))] +const TARGET_ARCH_FLAG: &str = "-march=rv32em"; +#[cfg(feature = "riscv-64")] +const TARGET_ARCH_FLAG: &str = "-march=rv64em"; + +#[cfg(not(feature = "riscv-64"))] +const TARGET_ABI_FLAG: &str = "-mabi=ilp32e"; +#[cfg(feature = "riscv-64")] +const TARGET_ABI_FLAG: &str = "-mabi=lp64e"; + fn compile(bitcode_path: &str) { let output = Command::new("clang") .args([ - "--target=riscv32", + TARGET_FLAG, "-Xclang", - "-triple=riscv32-unknown-unknown-elf", - "-march=rv32em", - "-mabi=ilp32e", + TARGET_TRIPLE_FLAG, + TARGET_ARCH_FLAG, + TARGET_ABI_FLAG, "-fno-exceptions", "-ffreestanding", "-Wall",