mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-05-06 02:17:57 +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:
@@ -1,10 +1,4 @@
|
||||
use inkwell::{
|
||||
builder::Builder,
|
||||
context::Context,
|
||||
module::Module,
|
||||
types::{BasicType, StructType},
|
||||
values::{BasicValueEnum, PointerValue},
|
||||
};
|
||||
use inkwell::{builder::Builder, context::Context, module::Module, values::IntValue};
|
||||
|
||||
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
||||
pub fn min_stack_size<'context>(
|
||||
@@ -21,115 +15,23 @@ pub fn min_stack_size<'context>(
|
||||
module
|
||||
}
|
||||
|
||||
/// Helper for building function calls with stack spilled arguments.
|
||||
/// - `pointer`: points to a struct of the packed argument struct type
|
||||
/// - `type`: the packed argument struct type
|
||||
/// - `arguments`: a correctly ordered list of the struct field values
|
||||
pub fn spill<'ctx>(
|
||||
/// Helper for packing two 32 bit integer values into a 64 bit integer value.
|
||||
pub fn pack_hi_lo_reg<'ctx>(
|
||||
builder: &Builder<'ctx>,
|
||||
pointer: PointerValue<'ctx>,
|
||||
r#type: StructType<'ctx>,
|
||||
arguments: &[BasicValueEnum<'ctx>],
|
||||
) -> anyhow::Result<()> {
|
||||
for index in 0..r#type.get_field_types().len() {
|
||||
let field_pointer = builder.build_struct_gep(
|
||||
r#type,
|
||||
pointer,
|
||||
index as u32,
|
||||
&format!("spill_parameter_{}", index),
|
||||
)?;
|
||||
let field_value = arguments
|
||||
.get(index)
|
||||
.ok_or_else(|| anyhow::anyhow!("invalid index {index} for struct type {}", r#type))?;
|
||||
builder.build_store(field_pointer, *field_value)?;
|
||||
}
|
||||
context: &'ctx Context,
|
||||
hi: IntValue<'ctx>,
|
||||
lo: IntValue<'ctx>,
|
||||
name: &str,
|
||||
) -> anyhow::Result<IntValue<'ctx>> {
|
||||
assert_eq!(hi.get_type(), context.i32_type());
|
||||
assert_eq!(lo.get_type(), context.i32_type());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a packed struct argument type for the `instantiate` API.
|
||||
pub fn instantiate(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// code_hash_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// ref_time_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// proof_size_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// deposit_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// value_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// salt_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a packed struct argument type for the `call` API.
|
||||
pub fn call(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// flags: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr:
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// ref_time_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// proof_size_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// deposit_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// value_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a packed struct argument type for the `delegate_call` API.
|
||||
pub fn delegate_call(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// flags: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr:
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// ref_time_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// proof_size_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// deposit_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
let lo_part = builder.build_int_z_extend(lo, context.i64_type(), &format!("{name}_lo_part"))?;
|
||||
let hi_part = builder.build_int_z_extend(hi, context.i64_type(), &format!("{name}_hi_part"))?;
|
||||
let hi_part_shifted = builder.build_left_shift(
|
||||
hi_part,
|
||||
context.i64_type().const_int(32, false),
|
||||
&format!("{name}_hi_part_shifted"),
|
||||
)?;
|
||||
Ok(builder.build_or(hi_part_shifted, lo_part, name)?)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user