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
10 changes: 5 additions & 5 deletions src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ use crate::{
SEGMENT_ARENA_BUILTIN_SIZE,
},
native_panic,
runtime::{BLAKE_CALL_COUNT, BUILTIN_COSTS},
runtime::{BLAKE_CALL_COUNT, BOX_ARENA, BUILTIN_COSTS},
starknet::{handler::StarknetSyscallHandlerCallbacks, StarknetSyscallHandler},
types::TypeBuilder,
utils::{libc_free, BuiltinCosts, RangeExt},
utils::{BuiltinCosts, RangeExt},
values::Value,
};
use bumpalo::Bump;
Expand Down Expand Up @@ -151,7 +151,6 @@ fn invoke_dynamic(
#[cfg(feature = "with-cheatcode")]
syscall_handler.as_mut().map(|h| h as *mut _ as *mut ()),
);

// Generate argument list.
let mut iter = args.iter();
for item in function_signature.param_types.iter().filter_map(|type_id| {
Expand Down Expand Up @@ -365,6 +364,7 @@ fn invoke_dynamic(
pub(crate) struct InvocationGuard {
builtin_costs: BuiltinCosts,
blake_call_count: u64,
box_arena: Bump,
#[cfg(feature = "with-cheatcode")]
syscall_handler: Option<*mut ()>,
}
Expand All @@ -379,6 +379,7 @@ impl InvocationGuard {
Self {
builtin_costs: BUILTIN_COSTS.replace(builtin_costs),
blake_call_count: BLAKE_CALL_COUNT.with(|c| c.replace(0)),
box_arena: BOX_ARENA.with(|c| std::mem::replace(&mut *c.borrow_mut(), Bump::new())),
#[cfg(feature = "with-cheatcode")]
syscall_handler: syscall_handler.map(|ptr| {
let previous_value = crate::starknet::SYSCALL_HANDLER_VTABLE.get();
Expand All @@ -393,6 +394,7 @@ impl Drop for InvocationGuard {
fn drop(&mut self) {
BUILTIN_COSTS.set(self.builtin_costs);
BLAKE_CALL_COUNT.with(|c| c.set(self.blake_call_count));
BOX_ARENA.with(|c| std::mem::swap(&mut *c.borrow_mut(), &mut self.box_arena));
#[cfg(feature = "with-cheatcode")]
if let Some(previous_value) = self.syscall_handler {
crate::starknet::SYSCALL_HANDLER_VTABLE.set(previous_value);
Expand Down Expand Up @@ -436,7 +438,6 @@ fn parse_result(
let ptr =
return_ptr.unwrap_or_else(|| NonNull::new_unchecked(ret_registers[0] as *mut ()));
let value = Value::from_ptr(ptr, &info.ty, registry, true)?;
libc_free(ptr.cast().as_ptr());
Ok(value)
},
CoreTypeConcrete::EcPoint(_) | CoreTypeConcrete::EcState(_) => Ok(Value::from_ptr(
Expand Down Expand Up @@ -574,7 +575,6 @@ fn parse_result(
} else {
let ptr = NonNull::new_unchecked(ptr);
let value = Value::from_ptr(ptr, &info.ty, registry, true)?;
libc_free(ptr.as_ptr().cast());
Ok(value)
}
},
Expand Down
7 changes: 1 addition & 6 deletions src/libfuncs/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ pub fn build_span_from_tuple<'ctx, 'this>(
location,
)?)?;

// Move the data into the array and free the original tuple. Since the tuple and the array are
// Move the data into the array. Since the tuple and the array are
// represented the same way, a simple memcpy is enough.
entry.memcpy(
context,
Expand All @@ -212,11 +212,6 @@ pub fn build_span_from_tuple<'ctx, 'this>(
data_ptr,
array_len_bytes_val,
);
entry.append_operation(ReallocBindingsMeta::free(
context,
entry.argument(0)?.into(),
location,
)?);

// Allocate metadata struct: { refcount: u32, max_len: u32, data_ptr: *mut u8 }
let metadata_size = entry.const_int(context, location, calc_metadata_size(), 64)?;
Expand Down
25 changes: 21 additions & 4 deletions src/libfuncs/blake.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cairo_lang_sierra::{
extensions::{
blake::BlakeConcreteLibfunc,
core::{CoreLibfunc, CoreType},
core::{CoreLibfunc, CoreType, CoreTypeConcrete},
lib_func::SignatureOnlyConcreteLibfunc,
},
program_registry::ProgramRegistry,
Expand All @@ -15,6 +15,8 @@ use melior::{
use crate::{
error::{panic::ToNativeAssertError, Result},
metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage},
native_panic,
types::TypeBuilder,
};

use super::LibfuncHelper;
Expand Down Expand Up @@ -57,35 +59,50 @@ pub fn build<'ctx, 'this>(
#[allow(clippy::too_many_arguments)]
fn build_blake_operation<'ctx, 'this>(
context: &'ctx Context,
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
_info: &SignatureOnlyConcreteLibfunc,
info: &SignatureOnlyConcreteLibfunc,
finalize: bool,
) -> Result<()> {
let state_ptr = entry.arg(0)?;
let bytes_count = entry.arg(1)?;
let message = entry.arg(2)?;
let k_finalize = entry.const_int(context, location, finalize as u8, 1)?;

// The state parameter is `Box<[u32; 8]>`; we need the layout of the inner
// `[u32; 8]` to size the output slot, not the layout of the box pointer.
let CoreTypeConcrete::Box(box_info) =
registry.get_type(&info.signature.param_signatures[0].ty)?
else {
native_panic!("blake state parameter should be a Box");
};
let inner_layout = registry.get_type(&box_info.ty)?.layout(registry)?;
let size = entry.const_int(context, location, inner_layout.size(), 64)?;
let align = entry.const_int(context, location, inner_layout.align(), 64)?;

let runtime_bindings = metadata
.get_mut::<RuntimeBindingsMeta>()
.to_native_assert_error("runtime library should be available")?;

let out_state_ptr =
runtime_bindings.box_alloc(context, helper, entry, location, size, align)?;

runtime_bindings.libfunc_blake_compress(
context,
helper,
entry,
out_state_ptr,
state_ptr,
message,
bytes_count,
k_finalize,
location,
)?;

helper.br(entry, 0, &[state_ptr], location)?;
helper.br(entry, 0, &[out_state_ptr], location)?;

Ok(())
}
Expand Down
52 changes: 26 additions & 26 deletions src/libfuncs/box.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
//! # Box libfuncs
//!
//! A heap allocated value, which is internally a pointer that can't be null.
//!
//! Allocations are made from the per-invocation arena (`cairo_native__box_alloc` runtime
//! function) and are freed all at once when the program invocation completes. Individual
//! boxes are therefore never freed on unbox.

use std::alloc::Layout;

use super::LibfuncHelper;
use crate::{
error::Result,
metadata::{realloc_bindings::ReallocBindingsMeta, MetadataStorage},
metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage},
types::TypeBuilder,
utils::ProgramRegistryExt,
};
Expand All @@ -21,12 +25,11 @@ use cairo_lang_sierra::{
program_registry::ProgramRegistry,
};
use melior::{
dialect::{
llvm::{self, r#type::pointer, LoadStoreOptions},
ods,
},
dialect::llvm::{self, LoadStoreOptions},
helpers::{ArithBlockExt, BuiltinBlockExt},
ir::{attribute::IntegerAttribute, r#type::IntegerType, Block, BlockLike, Location, Value},
ir::{
attribute::IntegerAttribute, r#type::IntegerType, Block, BlockLike, Location, Module, Value,
},
Context,
};

Expand Down Expand Up @@ -69,37 +72,38 @@ pub fn build_into_box<'ctx, 'this>(
metadata: &mut MetadataStorage,
info: &SignatureAndTypeConcreteLibfunc,
) -> Result<()> {
if metadata.get::<ReallocBindingsMeta>().is_none() {
metadata.insert(ReallocBindingsMeta::new(context, helper));
}

let inner_type = registry.get_type(&info.ty)?;
let inner_layout = inner_type.layout(registry)?;

let ptr = into_box(context, entry, location, entry.arg(0)?, inner_layout)?;
let ptr = into_box(
context,
helper.module,
entry,
location,
entry.arg(0)?,
inner_layout,
metadata,
)?;

helper.br(entry, 0, &[ptr], location)
}

/// Receives a value and inserts it into a box
/// Allocate an arena slot and store `inner_val` into it, returning a pointer.
pub fn into_box<'ctx, 'this>(
context: &'ctx Context,
module: &Module<'ctx>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
inner_val: Value<'ctx, 'this>,
inner_layout: Layout,
metadata: &mut MetadataStorage,
) -> Result<Value<'ctx, 'this>> {
let value_len = entry.const_int(context, location, inner_layout.pad_to_align().size(), 64)?;
let ptr = entry
.append_operation(ods::llvm::mlir_zero(context, pointer(context, 0), location).into())
.result(0)?
.into();
let ptr = entry
.append_operation(ReallocBindingsMeta::realloc(
context, ptr, value_len, location,
)?)
.result(0)?
.into();
let size = entry.const_int(context, location, inner_layout.size(), 64)?;
let align = entry.const_int(context, location, inner_layout.align(), 64)?;

let rtb = metadata.get_or_insert_with(RuntimeBindingsMeta::default);
let ptr = rtb.box_alloc(context, module, entry, location, size, align)?;

entry.append_operation(llvm::store(
context,
Expand All @@ -125,8 +129,6 @@ pub fn build_unbox<'ctx, 'this>(
metadata: &mut MetadataStorage,
info: &SignatureAndTypeConcreteLibfunc,
) -> Result<()> {
metadata.get_or_insert_with(|| ReallocBindingsMeta::new(context, helper));

let value = unbox(
context, registry, entry, location, helper, metadata, &info.ty,
)?;
Expand Down Expand Up @@ -162,8 +164,6 @@ pub fn unbox<'ctx, 'this>(
.result(0)?
.into();

entry.append_operation(ReallocBindingsMeta::free(context, entry.arg(0)?, location)?);

Ok(value)
}

Expand Down
29 changes: 12 additions & 17 deletions src/libfuncs/const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use super::LibfuncHelper;
use crate::{
error::{Error, Result},
libfuncs::{r#enum::build_enum_value, r#struct::build_struct_value},
metadata::{realloc_bindings::ReallocBindingsMeta, MetadataStorage},
libfuncs::{r#box::into_box, r#enum::build_enum_value, r#struct::build_struct_value},
metadata::MetadataStorage,
native_panic,
types::TypeBuilder,
utils::{felt_to_unsigned, ProgramRegistryExt, RangeExt},
Expand All @@ -23,7 +23,7 @@ use cairo_lang_sierra::{
program_registry::ProgramRegistry,
};
use melior::{
dialect::llvm::{self, r#type::pointer},
dialect::llvm::{self},
helpers::{ArithBlockExt, BuiltinBlockExt, LlvmBlockExt},
ir::{r#type::IntegerType, Block, Location, Value},
Context,
Expand Down Expand Up @@ -59,10 +59,6 @@ pub fn build_const_as_box<'ctx, 'this>(
metadata: &mut MetadataStorage,
info: &ConstAsBoxConcreteLibfunc,
) -> Result<()> {
if metadata.get::<ReallocBindingsMeta>().is_none() {
metadata.insert(ReallocBindingsMeta::new(context, helper));
}

let const_type_outer = registry.get_type(&info.const_type)?;

// Create constant
Expand All @@ -78,16 +74,15 @@ pub fn build_const_as_box<'ctx, 'this>(
let const_ty = registry.get_type(&const_type.inner_ty)?;
let inner_layout = const_ty.layout(registry)?;

// Create box
let value_len = entry.const_int(context, location, inner_layout.pad_to_align().size(), 64)?;

let ptr = entry.append_op_result(llvm::zero(pointer(context, 0), location))?;
let ptr = entry.append_op_result(ReallocBindingsMeta::realloc(
context, ptr, value_len, location,
)?)?;

// Store constant in box
entry.store(context, location, ptr, value)?;
let ptr = into_box(
context,
helper.module,
entry,
location,
value,
inner_layout,
metadata,
)?;

helper.br(entry, 0, &[ptr], location)
}
Expand Down
28 changes: 10 additions & 18 deletions src/libfuncs/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ use super::LibfuncHelper;
use crate::{
error::{panic::ToNativeAssertError, Error, Result},
libfuncs::r#box::into_box,
metadata::{
enum_snapshot_variants::EnumSnapshotVariantsMeta, realloc_bindings::ReallocBindingsMeta,
MetadataStorage,
},
metadata::{enum_snapshot_variants::EnumSnapshotVariantsMeta, MetadataStorage},
native_assert, native_panic,
types::TypeBuilder,
utils::ProgramRegistryExt,
Expand Down Expand Up @@ -592,9 +589,6 @@ pub fn build_boxed_match<'ctx, 'this>(
metadata: &mut MetadataStorage,
info: &EnumBoxedMatchConcreteLibfunc,
) -> Result<()> {
metadata.get_or_insert_with(|| ReallocBindingsMeta::new(context, helper));

// Get the variant type IDs from the concrete libfunc info
let variant_ids = &info.variants;

match variant_ids.len() {
Expand Down Expand Up @@ -626,7 +620,6 @@ pub fn build_boxed_match<'ctx, 'this>(
variant_ids,
)?;

// Tag is at offset 0 in the box, so load it directly from the pointer
let tag_val = entry.load(context, location, entry.arg(0)?, tag_ty)?;

let default_block = helper.append_block(Block::new(&[]));
Expand Down Expand Up @@ -666,7 +659,6 @@ pub fn build_boxed_match<'ctx, 'this>(
default_block.append_operation(llvm::unreachable(location));
}

// Enum variants.
for (i, (block, (payload_ty, payload_layout))) in
variant_blocks.into_iter().zip(variant_tys).enumerate()
{
Expand All @@ -683,13 +675,6 @@ pub fn build_boxed_match<'ctx, 'this>(
block.load(context, location, ptr, payload_ty)?
};

// Free the input box
block.append_operation(ReallocBindingsMeta::free(
context,
entry.arg(0)?,
location,
)?);

// Get the output variant type layout for boxing
let output_variant_type_id = &info.branch_signatures()[i].vars[0].ty;
let CoreTypeConcrete::Box(output_box_info) =
Expand All @@ -704,8 +689,15 @@ pub fn build_boxed_match<'ctx, 'this>(
&output_box_info.ty,
)?;

// Box the payload
let boxed_payload = into_box(context, block, location, payload_val, output_layout)?;
let boxed_payload = into_box(
context,
helper.module,
block,
location,
payload_val,
output_layout,
metadata,
)?;

helper.br(block, i, &[boxed_payload], location)?;
}
Expand Down
Loading
Loading