@@ -126,13 +126,14 @@ 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 =
130+ find_internal_vars ( & function. instructions , & |var : & Var | -> bool {
131+ function. arguments . contains ( var)
132+ } ) ;
132133
133134 // memory layout: pc, fp, args, return_vars, internal_vars
134135 let mut stack_pos = 2 ; // Reserve space for pc and fp
135- let mut var_positions = BTreeMap :: new ( ) ;
136+ let mut var_positions: BTreeMap < Var , usize > = BTreeMap :: new ( ) ;
136137
137138 for ( i, var) in function. arguments . iter ( ) . enumerate ( ) {
138139 var_positions. insert ( var. clone ( ) , stack_pos + i) ;
@@ -141,10 +142,7 @@ fn compile_function(
141142
142143 stack_pos += function. n_returned_vars ;
143144
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 ( ) ;
145+ stack_pos = layout_internal_vars ( & internal_vars, & mut var_positions, stack_pos) ;
148146
149147 compiler. func_name = function. name . clone ( ) ;
150148 compiler. var_positions = var_positions;
@@ -161,6 +159,37 @@ fn compile_function(
161159 )
162160}
163161
162+ fn layout_internal_vars (
163+ internal_vars : & InternalVars ,
164+ var_positions : & mut BTreeMap < Var , usize > ,
165+ initial_stack_pos : usize ,
166+ ) -> usize {
167+ let mut stack_pos = initial_stack_pos;
168+ match internal_vars {
169+ InternalVars :: One ( var) => {
170+ if !var_positions. contains_key ( var) {
171+ var_positions. insert ( var. clone ( ) , stack_pos) ;
172+ stack_pos += 1 ;
173+ }
174+ }
175+ InternalVars :: AllOf ( children) => {
176+ for child in children {
177+ stack_pos = layout_internal_vars ( child, var_positions, stack_pos) ;
178+ }
179+ }
180+ InternalVars :: OneOf ( children) => {
181+ // TODO: this is wrong b/c it can result in the same stack pos
182+ // being doubly assigned when a name is shared between branches?
183+ let mut new_stack_poss: Vec < usize > = Vec :: new ( ) ;
184+ for child in children {
185+ new_stack_poss. push ( layout_internal_vars ( child, var_positions, stack_pos) ) ;
186+ }
187+ stack_pos = * new_stack_poss. iter ( ) . max ( ) . unwrap_or ( & stack_pos) ;
188+ }
189+ }
190+ stack_pos
191+ }
192+
164193fn compile_lines (
165194 function_name : & Label ,
166195 lines : & [ SimpleLine ] ,
@@ -795,43 +824,62 @@ fn compile_function_ret(
795824 } ) ;
796825}
797826
798- fn find_internal_vars ( lines : & [ SimpleLine ] ) -> BTreeSet < Var > {
799- let mut internal_vars = BTreeSet :: new ( ) ;
827+ enum InternalVars {
828+ One ( Var ) ,
829+ AllOf ( Vec < InternalVars > ) ,
830+ OneOf ( Vec < InternalVars > ) ,
831+ }
832+
833+ fn find_internal_vars < F > ( lines : & [ SimpleLine ] , exclude : & F ) -> InternalVars
834+ where
835+ F : Fn ( & Var ) -> bool ,
836+ {
837+ let mut internal_vars: Vec < InternalVars > = Vec :: new ( ) ;
800838 for line in lines {
801839 match line {
802840 SimpleLine :: Match { arms, .. } => {
841+ let mut branch_vars: Vec < InternalVars > = Vec :: new ( ) ;
803842 for arm in arms {
804- internal_vars . extend ( find_internal_vars ( arm) ) ;
843+ branch_vars . push ( find_internal_vars ( arm, exclude ) ) ;
805844 }
845+ internal_vars. push ( InternalVars :: OneOf ( branch_vars) ) ;
806846 }
807847 SimpleLine :: Assignment { var, .. } => {
808- if let VarOrConstMallocAccess :: Var ( var) = var {
809- internal_vars. insert ( var. clone ( ) ) ;
810- }
848+ if let VarOrConstMallocAccess :: Var ( var) = var
849+ && !exclude ( var) {
850+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
851+ }
811852 }
812853 SimpleLine :: TestZero { .. } => { }
813854 SimpleLine :: HintMAlloc { var, .. }
814855 | SimpleLine :: ConstMalloc { var, .. }
815856 | SimpleLine :: DecomposeBits { var, .. }
816857 | SimpleLine :: DecomposeCustom { var, .. }
817858 | SimpleLine :: CounterHint { var } => {
818- internal_vars. insert ( var. clone ( ) ) ;
859+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
819860 }
820861 SimpleLine :: RawAccess { res, .. } => {
821- if let SimpleExpr :: Var ( var) = res {
822- internal_vars. insert ( var. clone ( ) ) ;
823- }
862+ if let SimpleExpr :: Var ( var) = res
863+ && !exclude ( var) {
864+ internal_vars. push ( InternalVars :: One ( var. clone ( ) ) ) ;
865+ }
824866 }
825867 SimpleLine :: FunctionCall { return_data, .. } => {
826- internal_vars. extend ( return_data. iter ( ) . cloned ( ) ) ;
868+ internal_vars. extend (
869+ return_data
870+ . iter ( ) . filter ( |& var| !exclude ( var) ) . cloned ( )
871+ . map ( InternalVars :: One ) ,
872+ ) ;
827873 }
828874 SimpleLine :: IfNotZero {
829875 then_branch,
830876 else_branch,
831877 ..
832878 } => {
833- internal_vars. extend ( find_internal_vars ( then_branch) ) ;
834- internal_vars. extend ( find_internal_vars ( else_branch) ) ;
879+ internal_vars. push ( InternalVars :: OneOf ( vec ! [
880+ find_internal_vars( then_branch, exclude) ,
881+ find_internal_vars( else_branch, exclude) ,
882+ ] ) ) ;
835883 }
836884 SimpleLine :: Panic
837885 | SimpleLine :: Print { .. }
@@ -840,5 +888,5 @@ fn find_internal_vars(lines: &[SimpleLine]) -> BTreeSet<Var> {
840888 | SimpleLine :: LocationReport { .. } => { }
841889 }
842890 }
843- internal_vars
891+ InternalVars :: AllOf ( internal_vars)
844892}
0 commit comments