Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,849 changes: 2,098 additions & 1,751 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,25 @@ revive-yul = { version = "1.0.0", path = "crates/yul" }
hex = "0.4.3"
cc = "1.2"
libc = "0.2.172"
tempfile = "3.23"
tempfile = "3.27"
anyhow = "1.0"
semver = { version = "1.0", features = ["serde"] }
itertools = "0.14"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
regex = "1.12"
num = "0.4.3"
sha1 = "0.10"
sha3 = "0.10"
sha1 = "0.11"
sha3 = "0.11"
thiserror = "2.0"
which = "8.0"
path-slash = "0.2"
rayon = "1.11"
clap = { version = "4", default-features = false, features = ["derive"] }
polkavm-common = "0.31.0"
polkavm-linker = "0.31.0"
polkavm-disassembler = "0.31.0"
polkavm = "0.31.0"
polkavm-common = "0.33.0"
polkavm-linker = "0.33.0"
polkavm-disassembler = "0.33.0"
polkavm = "0.33.0"
alloy-primitives = { version = "1.4", features = ["serde"] }
alloy-sol-types = "1.4"
alloy-genesis = "1.1.2"
Expand All @@ -66,19 +66,19 @@ flate2 = "1.1"
fs_extra = "1.3"
num_cpus = "1"
tar = "0.4"
toml = "0.9"
toml = "1"
assert_cmd = "2"
assert_fs = "1.1"
normpath = "1.5"

# polkadot-sdk and friends
codec = { version = "3.7.5", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.6", default-features = false }
polkadot-sdk = { version = "=2507.4.0" }
polkadot-sdk = { version = "=2603.0.0" }

# llvm
[workspace.dependencies.inkwell]
version = "0.8.0"
version = "0.9.0"
default-features = false
features = ["serde", "llvm21-1", "no-libffi-linking", "target-riscv"]

Expand Down
2 changes: 1 addition & 1 deletion crates/integration/codesize.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Baseline": 870,
"Computation": 2418,
"DivisionArithmetics": 9327,
"DivisionArithmetics": 9404,
"ERC20": 17160,
"Events": 1662,
"FibonacciIterative": 1427,
Expand Down
27 changes: 23 additions & 4 deletions crates/llvm-context/src/polkavm/context/function/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! The LLVM intrinsic functions.

use std::num::NonZeroU32;

use inkwell::types::BasicType;

use crate::polkavm::context::function::declaration::Declaration as FunctionDeclaration;
Expand Down Expand Up @@ -37,8 +39,17 @@ impl<'ctx> Intrinsics<'ctx> {
module: &inkwell::module::Module<'ctx>,
) -> Self {
let void_type = llvm.void_type();
let word_type = llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32);
let address_type = llvm.custom_width_int_type(revive_common::BIT_LENGTH_ETH_ADDRESS as u32);
let word_type = llvm
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_WORD as u32).expect("const is non-zero"),
)
.expect("valid integer width");
let address_type = llvm
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_ETH_ADDRESS as u32)
.expect("const is non-zero"),
)
.expect("valid integer width");

let trap = Self::declare(
llvm,
Expand Down Expand Up @@ -94,13 +105,21 @@ impl<'ctx> Intrinsics<'ctx> {
llvm: &'ctx inkwell::context::Context,
name: &str,
) -> Vec<inkwell::types::BasicTypeEnum<'ctx>> {
let word_type = llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32);
let word_type = llvm
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_WORD as u32).expect("const is non-zero"),
)
.expect("valid integer width");

match name {
_ if name == Self::FUNCTION_BYTE_SWAP_WORD => vec![word_type.as_basic_type_enum()],
_ if name == Self::FUNCTION_BYTE_SWAP_ETH_ADDRESS => {
vec![llvm
.custom_width_int_type(revive_common::BIT_LENGTH_ETH_ADDRESS as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_ETH_ADDRESS as u32)
.expect("const is non-zero"),
)
.expect("valid integer width")
.as_basic_type_enum()]
}
_ if name == Self::FUNCTION_COUNT_LEADING_ZEROS => {
Expand Down
33 changes: 27 additions & 6 deletions crates/llvm-context/src/polkavm/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::num::NonZeroU32;
use std::rc::Rc;

use inkwell::debug_info::AsDIScope;
Expand Down Expand Up @@ -1208,23 +1209,37 @@ impl<'ctx> Context<'ctx> {
/// Returns the default byte type.
pub fn byte_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_BYTE as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_BYTE as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Returns the integer type of the specified bit-length.
pub fn integer_type(&self, bit_length: usize) -> inkwell::types::IntType<'ctx> {
self.llvm.custom_width_int_type(bit_length as u32)
self.llvm
.custom_width_int_type(
NonZeroU32::new(bit_length as u32).expect("bit length is non-zero"),
)
.expect("valid integer width")
}

/// Returns the XLEN witdh sized type.
pub fn xlen_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm.custom_width_int_type(crate::polkavm::XLEN as u32)
self.llvm
.custom_width_int_type(
NonZeroU32::new(crate::polkavm::XLEN as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Returns the PolkaVM native register width sized type.
pub fn register_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_X64 as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_X64 as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Returns the sentinel pointer value.
Expand All @@ -1244,13 +1259,19 @@ impl<'ctx> Context<'ctx> {
/// Returns the runtime value width sized type.
pub fn value_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_VALUE as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_VALUE as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Returns the default word type.
pub fn word_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_WORD as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Returns the array type with the specified length.
Expand Down
25 changes: 16 additions & 9 deletions crates/llvm-context/src/polkavm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The LLVM context library.

use std::collections::BTreeMap;
use std::num::NonZeroU32;

use crate::debug_config::DebugConfig;
use crate::optimizer::settings::Settings as OptimizerSettings;
Expand Down Expand Up @@ -80,7 +81,7 @@ pub fn link(
Ok(format @ ObjectFormat::PVM) => (bytecode.to_vec(), format),
Ok(ObjectFormat::ELF) => {
let symbols = build_symbols(linker_symbols, factory_dependencies)?;
let bytecode_linked = ElfLinker::setup()?.link(bytecode, symbols.as_slice())?;
let bytecode_linked = ElfLinker::setup()?.link(bytecode, &symbols)?;
polkavm_linker(&bytecode_linked, strip_binary)
.map(|pvm| (pvm, ObjectFormat::PVM))
.unwrap_or_else(|error| {
Expand All @@ -105,11 +106,17 @@ pub fn link(
pub fn build_symbols(
linker_symbols: &BTreeMap<String, [u8; BYTE_LENGTH_ETH_ADDRESS]>,
factory_dependencies: &BTreeMap<String, [u8; BYTE_LENGTH_WORD]>,
) -> anyhow::Result<inkwell::memory_buffer::MemoryBuffer> {
) -> anyhow::Result<Vec<u8>> {
let context = inkwell::context::Context::create();
let module = context.create_module("symbols");
let word_type = context.custom_width_int_type(BIT_LENGTH_WORD as u32);
let address_type = context.custom_width_int_type(BIT_LENGTH_ETH_ADDRESS as u32);
let word_type = context
.custom_width_int_type(NonZeroU32::new(BIT_LENGTH_WORD as u32).expect("const is non-zero"))
.expect("valid integer width");
let address_type = context
.custom_width_int_type(
NonZeroU32::new(BIT_LENGTH_ETH_ADDRESS as u32).expect("const is non-zero"),
)
.expect("valid integer width");

for (name, value) in linker_symbols {
let global_value = module.add_global(address_type, Default::default(), name);
Expand Down Expand Up @@ -137,11 +144,11 @@ pub fn build_symbols(
);
}

Ok(
PolkaVMTargetMachine::new(PolkaVMTarget::PVM, &OptimizerSettings::none())?
.write_to_memory_buffer(&module)
.expect("ICE: the symbols module should be valid"),
)
let target_machine = PolkaVMTargetMachine::new(PolkaVMTarget::PVM, &OptimizerSettings::none())?;
let buffer = target_machine
.write_to_memory_buffer(&module)
.expect("ICE: the symbols module should be valid");
Ok(buffer.as_slice().to_vec())
}
/// Implemented by items which are translated into LLVM IR.
pub trait WriteLLVM {
Expand Down
6 changes: 3 additions & 3 deletions crates/llvm-context/src/target_machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ impl TargetMachine {
}

/// Writes the LLVM module to a memory buffer.
pub fn write_to_memory_buffer(
pub fn write_to_memory_buffer<'ctx>(
&self,
module: &inkwell::module::Module,
) -> Result<inkwell::memory_buffer::MemoryBuffer, inkwell::support::LLVMString> {
module: &inkwell::module::Module<'ctx>,
) -> Result<inkwell::memory_buffer::MemoryBuffer<'ctx>, inkwell::support::LLVMString> {
match self.target {
Target::PVM => self
.target_machine
Expand Down
11 changes: 6 additions & 5 deletions crates/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,12 @@ impl ExtBuilder {
.unwrap();

pallet_revive::GenesisConfig::<Runtime> {
debug_settings: Some(DebugSettings::new(
true, // allow unlimited contract size
true, // bypass EIP 3607
true, // enable PVM logs
)),
debug_settings: Some(
DebugSettings::default()
.set_allow_unlimited_contract_size(true)
.set_bypass_eip_3607(true)
.set_enable_pvm_logs(true),
),
..Default::default()
}
.assimilate_storage(&mut t)
Expand Down
2 changes: 0 additions & 2 deletions crates/runner/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ impl pallet_balances::Config for Runtime {
impl pallet_timestamp::Config for Runtime {}

parameter_types! {
pub const UnstableInterface: bool = true;
pub const DebugFlag: bool = true;
pub const DepositPerByte: Balance = 1;
pub const DepositPerItem: Balance = 2;
Expand All @@ -81,7 +80,6 @@ impl pallet_revive::Config for Runtime {
type AddressMapper = AccountId32Mapper<Self>;
type RuntimeMemory = ConstU32<{ 512 * 1024 * 1024 }>;
type PVFMemory = ConstU32<{ 1024 * 1024 * 1024 }>;
type UnsafeUnstableInterface = UnstableInterface;
type UploadOrigin = EnsureSigned<Self::AccountId>;
type InstantiateOrigin = EnsureSigned<Self::AccountId>;
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
Expand Down
4 changes: 2 additions & 2 deletions crates/runner/src/specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ impl Specs {
code,
data,
salt.0,
ExecConfig::new_substrate_tx(),
&ExecConfig::new_substrate_tx(),
);
results.push(CallResult::Instantiate {
result,
Expand Down Expand Up @@ -495,7 +495,7 @@ impl Specs {
deposit_limit: storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
},
data,
ExecConfig::new_substrate_tx(),
&ExecConfig::new_substrate_tx(),
);
results.push(CallResult::Exec {
result,
Expand Down
11 changes: 9 additions & 2 deletions crates/runtime-api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,17 @@ fn build_module(source_path: &str, bitcode_path: &str, rust_file: &str) {
let lib = Path::new(&out_dir).join(bitcode_path);
compile(source_path, lib.to_str().expect("$OUT_DIR should be UTF-8"));

let bitcode = fs::read(lib).expect("bitcode should have been built");
// `inkwell::MemoryBuffer::create_from_memory_range` requires a trailing nul byte
// (it subtracts one from the length to drop the terminator), so we embed the bitcode
// with an extra nul byte appended.
let mut bitcode = fs::read(lib).expect("bitcode should have been built");
bitcode.push(0);
let padded_name = format!("{bitcode_path}.nul");
let padded_path = Path::new(&out_dir).join(&padded_name);
fs::write(&padded_path, &bitcode).expect("should be able to write in $OUT_DIR");
let len = bitcode.len();
let src_path = Path::new(&out_dir).join(rust_file);
let src = format!("pub static BITCODE: &[u8; {len}] = include_bytes!(\"{bitcode_path}\");");
let src = format!("pub static BITCODE: &[u8; {len}] = include_bytes!(\"{padded_name}\");");
fs::write(src_path, src).expect("should be able to write in $OUT_DIR");
}

Expand Down
13 changes: 11 additions & 2 deletions crates/runtime-api/src/immutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
//!
//! [0]: https://llvm.org/docs/LangRef.html#global-variables

use std::num::NonZeroU32;

/// The immutable data module name.
pub static MODULE_NAME: &str = "__evm_immutables";
/// The immutable data global pointer.
Expand All @@ -28,13 +30,20 @@ pub static IMMUTABLE_DATA_MAX_SIZE: u32 = 4 * 1024;
/// Returns the immutable data global type.
pub fn data_type(context: &inkwell::context::Context, size: u32) -> inkwell::types::ArrayType<'_> {
context
.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32)
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_WORD as u32).expect("const is non-zero"),
)
.expect("valid integer width")
.array_type(size)
}

/// Returns the immutable data size global type.
pub fn size_type(context: &inkwell::context::Context) -> inkwell::types::IntType<'_> {
context.custom_width_int_type(revive_common::BIT_LENGTH_X32 as u32)
context
.custom_width_int_type(
NonZeroU32::new(revive_common::BIT_LENGTH_X32 as u32).expect("const is non-zero"),
)
.expect("valid integer width")
}

/// Creates a LLVM module with the immutable data and its `size` in bytes.
Expand Down
11 changes: 9 additions & 2 deletions crates/stdlib/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ fn main() {
"failed to assemble the stdlib: {output:?}"
);

let bitcode = fs::read(bitcode_path).expect("bitcode should have been built");
// `inkwell::MemoryBuffer::create_from_memory_range` requires a trailing nul byte
// (it subtracts one from the length to drop the terminator), so we embed the bitcode
// with an extra nul byte appended.
let mut bitcode = fs::read(bitcode_path).expect("bitcode should have been built");
bitcode.push(0);
let padded_lib = "stdlib_nul.bc";
let padded_path = Path::new(&out_dir).join(padded_lib);
fs::write(&padded_path, &bitcode).expect("should be able to write in $OUT_DIR");
let len = bitcode.len();
let src_path = Path::new(&out_dir).join("stdlib.rs");
let src = format!("pub static BITCODE: &[u8; {len}] = include_bytes!(\"{lib}\");");
let src = format!("pub static BITCODE: &[u8; {len}] = include_bytes!(\"{padded_lib}\");");
fs::write(src_path, src).expect("should be able to write in $OUT_DIR");

println!("cargo:rerun-if-changed=stdlib.ll");
Expand Down
8 changes: 4 additions & 4 deletions js/emscripten/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
"build:package": "node ./build.js"
},
"devDependencies": {
"@playwright/test": "^1.49.1",
"@playwright/test": "^1.59.1",
"chai": "^5.1.2",
"http-server": "^14.1.1",
"mocha": "^11.0.1",
"prettier": "^3.4.2",
"terser": "^5.37.0"
"mocha": "^11.7.5",
"prettier": "^3.8.2",
"terser": "^5.46.1"
}
}
Loading
Loading