mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-26 15:47:59 +00:00
Constructors and contract creation (#11)
Implement constructor logic and support create/create2 in the mock runtime Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
use inkwell::{
|
||||
builder::Builder,
|
||||
context::Context,
|
||||
types::{BasicType, StructType},
|
||||
values::{BasicValue, PointerValue},
|
||||
};
|
||||
|
||||
pub struct Spill<'ctx> {
|
||||
pointer: PointerValue<'ctx>,
|
||||
builder: &'ctx Builder<'ctx>,
|
||||
r#type: StructType<'ctx>,
|
||||
current_field: u32,
|
||||
}
|
||||
|
||||
impl<'ctx> Spill<'ctx> {
|
||||
pub fn new(
|
||||
builder: &'ctx Builder<'ctx>,
|
||||
r#type: StructType<'ctx>,
|
||||
name: &str,
|
||||
) -> anyhow::Result<Self> {
|
||||
Ok(Self {
|
||||
pointer: builder.build_alloca(r#type, name)?,
|
||||
builder,
|
||||
r#type,
|
||||
current_field: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next<V: BasicValue<'ctx>>(mut self, value: V) -> anyhow::Result<Self> {
|
||||
let field_pointer = self.builder.build_struct_gep(
|
||||
self.r#type,
|
||||
self.pointer,
|
||||
self.current_field,
|
||||
&format!("spill_parameter_{}", self.current_field),
|
||||
)?;
|
||||
self.builder.build_store(field_pointer, value)?;
|
||||
self.current_field += 1;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn skip(mut self) -> Self {
|
||||
self.current_field += 1;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn done(self) -> PointerValue<'ctx> {
|
||||
assert!(
|
||||
self.r#type
|
||||
.get_field_type_at_index(self.current_field)
|
||||
.is_none(),
|
||||
"there must not be any missing parameters"
|
||||
);
|
||||
|
||||
self.pointer
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// code_hash_ptr: u32,
|
||||
context.ptr_type(Default::default()).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.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// value_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// address_len_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// salt_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// salt_len: u32
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
],
|
||||
true,
|
||||
)
|
||||
}
|
||||
@@ -1,52 +1,2 @@
|
||||
//! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting
|
||||
//! with the `pallet-contracts` runtime API.
|
||||
//! At present, the contracts pallet requires blobs to export `call` and `deploy`,
|
||||
//! and offers a bunch of [runtime API methods][1]. The provided [module] implements
|
||||
//! those exports and imports.
|
||||
//! [0]: [https://crates.io/crates/polkavm]
|
||||
//! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html]
|
||||
|
||||
use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/polkavm_guest.rs"));
|
||||
|
||||
/// Creates a LLVM module from the [BITCODE].
|
||||
/// The module does:
|
||||
/// - Export the `call` and `deploy` functions (which are named thereafter).
|
||||
/// - Import (most) `pallet-contracts` runtime API functions.
|
||||
/// Returns `Error` if the bitcode fails to parse, which should never happen.
|
||||
pub fn module<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
) -> Result<Module<'context>, LLVMString> {
|
||||
let buf = MemoryBuffer::create_from_memory_range(BITCODE, module_name);
|
||||
Module::parse_bitcode_from_buffer(&buf, context)
|
||||
}
|
||||
|
||||
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
||||
pub fn min_stack_size<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
size: u32,
|
||||
) -> Module<'context> {
|
||||
let module = context.create_module(module_name);
|
||||
module.set_inline_assembly(&format!(
|
||||
".pushsection .polkavm_min_stack_size,\"\",@progbits
|
||||
.word {size}
|
||||
.popsection"
|
||||
));
|
||||
module
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||
let context = inkwell::context::Context::create();
|
||||
let module = crate::module(&context, "polkavm_guest").unwrap();
|
||||
|
||||
assert!(module.get_function("call").is_some());
|
||||
assert!(module.get_function("deploy").is_some());
|
||||
}
|
||||
}
|
||||
pub mod calling_convention;
|
||||
pub mod polkavm_guest;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting
|
||||
//! with the `pallet-contracts` runtime API.
|
||||
//! At present, the contracts pallet requires blobs to export `call` and `deploy`,
|
||||
//! and offers a bunch of [runtime API methods][1]. The provided [module] implements
|
||||
//! those exports and imports.
|
||||
//! [0]: [https://crates.io/crates/polkavm]
|
||||
//! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html]
|
||||
|
||||
use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/polkavm_guest.rs"));
|
||||
|
||||
/// Creates a LLVM module from the [BITCODE].
|
||||
/// The module does:
|
||||
/// - Export the `call` and `deploy` functions (which are named thereafter).
|
||||
/// - Import (most) `pallet-contracts` runtime API functions.
|
||||
/// Returns `Error` if the bitcode fails to parse, which should never happen.
|
||||
pub fn module<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
) -> Result<Module<'context>, LLVMString> {
|
||||
let buf = MemoryBuffer::create_from_memory_range(BITCODE, module_name);
|
||||
Module::parse_bitcode_from_buffer(&buf, context)
|
||||
}
|
||||
|
||||
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
||||
pub fn min_stack_size<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
size: u32,
|
||||
) -> Module<'context> {
|
||||
let module = context.create_module(module_name);
|
||||
module.set_inline_assembly(&format!(
|
||||
".pushsection .polkavm_min_stack_size,\"\",@progbits
|
||||
.word {size}
|
||||
.popsection"
|
||||
));
|
||||
module
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::polkavm_guest;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||
let context = inkwell::context::Context::create();
|
||||
let module = polkavm_guest::module(&context, "polkavm_guest").unwrap();
|
||||
|
||||
assert!(module.get_function("call").is_some());
|
||||
assert!(module.get_function("deploy").is_some());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user