diff --git a/Cargo.toml b/Cargo.toml index 7408f8848..10e470bd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ scarb = ["build-cli", "dep:scarb-ui", "dep:scarb-metadata"] with-cheatcode = [] with-debug-utils = [] with-mem-tracing = [] +with-profiler = [] with-runtime = ["dep:cairo-native-runtime"] # the aquamarine dep is only used in docs and cannot be detected as used by cargo udeps diff --git a/programs/examples/brainfuck.cairo b/programs/examples/brainfuck.cairo index d015de00d..e842f9e88 100644 --- a/programs/examples/brainfuck.cairo +++ b/programs/examples/brainfuck.cairo @@ -1,7 +1,8 @@ +use core::num::traits::WrappingSub; +use core::num::traits::WrappingAdd; use core::{ - traits::Default, - array::{ArrayTrait, SpanTrait}, debug::PrintTrait, dict::Felt252DictTrait, - integer::{u8_wrapping_add, u8_wrapping_sub}, option::OptionTrait, traits::Into, + traits::Default, array::{ArrayTrait, SpanTrait}, debug::PrintTrait, dict::Felt252DictTrait, + option::OptionTrait, traits::Into, }; fn generate_jump_table(program: @Array) -> Felt252Dict { @@ -50,9 +51,9 @@ fn run_program(program: @Array, input: Option>) { } else if op_code == '<' { mp -= 1; } else if op_code == '+' { - memory.insert(mp, u8_wrapping_add(memory.get(mp), 1)); + memory.insert(mp, memory.get(mp).wrapping_add(1)); } else if op_code == '-' { - memory.insert(mp, u8_wrapping_sub(memory.get(mp), 1)); + memory.insert(mp, memory.get(mp).wrapping_sub(1)); } else if op_code == '.' { memory.get(mp).print(); } else if op_code == ',' { diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 32fd46b95..1d1a38a8c 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -44,6 +44,10 @@ struct Args { /// Optimization level, Valid: 0, 1, 2, 3. Values higher than 3 are considered as 3. #[arg(short = 'O', long, default_value_t = 0)] opt_level: u8, + + #[cfg(feature = "with-profiler")] + #[arg(long)] + profiler_output: Option, } fn main() -> anyhow::Result<()> { @@ -138,5 +142,104 @@ fn main() -> anyhow::Result<()> { println!("Remaining gas: {gas}"); } + #[cfg(feature = "with-profiler")] + if let Some(profiler_output) = args.profiler_output { + use cairo_lang_sierra::{ids::ConcreteLibfuncId, program::Statement}; + use std::{collections::HashMap, fs::File, io::Write}; + + let mut trace = HashMap::, u64)>::new(); + + for (statement_idx, tick_delta) in cairo_native::metadata::profiler::ProfilerImpl::take() { + if let Statement::Invocation(invocation) = &sierra_program.statements[statement_idx.0] { + let (tick_deltas, extra_count) = + trace.entry(invocation.libfunc_id.clone()).or_default(); + + if tick_delta != u64::MAX { + tick_deltas.push(tick_delta); + } else { + *extra_count += 1; + } + } + } + + let mut trace = trace + .into_iter() + .map(|(libfunc_id, (mut tick_deltas, extra_count))| { + tick_deltas.sort(); + + // Drop outliers. + { + let q1 = tick_deltas[tick_deltas.len() / 4]; + let q3 = tick_deltas[3 * tick_deltas.len() / 4]; + let iqr = q3 - q1; + + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); + + tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } + + // Compute the quartiles. + let quartiles = [ + *tick_deltas.first().unwrap(), + tick_deltas[tick_deltas.len() / 4], + tick_deltas[tick_deltas.len() / 2], + tick_deltas[3 * tick_deltas.len() / 4], + *tick_deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = + tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = tick_deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (tick_deltas.len() as u64 + extra_count) as f64 + }; + + ( + libfunc_id, + ( + tick_deltas.len() as u64 + extra_count, + tick_deltas.iter().sum::() + + (extra_count as f64 * average).round() as u64, + quartiles, + average, + std_dev, + ), + ) + }) + .collect::>(); + + // Sort libfuncs by the order in which they are declared. + trace.sort_by_key(|(libfunc_id, _)| { + sierra_program + .libfunc_declarations + .iter() + .enumerate() + .find_map(|(i, x)| (&x.id == libfunc_id).then_some(i)) + .unwrap() + }); + + let mut output = File::create(profiler_output)?; + + for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in trace { + writeln!(output, "{libfunc_id}")?; + writeln!(output, " Samples : {n_samples}")?; + writeln!(output, " Sum : {sum}")?; + writeln!(output, " Average : {average}")?; + writeln!(output, " Deviation: {std_dev}")?; + writeln!(output, " Quartiles: {quartiles:?}")?; + writeln!(output)?; + } + } + Ok(()) } diff --git a/src/compiler.rs b/src/compiler.rs index d7c35f235..32073ca08 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -524,26 +524,6 @@ fn compile_func( let (state, _) = edit_state::take_args(state, invocation.args.iter())?; - let helper = LibfuncHelper { - module, - init_block: &pre_entry_block, - region: ®ion, - blocks_arena: &blocks_arena, - last_block: Cell::new(block), - branches: generate_branching_targets( - &blocks, - statements, - statement_idx, - invocation, - &state, - ), - results: invocation - .branches - .iter() - .map(|x| vec![Cell::new(None); x.results.len()]) - .collect::>(), - }; - let libfunc = registry.get_libfunc(&invocation.libfunc_id)?; if is_recursive { if let Some(target) = libfunc.is_function_call() { @@ -594,6 +574,45 @@ fn compile_func( } } + #[allow(unused_mut)] + let mut helper = LibfuncHelper { + module, + init_block: &pre_entry_block, + region: ®ion, + blocks_arena: &blocks_arena, + last_block: Cell::new(block), + branches: generate_branching_targets( + &blocks, + statements, + statement_idx, + invocation, + &state, + ), + results: invocation + .branches + .iter() + .map(|x| vec![Cell::new(None); x.results.len()]) + .collect::>(), + + #[cfg(feature = "with-profiler")] + profiler: match libfunc { + CoreConcreteLibfunc::FunctionCall(_) => { + // Tail-recursive function calls are broken. Also it'd include the entire function which + // doesn't make sense, therefore it's ignored on purpose. + None + } + _ => match metadata.remove::() + { + Some(profiler_meta) => { + let t0 = profiler_meta + .measure_timestamp(context, block, location)?; + Some((profiler_meta, statement_idx, t0)) + } + None => None, + }, + }, + }; + libfunc.build( context, registry, @@ -604,6 +623,11 @@ fn compile_func( )?; assert!(block.terminator().is_some()); + #[cfg(feature = "with-profiler")] + if let Some((profiler_meta, _, _)) = helper.profiler.take() { + metadata.insert(profiler_meta); + } + if let Some(tailrec_meta) = metadata.remove::() { if let Some(return_block) = tailrec_meta.return_target() { tailrec_state = Some((tailrec_meta.depth_counter(), return_block)); diff --git a/src/context.rs b/src/context.rs index de15fb9f2..ab3487362 100644 --- a/src/context.rs +++ b/src/context.rs @@ -167,6 +167,12 @@ impl NativeContext { // already some metadata of the same type. metadata.insert(gas_metadata); + #[cfg(feature = "with-profiler")] + metadata.insert(crate::metadata::profiler::ProfilerMeta::new( + &self.context, + &module, + )?); + // Create the Sierra program registry let registry = ProgramRegistry::::new(program)?; diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 500cfcdf0..9a0872803 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -85,6 +85,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -112,6 +115,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -138,6 +144,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -178,4 +187,14 @@ impl<'m> JitNativeExecutor<'m> { .get_function(function_id) .map(|func| &func.signature)?) } + + #[cfg(feature = "with-profiler")] + fn setup_profiling(&self) { + unsafe { + let callback_ptr: *mut extern "C" fn(u64, u64) = + self.engine.lookup("__profiler_callback").cast(); + + *callback_ptr = crate::metadata::profiler::ProfilerImpl::callback; + } + } } diff --git a/src/libfuncs.rs b/src/libfuncs.rs index 126d53fec..c61abbef5 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -21,7 +21,7 @@ use cairo_lang_sierra::{ }; use melior::{ dialect::{arith, cf}, - ir::{Block, BlockRef, Location, Module, Operation, Region, Value}, + ir::{Block, BlockRef, Location, Module, Region, Value}, Context, }; use num_bigint::BigInt; @@ -277,6 +277,13 @@ where pub branches: Vec<(&'this Block<'ctx>, Vec>)>, pub results: Vec>>>>, + + #[cfg(feature = "with-profiler")] + pub profiler: Option<( + crate::metadata::profiler::ProfilerMeta, + cairo_lang_sierra::program::StatementIdx, + (Value<'ctx, 'this>, Value<'ctx, 'this>), + )>, } impl<'ctx, 'this> LibfuncHelper<'ctx, 'this> @@ -328,10 +335,11 @@ where /// used later on when required. fn br( &self, + block: &'this Block<'ctx>, branch: usize, results: &[Value<'ctx, 'this>], location: Location<'ctx>, - ) -> Operation<'ctx> { + ) -> Result<()> { let (successor, operands) = &self.branches[branch]; for (dst, src) in self.results[branch].iter().zip(results) { @@ -347,7 +355,11 @@ where }) .collect::>(); - cf::br(successor, &destination_operands, location) + #[cfg(feature = "with-profiler")] + self.push_profiler_frame(unsafe { self.context().to_ref() }, block, location)?; + + block.append_operation(cf::br(successor, &destination_operands, location)); + Ok(()) } /// Creates a conditional binary branching operation, potentially jumping out of the libfunc and @@ -362,11 +374,12 @@ where fn cond_br( &self, context: &'ctx Context, + block: &'this Block<'ctx>, condition: Value<'ctx, 'this>, branches: [usize; 2], results: [&[Value<'ctx, 'this>]; 2], location: Location<'ctx>, - ) -> Operation<'ctx> { + ) -> Result<()> { let (block_true, args_true) = { let (successor, operands) = &self.branches[branches[0]]; @@ -405,7 +418,10 @@ where (*successor, destination_operands) }; - cf::cond_br( + #[cfg(feature = "with-profiler")] + self.push_profiler_frame(context, block, location)?; + + block.append_operation(cf::cond_br( context, condition, block_true, @@ -413,7 +429,25 @@ where &args_true, &args_false, location, - ) + )); + Ok(()) + } + + #[cfg(feature = "with-profiler")] + fn push_profiler_frame( + &self, + context: &'ctx Context, + block: &'this Block<'ctx>, + location: Location<'ctx>, + ) -> Result<()> { + if let Some((profiler_meta, statement_idx, t0)) = self.profiler.as_ref() { + let t0 = *t0; + let t1 = profiler_meta.measure_timestamp(context, block, location)?; + + profiler_meta.push_frame(context, block, statement_idx.0, t0, t1, location)?; + } + + Ok(()) } } @@ -486,6 +520,5 @@ fn build_noop<'ctx, 'this, const N: usize, const PROCESS_BUILTINS: bool>( params.push(param_val); } - entry.append_operation(helper.br(0, ¶ms, location)); - Ok(()) + helper.br(entry, 0, ¶ms, location) } diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index 7cf2ac77a..7f663cd90 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -118,8 +118,7 @@ pub fn build_new<'ctx, 'this>( let value = entry.insert_value(context, location, value, k0, 2)?; let value = entry.insert_value(context, location, value, k0, 3)?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `array_append` libfunc. @@ -310,7 +309,7 @@ pub fn build_append<'ctx, 'this>( let value = append_block.insert_value(context, location, append_block.arg(0)?, array_len, 2)?; - append_block.append_operation(helper.br(0, &[value], location)); + helper.br(append_block, 0, &[value], location)?; } Ok(()) @@ -357,8 +356,7 @@ pub fn build_len<'ctx, 'this>( _ => {} } - entry.append_operation(helper.br(0, &[array_len], location)); - Ok(()) + helper.br(entry, 0, &[array_len], location) } /// Generate MLIR operations for the `array_get` libfunc. @@ -528,20 +526,22 @@ pub fn build_get<'ctx, 'this>( } valid_block.append_operation(ReallocBindingsMeta::free(context, ptr, location)?); - valid_block.append_operation(helper.br(0, &[range_check, target_ptr], location)); + helper.br(valid_block, 0, &[range_check, target_ptr], location)?; } - metadata - .get::() - .ok_or(Error::MissingMetadata)? - .invoke_override( - context, - error_block, - location, - &info.param_signatures()[1].ty, - value, - )?; - error_block.append_operation(helper.br(1, &[range_check], location)); + { + metadata + .get::() + .ok_or(Error::MissingMetadata)? + .invoke_override( + context, + error_block, + location, + &info.param_signatures()[1].ty, + value, + )?; + helper.br(error_block, 1, &[range_check], location)?; + } Ok(()) } @@ -629,10 +629,11 @@ pub fn build_pop_front<'ctx, 'this>( let new_start = valid_block.addi(array_start, k1, location)?; let value = valid_block.insert_value(context, location, value, new_start, 1)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - empty_block.append_operation(helper.br(1, &[value], location)); + helper.br(empty_block, 1, &[value], location)?; + Ok(()) } @@ -719,20 +720,22 @@ pub fn build_pop_front_consume<'ctx, 'this>( let new_start = valid_block.addi(array_start, k1, location)?; let value = valid_block.insert_value(context, location, value, new_start, 1)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - metadata - .get::() - .ok_or(Error::MissingMetadata)? - .invoke_override( - context, - empty_block, - location, - &info.param_signatures()[0].ty, - value, - )?; - empty_block.append_operation(helper.br(1, &[], location)); + { + metadata + .get::() + .ok_or(Error::MissingMetadata)? + .invoke_override( + context, + empty_block, + location, + &info.param_signatures()[0].ty, + value, + )?; + helper.br(empty_block, 1, &[], location)?; + } Ok(()) } @@ -833,10 +836,11 @@ pub fn build_snapshot_pop_back<'ctx, 'this>( let value = valid_block.insert_value(context, location, value, new_end, 2)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - empty_block.append_operation(helper.br(1, &[value], location)); + helper.br(empty_block, 1, &[value], location)?; + Ok(()) } @@ -954,10 +958,10 @@ pub fn build_snapshot_multi_pop_front<'ctx, 'this>( valid_block.insert_value(context, location, array, new_array_start, 1)? }; - valid_block.append_operation(helper.br(0, &[range_check, array, return_ptr], location)); + helper.br(valid_block, 0, &[range_check, array, return_ptr], location)?; } - invalid_block.append_operation(helper.br(1, &[range_check, array], location)); + helper.br(invalid_block, 1, &[range_check, array], location)?; Ok(()) } @@ -1080,10 +1084,10 @@ pub fn build_snapshot_multi_pop_back<'ctx, 'this>( valid_block.insert_value(context, location, array, new_array_end, 2)? }; - valid_block.append_operation(helper.br(0, &[range_check, array, return_ptr], location)); + helper.br(valid_block, 0, &[range_check, array, return_ptr], location)?; } - invalid_block.append_operation(helper.br(1, &[range_check, array], location)); + helper.br(invalid_block, 1, &[range_check, array], location)?; Ok(()) } @@ -1206,7 +1210,7 @@ pub fn build_slice<'ctx, 'this>( _ => {} }; - slice_block.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(slice_block, 0, &[range_check, value], location)?; } { @@ -1231,7 +1235,7 @@ pub fn build_slice<'ctx, 'this>( entry.arg(1)?, )?; - error_block.append_operation(helper.br(1, &[range_check], location)); + helper.br(error_block, 1, &[range_check], location)?; } Ok(()) @@ -1317,9 +1321,7 @@ pub fn build_span_from_tuple<'ctx, 'this>( let array_container = entry.insert_value(context, location, array_container, ptr, 0)?; - entry.append_operation(helper.br(0, &[array_container], location)); - - Ok(()) + helper.br(entry, 0, &[array_container], location) } fn assert_nonnull<'ctx, 'this>( @@ -1508,10 +1510,10 @@ pub fn build_tuple_from_span<'ctx, 'this>( ); block_clone.append_operation(ReallocBindingsMeta::free(context, array_ptr, location)?); - block_clone.append_operation(helper.br(0, &[box_ptr], location)); + helper.br(block_clone, 0, &[box_ptr], location)?; } - block_forward.append_operation(helper.br(0, &[array_ptr], location)); + helper.br(block_forward, 0, &[array_ptr], location)?; } { @@ -1536,7 +1538,7 @@ pub fn build_tuple_from_span<'ctx, 'this>( entry.arg(0)?, )?; - block_err.append_operation(helper.br(1, &[], location)); + helper.br(block_err, 1, &[], location)?; } Ok(()) diff --git a/src/libfuncs/bitwise.rs b/src/libfuncs/bitwise.rs index 294640853..4e0dc7ef7 100644 --- a/src/libfuncs/bitwise.rs +++ b/src/libfuncs/bitwise.rs @@ -34,12 +34,12 @@ pub fn build<'ctx, 'this>( let logical_xor = entry.append_op_result(arith::xori(lhs, rhs, location))?; let logical_or = entry.append_op_result(arith::ori(lhs, rhs, location))?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[bitwise, logical_and, logical_xor, logical_or], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/bool.rs b/src/libfuncs/bool.rs index da431ad75..913fd22ba 100644 --- a/src/libfuncs/bool.rs +++ b/src/libfuncs/bool.rs @@ -126,8 +126,7 @@ fn build_bool_binary<'ctx, 'this>( let res = entry.insert_value(context, location, res, new_tag_value, 0)?; - entry.append_operation(helper.br(0, &[res], location)); - Ok(()) + helper.br(entry, 0, &[res], location) } /// Generate MLIR operations for the `bool_not_impl` libfunc. @@ -168,8 +167,7 @@ pub fn build_bool_not<'ctx, 'this>( ))?; let res = entry.insert_value(context, location, res, new_tag_value, 0)?; - entry.append_operation(helper.br(0, &[res], location)); - Ok(()) + helper.br(entry, 0, &[res], location) } /// Generate MLIR operations for the `unbox` libfunc. @@ -204,8 +202,7 @@ pub fn build_bool_to_felt252<'ctx, 'this>( let result = entry.extui(tag_value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } #[cfg(test)] diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index 5da4785e0..0b99cbf4f 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -190,8 +190,7 @@ fn build_add<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_sub` libfunc. @@ -318,8 +317,7 @@ fn build_sub<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_mul` libfunc. @@ -438,8 +436,7 @@ fn build_mul<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_divrem` libfunc. @@ -583,8 +580,7 @@ fn build_divrem<'ctx, 'this>( rem_value }; - entry.append_operation(helper.br(0, &[range_check, div_value, rem_value], location)); - Ok(()) + helper.br(entry, 0, &[range_check, div_value, rem_value], location) } /// Generate MLIR operations for the `bounded_int_constrain` libfunc. @@ -666,7 +662,7 @@ fn build_constrain<'ctx, 'this>( res_value }; - lower_block.append_operation(helper.br(0, &[range_check, res_value], location)); + helper.br(lower_block, 0, &[range_check, res_value], location)?; } { @@ -693,7 +689,7 @@ fn build_constrain<'ctx, 'this>( res_value }; - upper_block.append_operation(helper.br(1, &[range_check, res_value], location)); + helper.br(upper_block, 1, &[range_check, res_value], location)?; } Ok(()) @@ -722,14 +718,14 @@ fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int_from_type(context, location, 0, src_value.r#type())?; let src_is_zero = entry.cmpi(context, CmpiPredicate::Eq, src_value, k0, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, src_is_zero, [0, 1], [&[], &[src_value]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `bounded_int_wrap_non_zero` libfunc. diff --git a/src/libfuncs/box.rs b/src/libfuncs/box.rs index 224340959..3e48517ca 100644 --- a/src/libfuncs/box.rs +++ b/src/libfuncs/box.rs @@ -107,8 +107,7 @@ pub fn build_into_box<'ctx, 'this>( ))), )); - entry.append_operation(helper.br(0, &[ptr], location)); - Ok(()) + helper.br(entry, 0, &[ptr], location) } /// Generate MLIR operations for the `unbox` libfunc. @@ -146,8 +145,7 @@ pub fn build_unbox<'ctx, 'this>( entry.append_operation(ReallocBindingsMeta::free(context, entry.arg(0)?, location)?); - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } #[cfg(test)] diff --git a/src/libfuncs/bytes31.rs b/src/libfuncs/bytes31.rs index 63e59450a..e3cc647b5 100644 --- a/src/libfuncs/bytes31.rs +++ b/src/libfuncs/bytes31.rs @@ -75,9 +75,7 @@ pub fn build_const<'ctx, 'this>( location, )); - entry.append_operation(helper.br(0, &[op0.result(0)?.into()], location)); - - Ok(()) + helper.br(entry, 0, &[op0.result(0)?.into()], location) } /// Generate MLIR operations for the `bytes31_to_felt252` libfunc. @@ -101,9 +99,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_from_felt252` libfunc. @@ -161,9 +157,9 @@ pub fn build_from_felt252<'ctx, 'this>( )); let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(block_success, 0, &[range_check, value], location)?; - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/cast.rs b/src/libfuncs/cast.rs index 1e8ede5fd..7627c8306 100644 --- a/src/libfuncs/cast.rs +++ b/src/libfuncs/cast.rs @@ -60,14 +60,14 @@ pub fn build_downcast<'ctx, 'this>( if info.signature.param_signatures[1].ty == info.signature.branch_signatures[0].vars[1].ty { let k0 = entry.const_int(context, location, 0, 1)?; - entry.append_operation(helper.cond_br( + return helper.cond_br( context, + entry, k0, [0, 1], [&[range_check, src_value], &[range_check]], location, - )); - return Ok(()); + ); } let src_ty = registry.get_type(&info.signature.param_signatures[1].ty)?; @@ -183,13 +183,14 @@ pub fn build_downcast<'ctx, 'this>( let is_in_bounds = entry.const_int(context, location, 1, 1)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_bounds, [0, 1], [&[range_check, dst_value], &[range_check]], location, - )); + )?; } else { let lower_check = if dst_range.lower > src_range.lower { let dst_lower = entry.const_int_from_type( @@ -267,13 +268,14 @@ pub fn build_downcast<'ctx, 'this>( } else { dst_value }; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_bounds, [0, 1], [&[range_check, dst_value], &[range_check]], location, - )); + )?; } Ok(()) @@ -292,8 +294,7 @@ pub fn build_upcast<'ctx, 'this>( let src_value = entry.arg(0)?; if info.signature.param_signatures[0].ty == info.signature.branch_signatures[0].vars[0].ty { - entry.append_operation(helper.br(0, &[src_value], location)); - return Ok(()); + return helper.br(entry, 0, &[src_value], location); } let src_ty = registry.get_type(&info.signature.param_signatures[0].ty)?; @@ -383,8 +384,7 @@ pub fn build_upcast<'ctx, 'this>( dst_value }; - entry.append_operation(helper.br(0, &[dst_value], location)); - Ok(()) + helper.br(entry, 0, &[dst_value], location) } #[cfg(test)] diff --git a/src/libfuncs/circuit.rs b/src/libfuncs/circuit.rs index b7f0ad443..448a27f5d 100644 --- a/src/libfuncs/circuit.rs +++ b/src/libfuncs/circuit.rs @@ -123,9 +123,7 @@ fn build_init_circuit_data<'ctx, 'this>( &[k0], )?; - entry.append_operation(helper.br(0, &[rc, accumulator], location)); - - Ok(()) + helper.br(entry, 0, &[rc, accumulator], location) } /// Generate MLIR operations for the `add_circuit_input` libfunc. @@ -223,7 +221,7 @@ fn build_add_input<'ctx, 'this>( let accumulator = middle_insert_block.load(context, location, accumulator_ptr, accumulator.r#type())?; - middle_insert_block.append_operation(helper.br(1, &[accumulator], location)); + helper.br(middle_insert_block, 1, &[accumulator], location)?; } // If is last insert, then: @@ -297,7 +295,7 @@ fn build_add_input<'ctx, 'this>( // Load data from pointer let data = last_insert_block.load(context, location, data_ptr, data_type)?; - last_insert_block.append_operation(helper.br(0, &[data], location)); + helper.br(last_insert_block, 0, &[data], location)?; } Ok(()) @@ -319,9 +317,14 @@ fn build_try_into_circuit_modulus<'ctx, 'this>( let is_valid = entry.cmpi(context, arith::CmpiPredicate::Ugt, modulus, k1, location)?; - entry.append_operation(helper.cond_br(context, is_valid, [0, 1], [&[modulus], &[]], location)); - - Ok(()) + helper.cond_br( + context, + entry, + is_valid, + [0, 1], + [&[modulus], &[]], + location, + ) } /// Generate MLIR operations for the `get_circuit_descriptor` libfunc. @@ -342,9 +345,7 @@ fn build_get_descriptor<'ctx, 'this>( let unit = entry.append_op_result(llvm::undef(descriptor_type, location))?; - entry.append_operation(helper.br(0, &[unit], location)); - - Ok(()) + helper.br(entry, 0, &[unit], location) } /// Generate MLIR operations for the `eval_circuit` libfunc. @@ -413,7 +414,7 @@ fn build_eval<'ctx, 'this>( &gates, )?; - ok_block.append_operation(helper.br(0, &[add_mod, mul_mod, outputs], location)); + helper.br(ok_block, 0, &[add_mod, mul_mod, outputs], location)?; } // Error case @@ -438,7 +439,12 @@ fn build_eval<'ctx, 'this>( registry.build_type(context, helper, registry, metadata, failure_type_id)?, location, ))?; - err_block.append_operation(helper.br(1, &[add_mod, mul_mod, partial, failure], location)); + helper.br( + err_block, + 1, + &[add_mod, mul_mod, partial, failure], + location, + )?; } Ok(()) @@ -711,9 +717,7 @@ fn build_failure_guarantee_verify<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[rc, mul_mod, guarantee], location)); - - Ok(()) + helper.br(entry, 0, &[rc, mul_mod, guarantee], location) } /// Generate MLIR operations for the `u96_limbs_less_than_guarantee_verify` libfunc. @@ -740,15 +744,14 @@ fn build_u96_limbs_less_than_guarantee_verify<'ctx, 'this>( let u96 = entry.append_op_result(llvm::undef(u96_type, location))?; let kfalse = entry.const_int(context, location, 0, 64)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, kfalse, [0, 1], [&[guarantee], &[u96]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u96_single_limb_less_than_guarantee_verify` libfunc. @@ -767,9 +770,7 @@ fn build_u96_single_limb_less_than_guarantee_verify<'ctx, 'this>( let u96_type = registry.build_type(context, helper, registry, metadata, u96_type_id)?; let u96 = entry.append_op_result(llvm::undef(u96_type, location))?; - entry.append_operation(helper.br(0, &[u96], location)); - - Ok(()) + helper.br(entry, 0, &[u96], location) } /// Generate MLIR operations for the `get_circuit_output` libfunc. @@ -811,9 +812,7 @@ fn build_get_output<'ctx, 'this>( registry.build_type(context, helper, registry, metadata, guarantee_type_id)?; let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[output_struct, guarantee], location)); - - Ok(()) + helper.br(entry, 0, &[output_struct, guarantee], location) } fn u384_struct_to_integer<'a>( diff --git a/src/libfuncs/const.rs b/src/libfuncs/const.rs index 85ebdc51c..8553cb57d 100644 --- a/src/libfuncs/const.rs +++ b/src/libfuncs/const.rs @@ -88,8 +88,7 @@ pub fn build_const_as_box<'ctx, 'this>( // Store constant in box entry.store(context, location, ptr, value)?; - entry.append_operation(helper.br(0, &[ptr], location)); - Ok(()) + helper.br(entry, 0, &[ptr], location) } /// Generate MLIR operations for the `const_as_immediate` libfunc. @@ -113,8 +112,7 @@ pub fn build_const_as_immediate<'ctx, 'this>( context, registry, entry, location, helper, metadata, const_type, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_const_type_value<'ctx, 'this>( diff --git a/src/libfuncs/coupon.rs b/src/libfuncs/coupon.rs index f47999fbd..69c07bd08 100644 --- a/src/libfuncs/coupon.rs +++ b/src/libfuncs/coupon.rs @@ -73,9 +73,7 @@ pub fn build_buy<'ctx, 'this>( )?; let coupon = entry.append_op_result(llvm::undef(ty, location))?; - entry.append_operation(helper.br(0, &[coupon], location)); - - Ok(()) + helper.br(entry, 0, &[coupon], location) } /// Generate MLIR operations for the `coupon` libfunc. @@ -92,7 +90,5 @@ pub fn build_refund<'ctx, 'this>( // let gas = metadata.get::().ok_or(Error::MissingMetadata)?; // let gas_cost = gas.initial_required_gas(&info.function.id); - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/debug.rs b/src/libfuncs/debug.rs index 770db996a..d1f5ed129 100644 --- a/src/libfuncs/debug.rs +++ b/src/libfuncs/debug.rs @@ -31,12 +31,12 @@ use melior::{ Context, }; -pub fn build<'ctx>( +pub fn build<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, - entry: &Block<'ctx>, + entry: &'this Block<'ctx>, location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, '_>, + helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, selector: &DebugConcreteLibfunc, ) -> Result<()> { @@ -47,12 +47,12 @@ pub fn build<'ctx>( } } -pub fn build_print<'ctx>( +pub fn build_print<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, - entry: &Block<'ctx>, + entry: &'this Block<'ctx>, location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, '_>, + helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { @@ -121,7 +121,5 @@ pub fn build_print<'ctx>( location, ); - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/drop.rs b/src/libfuncs/drop.rs index eec53cfce..a133978f4 100644 --- a/src/libfuncs/drop.rs +++ b/src/libfuncs/drop.rs @@ -51,6 +51,5 @@ pub fn build<'ctx, 'this>( )?; } - entry.append_operation(helper.br(0, &[], location)); - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/dup.rs b/src/libfuncs/dup.rs index a0f6112b4..620fedfde 100644 --- a/src/libfuncs/dup.rs +++ b/src/libfuncs/dup.rs @@ -45,7 +45,5 @@ pub fn build<'ctx, 'this>( &info.signature.param_signatures[0].ty, entry.arg(0)?, )?; - entry.append_operation(helper.br(0, &[values.0, values.1], location)); - - Ok(()) + helper.br(entry, 0, &[values.0, values.1], location) } diff --git a/src/libfuncs/ec.rs b/src/libfuncs/ec.rs index 12b8bdfae..12358aecd 100644 --- a/src/libfuncs/ec.rs +++ b/src/libfuncs/ec.rs @@ -91,14 +91,14 @@ pub fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int(context, location, 0, 252)?; let y_is_zero = entry.cmpi(context, CmpiPredicate::Eq, y, k0, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, y_is_zero, [0, 1], [&[], &[entry.arg(0)?]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `ec_neg` libfunc. @@ -134,8 +134,7 @@ pub fn build_neg<'ctx, 'this>( let result = entry.insert_value(context, location, entry.arg(0)?, y_neg, 1)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `ec_point_from_x_nz` libfunc. @@ -179,14 +178,14 @@ pub fn build_point_from_x<'ctx, 'this>( let point = entry.load(context, location, point_ptr, ec_point_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result, [0, 1], [&[range_check, point], &[range_check]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `ec_state_add` libfunc. @@ -233,8 +232,7 @@ pub fn build_state_add<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[state], location)); - Ok(()) + helper.br(entry, 0, &[state], location) } /// Generate MLIR operations for the `ec_state_add_mul` libfunc. @@ -289,8 +287,7 @@ pub fn build_state_add_mul<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[ec_op, state], location)); - Ok(()) + helper.br(entry, 0, &[ec_op, state], location) } /// Generate MLIR operations for the `ec_state_try_finalize_nz` libfunc. @@ -335,8 +332,7 @@ pub fn build_state_finalize<'ctx, 'this>( let point = entry.load(context, location, point_ptr, ec_point_ty)?; - entry.append_operation(helper.cond_br(context, is_zero, [0, 1], [&[point], &[]], location)); - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[point], &[]], location) } /// Generate MLIR operations for the `ec_state_init` libfunc. @@ -374,8 +370,7 @@ pub fn build_state_init<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[state], location)); - Ok(()) + helper.br(entry, 0, &[state], location) } /// Generate MLIR operations for the `ec_point_try_new_nz` libfunc. @@ -417,8 +412,7 @@ pub fn build_try_new<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.cond_br(context, result, [0, 1], [&[point], &[]], location)); - Ok(()) + helper.cond_br(context, entry, result, [0, 1], [&[point], &[]], location) } /// Generate MLIR operations for the `ec_point_unwrap` libfunc. @@ -459,8 +453,7 @@ pub fn build_unwrap_point<'ctx, 'this>( 1, )?; - entry.append_operation(helper.br(0, &[x, y], location)); - Ok(()) + helper.br(entry, 0, &[x, y], location) } /// Generate MLIR operations for the `ec_point_zero` libfunc. @@ -489,8 +482,7 @@ pub fn build_zero<'ctx, 'this>( let point = entry.insert_value(context, location, point, k0, 1)?; - entry.append_operation(helper.br(0, &[point], location)); - Ok(()) + helper.br(entry, 0, &[point], location) } #[cfg(test)] diff --git a/src/libfuncs/enum.rs b/src/libfuncs/enum.rs index 1b2fba284..d5defdb3c 100644 --- a/src/libfuncs/enum.rs +++ b/src/libfuncs/enum.rs @@ -94,9 +94,8 @@ pub fn build_init<'ctx, 'this>( &info.signature.param_signatures[0].ty, info.index, )?; - entry.append_operation(helper.br(0, &[val], location)); - Ok(()) + helper.br(entry, 0, &[val], location) } #[allow(clippy::too_many_arguments)] @@ -246,9 +245,7 @@ pub fn build_from_bounded_int<'ctx, 'this>( let value = entry.append_op_result(llvm::undef(enum_ty, location))?; let value = entry.insert_value(context, location, value, tag_value, 0)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `enum_match` libfunc. @@ -283,7 +280,7 @@ pub fn build_match<'ctx, 'this>( entry.append_operation(llvm::unreachable(location)); } 1 => { - entry.append_operation(helper.br(0, &[entry.arg(0)?], location)); + helper.br(entry, 0, &[entry.arg(0)?], location)?; } _ => { let (layout, (tag_ty, _), variant_tys) = crate::types::r#enum::get_type_for_variants( @@ -400,7 +397,7 @@ pub fn build_match<'ctx, 'this>( } }; - block.append_operation(helper.br(i, &[payload_val], location)); + helper.br(block, i, &[payload_val], location)?; } } } @@ -444,7 +441,7 @@ pub fn build_snapshot_match<'ctx, 'this>( entry.append_operation(llvm::unreachable(location)); } 1 => { - entry.append_operation(helper.br(0, &[entry.arg(0)?], location)); + helper.br(entry, 0, &[entry.arg(0)?], location)?; } _ => { let (layout, (tag_ty, _), variant_tys) = crate::types::r#enum::get_type_for_variants( @@ -542,7 +539,7 @@ pub fn build_snapshot_match<'ctx, 'this>( } }; - block.append_operation(helper.br(i, &[payload_val], location)); + helper.br(block, i, &[payload_val], location)?; } } } diff --git a/src/libfuncs/felt252.rs b/src/libfuncs/felt252.rs index ad8225524..6be894e50 100644 --- a/src/libfuncs/felt252.rs +++ b/src/libfuncs/felt252.rs @@ -272,14 +272,11 @@ pub fn build_binary_operation<'ctx, 'this>( ))?; let result = inverse_result_block.trunci(result, felt252_ty, location)?; - inverse_result_block.append_operation(helper.br(0, &[result], location)); - return Ok(()); + return helper.br(inverse_result_block, 0, &[result], location); } }; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `felt252_const` libfunc. @@ -308,8 +305,8 @@ pub fn build_const<'ctx, 'this>( )?; let value = entry.const_int_from_type(context, location, value, felt252_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `felt252_is_zero` libfunc. @@ -327,8 +324,7 @@ pub fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - Ok(()) + helper.cond_br(context, entry, condition, [0, 1], [&[], &[arg0]], location) } #[cfg(test)] diff --git a/src/libfuncs/felt252_dict.rs b/src/libfuncs/felt252_dict.rs index 4b3f7a67d..4584c634a 100644 --- a/src/libfuncs/felt252_dict.rs +++ b/src/libfuncs/felt252_dict.rs @@ -56,8 +56,7 @@ pub fn build_new<'ctx, 'this>( let dict_ptr = runtime_bindings.dict_new(context, helper, entry, location)?; - entry.append_operation(helper.br(0, &[segment_arena, dict_ptr], location)); - Ok(()) + helper.br(entry, 0, &[segment_arena, dict_ptr], location) } pub fn build_squash<'ctx, 'this>( @@ -85,13 +84,12 @@ pub fn build_squash<'ctx, 'this>( let new_gas_builtin = entry.addi(gas_builtin, gas_refund, location)?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[range_check, new_gas_builtin, segment_arena, entry.arg(3)?], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/felt252_dict_entry.rs b/src/libfuncs/felt252_dict_entry.rs index 50ac436e8..3047f027a 100644 --- a/src/libfuncs/felt252_dict_entry.rs +++ b/src/libfuncs/felt252_dict_entry.rs @@ -153,11 +153,18 @@ pub fn build_get<'ctx, 'this>( block_vacant.append_operation(cf::br(block_final, &[value], location)); } - let entry = block_final.append_op_result(llvm::undef(entry_ty, location))?; - let entry = - block_final.insert_values(context, location, entry, &[dict_ptr, entry_value_ptr_ptr])?; + { + let entry = block_final.append_op_result(llvm::undef(entry_ty, location))?; + let entry = block_final.insert_values( + context, + location, + entry, + &[dict_ptr, entry_value_ptr_ptr], + )?; + + helper.br(block_final, 0, &[entry, block_final.arg(0)?], location)?; + } - block_final.append_operation(helper.br(0, &[entry, block_final.arg(0)?], location)); Ok(()) } @@ -265,8 +272,10 @@ pub fn build_finalize<'ctx, 'this>( block_vacant.append_operation(cf::br(block_final, &[value_ptr], location)); } - block_final.store(context, location, block_final.arg(0)?, entry_value)?; - block_final.append_operation(helper.br(0, &[dict_ptr], location)); + { + block_final.store(context, location, block_final.arg(0)?, entry_value)?; + helper.br(block_final, 0, &[dict_ptr], location)?; + } Ok(()) } diff --git a/src/libfuncs/function_call.rs b/src/libfuncs/function_call.rs index 6bd322b91..22df0ebea 100644 --- a/src/libfuncs/function_call.rs +++ b/src/libfuncs/function_call.rs @@ -121,7 +121,7 @@ pub fn build<'ctx, 'this>( } } - cont_block.append_operation(helper.br(0, &results, location)); + helper.br(cont_block, 0, &results, location)?; } else { let mut result_types = Vec::new(); let return_types = info @@ -290,7 +290,7 @@ pub fn build<'ctx, 'this>( } } - entry.append_operation(helper.br(0, &results, location)); + helper.br(entry, 0, &results, location)?; } if let Some(tailrec_meta) = tailrec_meta { diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index db8a924f8..089bc43e9 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -58,11 +58,12 @@ pub fn build_get_available_gas<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let gas = entry.arg(0)?; - let gas_u128 = entry.extui(gas, IntegerType::new(context, 128).into(), location)?; + let i128_ty = IntegerType::new(context, 128).into(); + + let gas_u128 = entry.extui(entry.arg(0)?, i128_ty, location)?; + // The gas is returned as u128 on the second arg. - entry.append_operation(helper.br(0, &[entry.arg(0)?, gas_u128], location)); - Ok(()) + helper.br(entry, 0, &[entry.arg(0)?, gas_u128], location) } /// Generate MLIR operations for the `withdraw_gas` libfunc. @@ -142,15 +143,14 @@ pub fn build_withdraw_gas<'ctx, 'this>( ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_enough, [0, 1], [&[range_check, resulting_gas], &[range_check, current_gas]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `withdraw_gas_all` libfunc. @@ -220,15 +220,14 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_enough, [0, 1], [&[range_check, resulting_gas], &[range_check, current_gas]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `get_builtin_costs` libfunc. @@ -252,9 +251,7 @@ pub fn build_get_builtin_costs<'ctx, 'this>( .into() }; - entry.append_operation(helper.br(0, &[builtin_ptr], location)); - - Ok(()) + helper.br(entry, 0, &[builtin_ptr], location) } #[cfg(test)] diff --git a/src/libfuncs/int_range.rs b/src/libfuncs/int_range.rs index f231da6da..ad714bce2 100644 --- a/src/libfuncs/int_range.rs +++ b/src/libfuncs/int_range.rs @@ -83,14 +83,14 @@ pub fn build_int_range_try_new<'ctx, 'this>( 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( + helper.cond_br( context, + entry, is_valid, [0, 1], [&[range_check, range], &[range_check, range]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `int_range_pop_front` libfunc. @@ -130,14 +130,14 @@ pub fn build_int_range_pop_front<'ctx, 'this>( }; let range = entry.insert_value(context, location, range, x_p_1, 0)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_valid, [1, 0], // failure, success [&[range, x], &[]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/mem.rs b/src/libfuncs/mem.rs index 7f1a39485..37501f682 100644 --- a/src/libfuncs/mem.rs +++ b/src/libfuncs/mem.rs @@ -85,8 +85,7 @@ pub fn build_alloc_local<'ctx, 'this>( let value = entry.append_op_result(llvm::undef(target_type, location))?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `store_local` libfunc. @@ -99,6 +98,5 @@ pub fn build_store_local<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureAndTypeConcreteLibfunc, ) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.arg(1)?], location)); - Ok(()) + helper.br(entry, 0, &[entry.arg(1)?], location) } diff --git a/src/libfuncs/nullable.rs b/src/libfuncs/nullable.rs index 79645e6cf..67f4787f4 100644 --- a/src/libfuncs/nullable.rs +++ b/src/libfuncs/nullable.rs @@ -65,8 +65,7 @@ fn build_null<'ctx, 'this>( 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(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `match_nullable` libfunc. @@ -109,8 +108,8 @@ fn build_match_nullable<'ctx, 'this>( location, )); - block_is_null.append_operation(helper.br(0, &[], location)); - block_is_not_null.append_operation(helper.br(1, &[arg], location)); + helper.br(block_is_null, 0, &[], location)?; + helper.br(block_is_not_null, 1, &[arg], location)?; Ok(()) } diff --git a/src/libfuncs/pedersen.rs b/src/libfuncs/pedersen.rs index d9ee3d3f8..2bfcefa4d 100644 --- a/src/libfuncs/pedersen.rs +++ b/src/libfuncs/pedersen.rs @@ -96,8 +96,7 @@ pub fn build_pedersen<'ctx>( let result = entry.load(context, location, dst_ptr, i256_ty)?; let result = entry.trunci(result, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[pedersen_builtin, result], location)); - Ok(()) + helper.br(entry, 0, &[pedersen_builtin, result], location) } #[cfg(test)] diff --git a/src/libfuncs/poseidon.rs b/src/libfuncs/poseidon.rs index 3ad52694f..7afe71325 100644 --- a/src/libfuncs/poseidon.rs +++ b/src/libfuncs/poseidon.rs @@ -109,9 +109,7 @@ pub fn build_hades_permutation<'ctx>( let op1 = entry.trunci(op1_i256, felt252_ty, location)?; let op2 = entry.trunci(op2_i256, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[poseidon_builtin, op0, op1, op2], location)); - - Ok(()) + helper.br(entry, 0, &[poseidon_builtin, op0, op1, op2], location) } #[cfg(test)] diff --git a/src/libfuncs/sint128.rs b/src/libfuncs/sint128.rs index 0242913ed..f5ea53a51 100644 --- a/src/libfuncs/sint128.rs +++ b/src/libfuncs/sint128.rs @@ -82,9 +82,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i128 operation libfunc. @@ -152,15 +150,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -185,15 +184,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i128_is_zero` libfunc. @@ -205,15 +203,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let value = entry.arg(0)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i128_to_felt252` libfunc. @@ -259,9 +254,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i128_from_felt252` libfunc. @@ -360,8 +353,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -386,14 +379,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint16.rs b/src/libfuncs/sint16.rs index c3b1e312d..db21bee9d 100644 --- a/src/libfuncs/sint16.rs +++ b/src/libfuncs/sint16.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i16 operation libfunc. @@ -153,15 +151,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between underflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Overflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -186,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i16_is_zero` libfunc. @@ -206,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i16_widemul` libfunc. @@ -242,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i16_to_felt252` libfunc. @@ -289,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i16_from_felt252` libfunc. @@ -390,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -416,14 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint32.rs b/src/libfuncs/sint32.rs index 37d5251e6..3ad9f5d2b 100644 --- a/src/libfuncs/sint32.rs +++ b/src/libfuncs/sint32.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i32 operation libfunc. @@ -153,15 +151,17 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; + Ok(()) } @@ -185,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i32_is_zero` libfunc. @@ -205,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i32_widemul` libfunc. @@ -241,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i32_to_felt252` libfunc. @@ -288,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i32_from_felt252` libfunc. @@ -389,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -415,15 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint64.rs b/src/libfuncs/sint64.rs index e13366fe9..6f9de56da 100644 --- a/src/libfuncs/sint64.rs +++ b/src/libfuncs/sint64.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i64 operation libfunc. @@ -153,15 +151,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -186,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i64_is_zero` libfunc. @@ -206,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i64_widemul` libfunc. @@ -242,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i64_to_felt252` libfunc. @@ -289,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i64_from_felt252` libfunc. @@ -390,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -416,14 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint8.rs b/src/libfuncs/sint8.rs index 0c19b6f35..7941e570f 100644 --- a/src/libfuncs/sint8.rs +++ b/src/libfuncs/sint8.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i8 operation libfunc. @@ -154,15 +152,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between underflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -187,15 +186,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i8_is_zero` libfunc. @@ -207,15 +205,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i8_widemul` libfunc. @@ -243,8 +238,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i8_to_felt252` libfunc. @@ -290,9 +284,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i8_from_felt252` libfunc. @@ -392,8 +384,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -418,14 +410,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index e0239ac45..f23d378d6 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -342,8 +342,9 @@ pub fn build_call_contract<'ctx, 'this>( IntegerType::new(context, 64).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -351,8 +352,7 @@ pub fn build_call_contract<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_class_hash_const<'ctx, 'this>( @@ -374,8 +374,7 @@ pub fn build_class_hash_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_class_hash_try_from_felt252<'ctx, 'this>( @@ -402,14 +401,14 @@ pub fn build_class_hash_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_contract_address_const<'ctx, 'this>( @@ -431,8 +430,7 @@ pub fn build_contract_address_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_contract_address_try_from_felt252<'ctx, 'this>( @@ -459,14 +457,14 @@ pub fn build_contract_address_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_storage_read<'ctx, 'this>( @@ -610,8 +608,9 @@ pub fn build_storage_read<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -619,8 +618,7 @@ pub fn build_storage_read<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_storage_write<'ctx, 'this>( @@ -772,8 +770,9 @@ pub fn build_storage_write<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -781,8 +780,7 @@ pub fn build_storage_write<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_storage_base_address_const<'ctx, 'this>( @@ -804,8 +802,7 @@ pub fn build_storage_base_address_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_storage_base_address_from_felt252<'ctx, 'this>( @@ -845,8 +842,7 @@ pub fn build_storage_base_address_from_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[range_check, value], location)); - Ok(()) + helper.br(entry, 0, &[range_check, value], location) } pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( @@ -861,8 +857,7 @@ pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( let offset = entry.extui(entry.arg(1)?, entry.argument(0)?.r#type(), location)?; let addr = entry.addi(entry.arg(0)?, offset, location)?; - entry.append_operation(helper.br(0, &[addr], location)); - Ok(()) + helper.br(entry, 0, &[addr], location) } pub fn build_storage_address_try_from_felt252<'ctx, 'this>( @@ -889,14 +884,14 @@ pub fn build_storage_address_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_emit_event<'ctx, 'this>( @@ -1089,8 +1084,9 @@ pub fn build_emit_event<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1098,8 +1094,7 @@ pub fn build_emit_event<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_block_hash<'ctx, 'this>( @@ -1238,8 +1233,9 @@ pub fn build_get_block_hash<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1247,8 +1243,7 @@ pub fn build_get_block_hash<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_execution_info<'ctx, 'this>( @@ -1381,8 +1376,9 @@ pub fn build_get_execution_info<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1390,8 +1386,7 @@ pub fn build_get_execution_info<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_execution_info_v2<'ctx, 'this>( @@ -1524,8 +1519,9 @@ pub fn build_get_execution_info_v2<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1533,8 +1529,7 @@ pub fn build_get_execution_info_v2<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_deploy<'ctx, 'this>( @@ -1762,8 +1757,9 @@ pub fn build_deploy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1788,8 +1784,7 @@ pub fn build_deploy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } pub fn build_keccak<'ctx, 'this>( @@ -1938,8 +1933,9 @@ pub fn build_keccak<'ctx, 'this>( }; let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1947,8 +1943,7 @@ pub fn build_keccak<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_library_call<'ctx, 'this>( @@ -2118,8 +2113,9 @@ pub fn build_library_call<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2127,8 +2123,7 @@ pub fn build_library_call<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_replace_class<'ctx, 'this>( @@ -2268,8 +2263,9 @@ pub fn build_replace_class<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2277,8 +2273,7 @@ pub fn build_replace_class<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_send_message_to_l1<'ctx, 'this>( @@ -2443,8 +2438,9 @@ pub fn build_send_message_to_l1<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2452,8 +2448,7 @@ pub fn build_send_message_to_l1<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_sha256_process_block_syscall<'ctx, 'this>( @@ -2595,8 +2590,9 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2604,8 +2600,7 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_class_hash_at<'ctx, 'this>( @@ -2748,8 +2743,9 @@ pub fn build_get_class_hash_at<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2757,8 +2753,7 @@ pub fn build_get_class_hash_at<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/starknet/secp256.rs b/src/libfuncs/starknet/secp256.rs index 9aa3a1b1e..e4032e300 100644 --- a/src/libfuncs/starknet/secp256.rs +++ b/src/libfuncs/starknet/secp256.rs @@ -271,8 +271,9 @@ pub fn build_k1_new<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -280,8 +281,7 @@ pub fn build_k1_new<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_add<'ctx, 'this>( @@ -484,8 +484,9 @@ pub fn build_k1_add<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -493,8 +494,7 @@ pub fn build_k1_add<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_mul<'ctx, 'this>( @@ -697,8 +697,9 @@ pub fn build_k1_mul<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -706,8 +707,7 @@ pub fn build_k1_mul<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_get_point_from_x<'ctx, 'this>( @@ -902,8 +902,9 @@ pub fn build_k1_get_point_from_x<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -911,8 +912,7 @@ pub fn build_k1_get_point_from_x<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_get_xy<'ctx, 'this>( @@ -1149,8 +1149,9 @@ pub fn build_k1_get_xy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1163,8 +1164,7 @@ pub fn build_k1_get_xy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } pub fn build_r1_new<'ctx, 'this>( @@ -1367,8 +1367,9 @@ pub fn build_r1_new<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1376,8 +1377,7 @@ pub fn build_r1_new<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_add<'ctx, 'this>( @@ -1580,8 +1580,9 @@ pub fn build_r1_add<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1589,8 +1590,7 @@ pub fn build_r1_add<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_mul<'ctx, 'this>( @@ -1796,8 +1796,9 @@ pub fn build_r1_mul<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1805,8 +1806,7 @@ pub fn build_r1_mul<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_get_point_from_x<'ctx, 'this>( @@ -2002,8 +2002,9 @@ pub fn build_r1_get_point_from_x<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2011,8 +2012,7 @@ pub fn build_r1_get_point_from_x<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_get_xy<'ctx, 'this>( @@ -2251,8 +2251,9 @@ pub fn build_r1_get_xy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2265,6 +2266,5 @@ pub fn build_r1_get_xy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } diff --git a/src/libfuncs/starknet/testing.rs b/src/libfuncs/starknet/testing.rs index 2b9b024c4..dbf4f6a45 100644 --- a/src/libfuncs/starknet/testing.rs +++ b/src/libfuncs/starknet/testing.rs @@ -116,7 +116,5 @@ pub fn build<'ctx, 'this>( location, LoadStoreOptions::new(), ))?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } diff --git a/src/libfuncs/struct.rs b/src/libfuncs/struct.rs index 7e30cfb3b..8140ba0ba 100644 --- a/src/libfuncs/struct.rs +++ b/src/libfuncs/struct.rs @@ -71,9 +71,7 @@ pub fn build_construct<'ctx, 'this>( &fields, )?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `struct_construct` libfunc. @@ -117,7 +115,5 @@ pub fn build_deconstruct<'ctx, 'this>( fields.push(value); } - entry.append_operation(helper.br(0, &fields, location)); - - Ok(()) + helper.br(entry, 0, &fields, location) } diff --git a/src/libfuncs/uint128.rs b/src/libfuncs/uint128.rs index cb96ca053..a80bb1096 100644 --- a/src/libfuncs/uint128.rs +++ b/src/libfuncs/uint128.rs @@ -97,8 +97,7 @@ pub fn build_byte_reverse<'ctx, 'this>( let res = entry.append_op_result(ods::llvm::intr_bswap(context, arg1, location).into())?; - entry.append_operation(helper.br(0, &[bitwise, res], location)); - Ok(()) + helper.br(entry, 0, &[bitwise, res], location) } /// Generate MLIR operations for the `u128_const` libfunc. @@ -123,9 +122,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `u128_safe_divmod` libfunc. @@ -146,8 +143,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u128_equal` libfunc. @@ -171,15 +167,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u128s_from_felt252` libfunc. @@ -207,14 +202,14 @@ pub fn build_from_felt252<'ctx, 'this>( let msb_bits = entry.shrui(value, k128, location)?; let msb_bits = entry.trunci(msb_bits, IntegerType::new(context, 128).into(), location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_wide, [1, 0], [&[range_check, msb_bits, lsb_bits], &[range_check, lsb_bits]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u128_is_zero` libfunc. @@ -227,14 +222,12 @@ pub fn build_is_zero<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let value = entry.arg(0)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u128_add` and `u128_sub` libfuncs. @@ -282,14 +275,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, overflow, [1, 0], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u128_sqrt` libfunc. @@ -427,8 +420,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i64_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u128_to_felt252` libfunc. @@ -447,8 +439,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, )); - entry.append_operation(helper.br(0, &[op.result(0)?.into()], location)); - Ok(()) + helper.br(entry, 0, &[op.result(0)?.into()], location) } /// Generate MLIR operations for the `u128_guarantee_mul` libfunc. @@ -487,8 +478,7 @@ pub fn build_guarantee_mul<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[result_hi, result_lo, guarantee], location)); - Ok(()) + helper.br(entry, 0, &[result_hi, result_lo, guarantee], location) } /// Generate MLIR operations for the `u128_guarantee_verify` libfunc. @@ -503,8 +493,7 @@ pub fn build_guarantee_verify<'ctx, 'this>( ) -> Result<()> { let range_check = super::increment_builtin_counter(context, entry, location, entry.arg(0)?)?; - entry.append_operation(helper.br(0, &[range_check], location)); - Ok(()) + helper.br(entry, 0, &[range_check], location) } #[cfg(test)] diff --git a/src/libfuncs/uint16.rs b/src/libfuncs/uint16.rs index 02aeae934..cab776dad 100644 --- a/src/libfuncs/uint16.rs +++ b/src/libfuncs/uint16.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u16 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u16_eq` libfunc. @@ -167,9 +165,7 @@ pub fn build_equal<'ctx, 'this>( let cond = entry.cmpi(context, CmpiPredicate::Eq, arg0, arg1, location)?; - entry.append_operation(helper.cond_br(context, cond, [1, 0], [&[]; 2], location)); - - Ok(()) + helper.cond_br(context, entry, cond, [1, 0], [&[]; 2], location) } /// Generate MLIR operations for the `u16_is_zero` libfunc. @@ -181,19 +177,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.append_op_result(arith::constant( - context, - IntegerAttribute::new(arg0.r#type(), 0).into(), - location, - ))?; - - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let value = entry.arg(0)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u16_safe_divmod` libfunc. @@ -213,8 +202,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u16_widemul` libfunc. @@ -241,8 +229,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u16_to_felt252` libfunc. @@ -266,9 +253,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u16_sqrt` libfunc. @@ -426,8 +411,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i8_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u16_from_felt252` libfunc. @@ -484,8 +468,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint256.rs b/src/libfuncs/uint256.rs index dacaf29b5..b5377e571 100644 --- a/src/libfuncs/uint256.rs +++ b/src/libfuncs/uint256.rs @@ -255,12 +255,12 @@ pub fn build_divmod<'ctx, 'this>( let op = entry.append_operation(llvm::undef(guarantee_type, location)); let guarantee = op.result(0)?.into(); - entry.append_operation(helper.br( + helper.br( + entry, 0, &[range_check, result_div, result_rem, guarantee], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u256_is_zero` libfunc. @@ -331,14 +331,14 @@ pub fn build_is_zero<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, val_is_zero, [0, 1], [&[], &[val_struct]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u256_sqrt` libfunc. @@ -634,8 +634,7 @@ pub fn build_square_root<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u256_guarantee_inv_mod_n` libfunc. @@ -938,8 +937,9 @@ pub fn build_u256_guarantee_inv_mod_n<'ctx, 'this>( let op = entry.append_operation(llvm::undef(guarantee_type, location)); let guarantee = op.result(0)?.into(); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, condition, [0, 1], [ @@ -958,9 +958,7 @@ pub fn build_u256_guarantee_inv_mod_n<'ctx, 'this>( &[entry.arg(0)?, guarantee, guarantee], ], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/uint32.rs b/src/libfuncs/uint32.rs index d7c3c5ade..9ada1a609 100644 --- a/src/libfuncs/uint32.rs +++ b/src/libfuncs/uint32.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u32 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u32_eq` libfunc. @@ -173,15 +171,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u32_is_zero` libfunc. @@ -193,15 +190,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u32_safe_divmod` libfunc. @@ -221,8 +215,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u32_widemul` libfunc. @@ -249,8 +242,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u32_to_felt252` libfunc. @@ -274,9 +266,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u32_sqrt` libfunc. @@ -414,8 +404,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i16_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u32_from_felt252` libfunc. @@ -467,8 +456,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint512.rs b/src/libfuncs/uint512.rs index 287a9a14b..5a4a8a98c 100644 --- a/src/libfuncs/uint512.rs +++ b/src/libfuncs/uint512.rs @@ -145,7 +145,8 @@ pub fn build_divmod_u256<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[ range_check, @@ -158,8 +159,7 @@ pub fn build_divmod_u256<'ctx, 'this>( guarantee, ], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/uint64.rs b/src/libfuncs/uint64.rs index 4d95445a5..58e56b425 100644 --- a/src/libfuncs/uint64.rs +++ b/src/libfuncs/uint64.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u64 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u64_eq` libfunc. @@ -167,9 +165,7 @@ pub fn build_equal<'ctx, 'this>( let cond = entry.cmpi(context, CmpiPredicate::Eq, arg0, arg1, location)?; - entry.append_operation(helper.cond_br(context, cond, [1, 0], [&[]; 2], location)); - - Ok(()) + helper.cond_br(context, entry, cond, [1, 0], [&[]; 2], location) } /// Generate MLIR operations for the `u64_is_zero` libfunc. @@ -187,9 +183,7 @@ pub fn build_is_zero<'ctx, 'this>( let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, condition, [0, 1], [&[], &[arg0]], location) } /// Generate MLIR operations for the `u64_safe_divmod` libfunc. @@ -209,8 +203,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u64_widemul` libfunc. @@ -237,8 +230,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u64_to_felt252` libfunc. @@ -262,9 +254,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u64_sqrt` libfunc. @@ -399,8 +389,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i32_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u64_from_felt252` libfunc. @@ -452,8 +441,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint8.rs b/src/libfuncs/uint8.rs index eb0cd7fbe..8ea87162e 100644 --- a/src/libfuncs/uint8.rs +++ b/src/libfuncs/uint8.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u8 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u8_eq` libfunc. @@ -173,15 +171,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u8_is_zero` libfunc. @@ -193,15 +190,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u8_safe_divmod` libfunc. @@ -221,8 +215,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u8_widemul` libfunc. @@ -249,8 +242,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_to_felt252` libfunc. @@ -274,9 +266,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_sqrt` libfunc. @@ -411,8 +401,7 @@ pub fn build_square_root<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u8_from_felt252` libfunc. @@ -463,9 +452,9 @@ pub fn build_from_felt252<'ctx, 'this>( )); let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(block_success, 0, &[range_check, value], location)?; - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/metadata.rs b/src/metadata.rs index 6f5038516..6a92ef75a 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -20,6 +20,7 @@ pub mod drop_overrides; pub mod dup_overrides; pub mod enum_snapshot_variants; pub mod gas; +pub mod profiler; pub mod realloc_bindings; pub mod runtime_bindings; pub mod tail_recursion; diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 88b65cd54..24951655c 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -1,20 +1,18 @@ +use crate::{error::Result as NativeResult, native_panic}; use cairo_lang_runner::token_gas_cost; use cairo_lang_sierra::{ extensions::gas::CostTokenType, ids::FunctionId, program::{Program, StatementIdx}, }; -use cairo_lang_sierra_ap_change::{ap_change_info::ApChangeInfo, calc_ap_changes}; use cairo_lang_sierra_ap_change::{ + ap_change_info::ApChangeInfo, calc_ap_changes, compute::calc_ap_changes as linear_calc_ap_changes, ApChangeError, }; use cairo_lang_sierra_gas::{ compute_postcost_info, compute_precost_info, gas_info::GasInfo, CostError, }; use cairo_lang_utils::ordered_hash_map::OrderedHashMap; - -use crate::{error::Result as NativeResult, native_panic}; - use std::collections::BTreeMap; /// Holds global gas info. diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs new file mode 100644 index 000000000..2a0434c3f --- /dev/null +++ b/src/metadata/profiler.rs @@ -0,0 +1,227 @@ +#![cfg(feature = "with-profiler")] + +use crate::{error::Result, utils::BlockExt}; +use cairo_lang_sierra::program::StatementIdx; +use melior::{ + dialect::{ + arith::{self, CmpiPredicate}, + llvm::{self, attributes::Linkage}, + ods, + }, + ir::{ + attribute::{FlatSymbolRefAttribute, StringAttribute, TypeAttribute}, + operation::OperationBuilder, + r#type::IntegerType, + Attribute, Block, Identifier, Location, Module, Region, Value, + }, + Context, +}; +use std::{cell::UnsafeCell, mem}; + +pub struct ProfilerMeta { + _private: (), +} + +impl ProfilerMeta { + pub fn new(context: &Context, module: &Module) -> Result { + // Generate the file descriptor holder. + module.body().append_operation( + ods::llvm::mlir_global( + context, + { + let region = Region::new(); + let block = region.append_block(Block::new(&[])); + + let null_ptr = block.append_op_result(llvm::zero( + llvm::r#type::pointer(context, 0), + Location::unknown(context), + ))?; + + block.append_operation(llvm::r#return( + Some(null_ptr), + Location::unknown(context), + )); + region + }, + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, "__profiler_callback"), + llvm::attributes::linkage(context, Linkage::Common), + Location::unknown(context), + ) + .into(), + ); + + Ok(Self { _private: () }) + } + + #[cfg(target_arch = "x86_64")] + pub fn measure_timestamp<'c, 'a>( + &self, + context: &'c Context, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result<(Value<'c, 'a>, Value<'c, 'a>)> { + let i32_ty = IntegerType::new(context, 32).into(); + let i64_ty = IntegerType::new(context, 64).into(); + let k32 = block.const_int_from_type(context, location, 32, i64_ty)?; + + // edx:eax := TimeStampCounter (clock value) + // ecx := IA32_TSC_AUX[31:0] (core ID) + let value = block.append_op_result( + OperationBuilder::new("llvm.inline_asm", location) + .add_attributes(&[ + ( + Identifier::new(context, "asm_string"), + StringAttribute::new(context, "mfence\nrdtscp\nlfence").into(), + ), + ( + Identifier::new(context, "has_side_effects"), + Attribute::unit(context), + ), + ( + Identifier::new(context, "constraints"), + StringAttribute::new(context, "={edx},={eax},={ecx}").into(), + ), + ]) + .add_results(&[llvm::r#type::r#struct( + context, + &[i32_ty, i32_ty, i32_ty], + false, + )]) + .build()?, + )?; + let value_hi = block.extract_value(context, location, value, i32_ty, 0)?; + let value_lo = block.extract_value(context, location, value, i32_ty, 1)?; + let core_idx = block.extract_value(context, location, value, i32_ty, 2)?; + + let value_hi = block.extui(value_hi, i64_ty, location)?; + let value_lo = block.extui(value_lo, i64_ty, location)?; + let value = block.shli(value_hi, k32, location)?; + let value = block.append_op_result(arith::ori(value, value_lo, location))?; + + Ok((value, core_idx)) + } + + #[cfg(target_arch = "aarch64")] + pub fn measure_timestamp<'c, 'a>( + &self, + context: &'c Context, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result<(Value<'c, 'a>, Value<'c, 'a>)> { + let i64_ty = IntegerType::new(context, 64).into(); + + let value = block.append_op_result( + OperationBuilder::new("llvm.inline_asm", location) + .add_attributes(&[ + ( + Identifier::new(context, "asm_string"), + StringAttribute::new(context, "isb\nmrs $0, CNTVCT_EL0\nisb").into(), + ), + ( + Identifier::new(context, "has_side_effects"), + Attribute::unit(context), + ), + ( + Identifier::new(context, "constraints"), + StringAttribute::new(context, "=r").into(), + ), + ]) + .add_results(&[i64_ty]) + .build()?, + )?; + let core_idx = block.const_int(context, location, 0, 64)?; + + Ok((value, core_idx)) + } + + pub fn push_frame<'c>( + &self, + context: &'c Context, + block: &Block<'c>, + statement_idx: usize, + t0: (Value<'c, '_>, Value<'c, '_>), + t1: (Value<'c, '_>, Value<'c, '_>), + location: Location<'c>, + ) -> Result<()> { + // If core idx matches: + // Calculate time delta. + // Write statement idx and time delta. + // If core idx does not match: + // Write statement idx and -1. + + let i64_ty = IntegerType::new(context, 64).into(); + + let statement_idx = block.const_int_from_type(context, location, statement_idx, i64_ty)?; + let is_same_core = block.cmpi(context, CmpiPredicate::Eq, t0.1, t1.1, location)?; + + let delta_value = block.append_op_result(arith::subi(t1.0, t0.0, location))?; + let invalid_value = block.const_int_from_type(context, location, u64::MAX, i64_ty)?; + let delta_value = block.append_op_result(arith::select( + is_same_core, + delta_value, + invalid_value, + location, + ))?; + + let callback_ptr = block.append_op_result( + ods::llvm::mlir_addressof( + context, + llvm::r#type::pointer(context, 0), + FlatSymbolRefAttribute::new(context, "__profiler_callback"), + location, + ) + .into(), + )?; + let callback_ptr = block.load( + context, + location, + callback_ptr, + llvm::r#type::pointer(context, 0), + )?; + + block.append_operation( + ods::llvm::call( + context, + &[callback_ptr, statement_idx, delta_value], + location, + ) + .into(), + ); + Ok(()) + } +} + +thread_local! { + static PROFILER_IMPL: UnsafeCell = const { UnsafeCell::new(ProfilerImpl::new()) }; +} + +pub struct ProfilerImpl { + trace: Vec<(StatementIdx, u64)>, +} + +impl ProfilerImpl { + const fn new() -> Self { + Self { trace: Vec::new() } + } + + pub fn take() -> Vec<(StatementIdx, u64)> { + PROFILER_IMPL.with(|x| { + let x = unsafe { &mut *x.get() }; + + let mut trace = Vec::new(); + mem::swap(&mut x.trace, &mut trace); + + trace + }) + } + + pub extern "C" fn callback(statement_idx: u64, tick_delta: u64) { + PROFILER_IMPL.with(|x| { + let x = unsafe { &mut *x.get() }; + + x.trace + .push((StatementIdx(statement_idx as usize), tick_delta)); + }); + } +}