Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime-api: pass call arguments in registers instead of spilling to stack #174

Merged
merged 2 commits into from
Jan 28, 2025
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## Unreleased

## v0.1.0-dev.9

This is a development pre-release.

### Added

### Changed
- Syscalls with more than 6 arguments now pack them into registers.

### Fixed

## v0.1.0-dev.8

This is a development pre-release.
Expand Down
748 changes: 366 additions & 382 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ cc = "1.0"
libc = "0.2.169"
tempfile = "3.8"
anyhow = "1.0"
semver = { version = "1.0", features = [ "serde" ] }
semver = { version = "1.0", features = ["serde"] }
itertools = "0.14"
serde = { version = "1.0", features = [ "derive" ] }
serde_json = { version = "1.0", features = [ "arbitrary_precision" ] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
regex = "1.10"
once_cell = "1.19"
num = "0.4.3"
Expand Down Expand Up @@ -73,7 +73,7 @@ assert_fs = "1.1.2"
# polkadot-sdk and friends
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.6", default-features = false }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "d62a90c8c729acd98c7e9a5cab9803b8b211ffc5" }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "4302f74f7874e6a894578731142a7b310a1449b0" }

# llvm
[workspace.dependencies.inkwell]
Expand Down
8 changes: 7 additions & 1 deletion crates/llvm-context/src/polkavm/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1339,11 +1339,17 @@ where
self.llvm.custom_width_int_type(bit_length as u32)
}

/// Returns the register witdh sized type.
/// 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)
}

/// 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)
}

/// Returns the sentinel pointer value.
pub fn sentinel_pointer(&self) -> Pointer<'ctx> {
let sentinel_pointer = self
Expand Down
122 changes: 67 additions & 55 deletions crates/llvm-context/src/polkavm/evm/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,39 +58,48 @@ where
};
let flags = context.xlen_type().const_int(flags as u64, false);

let argument_type = revive_runtime_api::calling_convention::call(context.llvm());
let argument_pointer = context.build_alloca_at_entry(argument_type, "call_arguments");
let arguments = &[
flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
deposit_pointer.value.as_basic_value_enum(),
value_pointer.value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(),
input_length.as_basic_value_enum(),
output_pointer.value.as_basic_value_enum(),
output_length_pointer.value.as_basic_value_enum(),
];
revive_runtime_api::calling_convention::spill(
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
argument_pointer.value,
argument_type,
arguments,
context.llvm(),
flags,
address_pointer.to_int(context),
"address_and_callee",
)?;
let deposit_and_value = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
deposit_pointer.to_int(context),
value_pointer.to_int(context),
"deposit_and_value",
)?;
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
input_length,
input_pointer.to_int(context),
"input_data",
)?;
let output_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
output_length_pointer.to_int(context),
output_pointer.to_int(context),
"output_data",
)?;

let name = revive_runtime_api::polkavm_imports::CALL;
let argument_pointer = context.builder().build_ptr_to_int(
argument_pointer.value,
context.xlen_type(),
"call_argument_pointer",
)?;
let success = context
.build_runtime_call(name, &[argument_pointer.into()])
.build_runtime_call(
name,
&[
flags_and_callee.into(),
context.register_type().const_all_ones().into(),
context.register_type().const_all_ones().into(),
deposit_and_value.into(),
input_data.into(),
output_data.into(),
],
)
.unwrap_or_else(|| panic!("{name} should return a value"))
.into_int_value();

Expand Down Expand Up @@ -144,38 +153,41 @@ where

let flags = context.xlen_type().const_int(0u64, false);

let argument_type = revive_runtime_api::calling_convention::delegate_call(context.llvm());
let argument_pointer = context.build_alloca_at_entry(argument_type, "delegate_call_arguments");
let arguments = &[
flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
deposit_pointer.value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(),
input_length.as_basic_value_enum(),
output_pointer.value.as_basic_value_enum(),
output_length_pointer.value.as_basic_value_enum(),
];
revive_runtime_api::calling_convention::spill(
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
flags,
address_pointer.to_int(context),
"address_and_callee",
)?;
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
argument_pointer.value,
argument_type,
arguments,
context.llvm(),
input_length,
input_pointer.to_int(context),
"input_data",
)?;
let output_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
output_length_pointer.to_int(context),
output_pointer.to_int(context),
"output_data",
)?;

let name = revive_runtime_api::polkavm_imports::DELEGATE_CALL;
let argument_pointer = context.builder().build_ptr_to_int(
argument_pointer.value,
context.xlen_type(),
"delegate_call_argument_pointer",
)?;
let success = context
.build_runtime_call(name, &[argument_pointer.into()])
.build_runtime_call(
name,
&[
flags_and_callee.into(),
context.register_type().const_all_ones().into(),
context.register_type().const_all_ones().into(),
deposit_pointer.to_int(context).into(),
input_data.into(),
output_data.into(),
],
)
.unwrap_or_else(|| panic!("{name} should return a value"))
.into_int_value();

Expand Down
65 changes: 27 additions & 38 deletions crates/llvm-context/src/polkavm/evm/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ where

let code_hash_pointer = context.build_heap_gep(input_offset, input_length)?;

let input_data_pointer = context.build_gep(
code_hash_pointer,
&[context
.xlen_type()
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false)],
context.byte_type(),
"input_ptr_parameter_offset",
);

let value_pointer = context.build_alloca_at_entry(context.value_type(), "transferred_value");
context.build_store(value_pointer, value)?;

Expand All @@ -56,40 +47,38 @@ where
let deposit_pointer = context.build_alloca_at_entry(context.word_type(), "deposit_pointer");
context.build_store(deposit_pointer, context.word_type().const_all_ones())?;

let argument_type = revive_runtime_api::calling_convention::instantiate(context.llvm());
let argument_pointer = context.build_alloca_at_entry(argument_type, "instantiate_arguments");
let arguments = &[
code_hash_pointer.value.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
context
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(),
deposit_pointer.value.as_basic_value_enum(),
value_pointer.value.as_basic_value_enum(),
input_data_pointer.value.as_basic_value_enum(),
input_length.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(),
salt_pointer.value.as_basic_value_enum(),
];
revive_runtime_api::calling_convention::spill(
let deposit_and_value = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
argument_pointer.value,
argument_type,
arguments,
context.llvm(),
deposit_pointer.to_int(context),
value_pointer.to_int(context),
"deposit_and_value",
)?;

let argument_pointer = context.builder().build_ptr_to_int(
argument_pointer.value,
context.xlen_type(),
"instantiate_argument_pointer",
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
input_length,
code_hash_pointer.to_int(context),
"input_data",
)?;
let address_and_salt = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
address_pointer.to_int(context),
salt_pointer.to_int(context),
"output_data",
)?;

context.build_runtime_call(
revive_runtime_api::polkavm_imports::INSTANTIATE,
&[argument_pointer.into()],
&[
context.register_type().const_all_ones().into(),
context.register_type().const_all_ones().into(),
deposit_and_value.into(),
input_data.into(),
context.register_type().const_all_ones().into(),
address_and_salt.into(),
],
);

let address = context.build_byte_swap(context.build_load(address_pointer, "address")?)?;
Expand Down
1 change: 1 addition & 0 deletions crates/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl ExtBuilder {
.unwrap();
pallet_balances::GenesisConfig::<Runtime> {
balances: self.balance_genesis_config,
dev_accounts: None,
}
.assimilate_storage(&mut t)
.unwrap();
Expand Down
1 change: 0 additions & 1 deletion crates/runner/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
pub type AccountId = pallet_revive::AccountId32Mapper<Runtime>;
pub type Block = frame_system::mocking::MockBlock<Runtime>;
pub type Hash = <Runtime as frame_system::Config>::Hash;
pub type EventRecord =

Check warning on line 14 in crates/runner/src/runtime.rs

View workflow job for this annotation

GitHub Actions / build-ubuntu-x86

type alias `EventRecord` is never used
frame_system::EventRecord<<Runtime as frame_system::Config>::RuntimeEvent, Hash>;

#[runtime]
Expand Down Expand Up @@ -87,6 +87,5 @@
type UploadOrigin = EnsureSigned<AccountId32>;
type InstantiateOrigin = EnsureSigned<AccountId32>;
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
type Debug = ();
type ChainId = ConstU64<420_420_420>;
}
Loading
Loading