From ebfa9a116d03618e90fc52773e73958b179dd775 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Fri, 15 Nov 2024 18:18:29 -0300 Subject: [PATCH 01/11] Add more runners (#934) * Add more runners * Add blocks in 900000 * Change blocks * Change blocks --- .github/workflows/daily.yml | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 274904a9f..afc85ace7 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -31,6 +31,36 @@ jobs: - 747000 - 748000 - 749000 + - 800000 + - 800050 + - 800100 + - 800150 + - 800200 + - 800250 + - 800300 + - 800350 + - 800400 + - 800450 + - 800500 + - 800550 + - 800600 + - 800650 + - 800700 + - 800750 + - 800800 + - 800850 + - 800900 + - 800950 + - 900000 + - 900100 + - 900200 + - 900300 + - 900400 + - 900500 + - 900600 + - 900700 + - 900800 + - 900900 runner: - native - vm @@ -120,6 +150,36 @@ jobs: - 747000 - 748000 - 749000 + - 800000 + - 800050 + - 800100 + - 800150 + - 800200 + - 800250 + - 800300 + - 800350 + - 800400 + - 800450 + - 800500 + - 800550 + - 800600 + - 800650 + - 800700 + - 800750 + - 800800 + - 800850 + - 800900 + - 800950 + - 900000 + - 900100 + - 900200 + - 900300 + - 900400 + - 900500 + - 900600 + - 900700 + - 900800 + - 900900 fail-fast: false defaults: run: From f6b37468bedb4e936017bfa95c2a0a3158305beb Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Tue, 19 Nov 2024 07:09:11 -0300 Subject: [PATCH 02/11] Remove asserts in libfuncs (#921) --- src/libfuncs/array.rs | 4 ++-- src/libfuncs/bounded_int.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index 4c7b09476..9fc2d2b76 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -1325,7 +1325,7 @@ pub fn build_slice<'ctx, 'this>( &info.signature.param_signatures[1].ty, )?; - // The following operation will because an array always has a drop implementation, + // The metadata get will never fail because an array always has a drop implementation, // which at this point is always inserted thanks to the `build_type()` just above. metadata .get::() @@ -1660,7 +1660,7 @@ pub fn build_tuple_from_span<'ctx, 'this>( &info.signature.param_signatures[0].ty, )?; - // The following operation will because an array always has a drop implementation, + // The metadata get will never fail because an array always has a drop implementation, // which at this point is always inserted thanks to the `build_type()` just above. metadata .get::() diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index f4ccc2f69..ead9eab18 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -115,11 +115,11 @@ fn build_add<'ctx, 'this>( let compute_ty = IntegerType::new(context, compute_range.offset_bit_width()).into(); // Zero-extend operands into the computation range. - assert!( + native_assert!( compute_range.offset_bit_width() >= lhs_width, "the lhs_range bit_width must be less or equal than the compute_range" ); - assert!( + native_assert!( compute_range.offset_bit_width() >= rhs_width, "the rhs_range bit_width must be less or equal than the compute_range" ); @@ -243,11 +243,11 @@ fn build_sub<'ctx, 'this>( let compute_ty = IntegerType::new(context, compute_range.offset_bit_width()).into(); // Zero-extend operands into the computation range. - assert!( + native_assert!( compute_range.offset_bit_width() >= lhs_width, "the lhs_range bit_width must be less or equal than the compute_range" ); - assert!( + native_assert!( compute_range.offset_bit_width() >= rhs_width, "the rhs_range bit_width must be less or equal than the compute_range" ); @@ -372,11 +372,11 @@ fn build_mul<'ctx, 'this>( let compute_ty = IntegerType::new(context, compute_range.zero_based_bit_width()).into(); // Zero-extend operands into the computation range. - assert!( + native_assert!( compute_range.offset_bit_width() >= lhs_width, "the lhs_range bit_width must be less or equal than the compute_range" ); - assert!( + native_assert!( compute_range.offset_bit_width() >= rhs_width, "the rhs_range bit_width must be less or equal than the compute_range" ); @@ -500,11 +500,11 @@ fn build_divrem<'ctx, 'this>( let compute_ty = IntegerType::new(context, compute_range.zero_based_bit_width()).into(); // Zero-extend operands into the computation range. - assert!( + native_assert!( compute_range.offset_bit_width() >= lhs_width, "the lhs_range bit_width must be less or equal than the compute_range" ); - assert!( + native_assert!( compute_range.offset_bit_width() >= rhs_width, "the rhs_range bit_width must be less or equal than the compute_range" ); @@ -756,7 +756,7 @@ fn build_wrap_non_zero<'ctx, 'this>( .get_type(&info.signature.param_signatures[0].ty)? .integer_range(registry)?; - assert!( + native_assert!( src_range.lower > BigInt::ZERO || BigInt::ZERO >= src_range.upper, "value must not be zero" ); From 69826a02329adf8f31be395b169cab043e51501d Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 19 Nov 2024 07:11:32 -0300 Subject: [PATCH 03/11] Remove panic in metadata (#904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add lints * Remove panic from AotExecutor * Remove panic from jit * Add panic lint * Add comment * Remove lint * Fix clippy * remove unwraps (realloc ones remaning) * remove more unwraps * fix error * error message more expressive * error message more expressive * remove free and alloc unwraps * remove free and alloc unwraps * format * remove more unwraps * format * remove more panics * remove more panics * better error message * format * changes * changes * better error message * better error message * format * clippy * format --------- Co-authored-by: Julián González Calderón --- src/executor/contract.rs | 2 +- src/libfuncs/array.rs | 24 ++++++------- src/libfuncs/box.rs | 4 +-- src/libfuncs/const.rs | 2 +- src/libfuncs/felt252_dict_entry.rs | 2 +- src/metadata.rs | 25 +++++++------ src/metadata/auto_breakpoint.rs | 2 +- src/metadata/debug_utils.rs | 2 +- src/metadata/drop_overrides.rs | 11 ++++-- src/metadata/dup_overrides.rs | 11 ++++-- src/metadata/gas.rs | 21 +++++++---- src/metadata/realloc_bindings.rs | 8 ++--- src/metadata/runtime_bindings.rs | 56 ++++++++++++++++++++---------- src/types/array.rs | 4 +-- src/types/box.rs | 4 +-- src/types/felt252_dict.rs | 2 +- src/types/nullable.rs | 4 +-- src/types/starknet.rs | 4 +-- 18 files changed, 115 insertions(+), 73 deletions(-) diff --git a/src/executor/contract.rs b/src/executor/contract.rs index b002c414b..404d336e3 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -157,7 +157,7 @@ impl AotContractExecutor { let initial_gas_costs = { let gas_meta: &GasMetadata = metadata.get().unwrap(); - gas_meta.initial_required_gas_for_entry_points() + gas_meta.initial_required_gas_for_entry_points()? }; let mut infos = BTreeMap::new(); diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index 9fc2d2b76..d7d1ae97d 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -294,7 +294,7 @@ pub fn build_append<'ctx, 'this>( ptr, realloc_size, location, - ))?; + )?)?; // No need to memmove, guaranteed by the fact that if we needed to memmove we'd have gone // through the memmove block instead of reallocating. @@ -495,7 +495,7 @@ pub fn build_get<'ctx, 'this>( )?; let target_ptr = valid_block.append_op_result(ReallocBindingsMeta::realloc( context, target_ptr, elem_size, location, - ))?; + )?)?; assert_nonnull( context, valid_block, @@ -587,7 +587,7 @@ pub fn build_get<'ctx, 'this>( } _ => {} } - valid_block.append_operation(ReallocBindingsMeta::free(context, ptr, location)); + valid_block.append_operation(ReallocBindingsMeta::free(context, ptr, location)?); valid_block.append_operation(helper.br(0, &[range_check, target_ptr], location)); } @@ -685,7 +685,7 @@ pub fn build_pop_front<'ctx, 'this>( )?; let target_ptr = valid_block.append_op_result(ReallocBindingsMeta::realloc( context, target_ptr, elem_size, location, - ))?; + )?)?; assert_nonnull( context, valid_block, @@ -785,7 +785,7 @@ pub fn build_pop_front_consume<'ctx, 'this>( )?; let target_ptr = valid_block.append_op_result(ReallocBindingsMeta::realloc( context, target_ptr, elem_size, location, - ))?; + )?)?; assert_nonnull( context, valid_block, @@ -911,7 +911,7 @@ pub fn build_snapshot_pop_back<'ctx, 'this>( )?; let target_ptr = valid_block.append_op_result(ReallocBindingsMeta::realloc( context, target_ptr, elem_size, location, - ))?; + )?)?; assert_nonnull( context, valid_block, @@ -1032,7 +1032,7 @@ pub fn build_snapshot_multi_pop_front<'ctx, 'this>( null_ptr, popped_size_value, location, - ))? + )?)? }; valid_block.memcpy(context, location, popped_ptr, return_ptr, popped_size_value); @@ -1161,7 +1161,7 @@ pub fn build_snapshot_multi_pop_back<'ctx, 'this>( null_ptr, popped_size_value, location, - ))? + )?)? }; valid_block.memcpy(context, location, popped_ptr, return_ptr, popped_size_value); @@ -1372,7 +1372,7 @@ pub fn build_span_from_tuple<'ctx, 'this>( context, entry.argument(0)?.into(), location, - )); + )?); let fields = struct_type_info.fields().expect("should have fields"); let (field_ty, field_layout) = @@ -1411,7 +1411,7 @@ pub fn build_span_from_tuple<'ctx, 'this>( let ptr = entry.append_op_result(ReallocBindingsMeta::realloc( context, ptr, total_size, location, - ))?; + )?)?; for (i, _) in fields.iter().enumerate() { let value: Value = entry.extract_value(context, location, container, field_ty, i)?; @@ -1611,7 +1611,7 @@ pub fn build_tuple_from_span<'ctx, 'this>( .append_op_result(llvm::zero(llvm::r#type::pointer(context, 0), location))?; let box_ptr = block_clone.append_op_result(ReallocBindingsMeta::realloc( context, box_ptr, tuple_len, location, - ))?; + )?)?; let elem_offset = block_clone.append_op_result(arith::extui( array_start, @@ -1644,7 +1644,7 @@ pub fn build_tuple_from_span<'ctx, 'this>( .into(), ); - block_clone.append_operation(ReallocBindingsMeta::free(context, array_ptr, location)); + block_clone.append_operation(ReallocBindingsMeta::free(context, array_ptr, location)?); block_clone.append_operation(helper.br(0, &[box_ptr], location)); } diff --git a/src/libfuncs/box.rs b/src/libfuncs/box.rs index 9150162b5..897e5d023 100644 --- a/src/libfuncs/box.rs +++ b/src/libfuncs/box.rs @@ -86,7 +86,7 @@ pub fn build_into_box<'ctx, 'this>( let ptr = entry .append_operation(ReallocBindingsMeta::realloc( context, ptr, value_len, location, - )) + )?) .result(0)? .into(); @@ -142,7 +142,7 @@ pub fn build_unbox<'ctx, 'this>( context, entry.argument(0)?.into(), location, - )); + )?); entry.append_operation(helper.br(0, &[value], location)); Ok(()) diff --git a/src/libfuncs/const.rs b/src/libfuncs/const.rs index a21e8802f..a51ac34e7 100644 --- a/src/libfuncs/const.rs +++ b/src/libfuncs/const.rs @@ -83,7 +83,7 @@ pub fn build_const_as_box<'ctx, 'this>( 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)?; diff --git a/src/libfuncs/felt252_dict_entry.rs b/src/libfuncs/felt252_dict_entry.rs index 3515a796e..6b9e4171b 100644 --- a/src/libfuncs/felt252_dict_entry.rs +++ b/src/libfuncs/felt252_dict_entry.rs @@ -259,7 +259,7 @@ pub fn build_finalize<'ctx, 'this>( let value_len = block_vacant.const_int(context, location, value_layout.size(), 64)?; let value_ptr = block_vacant.append_op_result(ReallocBindingsMeta::realloc( context, null_ptr, value_len, location, - ))?; + )?)?; block_vacant.store(context, location, value_ptr_ptr, value_ptr)?; block_vacant.append_operation(cf::br(block_final, &[value_ptr], location)); diff --git a/src/metadata.rs b/src/metadata.rs index f75a1cdcb..6f5038516 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -61,9 +61,11 @@ impl MetadataStorage { where T: Any, { - self.entries - .remove(&TypeId::of::()) - .map(|meta| *(Box::<(dyn Any + 'static)>::downcast::(meta).unwrap())) + self.entries.remove(&TypeId::of::()).map(|meta| { + *(Box::<(dyn Any + 'static)>::downcast::(meta).expect( + "attempt to downcast a boxed value to a type which does not match the actual", + )) + }) } /// Retrieve a reference to some metadata. @@ -74,9 +76,11 @@ impl MetadataStorage { where T: Any, { - self.entries - .get(&TypeId::of::()) - .map(|meta| meta.downcast_ref::().unwrap()) + self.entries.get(&TypeId::of::()).map(|meta| { + meta.downcast_ref::().expect( + "attempt to downcast a boxed value to a type which does not match the actual", + ) + }) } /// Retrieve a mutable reference to some metadata. @@ -87,9 +91,10 @@ impl MetadataStorage { where T: Any, { - self.entries - .get_mut(&TypeId::of::()) - .map(|meta| meta.downcast_mut::().unwrap()) + self.entries.get_mut(&TypeId::of::()).map(|meta| { + meta.downcast_mut::() + .expect("the given type does not match the actual") + }) } pub fn get_or_insert_with(&mut self, meta_gen: impl FnOnce() -> T) -> &mut T @@ -100,7 +105,7 @@ impl MetadataStorage { .entry(TypeId::of::()) .or_insert_with(|| Box::new(meta_gen())) .downcast_mut::() - .unwrap() + .expect("the given type does not match the actual") } } diff --git a/src/metadata/auto_breakpoint.rs b/src/metadata/auto_breakpoint.rs index 07612c4fd..776c1bc8e 100644 --- a/src/metadata/auto_breakpoint.rs +++ b/src/metadata/auto_breakpoint.rs @@ -38,7 +38,7 @@ impl AutoBreakpoint { if self.has_event(event) { metadata .get::() - .unwrap() + .ok_or(Error::MissingMetadata)? .debug_breakpoint_trap(block, location)?; } diff --git a/src/metadata/debug_utils.rs b/src/metadata/debug_utils.rs index 4da04050c..68cc54dac 100644 --- a/src/metadata/debug_utils.rs +++ b/src/metadata/debug_utils.rs @@ -61,7 +61,7 @@ //! .into(); //! //! metadata.get_mut::() -//! .unwrap() +//! .ok_or(Error::MissingMetadata)? //! .print_pointer(context, helper, entry, array_ptr, location)?; //! } //! diff --git a/src/metadata/drop_overrides.rs b/src/metadata/drop_overrides.rs index e0a1b30b8..e70447424 100644 --- a/src/metadata/drop_overrides.rs +++ b/src/metadata/drop_overrides.rs @@ -21,7 +21,10 @@ //! where `{type id}` is the numeric value of the `ConcreteTypeId`. use super::MetadataStorage; -use crate::{error::Result, utils::ProgramRegistryExt}; +use crate::{ + error::{Error, Result}, + utils::ProgramRegistryExt, +}; use cairo_lang_sierra::{ extensions::core::{CoreLibfunc, CoreType}, ids::ConcreteTypeId, @@ -92,11 +95,13 @@ impl DropOverridesMeta { ), ( Identifier::new(context, "llvm.CConv"), - Attribute::parse(context, "#llvm.cconv").unwrap(), + Attribute::parse(context, "#llvm.cconv") + .ok_or(Error::ParseAttributeError)?, ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), diff --git a/src/metadata/dup_overrides.rs b/src/metadata/dup_overrides.rs index dada18dd5..d9a560336 100644 --- a/src/metadata/dup_overrides.rs +++ b/src/metadata/dup_overrides.rs @@ -21,7 +21,10 @@ //! where `{type id}` is the numeric value of the `ConcreteTypeId`. use super::MetadataStorage; -use crate::{error::Result, utils::ProgramRegistryExt}; +use crate::{ + error::{Error, Result}, + utils::ProgramRegistryExt, +}; use cairo_lang_sierra::{ extensions::core::{CoreLibfunc, CoreType}, ids::ConcreteTypeId, @@ -92,11 +95,13 @@ impl DupOverridesMeta { ), ( Identifier::new(context, "llvm.CConv"), - Attribute::parse(context, "#llvm.cconv").unwrap(), + Attribute::parse(context, "#llvm.cconv") + .ok_or(Error::ParseAttributeError)?, ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 8a1007f3b..5cdeadbdc 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -11,7 +11,10 @@ use cairo_lang_sierra_ap_change::{ use cairo_lang_sierra_gas::{ compute_postcost_info, compute_precost_info, gas_info::GasInfo, CostError, }; -use cairo_lang_utils::{casts::IntoOrPanic, ordered_hash_map::OrderedHashMap}; +use cairo_lang_utils::ordered_hash_map::OrderedHashMap; + +use crate::{error::Result as NativeResult, native_panic}; + use std::collections::BTreeMap; /// Holds global gas info. @@ -99,17 +102,23 @@ impl GasMetadata { Some( self.gas_info.function_costs[func] .iter() - .map(|(token_type, val)| val.into_or_panic::() * token_gas_cost(*token_type)) + .map(|(token_type, val)| { + TryInto::::try_into(*val) + .expect("could not cast gas cost from i64 to usize") + * token_gas_cost(*token_type) + }) .sum::() as u64, ) } - pub fn initial_required_gas_for_entry_points(&self) -> BTreeMap> { + pub fn initial_required_gas_for_entry_points( + &self, + ) -> NativeResult>> { self.gas_info .function_costs .iter() .map(|func| { - (func.0.id, { + Ok((func.0.id, { let mut costs = BTreeMap::new(); for (token, val) in func.1.iter() { @@ -121,13 +130,13 @@ impl GasMetadata { CostTokenType::Poseidon => 4, CostTokenType::AddMod => 5, CostTokenType::MulMod => 6, - _ => unreachable!(), + _ => native_panic!("matched an unexpected CostTokenType"), }; costs.insert(offset, *val as u64); } costs - }) + })) }) .collect() } diff --git a/src/metadata/realloc_bindings.rs b/src/metadata/realloc_bindings.rs index 369bc709f..95a2c41d1 100644 --- a/src/metadata/realloc_bindings.rs +++ b/src/metadata/realloc_bindings.rs @@ -11,7 +11,7 @@ use melior::{ r#type::IntegerType, Identifier, Location, Module, Operation, Region, Value, }, - Context, + Context, Error, }; /// Memory allocation `realloc` metadata. @@ -64,7 +64,7 @@ impl ReallocBindingsMeta { ptr: Value<'c, 'a>, len: Value<'c, 'a>, location: Location<'c>, - ) -> Operation<'c> { + ) -> Result, Error> { OperationBuilder::new("llvm.call", location) .add_attributes(&[( Identifier::new(context, "callee"), @@ -73,7 +73,6 @@ impl ReallocBindingsMeta { .add_operands(&[ptr, len]) .add_results(&[llvm::r#type::pointer(context, 0)]) .build() - .unwrap() } /// Calls the `free` function. @@ -81,7 +80,7 @@ impl ReallocBindingsMeta { context: &'c Context, ptr: Value<'c, '_>, location: Location<'c>, - ) -> Operation<'c> { + ) -> Result, Error> { OperationBuilder::new("llvm.call", location) .add_attributes(&[( Identifier::new(context, "callee"), @@ -89,6 +88,5 @@ impl ReallocBindingsMeta { )]) .add_operands(&[ptr]) .build() - .unwrap() } } diff --git a/src/metadata/runtime_bindings.rs b/src/metadata/runtime_bindings.rs index 225b671c3..95b60c21b 100644 --- a/src/metadata/runtime_bindings.rs +++ b/src/metadata/runtime_bindings.rs @@ -3,7 +3,10 @@ //! This metadata ensures that the bindings to the runtime functions exist in the current //! compilation context. -use crate::{error::Result, utils::BlockExt}; +use crate::{ + error::{Error, Result}, + utils::BlockExt, +}; use melior::{ dialect::{func, llvm, ods}, ir::{ @@ -84,7 +87,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -142,7 +146,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -198,7 +203,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -246,7 +252,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -294,7 +301,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -337,7 +345,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -389,7 +398,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -444,7 +454,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -498,7 +509,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], location, @@ -551,7 +563,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -616,7 +629,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -678,7 +692,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -735,7 +750,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -794,7 +810,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -847,7 +864,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -890,7 +908,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), @@ -950,7 +969,8 @@ impl RuntimeBindingsMeta { ), ( Identifier::new(context, "llvm.linkage"), - Attribute::parse(context, "#llvm.linkage").unwrap(), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, ), ], Location::unknown(context), diff --git a/src/types/array.rs b/src/types/array.rs index f43129389..7aa2e21f4 100644 --- a/src/types/array.rs +++ b/src/types/array.rs @@ -178,7 +178,7 @@ fn build_dup<'ctx>( null_ptr, dst_value_len, location, - ))? + )?)? }; let src_value_ptr = { @@ -372,7 +372,7 @@ fn build_drop<'ctx>( _ => {} } - entry.append_operation(ReallocBindingsMeta::free(context, value_ptr, location)); + entry.append_operation(ReallocBindingsMeta::free(context, value_ptr, location)?); entry.append_operation(func::r#return(&[], location)); Ok(region) } diff --git a/src/types/box.rs b/src/types/box.rs index 1ab61d95a..17f994d08 100644 --- a/src/types/box.rs +++ b/src/types/box.rs @@ -106,7 +106,7 @@ fn build_dup<'ctx>( null_ptr, inner_len_val, location, - ))?; + )?)?; match metadata.get::() { Some(dup_override_meta) if dup_override_meta.is_overriden(&info.ty) => { @@ -161,7 +161,7 @@ fn build_drop<'ctx>( _ => {} } - entry.append_operation(ReallocBindingsMeta::free(context, value, location)); + entry.append_operation(ReallocBindingsMeta::free(context, value, location)?); entry.append_operation(func::r#return(&[], location)); Ok(region) } diff --git a/src/types/felt252_dict.rs b/src/types/felt252_dict.rs index 50d7fa226..e29df04db 100644 --- a/src/types/felt252_dict.rs +++ b/src/types/felt252_dict.rs @@ -105,7 +105,7 @@ fn build_dup<'ctx>( let old_ptr = entry.argument(0)?.into(); let new_ptr = entry.append_op_result(ReallocBindingsMeta::realloc( context, null_ptr, inner_len, location, - ))?; + )?)?; let value = entry.load(context, location, old_ptr, inner_ty)?; let values = metadata diff --git a/src/types/nullable.rs b/src/types/nullable.rs index 4286e97a9..beec95559 100644 --- a/src/types/nullable.rs +++ b/src/types/nullable.rs @@ -129,7 +129,7 @@ fn build_dup<'ctx>( null_ptr, inner_len_val, location, - ))?; + )?)?; match metadata.get::() { Some(dup_override_meta) if dup_override_meta.is_overriden(&info.ty) => { @@ -233,7 +233,7 @@ fn build_drop<'ctx>( _ => {} } - block_free.append_operation(ReallocBindingsMeta::free(context, value, location)); + block_free.append_operation(ReallocBindingsMeta::free(context, value, location)?); block_free.append_operation(func::r#return(&[], location)); } diff --git a/src/types/starknet.rs b/src/types/starknet.rs index 9299125c2..032a9f004 100644 --- a/src/types/starknet.rs +++ b/src/types/starknet.rs @@ -215,7 +215,7 @@ pub fn build_sha256_state_handle<'ctx>( let k32 = block.const_int(context, location, 32, 64)?; let new_ptr = block.append_op_result(ReallocBindingsMeta::realloc( context, null_ptr, k32, location, - ))?; + )?)?; block.append_operation( ods::llvm::intr_memcpy_inline( @@ -244,7 +244,7 @@ pub fn build_sha256_state_handle<'ctx>( context, block.argument(0)?.into(), location, - )); + )?); block.append_operation(func::r#return(&[], location)); Ok(Some(region)) From ae234bac7eb4b7f70715b3832363a843348c6927 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Tue, 19 Nov 2024 07:45:15 -0300 Subject: [PATCH 04/11] Remove panic (#908) Co-authored-by: Edgar --- src/execution_result.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/execution_result.rs b/src/execution_result.rs index 3ddee296a..c3b56e19c 100644 --- a/src/execution_result.rs +++ b/src/execution_result.rs @@ -2,7 +2,7 @@ /// /// This module contains the structures used to interpret the program execution results, either /// normal programs or starknet contracts. -use crate::{error::Error, utils::decode_error_message, values::Value}; +use crate::{error::Error, native_panic, utils::decode_error_message, values::Value}; use starknet_types_core::felt::Felt; #[derive( @@ -76,12 +76,12 @@ impl ContractExecutionResult { .iter() .map(|x| { if let Value::Felt252(f) = x { - *f + Ok(*f) } else { - panic!("should always be a felt") + native_panic!("should always be a felt") } }) - .collect(); + .collect::>()?; felt_vec } else { Err(Error::UnexpectedValue(format!( @@ -113,12 +113,12 @@ impl ContractExecutionResult { .iter() .map(|x| { if let Value::Felt252(f) = x { - *f + Ok(*f) } else { - panic!("should always be a felt") + native_panic!("should always be a felt") } }) - .collect(); + .collect::>()?; let bytes_err: Vec<_> = felt_vec .iter() From 4a6e239f453a092251d7bdeb78d6763f16f6a283 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Tue, 19 Nov 2024 12:10:19 -0300 Subject: [PATCH 05/11] Remove panics in executors (#920) * Remove panics in aot executor * Fix som leftover unwraps * Remove panics in jit executor * Remove panic from contract executor * Remove metadata unwrap * Fix clippy --- benches/libfuncs.rs | 12 ++++++--- examples/easy_api.rs | 3 ++- examples/erc20.rs | 3 ++- examples/invoke.rs | 3 ++- examples/starknet.rs | 3 ++- src/bin/cairo-native-run.rs | 4 +-- src/bin/utils/test.rs | 4 +-- src/cache/jit.rs | 2 +- src/executor.rs | 8 +++--- src/executor/aot.rs | 53 +++++++++++++++++++------------------ src/executor/contract.rs | 31 +++++++++++++--------- src/executor/jit.rs | 28 ++++++++++++-------- src/utils.rs | 2 +- tests/common.rs | 5 ++-- tests/tests/trampoline.rs | 2 +- 15 files changed, 92 insertions(+), 71 deletions(-) diff --git a/benches/libfuncs.rs b/benches/libfuncs.rs index 3528d16e6..8bfa26ca8 100644 --- a/benches/libfuncs.rs +++ b/benches/libfuncs.rs @@ -57,7 +57,8 @@ pub fn bench_libfuncs(c: &mut Criterion) { let module = native_context.compile(program, false).unwrap(); // pass manager internally verifies the MLIR output is correct. let native_executor = - JitNativeExecutor::from_native_module(module, OptLevel::Aggressive); + JitNativeExecutor::from_native_module(module, OptLevel::Aggressive) + .unwrap(); // Execute the program. let result = native_executor @@ -76,7 +77,8 @@ pub fn bench_libfuncs(c: &mut Criterion) { let module = native_context.compile(program, false).unwrap(); // pass manager internally verifies the MLIR output is correct. let native_executor = - JitNativeExecutor::from_native_module(module, OptLevel::Aggressive); + JitNativeExecutor::from_native_module(module, OptLevel::Aggressive) + .unwrap(); // warmup for _ in 0..5 { @@ -104,7 +106,8 @@ pub fn bench_libfuncs(c: &mut Criterion) { let module = native_context.compile(program, false).unwrap(); // pass manager internally verifies the MLIR output is correct. let native_executor = - AotNativeExecutor::from_native_module(module, OptLevel::Aggressive); + AotNativeExecutor::from_native_module(module, OptLevel::Aggressive) + .unwrap(); // Execute the program. let result = native_executor @@ -123,7 +126,8 @@ pub fn bench_libfuncs(c: &mut Criterion) { let module = native_context.compile(program, false).unwrap(); // pass manager internally verifies the MLIR output is correct. let native_executor = - AotNativeExecutor::from_native_module(module, OptLevel::Aggressive); + AotNativeExecutor::from_native_module(module, OptLevel::Aggressive) + .unwrap(); // warmup for _ in 0..5 { diff --git a/examples/easy_api.rs b/examples/easy_api.rs index 9c11f2ad8..cb9c7d5a9 100644 --- a/examples/easy_api.rs +++ b/examples/easy_api.rs @@ -26,7 +26,8 @@ fn main() { .expect("entry point not found"); // Instantiate the executor. - let native_executor = JitNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = + JitNativeExecutor::from_native_module(native_program, Default::default()).unwrap(); // Execute the program. let result = native_executor diff --git a/examples/erc20.rs b/examples/erc20.rs index de61c0f78..346b4decf 100644 --- a/examples/erc20.rs +++ b/examples/erc20.rs @@ -311,7 +311,8 @@ fn main() { find_entry_point_by_idx(&sierra_program, entry_point.function_idx).unwrap(); let fn_id = &entry_point_fn.id; - let native_executor = JitNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = + JitNativeExecutor::from_native_module(native_program, Default::default()).unwrap(); let result = native_executor .invoke_contract_dynamic( diff --git a/examples/invoke.rs b/examples/invoke.rs index 2468dc4e4..72ee8aa89 100644 --- a/examples/invoke.rs +++ b/examples/invoke.rs @@ -28,7 +28,8 @@ fn main() { let fn_id = &entry_point_fn.id; - let native_executor = JitNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = + JitNativeExecutor::from_native_module(native_program, Default::default()).unwrap(); let output = native_executor.invoke_dynamic(fn_id, &[Value::Felt252(1.into())], None); diff --git a/examples/starknet.rs b/examples/starknet.rs index 875051c84..2a9c570e7 100644 --- a/examples/starknet.rs +++ b/examples/starknet.rs @@ -442,7 +442,8 @@ fn main() { let fn_id = &entry_point_fn.id; - let native_executor = JitNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = + JitNativeExecutor::from_native_module(native_program, Default::default()).unwrap(); let result = native_executor .invoke_contract_dynamic(fn_id, &[Felt::ONE], Some(u64::MAX), SyscallHandler::new()) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index c0932f78e..03f0f48fb 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -77,7 +77,7 @@ fn main() -> anyhow::Result<()> { let native_executor: Box _> = match args.run_mode { RunMode::Aot => { let executor = - AotNativeExecutor::from_native_module(native_module, args.opt_level.into()); + AotNativeExecutor::from_native_module(native_module, args.opt_level.into())?; Box::new(move |function_id, args, gas, syscall_handler| { executor.invoke_dynamic_with_syscall_handler( function_id, @@ -89,7 +89,7 @@ fn main() -> anyhow::Result<()> { } RunMode::Jit => { let executor = - JitNativeExecutor::from_native_module(native_module, args.opt_level.into()); + JitNativeExecutor::from_native_module(native_module, args.opt_level.into())?; Box::new(move |function_id, args, gas, syscall_handler| { executor.invoke_dynamic_with_syscall_handler( function_id, diff --git a/src/bin/utils/test.rs b/src/bin/utils/test.rs index 6df09c091..45db60a71 100644 --- a/src/bin/utils/test.rs +++ b/src/bin/utils/test.rs @@ -141,7 +141,7 @@ pub fn run_tests( let native_executor: Box _> = match args.run_mode { RunMode::Aot => { let executor = - AotNativeExecutor::from_native_module(native_module, args.opt_level.into()); + AotNativeExecutor::from_native_module(native_module, args.opt_level.into())?; Box::new(move |function_id, args, gas, syscall_handler| { executor.invoke_dynamic_with_syscall_handler( function_id, @@ -153,7 +153,7 @@ pub fn run_tests( } RunMode::Jit => { let executor = - JitNativeExecutor::from_native_module(native_module, args.opt_level.into()); + JitNativeExecutor::from_native_module(native_module, args.opt_level.into())?; Box::new(move |function_id, args, gas, syscall_handler| { executor.invoke_dynamic_with_syscall_handler( function_id, diff --git a/src/cache/jit.rs b/src/cache/jit.rs index 223f4ba35..d926b5b2a 100644 --- a/src/cache/jit.rs +++ b/src/cache/jit.rs @@ -47,7 +47,7 @@ where opt_level: OptLevel, ) -> Result>> { let module = self.context.compile(program, false)?; - let executor = JitNativeExecutor::from_native_module(module, opt_level); + let executor = JitNativeExecutor::from_native_module(module, opt_level)?; let executor = Arc::new(executor); self.cache.insert(key, executor.clone()); diff --git a/src/executor.rs b/src/executor.rs index 4990d2100..86a967193 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -684,7 +684,7 @@ mod tests { let module = native_context .compile(&program, false) .expect("failed to compile context"); - let executor = AotNativeExecutor::from_native_module(module, OptLevel::default()); + let executor = AotNativeExecutor::from_native_module(module, OptLevel::default()).unwrap(); // The first function in the program is `run_test`. let entrypoint_function_id = &program.funcs.first().expect("should have a function").id; @@ -702,7 +702,7 @@ mod tests { let module = native_context .compile(&program, false) .expect("failed to compile context"); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::default()); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::default()).unwrap(); // The first function in the program is `run_test`. let entrypoint_function_id = &program.funcs.first().expect("should have a function").id; @@ -720,7 +720,7 @@ mod tests { let module = native_context .compile(&starknet_program, false) .expect("failed to compile context"); - let executor = AotNativeExecutor::from_native_module(module, OptLevel::default()); + let executor = AotNativeExecutor::from_native_module(module, OptLevel::default()).unwrap(); // The last function in the program is the `get` wrapper function. let entrypoint_function_id = &starknet_program @@ -747,7 +747,7 @@ mod tests { let module = native_context .compile(&starknet_program, false) .expect("failed to compile context"); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::default()); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::default()).unwrap(); // The last function in the program is the `get` wrapper function. let entrypoint_function_id = &starknet_program diff --git a/src/executor/aot.rs b/src/executor/aot.rs index 3305a00f6..5ea08785e 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -1,3 +1,5 @@ +use std::io; + use crate::{ error::Error, execution_result::{ContractExecutionResult, ExecutionResult}, @@ -48,27 +50,26 @@ impl AotNativeExecutor { } /// Utility to convert a [`NativeModule`] into an [`AotNativeExecutor`]. - pub fn from_native_module(module: NativeModule, opt_level: OptLevel) -> Self { + pub fn from_native_module(module: NativeModule, opt_level: OptLevel) -> Result { let NativeModule { module, registry, mut metadata, } = module; - let library_path = NamedTempFile::new() - .unwrap() + let library_path = NamedTempFile::new()? .into_temp_path() .keep() - .unwrap(); + .map_err(io::Error::from)?; - let object_data = crate::module_to_object(&module, opt_level).unwrap(); - crate::object_to_shared_lib(&object_data, &library_path).unwrap(); + let object_data = crate::module_to_object(&module, opt_level)?; + crate::object_to_shared_lib(&object_data, &library_path)?; - Self { - library: unsafe { Library::new(&library_path).unwrap() }, + Ok(Self { + library: unsafe { Library::new(&library_path)? }, registry, - gas_metadata: metadata.remove().unwrap(), - } + gas_metadata: metadata.remove().ok_or(Error::MissingMetadata)?, + }) } pub fn invoke_dynamic( @@ -95,9 +96,9 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, - self.find_function_ptr(function_id), + self.find_function_ptr(function_id)?, set_costs_builtin, - self.extract_signature(function_id), + self.extract_signature(function_id)?, args, available_gas, Option::::None, @@ -129,9 +130,9 @@ impl AotNativeExecutor { super::invoke_dynamic( &self.registry, - self.find_function_ptr(function_id), + self.find_function_ptr(function_id)?, set_costs_builtin, - self.extract_signature(function_id), + self.extract_signature(function_id)?, args, available_gas, Some(syscall_handler), @@ -163,9 +164,9 @@ impl AotNativeExecutor { ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, - self.find_function_ptr(function_id), + self.find_function_ptr(function_id)?, set_costs_builtin, - self.extract_signature(function_id), + self.extract_signature(function_id)?, &[Value::Struct { fields: vec![Value::Array( args.iter().cloned().map(Value::Felt252).collect(), @@ -177,17 +178,17 @@ impl AotNativeExecutor { )?) } - pub fn find_function_ptr(&self, function_id: &FunctionId) -> *mut c_void { + pub fn find_function_ptr(&self, function_id: &FunctionId) -> Result<*mut c_void, Error> { let function_name = generate_function_name(function_id, false); let function_name = format!("_mlir_ciface_{function_name}"); // Arguments and return values are hardcoded since they'll be handled by the trampoline. unsafe { - self.library - .get::(function_name.as_bytes()) - .unwrap() - .into_raw() + Ok(self + .library + .get::(function_name.as_bytes())? .into_raw() + .into_raw()) } } @@ -200,8 +201,8 @@ impl AotNativeExecutor { } } - fn extract_signature(&self, function_id: &FunctionId) -> &FunctionSignature { - &self.registry.get_function(function_id).unwrap().signature + fn extract_signature(&self, function_id: &FunctionId) -> Result<&FunctionSignature, Error> { + Ok(&self.registry.get_function(function_id)?.signature) } } @@ -265,7 +266,7 @@ mod tests { let module = native_context .compile(&program, false) .expect("failed to compile context"); - let executor = AotNativeExecutor::from_native_module(module, optlevel); + let executor = AotNativeExecutor::from_native_module(module, optlevel).unwrap(); // The first function in the program is `run_test`. let entrypoint_function_id = &program.funcs.first().expect("should have a function").id; @@ -286,7 +287,7 @@ mod tests { let module = native_context .compile(&program, false) .expect("failed to compile context"); - let executor = AotNativeExecutor::from_native_module(module, optlevel); + let executor = AotNativeExecutor::from_native_module(module, optlevel).unwrap(); // The second function in the program is `get_block_hash`. let entrypoint_function_id = &program.funcs.get(1).expect("should have a function").id; @@ -325,7 +326,7 @@ mod tests { let module = native_context .compile(&starknet_program, false) .expect("failed to compile context"); - let executor = AotNativeExecutor::from_native_module(module, optlevel); + let executor = AotNativeExecutor::from_native_module(module, optlevel).unwrap(); // The last function in the program is the `get` wrapper function. let entrypoint_function_id = &starknet_program diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 404d336e3..3051d46d7 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -34,11 +34,12 @@ use crate::{ arch::AbiArgument, context::NativeContext, - error::{Error, Result}, + error::{panic::ToNativeAssertError, Error}, execution_result::{BuiltinStats, ContractExecutionResult}, executor::invoke_trampoline, metadata::gas::GasMetadata, module::NativeModule, + native_panic, starknet::{handler::StarknetSyscallHandlerCallbacks, StarknetSyscallHandler}, types::TypeBuilder, utils::{ @@ -145,7 +146,7 @@ impl AotContractExecutor { sierra_program: &Program, entry_points: &ContractEntryPoints, opt_level: OptLevel, - ) -> Result { + ) -> Result { let native_context = NativeContext::new(); let module = native_context.compile(sierra_program, true)?; @@ -156,7 +157,7 @@ impl AotContractExecutor { } = module; let initial_gas_costs = { - let gas_meta: &GasMetadata = metadata.get().unwrap(); + let gas_meta: &GasMetadata = metadata.get().ok_or(Error::MissingMetadata)?; gas_meta.initial_required_gas_for_entry_points()? }; @@ -217,7 +218,7 @@ impl AotContractExecutor { CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::System(_)) => { builtins.push(BuiltinType::System) } - _ => unreachable!("{:?}", ty.info()), + _ => native_panic!("given type should be a builtin {:?}", ty.info()), } } else { break; @@ -236,7 +237,7 @@ impl AotContractExecutor { let library_path = NamedTempFile::new()? .into_temp_path() .keep() - .expect("can only fail on windows"); + .to_native_assert_error("can only fail on windows")?; let object_data = crate::module_to_object(&module, opt_level)?; crate::object_to_shared_lib(&object_data, &library_path)?; @@ -254,7 +255,7 @@ impl AotContractExecutor { } /// Save the library to the desired path, alongside it is saved also a json file with additional info. - pub fn save(&mut self, to: impl AsRef) -> Result<()> { + pub fn save(&mut self, to: impl AsRef) -> Result<(), Error> { let to = to.as_ref(); std::fs::copy(&self.path, to)?; @@ -269,7 +270,7 @@ impl AotContractExecutor { } /// Load the executor from an already compiled library with the additional info json file. - pub fn load(library_path: &Path) -> Result { + pub fn load(library_path: &Path) -> Result { let info_str = std::fs::read_to_string(library_path.with_extension("json"))?; let contract_info: NativeContractInfo = serde_json::from_str(&info_str)?; Ok(Self { @@ -288,7 +289,7 @@ impl AotContractExecutor { gas: Option, builtin_costs: Option, mut syscall_handler: impl StarknetSyscallHandler, - ) -> Result { + ) -> Result { let arena = Bump::new(); let mut invoke_data = Vec::::new(); @@ -324,7 +325,7 @@ impl AotContractExecutor { .contract_info .entry_points_info .get(&function_id.id) - .unwrap() + .to_native_assert_error("entry point info for function should be available")? .initial_cost .iter() { @@ -375,7 +376,10 @@ impl AotContractExecutor { let felt_layout = get_integer_layout(252).pad_to_align(); let ptr: *mut () = unsafe { libc_malloc(felt_layout.size() * args.len()).cast() }; - let len: u32 = args.len().try_into().unwrap(); + let len: u32 = args + .len() + .try_into() + .to_native_assert_error("number of arguments should fit into a u32")?; ptr.to_bytes(&mut invoke_data)?; 0u32.to_bytes(&mut invoke_data)?; // start @@ -481,7 +485,7 @@ impl AotContractExecutor { let tag_layout = Layout::from_size_align(1, 1)?; let enum_ptr = unsafe { NonNull::new(return_ptr.cast::().as_ptr().add(align_offset)) - .expect("nonnull is null") + .to_native_assert_error("return ptr should not be null")? }; let tag = *unsafe { enum_ptr.cast::().as_ref() } as usize; @@ -513,7 +517,8 @@ impl AotContractExecutor { for i in 0..num_elems { // safe to create a NonNull because if the array has elements, the data_ptr can't be null. - let cur_elem_ptr = NonNull::new(unsafe { data_ptr.byte_add(elem_stride * i) }).unwrap(); + let cur_elem_ptr = NonNull::new(unsafe { data_ptr.byte_add(elem_stride * i) }) + .to_native_assert_error("data_ptr should not be null")?; let data = unsafe { cur_elem_ptr.cast::<[u8; 32]>().as_mut() }; data[31] &= 0x0F; // Filter out first 4 bits (they're outside an i252). let data = Felt::from_bytes_le_slice(data); @@ -563,7 +568,7 @@ impl AotContractExecutor { &self, function_id: &FunctionId, is_for_contract_executor: bool, - ) -> Result<*mut c_void> { + ) -> Result<*mut c_void, Error> { let function_name = generate_function_name(function_id, is_for_contract_executor); let function_name = format!("_mlir_ciface_{function_name}"); diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 57ae68acc..c4a890688 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -41,19 +41,25 @@ impl std::fmt::Debug for JitNativeExecutor<'_> { } impl<'m> JitNativeExecutor<'m> { - pub fn from_native_module(native_module: NativeModule<'m>, opt_level: OptLevel) -> Self { + pub fn from_native_module( + native_module: NativeModule<'m>, + opt_level: OptLevel, + ) -> Result { let NativeModule { module, registry, metadata, } = native_module; - Self { + Ok(Self { engine: create_engine(&module, &metadata, opt_level), module, registry, - gas_metadata: metadata.get::().cloned().unwrap(), - } + gas_metadata: metadata + .get::() + .cloned() + .ok_or(Error::MissingMetadata)?, + }) } pub fn program_registry(&self) -> &ProgramRegistry { @@ -83,7 +89,7 @@ impl<'m> JitNativeExecutor<'m> { &self.registry, self.find_function_ptr(function_id), set_builtin_costs_fnptr, - self.extract_signature(function_id).unwrap(), + self.extract_signature(function_id)?, args, available_gas, Option::::None, @@ -110,7 +116,7 @@ impl<'m> JitNativeExecutor<'m> { &self.registry, self.find_function_ptr(function_id), set_builtin_costs_fnptr, - self.extract_signature(function_id).unwrap(), + self.extract_signature(function_id)?, args, available_gas, Some(syscall_handler), @@ -136,7 +142,7 @@ impl<'m> JitNativeExecutor<'m> { &self.registry, self.find_function_ptr(function_id), set_builtin_costs_fnptr, - self.extract_signature(function_id).unwrap(), + self.extract_signature(function_id)?, &[Value::Struct { fields: vec![Value::Array( args.iter().cloned().map(Value::Felt252).collect(), @@ -166,10 +172,10 @@ impl<'m> JitNativeExecutor<'m> { } } - fn extract_signature(&self, function_id: &FunctionId) -> Option<&FunctionSignature> { - self.program_registry() + fn extract_signature(&self, function_id: &FunctionId) -> Result<&FunctionSignature, Error> { + Ok(self + .program_registry() .get_function(function_id) - .ok() - .map(|func| &func.signature) + .map(|func| &func.signature)?) } } diff --git a/src/utils.rs b/src/utils.rs index 172f777a5..6456461de 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -706,7 +706,7 @@ pub mod test { .compile(program, false) .expect("Could not compile test program to MLIR."); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::Less); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Less).unwrap(); executor .invoke_dynamic_with_syscall_handler( entry_point_id, diff --git a/tests/common.rs b/tests/common.rs index 76398da67..1ee6d0c4c 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -237,7 +237,7 @@ pub fn run_native_program( ); // FIXME: There are some bugs with non-zero LLVM optimization levels. - let executor = JitNativeExecutor::from_native_module(module, OptLevel::None); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::None).unwrap(); match syscall_handler { Some(syscall_handler) => executor .invoke_dynamic_with_syscall_handler(entry_point_id, args, gas, syscall_handler) @@ -427,7 +427,8 @@ pub fn run_native_starknet_contract( let entry_point_fn = find_entry_point_by_idx(sierra_program, entry_point_function_idx).unwrap(); let entry_point_id = &entry_point_fn.id; - let native_executor = AotNativeExecutor::from_native_module(native_program, Default::default()); + let native_executor = + AotNativeExecutor::from_native_module(native_program, Default::default()).unwrap(); native_executor .invoke_contract_dynamic(entry_point_id, args, u64::MAX.into(), handler) .expect("failed to execute the given contract") diff --git a/tests/tests/trampoline.rs b/tests/tests/trampoline.rs index 02fd83d6d..aba95ca6c 100644 --- a/tests/tests/trampoline.rs +++ b/tests/tests/trampoline.rs @@ -15,7 +15,7 @@ fn run_program(program: &Program, entry_point: &str, args: &[Value]) -> Executio let context = NativeContext::new(); let module = context.compile(program, false).unwrap(); // FIXME: There are some bugs with non-zero LLVM optimization levels. - let executor = JitNativeExecutor::from_native_module(module, OptLevel::None); + let executor = JitNativeExecutor::from_native_module(module, OptLevel::None).unwrap(); executor.invoke_dynamic(entry_point_id, args, None).unwrap() } From a18f1aea5c15bed3ba2bdd60d4e0acbe9090db47 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Tue, 19 Nov 2024 12:20:44 -0300 Subject: [PATCH 06/11] Remove panic in utils.rs (#924) * Remove some unwraps * Remove expect in felt parse * Remove unwrap * Fix clippy --------- Co-authored-by: Edgar --- benches/util.rs | 2 +- examples/easy_api.rs | 2 +- examples/invoke.rs | 2 +- src/bin/cairo-native-compile.rs | 2 +- src/utils.rs | 31 +++++++++++++++---------------- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/benches/util.rs b/benches/util.rs index 0c8728f44..813898c23 100644 --- a/benches/util.rs +++ b/benches/util.rs @@ -11,7 +11,7 @@ pub fn prepare_programs(path: &str) -> Vec<(Arc, String)> { let path = e.path(); match path.extension().map(|x| x.to_str().unwrap()) { Some("cairo") => Some(( - cairo_native::utils::cairo_to_sierra(path), + cairo_native::utils::cairo_to_sierra(path).unwrap(), path.display().to_string(), )), _ => None, diff --git a/examples/easy_api.rs b/examples/easy_api.rs index cb9c7d5a9..be1851b66 100644 --- a/examples/easy_api.rs +++ b/examples/easy_api.rs @@ -12,7 +12,7 @@ fn main() { let native_context = NativeContext::new(); // Compile the cairo program to sierra. - let sierra_program = cairo_to_sierra(program_path); + let sierra_program = cairo_to_sierra(program_path).unwrap(); // Compile the sierra program into a MLIR module. let native_program = native_context.compile(&sierra_program, false).unwrap(); diff --git a/examples/invoke.rs b/examples/invoke.rs index 72ee8aa89..8698bac83 100644 --- a/examples/invoke.rs +++ b/examples/invoke.rs @@ -16,7 +16,7 @@ fn main() { let program_path = Path::new("programs/echo.cairo"); // Compile the cairo program to sierra. - let sierra_program = cairo_native::utils::cairo_to_sierra(program_path); + let sierra_program = cairo_native::utils::cairo_to_sierra(program_path).unwrap(); let native_context = NativeContext::new(); diff --git a/src/bin/cairo-native-compile.rs b/src/bin/cairo-native-compile.rs index a2c136158..1381bee28 100644 --- a/src/bin/cairo-native-compile.rs +++ b/src/bin/cairo-native-compile.rs @@ -52,7 +52,7 @@ fn main() -> anyhow::Result<()> { check_compiler_path(args.single_file, &args.path)?; let native_context = NativeContext::new(); - let sierra_program = cairo_to_sierra(&args.path); + let sierra_program = cairo_to_sierra(&args.path).unwrap(); // Compile the sierra program into a MLIR module. let native_module = native_context.compile(&sierra_program, false).unwrap(); diff --git a/src/utils.rs b/src/utils.rs index 6456461de..a63ad114f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -21,14 +21,12 @@ use melior::{ use num_bigint::{BigInt, BigUint, Sign}; use serde::{Deserialize, Serialize}; use starknet_types_core::felt::Felt; -use std::sync::LazyLock; +use std::sync::{Arc, LazyLock}; use std::{ alloc::Layout, borrow::Cow, fmt::{self, Display}, - ops::Neg, path::Path, - sync::Arc, }; use thiserror::Error; @@ -46,12 +44,12 @@ pub const SHARED_LIBRARY_EXT: &str = "so"; pub static PRIME: LazyLock = LazyLock::new(|| { "3618502788666131213697322783095070105623107215331596699973092056135872020481" .parse() - .unwrap() + .expect("hardcoded prime constant should be valid") }); pub static HALF_PRIME: LazyLock = LazyLock::new(|| { "1809251394333065606848661391547535052811553607665798349986546028067936010240" .parse() - .unwrap() + .expect("hardcoded half prime constant should be valid") }); #[derive(Debug, Clone, Copy, Deserialize, Serialize)] @@ -163,12 +161,13 @@ pub fn get_integer_layout(width: u32) -> Layout { Layout::new::() } else { // According to the docs this should never return an error. - Layout::from_size_align((width as usize).next_multiple_of(8) >> 3, 16).unwrap() + Layout::from_size_align((width as usize).next_multiple_of(8) >> 3, 16) + .expect("only fails if size is greater than ISIZE::MAX") } } /// Compile a cairo program found at the given path to sierra. -pub fn cairo_to_sierra(program: &Path) -> Arc { +pub fn cairo_to_sierra(program: &Path) -> anyhow::Result> { if program .extension() .map(|x| { @@ -185,14 +184,13 @@ pub fn cairo_to_sierra(program: &Path) -> Arc { ..Default::default() }, ) - .unwrap() - .into() + .map(Arc::new) } else { - let source = std::fs::read_to_string(program).unwrap(); + let source = std::fs::read_to_string(program)?; cairo_lang_sierra::ProgramParser::new() .parse(&source) - .unwrap() - .into() + .map_err(|err| anyhow::Error::msg(err.to_string())) + .map(Arc::new) } } @@ -234,9 +232,10 @@ pub fn felt252_str(value: &str) -> Felt { let value = value .parse::() .expect("value must be a digit number"); + let value = match value.sign() { - Sign::Minus => &*PRIME - value.neg().to_biguint().unwrap(), - _ => value.to_biguint().unwrap(), + Sign::Minus => &*PRIME - value.magnitude(), + _ => value.magnitude().clone(), }; value.into() @@ -1086,7 +1085,7 @@ pub mod test { // Define the path to the cairo program. let program_path = Path::new("programs/examples/hello.cairo"); // Compile the cairo program to sierra. - let sierra_program = cairo_to_sierra(program_path); + let sierra_program = cairo_to_sierra(program_path).unwrap(); // Define the entry point function for comparison. let entry_point = "hello::hello::greet"; @@ -1112,7 +1111,7 @@ pub mod test { let file_path = file.path().to_path_buf(); // Compile the cairo program to sierra using the path of the temporary file. - let sierra_program = cairo_to_sierra(&file_path); + let sierra_program = cairo_to_sierra(&file_path).unwrap(); // Assert that the sierra program has no library function declarations, statements, or functions. assert!(sierra_program.libfunc_declarations.is_empty()); From 5b9f6ff01e9b0a0a6f0546f67b930ffb4d2217b2 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Tue, 19 Nov 2024 12:20:58 -0300 Subject: [PATCH 07/11] Remove panic in context.rs (#907) * Remove unwraps * Add NativeAssertError with backtrace and location * Use backtrace or location * Remove panic for error handling * Make panic compatible * Move to panic module * Fix message * Rename abstractoin * Revert * Add documentation * Support multiple args * Fix clippy * Rename * Fix message * Use ParseAttributeError * Remove panic * Add native_assert macro * Fix native assert macro --- src/context.rs | 27 ++++++++++++--------------- src/error.rs | 3 ++- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/context.rs b/src/context.rs index f868c0faa..f263856f0 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,5 +1,5 @@ use crate::{ - error::Error, + error::{panic::ToNativeAssertError, Error}, ffi::{get_data_layout_rep, get_target_triple}, metadata::{ gas::{GasMetadata, MetadataComputationConfig}, @@ -7,6 +7,7 @@ use crate::{ MetadataStorage, }, module::NativeModule, + native_assert, utils::run_pass_manager, }; use cairo_lang_sierra::{ @@ -150,9 +151,11 @@ impl NativeContext { ]) .add_regions([module_region]) .build()?; - assert!(op.verify(), "module operation is not valid"); - let mut module = Module::from_operation(op).expect("module failed to create"); + native_assert!(op.verify(), "module operation should be valid"); + + let mut module = Module::from_operation(op) + .to_native_assert_error("value should be module operation")?; let has_gas_builtin = program .type_declarations @@ -193,22 +196,19 @@ impl NativeContext { if let Ok(x) = std::env::var("NATIVE_DEBUG_DUMP") { if x == "1" || x == "true" { - std::fs::write("dump-prepass.mlir", module.as_operation().to_string()) - .expect("should work"); + std::fs::write("dump-prepass.mlir", module.as_operation().to_string())?; std::fs::write( "dump-prepass-debug-valid.mlir", module.as_operation().to_string_with_flags( OperationPrintingFlags::new().enable_debug_info(true, false), )?, - ) - .expect("failed to write dump-prepass-debug-valid.mlir"); + )?; std::fs::write( "dump-prepass-debug-pretty.mlir", module.as_operation().to_string_with_flags( OperationPrintingFlags::new().enable_debug_info(true, false), )?, - ) - .expect("failed to writedump-prepass-debug-pretty.mlir"); + )?; } } @@ -220,22 +220,19 @@ impl NativeContext { if let Ok(x) = std::env::var("NATIVE_DEBUG_DUMP") { if x == "1" || x == "true" { - std::fs::write("dump.mlir", module.as_operation().to_string()) - .expect("should work"); + std::fs::write("dump.mlir", module.as_operation().to_string())?; std::fs::write( "dump-debug-pretty.mlir", module.as_operation().to_string_with_flags( OperationPrintingFlags::new().enable_debug_info(true, false), )?, - ) - .expect("failed to write dump-debug-pretty.mlir"); + )?; std::fs::write( "dump-debug.mlir", module.as_operation().to_string_with_flags( OperationPrintingFlags::new().enable_debug_info(true, false), )?, - ) - .expect("failed to write dump-debug.mlir"); + )?; } } diff --git a/src/error.rs b/src/error.rs index ab2e95e57..973d29c8b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -188,6 +188,8 @@ pub mod panic { }; } + /// Macro that mimicks the behaviour of `assert!`. + /// It should only be used inside of a function that returns Result #[macro_export] macro_rules! native_assert { ($cond:expr, $($arg:tt)*) => { @@ -196,7 +198,6 @@ pub mod panic { } }; } - /// If `RUST_BACKTRACE` env var is not set, then the backtrace won't be captured. /// In that case, only the location is saved, which is better than nothing. #[derive(Debug)] From 0366750212af9ce35917e167c715efa01d56afb3 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Wed, 20 Nov 2024 05:33:24 -0300 Subject: [PATCH 08/11] Fix compare head vs base ci (#935) * debug * change gas usize to gas u128 * clippy * fix usize problem * fix usize problem * check error * try fix * try fix * try fix * try fix * try fix * check error * try fix * reestructure * reestructure * fix * fix * fix * fix * fix * fix * fix --- .github/workflows/bench-hyperfine.yml | 141 ++++++++++++++------------ 1 file changed, 78 insertions(+), 63 deletions(-) diff --git a/.github/workflows/bench-hyperfine.yml b/.github/workflows/bench-hyperfine.yml index d2948dd7f..ff113f305 100644 --- a/.github/workflows/bench-hyperfine.yml +++ b/.github/workflows/bench-hyperfine.yml @@ -92,7 +92,7 @@ jobs: strategy: matrix: branch: [ base, head ] - name: Build cairo-native-run for ${{ matrix.branch }} + name: Build Binary for ${{ matrix.branch }} runs-on: ubuntu-24.04 steps: - name: Cache binary @@ -129,11 +129,9 @@ jobs: sudo rm -rf /usr/share/dotnet/ sudo rm -rf /usr/local/lib/android df -h - - name: Install Rust if: ${{ steps.cache-binary.outputs.cache-hit != 'true' || steps.cache-library.outputs.cache-hit != 'true' }} uses: dtolnay/rust-toolchain@1.82.0 - - name: add llvm deb repository if: ${{ steps.cache-binary.outputs.cache-hit != 'true' || steps.cache-library.outputs.cache-hit != 'true' }} uses: myci-actions/add-deb-repo@11 @@ -141,7 +139,6 @@ jobs: repo: deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main repo-name: llvm-repo keys-asc: https://apt.llvm.org/llvm-snapshot.gpg.key - - name: Install LLVM if: ${{ steps.cache-binary.outputs.cache-hit != 'true' || steps.cache-library.outputs.cache-hit != 'true' }} run: sudo apt-get update && sudo apt-get install llvm-19 llvm-19-dev llvm-19-runtime clang-19 clang-tools-19 lld-19 libpolly-19-dev libmlir-19-dev mlir-19-tools @@ -164,87 +161,105 @@ jobs: cp target/release/cairo-native-run bin/cairo-native-run-${{ matrix.branch }} cp target/release/libcairo_native_runtime.a lib/libcairo-native-runtime-${{ matrix.branch }}.a - hyperfine-prs: - name: Bench PR (linux, amd64) - needs: [ build-binaries ] - runs-on: ubuntu-24.04 + run-bench: env: - PROGRAM: fib_2M - OUTPUT_DIR: bench-outputs + MLIR_SYS_190_PREFIX: /usr/lib/llvm-19/ + LLVM_SYS_191_PREFIX: /usr/lib/llvm-19/ + TABLEGEN_190_PREFIX: /usr/lib/llvm-19/ + RUST_LOG: cairo_native=debug,cairo_native_test=debug + strategy: + matrix: + branch: [ base, head ] + name: Run benches for ${{ matrix.branch }} + runs-on: ubuntu-24.04 + needs: [ build-binaries ] steps: - - uses: actions/checkout@v4 + - name: Checkout base commit + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request[matrix.branch].sha }} - name: Install Hyperfine uses: taiki-e/install-action@v2 with: tool: hyperfine@1.16 - - name: Fetch base binary + - name: Fetch ${{ matrix.branch }} binary uses: actions/cache/restore@v3 with: - path: bin/cairo-native-run-base - key: binary-${{ github.event.pull_request.base.sha }} - - - name: Fetch HEAD binary - uses: actions/cache/restore@v3 - with: - path: bin/cairo-native-run-head - key: binary-${{ github.event.pull_request.head.sha }} - - - name: Fetch base runtime-library - uses: actions/cache/restore@v3 - with: - path: lib/libcairo-native-runtime-base.a - key: library-${{ github.event.pull_request.base.sha }} + path: bin/cairo-native-run-${{ matrix.branch }} + key: binary-${{ github.event.pull_request[matrix.branch].sha }} - - name: Fetch head runtime-library + - name: Fetch ${{ matrix.branch }} runtime-library uses: actions/cache/restore@v3 with: - path: lib/libcairo-native-runtime-head.a - key: library-${{ github.event.pull_request.head.sha }} - - - name: Build Dependencies - run: make deps + path: lib/libcairo-native-runtime-${{ matrix.branch }}.a + key: library-${{ github.event.pull_request[matrix.branch].sha }} - name: Run Program run: | - mkdir $OUTPUT_DIR - cp programs/benches/*.cairo $OUTPUT_DIR - for f in $OUTPUT_DIR/*.cairo; do + make deps + mkdir bench-results-${{ matrix.branch }} + cp programs/benches/*.cairo bench-results-${{ matrix.branch }} + for f in bench-results-${{ matrix.branch }}/*.cairo; do hyperfine \ + --show-output \ --export-markdown "${f%.*}.md" \ --export-json "${f%.*}.json" \ --warmup 3 \ - -n "head $(basename $f) (JIT)" "./bin/cairo-native-run-head --run-mode=jit -s $f --opt-level 3 --available-gas 18446744073709551615" \ - -n "base $(basename $f) (JIT)" "./bin/cairo-native-run-base --run-mode=jit -s $f --opt-level 3 --available-gas 18446744073709551615" \ - -n "head $(basename $f) (AOT)" "CAIRO_NATIVE_RUNTIME_LIBRARY=lib/libcairo-native-runtime-head.a ./bin/cairo-native-run-head --run-mode=aot -s $f --opt-level 3 --available-gas 18446744073709551615" \ - -n "base $(basename $f) (AOT)" "CAIRO_NATIVE_RUNTIME_LIBRARY=lib/libcairo-native-runtime-base.a ./bin/cairo-native-run-base --run-mode=aot -s $f --opt-level 3 --available-gas 18446744073709551615" \ + -n "${{matrix.branch}} $(basename $f) (JIT)" "./bin/cairo-native-run-${{ matrix.branch }} --run-mode=jit -s $f --opt-level 3 --available-gas 18446744073709551615" \ + -n "${{matrix.branch}} $(basename $f) (AOT)" "CAIRO_NATIVE_RUNTIME_LIBRARY=lib/libcairo-native-runtime-${{ matrix.branch }}.a ./bin/cairo-native-run-${{ matrix.branch }} --run-mode=aot -s $f --opt-level 3 --available-gas 18446744073709551615" \ >> /dev/stderr done - - name: Print tables - run: | - { - echo "${bold}Benchmark results Main vs HEAD.${normal}" - for f in $OUTPUT_DIR/*.md; do - echo - cat $f - done - } | tee -a comment_body.md - - name: Find Bench Comment - continue-on-error: true - uses: peter-evans/find-comment@v3 - id: fc + - name: Upload benches ${{matrix.branch}} + uses: actions/upload-artifact@v4 with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: "github-actions[bot]" - body-includes: Benchmark results Main vs HEAD + name: results-${{matrix.branch}} + path: bench-results-${{matrix.branch}} - - name: Create or update bench comment - continue-on-error: true - uses: peter-evans/create-or-update-comment@v4 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body-path: comment_body.md - edit-mode: replace + show-outputs: + name: Print Bench Results + runs-on: ubuntu-24.04 + needs: [ run-bench ] + steps: + - name: Fetch Base Result + uses: actions/download-artifact@v4 + with: + name: results-base + path: bench-results-base + + - name: Fetch Head Result + uses: actions/download-artifact@v4 + with: + name: results-head + path: bench-results-head + + - name: Print tables + run: | + { + echo "${bold}Benchmark results Main vs HEAD.${normal}" + for f in bench-results-base/*.md; do + echo + cat $f + cat bench-results-head/$(basename $f) + done + } | tee -a comment_body.md + + - name: Find Bench Comment + continue-on-error: true + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: "github-actions[bot]" + body-includes: Benchmark results Main vs HEAD + + - name: Create or update bench comment + continue-on-error: true + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body-path: comment_body.md + edit-mode: replace From 3830367b994320556953f5d632a118b6261c03bf Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Wed, 20 Nov 2024 05:33:38 -0300 Subject: [PATCH 09/11] Remove panics in arch.rs (#926) * remove panics * format --- src/arch.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/arch.rs b/src/arch.rs index 6017e3158..6a4b6efa1 100644 --- a/src/arch.rs +++ b/src/arch.rs @@ -1,5 +1,6 @@ use crate::{ - error, + error::Result, + native_panic, starknet::{ArrayAbi, Secp256k1Point, Secp256r1Point}, types::TypeBuilder, utils::libc_malloc, @@ -23,7 +24,7 @@ mod x86_64; pub trait AbiArgument { /// Serialize the argument into the buffer. This method should keep track of arch-dependent /// stuff like register vs stack allocation. - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), error::Error>; + fn to_bytes(&self, buffer: &mut Vec) -> Result<()>; } /// A wrapper that implements `AbiArgument` for `Value`s. It contains all the required stuff to @@ -42,7 +43,7 @@ impl<'a> ValueWithInfoWrapper<'a> { &'b self, value: &'b Value, type_id: &'b ConcreteTypeId, - ) -> Result, error::Error> + ) -> Result> where 'b: 'a, { @@ -57,7 +58,7 @@ impl<'a> ValueWithInfoWrapper<'a> { } impl<'a> AbiArgument for ValueWithInfoWrapper<'a> { - fn to_bytes(&self, buffer: &mut Vec) -> Result<(), error::Error> { + fn to_bytes(&self, buffer: &mut Vec) -> Result<()> { match (self.value, self.info) { (value, CoreTypeConcrete::Box(info)) => { let ptr = value.to_ptr(self.arena, self.registry, self.type_id)?; @@ -102,7 +103,9 @@ impl<'a> AbiArgument for ValueWithInfoWrapper<'a> { abi.until.to_bytes(buffer)?; abi.capacity.to_bytes(buffer)?; } - (Value::BoundedInt { .. }, CoreTypeConcrete::BoundedInt(_)) => todo!(), + (Value::BoundedInt { .. }, CoreTypeConcrete::BoundedInt(_)) => { + native_panic!("todo: implement AbiArgument for Value::BoundedInt case") + } (Value::Bytes31(value), CoreTypeConcrete::Bytes31(_)) => value.to_bytes(buffer)?, (Value::EcPoint(x, y), CoreTypeConcrete::EcPoint(_)) => { x.to_bytes(buffer)?; @@ -141,7 +144,7 @@ impl<'a> AbiArgument for ValueWithInfoWrapper<'a> { ) => value.to_bytes(buffer)?, (Value::Felt252Dict { .. }, CoreTypeConcrete::Felt252Dict(_)) => { #[cfg(not(feature = "with-runtime"))] - unimplemented!("enable the `with-runtime` feature to use felt252 dicts"); + native_panic!("enable the `with-runtime` feature to use felt252 dicts"); // TODO: Assert that `info.ty` matches all the values' types. @@ -183,8 +186,8 @@ impl<'a> AbiArgument for ValueWithInfoWrapper<'a> { (Value::Uint32(value), CoreTypeConcrete::Uint32(_)) => value.to_bytes(buffer)?, (Value::Uint64(value), CoreTypeConcrete::Uint64(_)) => value.to_bytes(buffer)?, (Value::Uint8(value), CoreTypeConcrete::Uint8(_)) => value.to_bytes(buffer)?, - _ => todo!( - "abi argument unimplemented for ({:?}, {:?})", + _ => native_panic!( + "todo: abi argument unimplemented for ({:?}, {:?})", self.value, self.type_id ), From 5e60089288c461eca98bf3dbe03cc882778ff677 Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 20 Nov 2024 16:05:44 +0100 Subject: [PATCH 10/11] cairo 2.9.0-dev (native v0.2.3 branch) (#877) * update to cairo 2.9.0-dev * compile * avoid semver auto update * Implement get_class_hash_at syscall (#880) * implement get_class_hash_at syscall * fix * int range * upd * add fixes * fix test * fi * Version 0.2.2-alpha.0 * fix * ci * upd replay * fix * fix * fixes * seq rev * version 0.2.3 * update ci * fix * readme * Update examples/erc20.rs Co-authored-by: MrAzteca * Update examples/starknet.rs Co-authored-by: MrAzteca * edits * native panic --------- Co-authored-by: Pedro Fontana Co-authored-by: MrAzteca --- .github/workflows/daily.yml | 2 +- .github/workflows/starknet-blocks.yml | 4 +- Cargo.lock | 184 +++++++++++-------- Cargo.toml | 36 ++-- Makefile | 2 +- README.md | 2 +- examples/erc20.rs | 8 + examples/starknet.rs | 8 + runtime/Cargo.toml | 4 +- scripts/bench-hyperfine.sh | 1 - src/bin/cairo-native-test.rs | 18 +- src/bin/utils/mod.rs | 1 + src/debug.rs | 6 + src/executor.rs | 2 + src/executor/contract.rs | 4 +- src/libfuncs.rs | 4 + src/libfuncs/int_range.rs | 181 ++++++++++++++++++ src/libfuncs/starknet.rs | 161 ++++++++++++++++ src/starknet.rs | 45 ++++- src/starknet_stub.rs | 8 + src/types.rs | 23 ++- src/types/int_range.rs | 46 +++++ src/values.rs | 59 ++++++ tests/common.rs | 27 +-- tests/tests/starknet/keccak.rs | 2 +- tests/tests/starknet/programs/syscalls.cairo | 7 +- tests/tests/starknet/secp256.rs | 8 + tests/tests/starknet/syscalls.rs | 28 +++ 28 files changed, 754 insertions(+), 127 deletions(-) create mode 100644 src/libfuncs/int_range.rs create mode 100644 src/types/int_range.rs diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index afc85ace7..b8f26d7f1 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -7,7 +7,7 @@ on: env: RANGE_SIZE: 25 - SEQUENCER_REV: 93b6da848802297626556950a0c715952aca552d + SEQUENCER_REV: 8d3e6b5515e7b62e7ab173026b2c81c750dbb853 jobs: run: diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 74d9df246..50f1b2759 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -27,7 +27,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 with: - key: "ref-3da09d1b6f3d5c089900f5521cf05b6444893e61" + key: "ref-16302c859b1aacc019eea154a58eddc7b32050c1" - name: Check and free hdd space left if: ${{ matrix.runner == 'native' }} @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v4 with: repository: lambdaclass/starknet-replay - ref: 3da09d1b6f3d5c089900f5521cf05b6444893e61 + ref: 16302c859b1aacc019eea154a58eddc7b32050c1 path: replay - name: Install Starknet Replay deps diff --git a/Cargo.lock b/Cargo.lock index 54aafac03..ad90db644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,9 +427,9 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4d6659539ace9649c8e8a7434e51b0c50a7a700111d0a2b967dde220ddff49" +checksum = "e1e0dcdb6358bb639dd729546611bd99bada94c86e3f262c3637855abea9a972" dependencies = [ "cairo-lang-utils", "indoc", @@ -441,9 +441,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2016966ed29f3a44487fd1bbdb05320fb6ea8ec46201c04c6b222ccb5264e0a" +checksum = "b8657f5a5611f341a85e80ba0b21848fc34bfdf391bfd93df0baf4516c3e4159" dependencies = [ "anyhow", "cairo-lang-defs", @@ -467,18 +467,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c804649297ca417206435ee3e8041d2100cc31ebf4a95bc4b92ed02dc63469" +checksum = "0635aa554d297acefe6a35b495aba2795d0af5b7f97c4ab63829c7d62291ef41" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fbda467ac36f73bb1879e1f741898fc719d6f9239a01cc422e6a023281319b" +checksum = "86b356e1c09898e8b8cfdd9731579d89365a13d8b4f7e717962e0cc7d125b83c" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -493,9 +493,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c843ef4715e3d21de5388d02206db2506e2d2ec0e80e2629e0ae9900a08b8674" +checksum = "2dfe7c6ff96182da29012b707a3554e34a50f19cc96013ee45b0eb36dd396ec8" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a416c5871960fb4823160ebef2abc51e0c1b86fef1e97a1ebb2e5f3c3795d3" +checksum = "723d244465309d5409e297b5486d62cbec06f2c47b05044414bb640e3f14caab" dependencies = [ "cairo-lang-utils", "good_lp", @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47189e0cb84b21defd201af4cf24a94c6b0d09f48706cf659c9ffa0def8a7a43" +checksum = "237030772ae5368f19a9247e1f63f753f8ad8de963477166e402f4825c0a141d" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -526,13 +526,14 @@ dependencies = [ "semver", "serde", "smol_str", + "toml", ] [[package]] name = "cairo-lang-formatter" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6409ff1f4a93ce7c0968d9d857d2a8c03657617a827159d33f978110b718b31d" +checksum = "5b71f0eb3a36a6cb5f7f07843926783c4c17e44c9516b53171727a108782f3eb" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -545,15 +546,14 @@ dependencies = [ "itertools 0.12.1", "rust-analyzer-salsa", "serde", - "smol_str", "thiserror", ] [[package]] name = "cairo-lang-lowering" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e224e006c82ef21bd9e243390992de2be25ae6fbbdaa8544067b3f0c31977f1" +checksum = "7d095d78e2f1de499429c95655d6135a3d24c384b36d8de9f84e0aa4e07ee152" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -568,6 +568,7 @@ dependencies = [ "itertools 0.12.1", "log", "num-bigint", + "num-integer", "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", @@ -575,9 +576,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb260ba349c2b699639e56f9b64deb969ff01179a0253087e2c8ceec7e32157" +checksum = "bb828af7f948a3ef7fa65de14e3f639daedefb046dfefcad6e3116d2cb0f89a0" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -595,9 +596,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a2e500dc8ddea4d25a866d8a839158b0e4c41a6c023f21911e2da252bd91b3" +checksum = "135a600043bf7030eacc6ebf2a609c2364d6ffeb04e1f3c809a2738f6b02c829" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -614,9 +615,9 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d72f17373740f242d6995e896b9195c2cedff7e8b14e496afdd16b405039d1fb" +checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" dependencies = [ "cairo-lang-debug", "quote", @@ -625,9 +626,9 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13294f08d2013fcd6e815e7235935680963dec3390e5baf454f33da866fc44b6" +checksum = "23cc37b7f8889cdea631aeea3bcc70d5c86ac8fb1d98aabc83f16283d60f1643" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -639,9 +640,9 @@ dependencies = [ [[package]] name = "cairo-lang-runner" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b9e6a21d92255b92f64c60658b4224dd7d290cde8beea783fadc10fbfcd8c" +checksum = "7474375528ffa7f47e343983d32051898e4e7b05ac0bdc48ee84b1325d8b562a" dependencies = [ "ark-ff", "ark-secp256k1", @@ -655,7 +656,7 @@ dependencies = [ "cairo-lang-sierra-type-size", "cairo-lang-starknet", "cairo-lang-utils", - "cairo-vm", + "cairo-vm 1.0.1", "itertools 0.12.1", "keccak", "num-bigint", @@ -670,9 +671,9 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6936215bca75c23e71873998420a3d46c322507a09917ce676c8d39f8c1bd6fe" +checksum = "c560cf4b4a89325d3a9594f490fffee38cf30e0990e808bb927619de9d0c973a" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -696,9 +697,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424f55450494e959c1ae26c52a71075767a90f76e3ecca6e81056dd7517e8ba0" +checksum = "8118f55ca7d567bfc60960b445d388564d04bf48335c983b1595cb35f67a01c5" dependencies = [ "anyhow", "cairo-lang-utils", @@ -723,9 +724,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053dd520e0b9d1c1078d93ea69045f6f334c3d41b4b75db183ab33e32cfd8570" +checksum = "2716ef8d4ce0fb700f83ed3281f3656436570e60249d41c65c79dc1ca27be002" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -739,9 +740,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a73227867377efc62ebb893cddaa88df3940bf2be5dbdc2f0b00f9edf69288e" +checksum = "24a44da87a35845470c4f4c648225232a15e0875fe809045b6088464491f838b" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -755,9 +756,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3752cacd475ea089d9a536357804150e693a124e703fcc33a55566d568094b3" +checksum = "15bc5cf9f3965a7030a114dfe3d31d183287fbfbfbf904deaaa2468cadb936aa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -779,9 +780,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7162fb3c93960dfc6d8005b65064e518e3f1ed6102e8981b42ea41879c331184" +checksum = "18b7616f1a3c41c4646094b5abf774e558428e9c1eda5d78d7b0638ec5c264e5" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -800,9 +801,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b80c117e2b05a6d300f2e2247892cc99e42e950e79f6085e6ed6cbcb44d12" +checksum = "871077dbc08df5d134dc3975538171c14b266ba405d1298085afdb227216f0a3" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -810,9 +811,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafaabc43f78dfa2f45d935993ba21c05c164bbb3bf277d348847a51e5939a9f" +checksum = "9f21804eb8931d41e258e7a393afc8ee8858308e95b3ed2e9b6b469ef68a6a50" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -840,9 +841,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832fd9072ddf4204ca6d227c0238929349f10146bd066a98025d51ac15d27fad" +checksum = "b2496bccd68fa0286b35b72c98439316a3a872ef7ec6d881f0dac90b17997490" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -863,9 +864,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cebe67c0d68f9acf8709d170c1308ca57a778d22f70da38a57f74ae250eee28a" +checksum = "8d77ea2e35d3610098ff13e373fc519aedc6a5096ed8547081aacfc104ef4422" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -879,9 +880,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31cef5b4347626e61bad8f070495cd35d637a5cb6744c34d20dd382c7431aff8" +checksum = "6b01d505ab26ca9ce829faf3a8dd097f5d7962d2eb8f136017a260694a6a72e8" dependencies = [ "genco", "xshell", @@ -889,9 +890,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-plugin" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5f036132e07b7829cb1d61b1ecc02789a70c7d16b2733722a2aca992492bc3" +checksum = "05f83e082c8ebf81295156f13399f880037c749a9f1fc3f55b1be7e49fe124c6" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -916,9 +917,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060c61ac4a3ae0428771244ff8db903105f127392b7d725d919fe3fb1ec4132f" +checksum = "eb143a22f5a3510df8c4dec76e17c1e36bbcbddcd7915601f6a51a72418c454f" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -929,9 +930,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.8.4" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bfc6372538143afad658c853a35bdc9f5210c5cb54e0c8f04ab78e268139466" +checksum = "35df943ebcf8e1db11ee9f4f46f843dde5b71639ca79ea0d8caa7973f91d8b12" dependencies = [ "hashbrown 0.14.5", "indexmap 2.6.0", @@ -944,7 +945,7 @@ dependencies = [ [[package]] name = "cairo-native" -version = "0.2.0-alpha.4" +version = "0.2.3" dependencies = [ "anyhow", "aquamarine", @@ -967,7 +968,7 @@ dependencies = [ "cairo-lang-test-plugin", "cairo-lang-utils", "cairo-native-runtime", - "cairo-vm", + "cairo-vm 2.0.0-rc0", "cc", "clap", "colored", @@ -1007,7 +1008,7 @@ dependencies = [ [[package]] name = "cairo-native-runtime" -version = "0.2.0-alpha.4" +version = "0.2.3" dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", @@ -1023,6 +1024,37 @@ name = "cairo-vm" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58363ad8065ed891e3b14a8191b707677c7c7cb5b9d10030822506786d8d8108" +dependencies = [ + "anyhow", + "bincode", + "bitvec", + "generic-array", + "hashbrown 0.14.5", + "hex", + "keccak", + "lazy_static", + "nom", + "num-bigint", + "num-integer", + "num-prime", + "num-traits 0.2.19", + "rand", + "rust_decimal", + "serde", + "serde_json", + "sha2", + "sha3", + "starknet-crypto", + "starknet-types-core", + "thiserror-no-std", + "zip", +] + +[[package]] +name = "cairo-vm" +version = "2.0.0-rc0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db4375450795765e55bf6c58974b26742a1a3935afd07f996062d7d2e545b4a4" dependencies = [ "anyhow", "ark-ff", @@ -1051,6 +1083,7 @@ dependencies = [ "starknet-crypto", "starknet-types-core", "thiserror-no-std", + "wasm-bindgen", "zip", ] @@ -2132,9 +2165,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -3898,20 +3931,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", - "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -3924,9 +3956,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3934,9 +3966,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -3947,15 +3979,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index cd5988623..01020d53e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native" -version = "0.2.0-alpha.4" +version = "0.2.3" edition = "2021" license = "Apache-2.0" description = "A compiler to convert Cairo's intermediate representation Sierra code to MLIR." @@ -59,12 +59,12 @@ normal = ["aquamarine"] [dependencies] aquamarine = "0.5.0" bumpalo = "3.16.0" -cairo-lang-compiler = "2.8.4" -cairo-lang-defs = "2.8.4" -cairo-lang-filesystem = "2.8.4" -cairo-lang-semantic = "2.8.4" -cairo-lang-sierra = "2.8.4" -cairo-lang-sierra-generator = "2.8.4" +cairo-lang-compiler = "2.9.0-dev.0" +cairo-lang-defs = "2.9.0-dev.0" +cairo-lang-filesystem = "2.9.0-dev.0" +cairo-lang-semantic = "2.9.0-dev.0" +cairo-lang-sierra = "2.9.0-dev.0" +cairo-lang-sierra-generator = "2.9.0-dev.0" educe = "0.5.11" # can't update until https://github.com/magiclen/educe/issues/27 itertools = "0.13.0" lazy_static = "1.5" @@ -86,12 +86,12 @@ utf8_iter = "1.0.4" # CLI dependencies -cairo-lang-sierra-ap-change = "2.8.4" -cairo-lang-sierra-gas = "2.8.4" -cairo-lang-starknet = "2.8.4" -cairo-lang-utils = "2.8.4" -cairo-lang-starknet-classes = "2.8.4" -cairo-native-runtime = { version = "0.2.0-alpha.4", path = "runtime", optional = true } +cairo-lang-sierra-ap-change = "2.9.0-dev.0" +cairo-lang-sierra-gas = "2.9.0-dev.0" +cairo-lang-starknet = "2.9.0-dev.0" +cairo-lang-utils = "2.9.0-dev.0" +cairo-lang-starknet-classes = "2.9.0-dev.0" +cairo-native-runtime = { version = "0.2.3", path = "runtime", optional = true } clap = { version = "4.5.19", features = ["derive"], optional = true } libloading = "0.8.5" tracing-subscriber = { version = "0.3.18", features = [ @@ -101,8 +101,8 @@ tracing-subscriber = { version = "0.3.18", features = [ ], optional = true } serde = { version = "1.0", features = ["derive"] } anyhow = { version = "1.0", optional = true } -cairo-lang-test-plugin = { version = "2.8.4", optional = true } -cairo-lang-runner = { version = "2.8.4", optional = true } +cairo-lang-test-plugin = { version = "2.9.0-dev.0", optional = true } +cairo-lang-runner = { version = "2.9.0-dev.0", optional = true } colored = { version = "2.1.0", optional = true } # needed to interface with cairo-lang-* keccak = "0.1.5" @@ -120,9 +120,9 @@ ark-ff = "0.4.2" num-integer = "0.1.46" [dev-dependencies] -cairo-vm = { version = "1.0.1", features = ["cairo-1-hints"] } -cairo-lang-runner = "2.8.4" -cairo-lang-semantic = { version = "2.8.4", features = ["testing"] } +cairo-vm = { version = "2.0.0-rc0", features = ["cairo-1-hints"] } +cairo-lang-runner = "2.9.0-dev.0" +cairo-lang-semantic = { version = "2.9.0-dev.0", features = ["testing"] } criterion = { version = "0.5.1", features = ["html_reports"] } lambdaworks-math = "0.10.0" pretty_assertions_sorted = "1.2.3" diff --git a/Makefile b/Makefile index 6c6c75318..b028dbcd2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Environment detection. UNAME := $(shell uname) -CAIRO_2_VERSION = 2.8.4 +CAIRO_2_VERSION = 2.9.0-dev.0 SCARB_VERSION = 2.8.4 # Usage is the default target for newcomers running `make`. diff --git a/README.md b/README.md index 9a831e594..80ccd68d8 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,7 @@ Options: ### Requirements - [hyperfine](https://github.com/sharkdp/hyperfine): `cargo install hyperfine` -- [cairo 2.8.2](https://github.com/starkware-libs/cairo) +- [cairo 2.9.0-dev.0](https://github.com/starkware-libs/cairo) - Cairo Corelibs - LLVM 19 with MLIR diff --git a/examples/erc20.rs b/examples/erc20.rs index 346b4decf..b36d2947d 100644 --- a/examples/erc20.rs +++ b/examples/erc20.rs @@ -274,6 +274,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } fn main() { diff --git a/examples/starknet.rs b/examples/starknet.rs index 2a9c570e7..e64716325 100644 --- a/examples/starknet.rs +++ b/examples/starknet.rs @@ -405,6 +405,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } fn main() { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index cdf46ad32..ac403ac91 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cairo-native-runtime" -version = "0.2.0-alpha.4" +version = "0.2.3" description = "The runtime for cairo-native." edition = "2021" license = "Apache-2.0" @@ -15,7 +15,7 @@ starknet-types-core = { version = "0.1.7", default-features = false, features = "serde", "hash", ] } -cairo-lang-sierra-gas = "2.8.4" +cairo-lang-sierra-gas = "2.9.0-dev.0" starknet-curve = "0.5.1" lazy_static = "1.5.0" rand = "0.8.5" diff --git a/scripts/bench-hyperfine.sh b/scripts/bench-hyperfine.sh index 473c67265..aa02a1e94 100755 --- a/scripts/bench-hyperfine.sh +++ b/scripts/bench-hyperfine.sh @@ -57,7 +57,6 @@ run_bench() { -L"$OUTPUT_DIR/" \ -Wl,-rpath "$MLIR_DIR/lib" \ -Wl,-rpath "$OUTPUT_DIR" \ - -Wl,--rpath-link "$OUTPUT_DIR" \ -l"$base_name" \ -lm \ -o "$OUTPUT_DIR/$base_name-march-native" \ diff --git a/src/bin/cairo-native-test.rs b/src/bin/cairo-native-test.rs index b69a48b5c..cb39f4f8d 100644 --- a/src/bin/cairo-native-test.rs +++ b/src/bin/cairo-native-test.rs @@ -1,6 +1,7 @@ use anyhow::bail; use cairo_lang_compiler::{ db::RootDatabase, + diagnostics::DiagnosticsReporter, project::{check_compiler_path, setup_project}, }; use cairo_lang_filesystem::cfg::{Cfg, CfgSet}; @@ -83,15 +84,18 @@ fn main() -> anyhow::Result<()> { starknet: args.starknet, add_statements_functions: false, add_statements_code_locations: false, + contract_declarations: None, + contract_crate_ids: None, + executable_crate_ids: None, }; - let build_test_compilation = compile_test_prepared_db( - &db, - test_config, - main_crate_ids.clone(), - test_crate_ids.clone(), - args.allow_warnings, - )?; + let mut diag_reporter = DiagnosticsReporter::stderr().with_crates(&main_crate_ids); + if args.allow_warnings { + diag_reporter = diag_reporter.allow_warnings(); + } + + let build_test_compilation = + compile_test_prepared_db(&db, test_config, test_crate_ids.clone(), diag_reporter)?; let (compiled, filtered_out) = filter_test_cases( build_test_compilation, diff --git a/src/bin/utils/mod.rs b/src/bin/utils/mod.rs index fc145c5b1..b4cce9a1f 100644 --- a/src/bin/utils/mod.rs +++ b/src/bin/utils/mod.rs @@ -178,6 +178,7 @@ fn jitvalue_to_felt(value: &Value) -> Vec { vec![x.lo.into(), x.hi.into(), y.lo.into(), y.hi.into()] } Value::Null => vec![0.into()], + Value::IntRange { x, y } => [jitvalue_to_felt(x), jitvalue_to_felt(y)].concat(), } } diff --git a/src/debug.rs b/src/debug.rs index 93c0555b4..0c3799290 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -24,6 +24,7 @@ use cairo_lang_sierra::extensions::{ nullable::NullableConcreteLibfunc, pedersen::PedersenConcreteLibfunc, poseidon::PoseidonConcreteLibfunc, + range::IntRangeConcreteLibfunc, starknet::{ secp256::{Secp256ConcreteLibfunc, Secp256OpConcreteLibfunc}, testing::TestingConcreteLibfunc, @@ -371,6 +372,7 @@ pub fn libfunc_to_name(value: &CoreConcreteLibfunc) -> &'static str { StarkNetConcreteLibfunc::Sha256ProcessBlock(_) => "sha256_process_block", StarkNetConcreteLibfunc::Sha256StateHandleInit(_) => "sha256_state_handle_init", StarkNetConcreteLibfunc::Sha256StateHandleDigest(_) => "sha256_state_handle_digest", + StarkNetConcreteLibfunc::GetClassHashAt(_) => "get_class_hash_at_syscall", }, CoreConcreteLibfunc::Debug(value) => match value { DebugConcreteLibfunc::Print(_) => "debug_print", @@ -407,5 +409,9 @@ pub fn libfunc_to_name(value: &CoreConcreteLibfunc) -> &'static str { BoundedIntConcreteLibfunc::IsZero(_) => "bounded_int_is_zero", BoundedIntConcreteLibfunc::WrapNonZero(_) => "bounded_int_wrap_non_zero", }, + CoreConcreteLibfunc::IntRange(selector) => match selector { + IntRangeConcreteLibfunc::TryNew(_) => "int_range_try_new", + IntRangeConcreteLibfunc::PopFront(_) => "int_range_pop_front", + }, } } diff --git a/src/executor.rs b/src/executor.rs index 86a967193..dad147b76 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -624,6 +624,8 @@ fn parse_result( | CoreTypeConcrete::Uint128MulGuarantee(_) | CoreTypeConcrete::Circuit(_) | CoreTypeConcrete::RangeCheck96(_) => todo!(), + // 2.9.0 + CoreTypeConcrete::IntRange(_) => todo!(), } } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 3051d46d7..848c9ea98 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -727,7 +727,7 @@ mod tests { .unwrap(); assert_eq!(result.return_values, vec![Felt::from(n), Felt::from(n * 2)]); - assert_eq!(result.remaining_gas, 18446744073709548175); + assert_eq!(result.remaining_gas, 18446744073709548475); }); } @@ -797,7 +797,7 @@ mod tests { .unwrap(); assert_eq!(result.return_values, vec![Felt::from(3628800)]); - assert_eq!(result.remaining_gas, 18446744073709533805); + assert_eq!(result.remaining_gas, 18446744073709534105); } #[rstest] diff --git a/src/libfuncs.rs b/src/libfuncs.rs index 7fa94b4cb..b7405efaa 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -43,6 +43,7 @@ mod felt252_dict; mod felt252_dict_entry; mod function_call; mod gas; +mod int_range; mod mem; mod nullable; mod pedersen; @@ -233,6 +234,9 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::BoundedInt(info) => { self::bounded_int::build(context, registry, entry, location, helper, metadata, info) } + Self::IntRange(selector) => self::int_range::build( + context, registry, entry, location, helper, metadata, selector, + ), } } diff --git a/src/libfuncs/int_range.rs b/src/libfuncs/int_range.rs new file mode 100644 index 000000000..38e337bd7 --- /dev/null +++ b/src/libfuncs/int_range.rs @@ -0,0 +1,181 @@ +//! # Int range libfuncs + +use super::LibfuncHelper; +use crate::{ + error::Result, + metadata::MetadataStorage, + types::TypeBuilder, + utils::{BlockExt, ProgramRegistryExt}, +}; +use cairo_lang_sierra::{ + extensions::{ + core::{CoreLibfunc, CoreType}, + lib_func::SignatureOnlyConcreteLibfunc, + range::IntRangeConcreteLibfunc, + ConcreteLibfunc, + }, + program_registry::ProgramRegistry, +}; +use melior::{ + dialect::{ + arith::{self, CmpiPredicate}, + ods, + }, + ir::{Block, Location}, + Context, +}; +use num_bigint::BigInt; + +/// Select and call the correct libfunc builder function from the selector. +pub fn build<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + selector: &IntRangeConcreteLibfunc, +) -> Result<()> { + match selector { + IntRangeConcreteLibfunc::TryNew(info) => { + build_int_range_try_new(context, registry, entry, location, helper, metadata, info) + } + IntRangeConcreteLibfunc::PopFront(info) => { + build_int_range_pop_front(context, registry, entry, location, helper, metadata, info) + } + } +} + +/// Generate MLIR operations for the `int_range_try_new` libfunc. +pub fn build_int_range_try_new<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + let range_check = entry.argument(0)?.into(); + let x = entry.argument(1)?.into(); + let y = entry.argument(2)?.into(); + let range_ty = registry.build_type( + context, + helper, + registry, + metadata, + &info.branch_signatures()[0].vars[1].ty, + )?; + let inner = registry.get_type(&info.param_signatures()[1].ty)?; + // to know if it is signed + let inner_range = inner.integer_range(registry)?; + + let is_valid = if inner_range.lower < BigInt::ZERO { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Sle, x, y, location))? + } else { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Ule, x, y, location))? + }; + + let range = + entry.append_op_result(ods::llvm::mlir_undef(context, range_ty, location).into())?; + + // if the range is not valid, return the empty range [y, y) + let x_val = entry.append_op_result(arith::select(is_valid, x, y, location))?; + let range = entry.insert_values(context, location, range, &[x_val, y])?; + + entry.append_operation(helper.cond_br( + context, + is_valid, + [0, 1], + [&[range_check, range], &[range_check, range]], + location, + )); + Ok(()) +} + +/// Generate MLIR operations for the `int_range_pop_front` libfunc. +pub fn build_int_range_pop_front<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + let range = entry.argument(0)?.into(); + + let inner_ty = registry.build_type( + context, + helper, + registry, + metadata, + &info.branch_signatures()[1].vars[1].ty, + )?; + + let inner = registry.get_type(&info.branch_signatures()[1].vars[1].ty)?; + + let x = entry.extract_value(context, location, range, inner_ty, 0)?; + let k1 = entry.const_int_from_type(context, location, 1, inner_ty)?; + let x_p_1 = entry.append_op_result(arith::addi(x, k1, location))?; + let y = entry.extract_value(context, location, range, inner_ty, 1)?; + + // to know if it is signed + let inner_range = inner.integer_range(registry)?; + + let is_valid = if inner_range.lower < BigInt::ZERO { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Slt, x, y, location))? + } else { + entry.append_op_result(arith::cmpi(context, CmpiPredicate::Ult, x, y, location))? + }; + let range = entry.insert_value(context, location, range, x_p_1, 0)?; + + entry.append_operation(helper.cond_br( + context, + is_valid, + [1, 0], // failure, success + [&[range, x], &[]], + location, + )); + Ok(()) +} + +#[cfg(test)] +mod test { + use crate::{ + utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}, + values::Value, + }; + use cairo_lang_sierra::program::Program; + use lazy_static::lazy_static; + + lazy_static! { + static ref INT_RANGE_TRY_NEW: (String, Program) = load_cairo! { + #[derive(Copy, Drop)] + pub extern type IntRange; + pub extern fn int_range_try_new( + x: T, y: T + ) -> Result, IntRange> implicits(core::RangeCheck) nopanic; + + fn run_test(lhs: u64, rhs: u64) -> IntRange { + int_range_try_new(lhs, rhs).unwrap() + } + }; + } + + #[test] + fn int_range_try_new() { + run_program_assert_output( + &INT_RANGE_TRY_NEW, + "run_test", + &[2u64.into(), 4u64.into()], + jit_enum!( + 0, + jit_struct!(Value::IntRange { + x: Box::new(2u64.into()), + y: Box::new(4u64.into()), + }) + ), + ); + } +} diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index f90cd05ad..9302d5d66 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -142,6 +142,9 @@ pub fn build<'ctx, 'this>( StarkNetConcreteLibfunc::Sha256StateHandleDigest(info) => build_sha256_state_handle_digest( context, registry, entry, location, helper, metadata, info, ), + StarkNetConcreteLibfunc::GetClassHashAt(info) => { + build_get_class_hash_at(context, registry, entry, location, helper, metadata, info) + } #[cfg(feature = "with-cheatcode")] StarkNetConcreteLibfunc::Testing(TestingConcreteLibfunc::Cheatcode(info)) => { self::testing::build(context, registry, entry, location, helper, metadata, info) @@ -2836,6 +2839,164 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( Ok(()) } +pub fn build_get_class_hash_at<'ctx, 'this>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + metadata: &mut MetadataStorage, + info: &SignatureOnlyConcreteLibfunc, +) -> Result<()> { + // Extract self pointer. + let ptr = entry.load( + context, + location, + entry.argument(1)?.into(), + llvm::r#type::pointer(context, 0), + )?; + + // Allocate space for the return value. + let (result_layout, (result_tag_ty, _), variant_tys) = + crate::types::r#enum::get_type_for_variants( + context, + helper, + registry, + metadata, + &[ + info.branch_signatures()[0].vars[2].ty.clone(), + info.branch_signatures()[1].vars[2].ty.clone(), + ], + )?; + + let result_ptr = helper.init_block().alloca1( + context, + location, + llvm::r#type::r#struct( + context, + &[ + result_tag_ty, + llvm::r#type::array( + IntegerType::new(context, 8).into(), + (result_layout.size() - 1).try_into()?, + ), + ], + false, + ), + result_layout.align(), + )?; + + // Allocate space and write the current gas. + let (gas_ty, gas_layout) = registry.build_type_with_layout( + context, + helper, + registry, + metadata, + &info.param_signatures()[0].ty, + )?; + let gas_builtin_ptr = + helper + .init_block() + .alloca1(context, location, gas_ty, gas_layout.align())?; + entry.append_operation(llvm::store( + context, + entry.argument(0)?.into(), + gas_builtin_ptr, + location, + LoadStoreOptions::default(), + )); + + // Allocate `contract_address` argument and write the value. + let contract_address_ptr = helper.init_block().alloca_int(context, location, 252)?; + entry.store( + context, + location, + contract_address_ptr, + entry.argument(2)?.into(), + )?; + + // Extract function pointer. + let fn_ptr = entry.gep( + context, + location, + entry.argument(1)?.into(), + &[GepIndex::Const( + StarknetSyscallHandlerCallbacks::<()>::GET_CLASS_HASH_AT.try_into()?, + )], + pointer(context, 0), + )?; + let fn_ptr = entry.load(context, location, fn_ptr, llvm::r#type::pointer(context, 0))?; + + entry.append_operation( + OperationBuilder::new("llvm.call", location) + .add_operands(&[ + fn_ptr, + result_ptr, + ptr, + gas_builtin_ptr, + contract_address_ptr, + ]) + .build()?, + ); + + let result = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct( + context, + &[ + result_tag_ty, + llvm::r#type::array( + IntegerType::new(context, 8).into(), + (result_layout.size() - 1).try_into()?, + ), + ], + false, + ), + )?; + let result_tag = entry.extract_value( + context, + location, + result, + IntegerType::new(context, 1).into(), + 0, + )?; + + let payload_ok = { + let value = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct(context, &[result_tag_ty, variant_tys[0].0], false), + )?; + entry.extract_value(context, location, value, variant_tys[0].0, 1)? + }; + let payload_err = { + let value = entry.load( + context, + location, + result_ptr, + llvm::r#type::r#struct(context, &[result_tag_ty, variant_tys[1].0], false), + )?; + entry.extract_value(context, location, value, variant_tys[1].0, 1)? + }; + + let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; + + entry.append_operation(helper.cond_br( + context, + result_tag, + [1, 0], + [ + &[remaining_gas, entry.argument(1)?.into(), payload_err], + &[remaining_gas, entry.argument(1)?.into(), payload_ok], + ], + location, + )); + Ok(()) +} + #[cfg(test)] mod test { use crate::utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}; diff --git a/src/starknet.rs b/src/starknet.rs index 58dc42935..58e8faf4c 100644 --- a/src/starknet.rs +++ b/src/starknet.rs @@ -321,6 +321,12 @@ pub trait StarknetSyscallHandler { remaining_gas: &mut u64, ) -> SyscallResult<()>; + fn get_class_hash_at( + &mut self, + contract_address: Felt, + remaining_gas: &mut u64, + ) -> SyscallResult; + #[cfg(feature = "with-cheatcode")] fn cheatcode(&mut self, _selector: Felt, _input: &[Felt]) -> Vec { unimplemented!(); @@ -521,6 +527,14 @@ impl StarknetSyscallHandler for DummySyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } // TODO: Move to the correct place or remove if unused. @@ -797,6 +811,12 @@ pub(crate) mod handler { state: *mut [u32; 8], block: &[u32; 16], ), + get_class_hash_at: extern "C" fn( + result_ptr: &mut SyscallResultAbi, + ptr: &mut T, + gas: &mut u64, + contract_address: &Felt252Abi, + ), // testing syscalls #[cfg(feature = "with-cheatcode")] pub cheatcode: extern "C" fn( @@ -837,7 +857,10 @@ pub(crate) mod handler { pub const SECP256R1_GET_POINT_FROM_X: usize = field_offset!(Self, secp256r1_get_point_from_x) >> 3; pub const SECP256R1_GET_XY: usize = field_offset!(Self, secp256r1_get_xy) >> 3; + pub const SHA256_PROCESS_BLOCK: usize = field_offset!(Self, sha256_process_block) >> 3; + + pub const GET_CLASS_HASH_AT: usize = field_offset!(Self, get_class_hash_at) >> 3; } #[allow(unused_variables)] @@ -871,6 +894,7 @@ pub(crate) mod handler { secp256r1_get_point_from_x: Self::wrap_secp256r1_get_point_from_x, secp256r1_get_xy: Self::wrap_secp256r1_get_xy, sha256_process_block: Self::wrap_sha256_process_block, + get_class_hash_at: Self::wrap_get_class_hash_at, #[cfg(feature = "with-cheatcode")] cheatcode: Self::wrap_cheatcode, } @@ -1116,8 +1140,6 @@ pub(crate) mod handler { }; } - // TODO: change all from_bytes_be to from_bytes_ne when added and undo byte swapping. - extern "C" fn wrap_deploy( result_ptr: &mut SyscallResultAbi<(Felt252Abi, ArrayAbi)>, ptr: &mut T, @@ -1632,6 +1654,25 @@ pub(crate) mod handler { Err(e) => Self::wrap_error(&e), }; } + + extern "C" fn wrap_get_class_hash_at( + result_ptr: &mut SyscallResultAbi, + ptr: &mut T, + gas: &mut u64, + contract_address: &Felt252Abi, + ) { + let result = ptr.get_class_hash_at(contract_address.into(), gas); + + *result_ptr = match result { + Ok(x) => SyscallResultAbi { + ok: ManuallyDrop::new(SyscallResultAbiOk { + tag: 0u8, + payload: ManuallyDrop::new(Felt252Abi(x.to_bytes_le())), + }), + }, + Err(e) => Self::wrap_error(&e), + }; + } } } diff --git a/src/starknet_stub.rs b/src/starknet_stub.rs index 228dc722b..ca8ec9779 100644 --- a/src/starknet_stub.rs +++ b/src/starknet_stub.rs @@ -647,6 +647,14 @@ impl StarknetSyscallHandler for &mut StubSyscallHandler { sha2::compress256(state, &[data_as_bytes]); Ok(()) } + + fn get_class_hash_at( + &mut self, + contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + Ok(contract_address) + } } #[cfg(test)] diff --git a/src/types.rs b/src/types.rs index 3878d8400..0682b73f0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -45,6 +45,7 @@ mod felt252; mod felt252_dict; mod felt252_dict_entry; mod gas_builtin; +mod int_range; mod non_zero; mod nullable; mod pedersen; @@ -430,6 +431,13 @@ impl TypeBuilder for CoreTypeConcrete { metadata, WithSelf::new(self_ty, info), ), + Self::IntRange(info) => self::int_range::build( + context, + module, + registry, + metadata, + WithSelf::new(self_ty, info), + ), } } @@ -533,7 +541,9 @@ impl TypeBuilder for CoreTypeConcrete { | CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::Sha256StateHandle(_)) => todo!(), CoreTypeConcrete::Coupon(_) => false, - CoreTypeConcrete::Circuit(info) => circuit::is_complex(info) + CoreTypeConcrete::Circuit(info) => circuit::is_complex(info), + + CoreTypeConcrete::IntRange(_info) => false }) } @@ -613,6 +623,11 @@ impl TypeBuilder for CoreTypeConcrete { } CoreTypeConcrete::Span(_) => todo!(), CoreTypeConcrete::Circuit(info) => circuit::is_zst(info), + + CoreTypeConcrete::IntRange(info) => { + let type_info = registry.get_type(&info.ty)?; + type_info.is_zst(registry)? + } }) } @@ -718,6 +733,11 @@ impl TypeBuilder for CoreTypeConcrete { CoreTypeConcrete::Coupon(_) => Layout::new::<()>(), CoreTypeConcrete::RangeCheck96(_) => get_integer_layout(64), CoreTypeConcrete::Circuit(info) => circuit::layout(registry, info)?, + + CoreTypeConcrete::IntRange(info) => { + let inner = registry.get_type(&info.ty)?.layout(registry)?; + inner.extend(inner).unwrap().0 + } } .pad_to_align()) } @@ -729,6 +749,7 @@ impl TypeBuilder for CoreTypeConcrete { // Right now, only enums and other structures which may end up passing a flattened enum as // arguments. Ok(match self { + CoreTypeConcrete::IntRange(_) => false, CoreTypeConcrete::Array(_) => false, CoreTypeConcrete::Bitwise(_) => false, CoreTypeConcrete::Box(_) => false, diff --git a/src/types/int_range.rs b/src/types/int_range.rs new file mode 100644 index 000000000..11d901663 --- /dev/null +++ b/src/types/int_range.rs @@ -0,0 +1,46 @@ +//! # Int range of type T +//! +//! A range [x, y) where x <= y +//! +//! ## Layout +//! +//! A struct with 2 fields of type T +//! +//! ``` +//! #[repr(transparent)] +//! pub struct NonZero(pub T); +//! ``` + +use super::WithSelf; +use crate::{error::Result, metadata::MetadataStorage, utils::ProgramRegistryExt}; +use cairo_lang_sierra::{ + extensions::{ + core::{CoreLibfunc, CoreType}, + types::InfoAndTypeConcreteType, + }, + program_registry::ProgramRegistry, +}; +use melior::{ + ir::{Module, Type}, + Context, +}; + +/// Build the MLIR type. +/// +/// Check out [the module](self) for more info. +pub fn build<'ctx>( + context: &'ctx Context, + module: &Module<'ctx>, + registry: &ProgramRegistry, + metadata: &mut MetadataStorage, + info: WithSelf, +) -> Result> { + // TODO: Can its inner type require dup or drop? probably not since they are integers + let inner = registry.build_type(context, module, registry, metadata, &info.ty)?; + + Ok(melior::dialect::llvm::r#type::r#struct( + context, + &[inner, inner], + false, + )) +} diff --git a/src/values.rs b/src/values.rs index 796933dec..5b9d1ff76 100644 --- a/src/values.rs +++ b/src/values.rs @@ -4,6 +4,7 @@ use crate::{ error::{CompilerError, Error}, + native_panic, starknet::{Secp256k1Point, Secp256r1Point}, types::TypeBuilder, utils::{ @@ -76,6 +77,10 @@ pub enum Value { #[serde(with = "range_serde")] range: Range, }, + IntRange { + x: Box, + y: Box, + }, /// Used as return value for Nullables that are null. Null, } @@ -511,6 +516,38 @@ impl Value { Self::Null => { unimplemented!("null is meant as return value for nullable for now") } + Self::IntRange { x, y } => { + if let CoreTypeConcrete::IntRange(info) = Self::resolve_type(ty, registry)? { + let inner = registry.get_type(&info.ty)?; + let inner_layout = inner.layout(registry)?; + + let x_ptr = x.to_ptr(arena, registry, &info.ty)?; + + let (struct_layout, y_offset) = inner_layout.extend(inner_layout)?; + + let y_ptr = y.to_ptr(arena, registry, &info.ty)?; + + let ptr = arena.alloc_layout(struct_layout.pad_to_align()).as_ptr(); + + std::ptr::copy_nonoverlapping( + x_ptr.cast::().as_ptr(), + ptr, + inner_layout.size(), + ); + + std::ptr::copy_nonoverlapping( + y_ptr.cast::().as_ptr(), + ptr.byte_add(y_offset), + inner_layout.size(), + ); + + NonNull::new_unchecked(ptr).cast() + } else { + native_panic!( + "an IntRange value should always have an IntRange CoreTypeConcrete" + ) + } + } } }) } @@ -802,6 +839,28 @@ impl Value { CoreTypeConcrete::Coupon(_) | CoreTypeConcrete::Circuit(_) | CoreTypeConcrete::RangeCheck96(_) => todo!(), + CoreTypeConcrete::IntRange(info) => { + let member = registry.get_type(&info.ty)?; + let member_layout = member.layout(registry)?; + + let x = + Self::from_ptr(NonNull::new(ptr.as_ptr()).unwrap(), &info.ty, registry)?; + + let y = Self::from_ptr( + NonNull::new( + ptr.as_ptr() + .byte_add(member_layout.extend(member_layout)?.1), + ) + .unwrap(), + &info.ty, + registry, + )?; + + Self::IntRange { + x: x.into(), + y: y.into(), + } + } } }) } diff --git a/tests/common.rs b/tests/common.rs index 1ee6d0c4c..39ade8c19 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -21,13 +21,16 @@ use cairo_lang_sierra::{ program::Program, program_registry::ProgramRegistry, }; -use cairo_lang_sierra_generator::replace_ids::DebugReplacer; +use cairo_lang_sierra_generator::replace_ids::{DebugReplacer, SierraIdReplacer}; use cairo_lang_starknet::{ - compile::compile_contract_in_prepared_db, contract::get_contracts_info, starknet_plugin_suite, + compile::compile_contract_in_prepared_db, + contract::{find_contracts, get_contracts_info}, + starknet_plugin_suite, }; use cairo_lang_starknet_classes::{ casm_contract_class::CasmContractClass, contract_class::ContractClass, }; +use cairo_lang_utils::Upcast; use cairo_native::{ context::NativeContext, execution_result::{ContractExecutionResult, ExecutionResult}, @@ -113,11 +116,7 @@ pub fn load_cairo_str(program_str: &str) -> (String, Program, SierraCasmRunner) .unwrap(); fs::write(&mut program_file, program_str).unwrap(); - let mut db = RootDatabase::default(); - init_dev_corelib( - &mut db, - Path::new(&var("CARGO_MANIFEST_DIR").unwrap()).join("corelib/src"), - ); + let mut db = RootDatabase::builder().detect_corelib().build().unwrap(); let main_crate_ids = setup_project(&mut db, program_file.path()).unwrap(); let sierra_program_with_dbg = compile_prepared_db( &db, @@ -134,7 +133,9 @@ pub fn load_cairo_str(program_str: &str) -> (String, Program, SierraCasmRunner) let module_name = module_name.file_name().unwrap().to_str().unwrap(); let replacer = DebugReplacer { db: &db }; - let contracts_info = get_contracts_info(&db, main_crate_ids, &replacer).unwrap(); + + let contracts = find_contracts((db).upcast(), &main_crate_ids); + let contracts_info = get_contracts_info(&db, contracts, &replacer).unwrap(); let runner = SierraCasmRunner::new( program.clone(), @@ -165,13 +166,17 @@ pub fn load_cairo_path(program_path: &str) -> (String, Program, SierraCasmRunner }, ) .unwrap(); - let program = sierra_program_with_dbg.program; + let mut program = sierra_program_with_dbg.program; let module_name = program_file.with_extension(""); let module_name = module_name.file_name().unwrap().to_str().unwrap(); let replacer = DebugReplacer { db: &db }; - let contracts_info = get_contracts_info(&db, main_crate_ids, &replacer).unwrap(); + replacer.enrich_function_names(&mut program); + let contracts = find_contracts((db).upcast(), &main_crate_ids); + let contracts_info = get_contracts_info(&db, contracts, &replacer).unwrap(); + + let program = replacer.apply(&program); let runner = SierraCasmRunner::new( program.clone(), @@ -283,7 +288,7 @@ pub fn run_vm_contract( .expect("failed to extract program from casm contract"); // Initialize runner and builtins - let mut runner = CairoRunner::new(&program, LayoutName::all_cairo, false, false) + let mut runner = CairoRunner::new(&program, LayoutName::all_cairo, None, false, false) .expect("failed to build runner"); let program_builtins = contract diff --git a/tests/tests/starknet/keccak.rs b/tests/tests/starknet/keccak.rs index 9de56a5f8..71babc3c7 100644 --- a/tests/tests/starknet/keccak.rs +++ b/tests/tests/starknet/keccak.rs @@ -36,7 +36,7 @@ fn keccak_test() { ); assert!(!result.failure_flag); - assert_eq!(result.remaining_gas, 18446744073709483675); + assert_eq!(result.remaining_gas, 18446744073709483875); assert_eq!(result.return_values, vec![1.into()]); let result_aot_ct = run_native_starknet_aot_contract( diff --git a/tests/tests/starknet/programs/syscalls.cairo b/tests/tests/starknet/programs/syscalls.cairo index c57362bc4..72d6d5266 100644 --- a/tests/tests/starknet/programs/syscalls.cairo +++ b/tests/tests/starknet/programs/syscalls.cairo @@ -4,10 +4,11 @@ use core::starknet::{ keccak_syscall, library_call_syscall, replace_class_syscall, send_message_to_l1_syscall, storage_address_try_from_felt252, storage_read_syscall, storage_write_syscall, SyscallResult, - testing::cheatcode, + testing::cheatcode, class_hash::ClassHash }; use core::starknet::syscalls::get_execution_info_syscall; use core::starknet::syscalls::get_execution_info_v2_syscall; +use core::starknet::syscalls::get_class_hash_at_syscall; use core::sha256::{sha256_state_handle_init, sha256_state_handle_digest, SHA256_INITIAL_STATE}; use core::box::BoxTrait; use core::starknet::SyscallResultTrait; @@ -16,6 +17,10 @@ fn get_block_hash() -> SyscallResult { get_block_hash_syscall(0) } +fn get_class_hash_at() -> SyscallResult { + get_class_hash_at_syscall(contract_address_const::<2>()) +} + fn get_execution_info() -> SyscallResult> { get_execution_info_syscall() } diff --git a/tests/tests/starknet/secp256.rs b/tests/tests/starknet/secp256.rs index 891efbcfe..e3f41ba90 100644 --- a/tests/tests/starknet/secp256.rs +++ b/tests/tests/starknet/secp256.rs @@ -256,6 +256,14 @@ impl StarknetSyscallHandler for &mut SyscallHandler { ) -> SyscallResult<()> { unimplemented!() } + + fn get_class_hash_at( + &mut self, + _contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + unimplemented!() + } } lazy_static! { diff --git a/tests/tests/starknet/syscalls.rs b/tests/tests/starknet/syscalls.rs index 12c94f817..2a7d9bbad 100644 --- a/tests/tests/starknet/syscalls.rs +++ b/tests/tests/starknet/syscalls.rs @@ -502,6 +502,14 @@ impl StarknetSyscallHandler for SyscallHandler { ) -> SyscallResult<()> { Ok(()) } + + fn get_class_hash_at( + &mut self, + contract_address: Felt, + _remaining_gas: &mut u64, + ) -> SyscallResult { + Ok(contract_address) + } } lazy_static! { @@ -1200,3 +1208,23 @@ fn sha256_process() { }, ); } + +#[test] +fn get_class_hash_at() { + let result = run_native_program( + &SYSCALLS_PROGRAM, + "get_class_hash_at", + &[], + Some(u64::MAX), + Some(SyscallHandler::new()), + ); + + assert_eq_sorted!( + result.return_value, + Value::Enum { + tag: 0, + value: Box::new(Value::Felt252(2.into())), + debug_name: None, + }, + ); +} From 107ff62555b9c65acb4897ed7041ba4e17d85689 Mon Sep 17 00:00:00 2001 From: MrAzteca Date: Thu, 21 Nov 2024 14:49:48 +0100 Subject: [PATCH 11/11] Coalesce all compatible no-op libfuncs into a single function. (#919) * Coalesce all compatible no-op libfuncs into a single function. * Fix stuff. * Fix stuff. * Fix return type. --------- Co-authored-by: Edgar Co-authored-by: Julian Gonzalez Calderon --- env.sh | 4 +- src/compiler.rs | 8 +- src/libfuncs.rs | 146 +++++++++++++++++++---------- src/libfuncs/ap_tracking.rs | 87 ----------------- src/libfuncs/bounded_int.rs | 17 ++-- src/libfuncs/box.rs | 25 ++--- src/libfuncs/branch_align.rs | 33 ------- src/libfuncs/circuit.rs | 70 +++----------- src/libfuncs/mem.rs | 87 ++++++----------- src/libfuncs/nullable.rs | 56 +++-------- src/libfuncs/snapshot_take.rs | 29 ------ src/libfuncs/starknet.rs | 132 ++++---------------------- src/libfuncs/unconditional_jump.rs | 30 ------ src/libfuncs/unwrap_non_zero.rs | 30 ------ 14 files changed, 195 insertions(+), 559 deletions(-) delete mode 100644 src/libfuncs/ap_tracking.rs delete mode 100644 src/libfuncs/branch_align.rs delete mode 100644 src/libfuncs/snapshot_take.rs delete mode 100644 src/libfuncs/unconditional_jump.rs delete mode 100644 src/libfuncs/unwrap_non_zero.rs diff --git a/env.sh b/env.sh index d20ca7fc8..4e85405f0 100644 --- a/env.sh +++ b/env.sh @@ -11,7 +11,7 @@ case $(uname) in MLIR_SYS_190_PREFIX="$(brew --prefix llvm@19)" LLVM_SYS_191_PREFIX="$(brew --prefix llvm@19)" TABLEGEN_190_PREFIX="$(brew --prefix llvm@19)" - CAIRO_NATIVE_RUNTIME_LIBRARY="$(pwd)/target/debug/libcairo_native_runtime.a" + CAIRO_NATIVE_RUNTIME_LIBRARY="$(pwd)/target/release/libcairo_native_runtime.a" export LIBRARY_PATH export MLIR_SYS_190_PREFIX @@ -24,7 +24,7 @@ case $(uname) in MLIR_SYS_190_PREFIX=/usr/lib/llvm-19 LLVM_SYS_191_PREFIX=/usr/lib/llvm-19 TABLEGEN_190_PREFIX=/usr/lib/llvm-19 - CAIRO_NATIVE_RUNTIME_LIBRARY="$(pwd)/target/debug/libcairo_native_runtime.a" + CAIRO_NATIVE_RUNTIME_LIBRARY="$(pwd)/target/release/libcairo_native_runtime.a" export MLIR_SYS_190_PREFIX export LLVM_SYS_191_PREFIX diff --git a/src/compiler.rs b/src/compiler.rs index 7c2c653ba..550aedb03 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -614,9 +614,8 @@ fn compile_func( invocation .branches .iter() - .zip(helper.results()) + .zip(helper.results()?) .map(|(branch_info, result_values)| { - let result_values = result_values?; assert_eq!( branch_info.results.len(), result_values.len(), @@ -625,10 +624,7 @@ fn compile_func( Ok(edit_state::put_results( state.clone(), - branch_info - .results - .iter() - .zip(result_values.iter().copied()), + branch_info.results.iter().zip(result_values.into_iter()), )?) }) .collect::>()?, diff --git a/src/libfuncs.rs b/src/libfuncs.rs index b7405efaa..43f110786 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -3,13 +3,19 @@ //! Contains libfunc generation stuff (aka. the actual instructions). use crate::{ - error::{panic::ToNativeAssertError, Error as CoreLibfuncBuilderError, Result as NativeResult}, + error::{panic::ToNativeAssertError, Error as CoreLibfuncBuilderError, Result}, metadata::MetadataStorage, + types::TypeBuilder, utils::BlockExt, }; use bumpalo::Bump; use cairo_lang_sierra::{ - extensions::core::{CoreConcreteLibfunc, CoreLibfunc, CoreType}, + extensions::{ + core::{CoreConcreteLibfunc, CoreLibfunc, CoreType, CoreTypeConcrete}, + lib_func::ParamSignature, + starknet::StarkNetTypeConcrete, + ConcreteLibfunc, + }, ids::FunctionId, program_registry::ProgramRegistry, }; @@ -21,13 +27,11 @@ use melior::{ use num_bigint::BigInt; use std::{cell::Cell, error::Error, ops::Deref}; -mod ap_tracking; mod array; mod bitwise; mod r#bool; mod bounded_int; mod r#box; -mod branch_align; mod bytes31; mod cast; mod circuit; @@ -53,7 +57,6 @@ mod sint16; mod sint32; mod sint64; mod sint8; -mod snapshot_take; mod starknet; mod r#struct; mod uint128; @@ -63,8 +66,6 @@ mod uint32; mod uint512; mod uint64; mod uint8; -mod unconditional_jump; -mod unwrap_non_zero; /// Generation of MLIR operations from their Sierra counterparts. /// @@ -83,7 +84,7 @@ pub trait LibfuncBuilder { location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, - ) -> Result<(), Self::Error>; + ) -> Result<()>; /// Return the target function if the statement is a function call. /// @@ -103,20 +104,28 @@ impl LibfuncBuilder for CoreConcreteLibfunc { location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, - ) -> Result<(), Self::Error> { + ) -> Result<()> { match self { - Self::ApTracking(selector) => self::ap_tracking::build( - context, registry, entry, location, helper, metadata, selector, - ), + Self::ApTracking(_) | Self::BranchAlign(_) | Self::UnconditionalJump(_) => { + build_noop::<0, true>( + context, + registry, + entry, + location, + helper, + metadata, + self.param_signatures(), + ) + } Self::Array(selector) => self::array::build( context, registry, entry, location, helper, metadata, selector, ), - Self::BranchAlign(info) => self::branch_align::build( - context, registry, entry, location, helper, metadata, info, - ), Self::Bool(selector) => self::r#bool::build( context, registry, entry, location, helper, metadata, selector, ), + Self::BoundedInt(info) => { + self::bounded_int::build(context, registry, entry, location, helper, metadata, info) + } Self::Box(selector) => self::r#box::build( context, registry, entry, location, helper, metadata, selector, ), @@ -126,16 +135,25 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::Cast(selector) => self::cast::build( context, registry, entry, location, helper, metadata, selector, ), + Self::Circuit(info) => { + self::circuit::build(context, registry, entry, location, helper, metadata, info) + } Self::Const(selector) => self::r#const::build( context, registry, entry, location, helper, metadata, selector, ), + Self::Coupon(info) => { + self::coupon::build(context, registry, entry, location, helper, metadata, info) + } + Self::CouponCall(info) => self::function_call::build( + context, registry, entry, location, helper, metadata, info, + ), Self::Debug(selector) => self::debug::build( context, registry, entry, location, helper, metadata, selector, ), Self::Drop(info) => { self::drop::build(context, registry, entry, location, helper, metadata, info) } - Self::Dup(info) => { + Self::Dup(info) | Self::SnapshotTake(info) => { self::dup::build(context, registry, entry, location, helper, metadata, info) } Self::Ec(selector) => self::ec::build( @@ -159,6 +177,9 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::Gas(selector) => self::gas::build( context, registry, entry, location, helper, metadata, selector, ), + Self::IntRange(selector) => self::int_range::build( + context, registry, entry, location, helper, metadata, selector, + ), Self::Mem(selector) => self::mem::build( context, registry, entry, location, helper, metadata, selector, ), @@ -186,9 +207,6 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::Sint128(info) => { self::sint128::build(context, registry, entry, location, helper, metadata, info) } - Self::SnapshotTake(info) => self::snapshot_take::build( - context, registry, entry, location, helper, metadata, info, - ), Self::StarkNet(selector) => self::starknet::build( context, registry, entry, location, helper, metadata, selector, ), @@ -216,26 +234,14 @@ impl LibfuncBuilder for CoreConcreteLibfunc { Self::Uint512(selector) => self::uint512::build( context, registry, entry, location, helper, metadata, selector, ), - Self::UnconditionalJump(info) => self::unconditional_jump::build( - context, registry, entry, location, helper, metadata, info, - ), - Self::UnwrapNonZero(info) => self::unwrap_non_zero::build( - context, registry, entry, location, helper, metadata, info, - ), - Self::Coupon(info) => { - self::coupon::build(context, registry, entry, location, helper, metadata, info) - } - Self::CouponCall(info) => self::function_call::build( - context, registry, entry, location, helper, metadata, info, - ), - Self::Circuit(info) => { - self::circuit::build(context, registry, entry, location, helper, metadata, info) - } - Self::BoundedInt(info) => { - self::bounded_int::build(context, registry, entry, location, helper, metadata, info) - } - Self::IntRange(selector) => self::int_range::build( - context, registry, entry, location, helper, metadata, selector, + Self::UnwrapNonZero(info) => build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, ), } } @@ -278,17 +284,21 @@ where 'this: 'ctx, { #[doc(hidden)] - pub(crate) fn results(self) -> impl Iterator>>> { - self.results.into_iter().enumerate().map(|(branch_idx, x)| { - x.into_iter() - .enumerate() - .map(|(arg_idx, x)| { - x.into_inner().to_native_assert_error(&format!( - "Argument #{arg_idx} of branch {branch_idx} doesn't have a value." - )) - }) - .collect() - }) + pub(crate) fn results(self) -> Result>>> { + self.results + .into_iter() + .enumerate() + .map(|(branch_idx, x)| { + x.into_iter() + .enumerate() + .map(|(arg_idx, x)| { + x.into_inner().to_native_assert_error(&format!( + "Argument #{arg_idx} of branch {branch_idx} doesn't have a value." + )) + }) + .collect() + }) + .collect() } /// Return the initialization block. @@ -443,3 +453,39 @@ fn increment_builtin_counter_by<'ctx: 'a, 'a>( location, )) } + +fn build_noop<'ctx, 'this, const N: usize, const PROCESS_BUILTINS: bool>( + context: &'ctx Context, + registry: &ProgramRegistry, + entry: &'this Block<'ctx>, + location: Location<'ctx>, + helper: &LibfuncHelper<'ctx, 'this>, + _metadata: &mut MetadataStorage, + param_signatures: &[ParamSignature], +) -> Result<()> { + let mut params = Vec::with_capacity(N); + + #[allow(clippy::needless_range_loop)] + for i in 0..N { + let param_ty = registry.get_type(¶m_signatures[i].ty)?; + let mut param_val = entry.argument(i)?.into(); + + if PROCESS_BUILTINS + && param_ty.is_builtin() + && !matches!( + param_ty, + CoreTypeConcrete::BuiltinCosts(_) + | CoreTypeConcrete::Coupon(_) + | CoreTypeConcrete::GasBuiltin(_) + | CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::System(_)) + ) + { + param_val = increment_builtin_counter(context, entry, location, param_val)?; + } + + params.push(param_val); + } + + entry.append_operation(helper.br(0, ¶ms, location)); + Ok(()) +} diff --git a/src/libfuncs/ap_tracking.rs b/src/libfuncs/ap_tracking.rs deleted file mode 100644 index 3aefa766a..000000000 --- a/src/libfuncs/ap_tracking.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! # `AP` tracking libfuncs -//! -//! Natively compiled code doesn't need `AP` tracking because it has no notion of the `AP` pointer. -//! Because of this, all `AP`-related libfuncs are no-ops. - -use super::LibfuncHelper; -use crate::{error::Result, metadata::MetadataStorage}; -use cairo_lang_sierra::{ - extensions::{ - ap_tracking::ApTrackingConcreteLibfunc, - core::{CoreLibfunc, CoreType}, - lib_func::SignatureOnlyConcreteLibfunc, - }, - program_registry::ProgramRegistry, -}; -use melior::{ - ir::{Block, Location}, - Context, -}; - -/// Select and call the correct libfunc builder function from the selector. -pub fn build<'ctx, 'this>( - context: &'ctx Context, - registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - metadata: &mut MetadataStorage, - selector: &ApTrackingConcreteLibfunc, -) -> Result<()> { - match selector { - ApTrackingConcreteLibfunc::Revoke(info) => { - build_revoke(context, registry, entry, location, helper, metadata, info) - } - ApTrackingConcreteLibfunc::Enable(info) => { - build_enable(context, registry, entry, location, helper, metadata, info) - } - ApTrackingConcreteLibfunc::Disable(info) => { - build_disable(context, registry, entry, location, helper, metadata, info) - } - } -} - -/// Generate MLIR operations for the `enable_ap_tracking` libfunc. -pub fn build_enable<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) -} - -/// Generate MLIR operations for the `disable_ap_tracking` libfunc. -pub fn build_disable<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) -} - -/// Generate MLIR operations for the `revoke_ap_tracking.` libfunc. -pub fn build_revoke<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) -} diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index ead9eab18..7a04c23d3 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -742,16 +742,14 @@ fn build_is_zero<'ctx, 'this>( /// Generate MLIR operations for the `bounded_int_wrap_non_zero` libfunc. fn build_wrap_non_zero<'ctx, 'this>( - _context: &'ctx Context, + context: &'ctx Context, registry: &ProgramRegistry, entry: &'this Block<'ctx>, location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, + metadata: &mut MetadataStorage, info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let src_value = entry.argument(0)?.into(); - let src_range = registry .get_type(&info.signature.param_signatures[0].ty)? .integer_range(registry)?; @@ -761,6 +759,13 @@ fn build_wrap_non_zero<'ctx, 'this>( "value must not be zero" ); - entry.append_operation(helper.br(0, &[src_value], location)); - Ok(()) + super::build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, + ) } diff --git a/src/libfuncs/box.rs b/src/libfuncs/box.rs index 897e5d023..37135bfa4 100644 --- a/src/libfuncs/box.rs +++ b/src/libfuncs/box.rs @@ -43,9 +43,15 @@ pub fn build<'ctx, 'this>( BoxConcreteLibfunc::Unbox(info) => { build_unbox(context, registry, entry, location, helper, metadata, info) } - BoxConcreteLibfunc::ForwardSnapshot(info) => { - build_forward_snapshot(context, registry, entry, location, helper, metadata, info) - } + BoxConcreteLibfunc::ForwardSnapshot(info) => super::build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, + ), } } @@ -148,19 +154,6 @@ pub fn build_unbox<'ctx, 'this>( Ok(()) } -fn build_forward_snapshot<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureAndTypeConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - #[cfg(test)] mod test { use crate::{ diff --git a/src/libfuncs/branch_align.rs b/src/libfuncs/branch_align.rs deleted file mode 100644 index b5b91e023..000000000 --- a/src/libfuncs/branch_align.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! # Branch alignment libfunc -//! -//! Natively compiled code doesn't need branch alignment because it has no notion of segments. -//! Because of this, this libfunc is a no-op. - -use super::LibfuncHelper; -use crate::{error::Result, metadata::MetadataStorage}; -use cairo_lang_sierra::{ - extensions::{ - core::{CoreLibfunc, CoreType}, - lib_func::SignatureOnlyConcreteLibfunc, - }, - program_registry::ProgramRegistry, -}; -use melior::{ - ir::{Block, Location}, - Context, -}; - -/// Generate MLIR operations for the `branch_align` libfunc. -pub fn build<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) -} diff --git a/src/libfuncs/circuit.rs b/src/libfuncs/circuit.rs index c04e73640..8391b21ef 100644 --- a/src/libfuncs/circuit.rs +++ b/src/libfuncs/circuit.rs @@ -1,6 +1,6 @@ //! # Circuit libfuncs -use super::{increment_builtin_counter, increment_builtin_counter_by, LibfuncHelper}; +use super::{increment_builtin_counter_by, LibfuncHelper}; use crate::{ error::{Result, SierraAssertError}, libfuncs::r#struct::build_struct_value, @@ -63,11 +63,20 @@ pub fn build<'ctx, 'this>( CircuitConcreteLibfunc::FailureGuaranteeVerify(info) => build_failure_guarantee_verify( context, registry, entry, location, helper, metadata, info, ), - CircuitConcreteLibfunc::IntoU96Guarantee(info) => { - build_into_u96_guarantee(context, registry, entry, location, helper, metadata, info) - } - CircuitConcreteLibfunc::U96GuaranteeVerify(info) => { - build_u96_guarantee_verify(context, registry, entry, location, helper, metadata, info) + CircuitConcreteLibfunc::IntoU96Guarantee(SignatureAndTypeConcreteLibfunc { + signature, + .. + }) + | CircuitConcreteLibfunc::U96GuaranteeVerify(SignatureOnlyConcreteLibfunc { signature }) => { + super::build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &signature.param_signatures, + ) } CircuitConcreteLibfunc::U96LimbsLessThanGuaranteeVerify(info) => { build_u96_limbs_less_than_guarantee_verify( @@ -125,35 +134,6 @@ fn build_init_circuit_data<'ctx, 'this>( Ok(()) } -/// Generate MLIR operations for the `into_u96_guarantee` libfunc. -#[allow(clippy::too_many_arguments)] -fn build_into_u96_guarantee<'ctx, 'this>( - context: &'ctx Context, - registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - metadata: &mut MetadataStorage, - info: &SignatureAndTypeConcreteLibfunc, -) -> Result<()> { - // input is a BoundedInt<0, 79228162514264337593543950335> - let input: Value = entry.argument(0)?.into(); - // output is a U96Guarantee - let output_ty = registry.build_type( - context, - helper, - registry, - metadata, - &info.branch_signatures()[0].vars[0].ty, - )?; - // they have the same type (i96) - debug_assert_eq!(input.r#type(), output_ty); - - entry.append_operation(helper.br(0, &[input], location)); - - Ok(()) -} - /// Generate MLIR operations for the `add_circuit_input` libfunc. #[allow(clippy::too_many_arguments)] fn build_add_input<'ctx, 'this>( @@ -809,26 +789,6 @@ fn build_u96_limbs_less_than_guarantee_verify<'ctx, 'this>( Ok(()) } -/// Generate MLIR operations for the `u96_guarantee_verify` libfunc. -/// NOOP -#[allow(clippy::too_many_arguments)] -fn build_u96_guarantee_verify<'ctx, 'this>( - context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - let rc = entry.argument(0)?.into(); - let rc = increment_builtin_counter(context, entry, location, rc)?; - - entry.append_operation(helper.br(0, &[rc], location)); - - Ok(()) -} - /// Generate MLIR operations for the `u96_single_limb_less_than_guarantee_verify` libfunc. /// NOOP #[allow(clippy::too_many_arguments)] diff --git a/src/libfuncs/mem.rs b/src/libfuncs/mem.rs index c8c2eee79..59f6b97dd 100644 --- a/src/libfuncs/mem.rs +++ b/src/libfuncs/mem.rs @@ -35,39 +35,36 @@ pub fn build<'ctx, 'this>( selector: &MemConcreteLibfunc, ) -> Result<()> { match selector { - MemConcreteLibfunc::StoreTemp(info) => { - build_store_temp(context, registry, entry, location, helper, info) + MemConcreteLibfunc::AllocLocal(info) => { + build_alloc_local(context, registry, entry, location, helper, metadata, info) } MemConcreteLibfunc::StoreLocal(info) => { build_store_local(context, registry, entry, location, helper, metadata, info) } - MemConcreteLibfunc::FinalizeLocals(info) => { - build_finalize_locals(context, registry, entry, location, helper, info) - } - MemConcreteLibfunc::AllocLocal(info) => { - build_alloc_local(context, registry, entry, location, helper, metadata, info) - } - MemConcreteLibfunc::Rename(info) => { - build_rename(context, registry, entry, location, helper, info) + MemConcreteLibfunc::FinalizeLocals(info) => super::build_noop::<0, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, + ), + MemConcreteLibfunc::Rename(SignatureOnlyConcreteLibfunc { signature }) + | MemConcreteLibfunc::StoreTemp(SignatureAndTypeConcreteLibfunc { signature, .. }) => { + super::build_noop::<1, false>( + context, + registry, + entry, + location, + helper, + metadata, + &signature.param_signatures, + ) } } } -/// Generate MLIR operations for the `store_local` libfunc. -pub fn build_store_local<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureAndTypeConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(1)?.into()], location)); - - Ok(()) -} - /// Generate MLIR operations for the `alloc_local` libfunc. pub fn build_alloc_local<'ctx, 'this>( context: &'ctx Context, @@ -86,50 +83,22 @@ pub fn build_alloc_local<'ctx, 'this>( &info.branch_signatures()[0].vars[0].ty, )?; - let value_undef = entry.append_op_result(llvm::undef(target_type, location))?; - - entry.append_operation(helper.br(0, &[value_undef], location)); - - Ok(()) -} + let value = entry.append_op_result(llvm::undef(target_type, location))?; -/// Generate MLIR operations for the `finalize_locals` libfunc. -pub fn build_finalize_locals<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); + entry.append_operation(helper.br(0, &[value], location)); Ok(()) } -/// Generate MLIR operations for the `store_temp` libfunc. -pub fn build_store_temp<'ctx, 'this>( +/// Generate MLIR operations for the `store_local` libfunc. +pub fn build_store_local<'ctx, 'this>( _context: &'ctx Context, _registry: &ProgramRegistry, entry: &'this Block<'ctx>, location: Location<'ctx>, helper: &LibfuncHelper<'ctx, 'this>, + _metadata: &mut MetadataStorage, _info: &SignatureAndTypeConcreteLibfunc, ) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - - Ok(()) -} - -/// Generate MLIR operations for the `rename` libfunc. -pub fn build_rename<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - + entry.append_operation(helper.br(0, &[entry.argument(1)?.into()], location)); Ok(()) } diff --git a/src/libfuncs/nullable.rs b/src/libfuncs/nullable.rs index 974dcef29..c7eed1b20 100644 --- a/src/libfuncs/nullable.rs +++ b/src/libfuncs/nullable.rs @@ -32,17 +32,21 @@ pub fn build<'ctx, 'this>( selector: &NullableConcreteLibfunc, ) -> Result<()> { match selector { - NullableConcreteLibfunc::Null(info) => { - build_null(context, registry, entry, location, helper, metadata, info) - } - NullableConcreteLibfunc::NullableFromBox(info) => { - build_nullable_from_box(context, registry, entry, location, helper, metadata, info) - } + NullableConcreteLibfunc::ForwardSnapshot(info) + | NullableConcreteLibfunc::NullableFromBox(info) => super::build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, + ), NullableConcreteLibfunc::MatchNullable(info) => { build_match_nullable(context, registry, entry, location, helper, metadata, info) } - NullableConcreteLibfunc::ForwardSnapshot(info) => { - build_forward_snapshot(context, registry, entry, location, helper, metadata, info) + NullableConcreteLibfunc::Null(info) => { + build_null(context, registry, entry, location, helper, metadata, info) } } } @@ -58,27 +62,10 @@ fn build_null<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let op = - entry.append_operation(ods::llvm::mlir_zero(context, pointer(context, 0), location).into()); - - entry.append_operation(helper.br(0, &[op.result(0)?.into()], location)); - - Ok(()) -} - -/// Generate MLIR operations for the `nullable_from_box` libfunc. -#[allow(clippy::too_many_arguments)] -fn build_nullable_from_box<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureAndTypeConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); + let value = entry + .append_op_result(ods::llvm::mlir_zero(context, pointer(context, 0), location).into())?; + entry.append_operation(helper.br(0, &[value], location)); Ok(()) } @@ -128,19 +115,6 @@ fn build_match_nullable<'ctx, 'this>( Ok(()) } -fn build_forward_snapshot<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureAndTypeConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - #[cfg(test)] mod test { use crate::{ diff --git a/src/libfuncs/snapshot_take.rs b/src/libfuncs/snapshot_take.rs deleted file mode 100644 index 571410790..000000000 --- a/src/libfuncs/snapshot_take.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! # Snapshot taking libfuncs - -use super::LibfuncHelper; -use crate::{error::Result, metadata::MetadataStorage}; -use cairo_lang_sierra::{ - extensions::{ - core::{CoreLibfunc, CoreType}, - lib_func::SignatureOnlyConcreteLibfunc, - }, - program_registry::ProgramRegistry, -}; -use melior::{ - ir::{Block, Location}, - Context, -}; - -/// Generate MLIR operations for the `snapshot_take` libfunc. -pub fn build<'ctx, 'this>( - context: &'ctx Context, - registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - metadata: &mut MetadataStorage, - info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - // Taking a snapshot in native is equivalent to duplicating the value. - super::dup::build(context, registry, entry, location, helper, metadata, info) -} diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index 9302d5d66..8705848f6 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -46,6 +46,20 @@ pub fn build<'ctx, 'this>( selector: &StarkNetConcreteLibfunc, ) -> Result<()> { match selector { + StarkNetConcreteLibfunc::ClassHashToFelt252(info) + | StarkNetConcreteLibfunc::ContractAddressToFelt252(info) + | StarkNetConcreteLibfunc::StorageAddressFromBase(info) + | StarkNetConcreteLibfunc::StorageAddressToFelt252(info) + | StarkNetConcreteLibfunc::Sha256StateHandleInit(info) + | StarkNetConcreteLibfunc::Sha256StateHandleDigest(info) => super::build_noop::<1, true>( + context, + registry, + entry, + location, + helper, + metadata, + &info.signature.param_signatures, + ), StarkNetConcreteLibfunc::CallContract(info) => { build_call_contract(context, registry, entry, location, helper, metadata, info) } @@ -57,9 +71,6 @@ pub fn build<'ctx, 'this>( context, registry, entry, location, helper, metadata, info, ) } - StarkNetConcreteLibfunc::ClassHashToFelt252(info) => { - build_class_hash_to_felt252(context, registry, entry, location, helper, metadata, info) - } StarkNetConcreteLibfunc::ContractAddressConst(info) => { build_contract_address_const(context, registry, entry, location, helper, metadata, info) } @@ -68,11 +79,6 @@ pub fn build<'ctx, 'this>( context, registry, entry, location, helper, metadata, info, ) } - StarkNetConcreteLibfunc::ContractAddressToFelt252(info) => { - build_contract_address_to_felt252( - context, registry, entry, location, helper, metadata, info, - ) - } StarkNetConcreteLibfunc::StorageRead(info) => { build_storage_read(context, registry, entry, location, helper, metadata, info) } @@ -87,17 +93,11 @@ pub fn build<'ctx, 'this>( context, registry, entry, location, helper, metadata, info, ) } - StarkNetConcreteLibfunc::StorageAddressFromBase(info) => build_storage_address_from_base( - context, registry, entry, location, helper, metadata, info, - ), StarkNetConcreteLibfunc::StorageAddressFromBaseAndOffset(info) => { build_storage_address_from_base_and_offset( context, registry, entry, location, helper, metadata, info, ) } - StarkNetConcreteLibfunc::StorageAddressToFelt252(info) => build_storage_address_to_felt252( - context, registry, entry, location, helper, metadata, info, - ), StarkNetConcreteLibfunc::StorageAddressTryFromFelt252(info) => { build_storage_address_try_from_felt252( context, registry, entry, location, helper, metadata, info, @@ -109,6 +109,9 @@ pub fn build<'ctx, 'this>( StarkNetConcreteLibfunc::GetBlockHash(info) => { build_get_block_hash(context, registry, entry, location, helper, metadata, info) } + StarkNetConcreteLibfunc::GetClassHashAt(info) => { + build_get_class_hash_at(context, registry, entry, location, helper, metadata, info) + } StarkNetConcreteLibfunc::GetExecutionInfo(info) => { build_get_execution_info(context, registry, entry, location, helper, metadata, info) } @@ -136,15 +139,6 @@ pub fn build<'ctx, 'this>( StarkNetConcreteLibfunc::Sha256ProcessBlock(info) => build_sha256_process_block_syscall( context, registry, entry, location, helper, metadata, info, ), - StarkNetConcreteLibfunc::Sha256StateHandleInit(info) => build_sha256_state_handle_init( - context, registry, entry, location, helper, metadata, info, - ), - StarkNetConcreteLibfunc::Sha256StateHandleDigest(info) => build_sha256_state_handle_digest( - context, registry, entry, location, helper, metadata, info, - ), - StarkNetConcreteLibfunc::GetClassHashAt(info) => { - build_get_class_hash_at(context, registry, entry, location, helper, metadata, info) - } #[cfg(feature = "with-cheatcode")] StarkNetConcreteLibfunc::Testing(TestingConcreteLibfunc::Cheatcode(info)) => { self::testing::build(context, registry, entry, location, helper, metadata, info) @@ -389,19 +383,6 @@ pub fn build_class_hash_const<'ctx, 'this>( Ok(()) } -pub fn build_class_hash_to_felt252<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - pub fn build_class_hash_try_from_felt252<'ctx, 'this>( context: &'ctx Context, _registry: &ProgramRegistry, @@ -507,19 +488,6 @@ pub fn build_contract_address_try_from_felt252<'ctx, 'this>( Ok(()) } -pub fn build_contract_address_to_felt252<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - pub fn build_storage_read<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, @@ -922,19 +890,6 @@ pub fn build_storage_base_address_from_felt252<'ctx, 'this>( Ok(()) } -pub fn build_storage_address_from_base<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( _context: &'ctx Context, _registry: &ProgramRegistry, @@ -955,19 +910,6 @@ pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( Ok(()) } -pub fn build_storage_address_to_felt252<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - Ok(()) -} - pub fn build_storage_address_try_from_felt252<'ctx, 'this>( context: &'ctx Context, _registry: &ProgramRegistry, @@ -2647,46 +2589,6 @@ pub fn build_send_message_to_l1<'ctx, 'this>( Ok(()) } -/// -/// From the corelib -/// ```text, no_run -/// // Initializes a new SHA-256 state handle. -/// extern fn sha256_state_handle_init(state: Box<[u32; 8]>) -> Sha256StateHandle nopanic; -/// ``` -pub fn build_sha256_state_handle_init<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - let value = entry.argument(0)?.into(); - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) -} - -/// -/// From the corelib -/// ```text, no_run -/// // Initializes a new SHA-256 state handle. -/// extern fn sha256_state_handle_digest(state: Sha256StateHandle) -> Box<[u32; 8]> nopanic; -/// ``` -pub fn build_sha256_state_handle_digest<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - let value = entry.argument(0)?.into(); - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) -} - pub fn build_sha256_process_block_syscall<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, diff --git a/src/libfuncs/unconditional_jump.rs b/src/libfuncs/unconditional_jump.rs deleted file mode 100644 index 223cdf2bc..000000000 --- a/src/libfuncs/unconditional_jump.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! # Unconditional jump libfunc - -use super::LibfuncHelper; -use crate::{error::Result, metadata::MetadataStorage}; -use cairo_lang_sierra::{ - extensions::{ - core::{CoreLibfunc, CoreType}, - lib_func::SignatureOnlyConcreteLibfunc, - }, - program_registry::ProgramRegistry, -}; -use melior::{ - ir::{Block, Location}, - Context, -}; - -/// Generate MLIR operations for the `jump` libfunc. -pub fn build<'ctx>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, '_>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) -} diff --git a/src/libfuncs/unwrap_non_zero.rs b/src/libfuncs/unwrap_non_zero.rs deleted file mode 100644 index b9be79734..000000000 --- a/src/libfuncs/unwrap_non_zero.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! # Non-zero unwrapping libfuncs - -use super::LibfuncHelper; -use crate::{error::Result, metadata::MetadataStorage}; -use cairo_lang_sierra::{ - extensions::{ - core::{CoreLibfunc, CoreType}, - lib_func::SignatureOnlyConcreteLibfunc, - }, - program_registry::ProgramRegistry, -}; -use melior::{ - ir::{Block, Location}, - Context, -}; - -/// Generate MLIR operations for the `unwrap_non_zero` libfunc. -pub fn build<'ctx, 'this>( - _context: &'ctx Context, - _registry: &ProgramRegistry, - entry: &'this Block<'ctx>, - location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, 'this>, - _metadata: &mut MetadataStorage, - _info: &SignatureOnlyConcreteLibfunc, -) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.argument(0)?.into()], location)); - - Ok(()) -}