@@ -126,13 +126,16 @@ fn compile_function(
126126 function : & SimpleFunction ,
127127 compiler : & mut Compiler ,
128128) -> Result < Vec < IntermediateInstruction > , String > {
129- let mut internal_vars = find_internal_vars ( & function. instructions ) ;
130-
131- internal_vars. retain ( |var| !function. arguments . contains ( var) ) ;
129+ let internal_vars: InternalVars = find_internal_vars (
130+ & function. instructions ,
131+ & |var : & Var | -> bool {
132+ function. arguments . contains ( var)
133+ }
134+ ) ;
132135
133136 // memory layout: pc, fp, args, return_vars, internal_vars
134137 let mut stack_pos = 2 ; // Reserve space for pc and fp
135- let mut var_positions = BTreeMap :: new ( ) ;
138+ let mut var_positions: BTreeMap < Var , usize > = BTreeMap :: new ( ) ;
136139
137140 for ( i, var) in function. arguments . iter ( ) . enumerate ( ) {
138141 var_positions. insert ( var. clone ( ) , stack_pos + i) ;
@@ -141,10 +144,7 @@ fn compile_function(
141144
142145 stack_pos += function. n_returned_vars ;
143146
144- for ( i, var) in internal_vars. iter ( ) . enumerate ( ) {
145- var_positions. insert ( var. clone ( ) , stack_pos + i) ;
146- }
147- stack_pos += internal_vars. len ( ) ;
147+ stack_pos = layout_internal_vars ( & internal_vars, & mut var_positions, stack_pos) ;
148148
149149 compiler. func_name = function. name . clone ( ) ;
150150 compiler. var_positions = var_positions;
@@ -161,6 +161,37 @@ fn compile_function(
161161 )
162162}
163163
164+ fn layout_internal_vars (
165+ internal_vars : & InternalVars ,
166+ var_positions : & mut BTreeMap < Var , usize > ,
167+ initial_stack_pos : usize
168+ ) -> usize {
169+ let mut stack_pos = initial_stack_pos;
170+ match internal_vars {
171+ InternalVars :: One ( var) => {
172+ if !var_positions. contains_key ( var) {
173+ var_positions. insert ( var. clone ( ) , stack_pos) ;
174+ stack_pos += 1 ;
175+ }
176+ } ,
177+ InternalVars :: AllOf ( children) => {
178+ for child in children {
179+ stack_pos = layout_internal_vars ( child, var_positions, stack_pos) ;
180+ }
181+ } ,
182+ InternalVars :: OneOf ( children) => {
183+ // TODO: this is wrong b/c it can result in the same stack pos
184+ // being doubly assigned when a name is shared between branches?
185+ let mut new_stack_poss: Vec < usize > = Vec :: new ( ) ;
186+ for child in children {
187+ new_stack_poss. push ( layout_internal_vars ( child, var_positions, stack_pos) ) ;
188+ }
189+ stack_pos = * new_stack_poss. iter ( ) . max ( ) . unwrap_or ( & stack_pos) ;
190+ } ,
191+ }
192+ stack_pos
193+ }
194+
164195fn compile_lines (
165196 function_name : & Label ,
166197 lines : & [ SimpleLine ] ,
@@ -795,18 +826,30 @@ fn compile_function_ret(
795826 } ) ;
796827}
797828
798- fn find_internal_vars ( lines : & [ SimpleLine ] ) -> BTreeSet < Var > {
799- let mut internal_vars = BTreeSet :: new ( ) ;
829+ enum InternalVars {
830+ One ( Var ) ,
831+ AllOf ( Vec < InternalVars > ) ,
832+ OneOf ( Vec < InternalVars > ) ,
833+ }
834+
835+ fn find_internal_vars < F > ( lines : & [ SimpleLine ] , exclude : & F ) -> InternalVars
836+ where F : Fn ( & Var ) -> bool
837+ {
838+ let mut internal_vars: Vec < InternalVars > = Vec :: new ( ) ;
800839 for line in lines {
801840 match line {
802841 SimpleLine :: Match { arms, .. } => {
842+ let mut branch_vars: Vec < InternalVars > = Vec :: new ( ) ;
803843 for arm in arms {
804- internal_vars . extend ( find_internal_vars ( arm) ) ;
844+ branch_vars . push ( find_internal_vars ( arm, exclude ) ) ;
805845 }
846+ internal_vars. push ( InternalVars :: OneOf ( branch_vars) ) ;
806847 }
807848 SimpleLine :: Assignment { var, .. } => {
808849 if let VarOrConstMallocAccess :: Var ( var) = var {
809- internal_vars. insert ( var. clone ( ) ) ;
850+ if !exclude ( var) {
851+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
852+ }
810853 }
811854 }
812855 SimpleLine :: TestZero { .. } => { }
@@ -815,23 +858,32 @@ fn find_internal_vars(lines: &[SimpleLine]) -> BTreeSet<Var> {
815858 | SimpleLine :: DecomposeBits { var, .. }
816859 | SimpleLine :: DecomposeCustom { var, .. }
817860 | SimpleLine :: CounterHint { var } => {
818- internal_vars. insert ( var. clone ( ) ) ;
861+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
819862 }
820863 SimpleLine :: RawAccess { res, .. } => {
821864 if let SimpleExpr :: Var ( var) = res {
822- internal_vars. insert ( var. clone ( ) ) ;
865+ if !exclude ( var) {
866+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
867+ }
823868 }
824869 }
825870 SimpleLine :: FunctionCall { return_data, .. } => {
826- internal_vars. extend ( return_data. iter ( ) . cloned ( ) ) ;
871+ internal_vars. extend ( return_data. iter ( ) . cloned ( )
872+ . filter ( |var| !exclude ( var) )
873+ . map ( InternalVars :: One )
874+ ) ;
827875 }
828876 SimpleLine :: IfNotZero {
829877 then_branch,
830878 else_branch,
831879 ..
832880 } => {
833- internal_vars. extend ( find_internal_vars ( then_branch) ) ;
834- internal_vars. extend ( find_internal_vars ( else_branch) ) ;
881+ internal_vars. push ( InternalVars :: OneOf (
882+ vec ! [
883+ find_internal_vars( then_branch, exclude) ,
884+ find_internal_vars( else_branch, exclude)
885+ ]
886+ ) ) ;
835887 }
836888 SimpleLine :: Panic
837889 | SimpleLine :: Print { .. }
@@ -840,5 +892,5 @@ fn find_internal_vars(lines: &[SimpleLine]) -> BTreeSet<Var> {
840892 | SimpleLine :: LocationReport { .. } => { }
841893 }
842894 }
843- internal_vars
895+ InternalVars :: AllOf ( internal_vars)
844896}
0 commit comments