mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 22:21:05 +00:00
runtime-api: pass call arguments in registers instead of spilling to stack (#174)
Companion to paritytech/polkadot-sdk#7319 Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(),
|
||||
argument_pointer.value,
|
||||
argument_type,
|
||||
arguments,
|
||||
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(),
|
||||
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();
|
||||
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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 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",
|
||||
)?;
|
||||
|
||||
let argument_pointer = context.builder().build_ptr_to_int(
|
||||
argument_pointer.value,
|
||||
context.xlen_type(),
|
||||
"instantiate_argument_pointer",
|
||||
)?;
|
||||
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")?)?;
|
||||
|
||||
Reference in New Issue
Block a user