diff --git a/crates/cairo-lang-sierra-generator/src/local_variables_test_data/e2e b/crates/cairo-lang-sierra-generator/src/local_variables_test_data/e2e index a67828fc5cd..7252de94056 100644 --- a/crates/cairo-lang-sierra-generator/src/local_variables_test_data/e2e +++ b/crates/cairo-lang-sierra-generator/src/local_variables_test_data/e2e @@ -97,15 +97,14 @@ enum_match([0]) { fallthrough([5]) label_test::foo::1([6]) } branch_align() -> () drop([5]) -> () function_call() -> ([7]) -rename([7]) -> ([1]) +store_local([2], [7]) -> ([1]) jump() { label_test::foo::3() } label_test::foo::1: branch_align() -> () drop([6]) -> () const_as_immediate>() -> ([8]) -store_temp([8]) -> ([1]) +store_local([2], [8]) -> ([1]) label_test::foo::3: -store_local([2], [1]) -> ([1]) function_call() -> ([9]) drop([9]) -> () felt252_add([3], [1]) -> ([10]) @@ -386,3 +385,57 @@ felt252_add([2], [9]) -> ([10]) store_temp([10]) -> ([10]) return([10]) label_test::foo::2: + +//! > ========================================================================== + +//! > store local instead of push + +//! > test_runner_name +test_function_generator + +//! > function +fn foo(x: felt252) -> felt252 { + let a = if x == 0 { + 1 + } else { + 2 + }; + revoke_ap(); + a +} + +//! > function_name +foo + +//! > module_code +fn revoke_ap() -> felt252 { + revoke_ap() +} + +//! > semantic_diagnostics + +//! > lowering_diagnostics + +//! > sierra_gen_diagnostics + +//! > sierra_code +label_test::foo::0: +alloc_local() -> ([2]) +finalize_locals() -> () +disable_ap_tracking() -> () +felt252_is_zero([0]) { fallthrough() label_test::foo::1([3]) } +branch_align() -> () +const_as_immediate>() -> ([4]) +store_local([2], [4]) -> ([1]) +jump() { label_test::foo::3() } +label_test::foo::1: +branch_align() -> () +drop>([3]) -> () +const_as_immediate>() -> ([5]) +store_local([2], [5]) -> ([1]) +label_test::foo::3: +function_call() -> ([6]) +drop([6]) -> () +store_temp([1]) -> ([1]) +return([1]) +label_test::foo::2: diff --git a/crates/cairo-lang-sierra-generator/src/store_variables/mod.rs b/crates/cairo-lang-sierra-generator/src/store_variables/mod.rs index 80990bca537..d78049147b9 100644 --- a/crates/cairo-lang-sierra-generator/src/store_variables/mod.rs +++ b/crates/cairo-lang-sierra-generator/src/store_variables/mod.rs @@ -348,6 +348,25 @@ impl<'a> AddStoreVariableStatements<'a> { for (i, pre_sierra::PushValue { var, var_on_stack, ty, dup }) in push_values.iter().enumerate() { + + if !dup && var != var_on_stack{ + if let Some(uninitialized_local_var_id) = + self.local_variables.get(var_on_stack) + { + self.store_local_ex( + var, + &uninitialized_local_var_id.clone(), + var_on_stack, + ty, + ); + + state.pop_var_state(var); + state.variables.insert(var_on_stack.clone(), VarState::LocalVar ); + continue; + } + } + + let (is_on_stack, var_state) = match state.pop_var_state(var) { VarState::Deferred { info: deferred_info } => { if let DeferredVariableKind::Const = deferred_info.kind { @@ -512,6 +531,22 @@ impl<'a> AddStoreVariableStatements<'a> { )); } + /// Adds a `store_local` command storing `var` into itself using the preallocated + /// `uninitialized_local_var_id`. + fn store_local_ex( + &mut self, + var: &sierra::ids::VarId, + uninitialized_local_var_id: &sierra::ids::VarId, + output: &sierra::ids::VarId, + ty: &sierra::ids::ConcreteTypeId, + ) { + self.result.push(simple_statement( + store_local_libfunc_id(self.db, ty.clone()), + &[uninitialized_local_var_id.clone(), var.clone()], + &[output.clone()], + )); + } + /// Adds a call to the dup() libfunc, duplicating `var` into `dup_var`. fn dup( &mut self, diff --git a/crates/cairo-lang-sierra-generator/src/store_variables/test.rs b/crates/cairo-lang-sierra-generator/src/store_variables/test.rs index 4b189e8e962..9f23b455ca1 100644 --- a/crates/cairo-lang-sierra-generator/src/store_variables/test.rs +++ b/crates/cairo-lang-sierra-generator/src/store_variables/test.rs @@ -421,11 +421,11 @@ fn store_local_result_of_if() { let statements: Vec = vec![ dummy_simple_branch(&db, "branch", &[], 0), // If part. - dummy_simple_statement(&db, "store_temp", &["100"], &["100"]), + dummy_push_values(&db, &[("100", "200")]), dummy_jump_statement(&db, 1), // Else part. dummy_label(&db, 0), - dummy_push_values(&db, &[("0", "100")]), + dummy_push_values(&db, &[("0", "200")]), // Post-if. dummy_label(&db, 1), dummy_simple_statement(&db, "nope", &[], &[]), @@ -437,18 +437,17 @@ fn store_local_result_of_if() { test_add_store_statements( &db, statements, - OrderedHashMap::from_iter(vec![("100".into(), "200".into()),],), + OrderedHashMap::from_iter(vec![("200".into(), "300".into()),],), &["0", "100"], ), vec![ "branch() { label_test::test::0() fallthrough() }", - "store_temp(100) -> (100)", + "store_local(300, 100) -> (200)", "jump() { label_test::test::1() }", "label_test::test::0:", - "store_temp(0) -> (100)", + "store_local(300, 0) -> (200)", "label_test::test::1:", "nope() -> ()", - "store_local(200, 100) -> (100)", "revoke_ap() -> ()", "return()", ],