@@ -179,14 +179,12 @@ def block(self, head: str):
179
179
180
180
def stack_adjust (
181
181
self ,
182
- diff : int ,
183
182
input_effects : list [StackEffect ],
184
183
output_effects : list [StackEffect ],
185
184
):
186
- # TODO: Get rid of 'diff' parameter
187
185
shrink , isym = list_effect_size (input_effects )
188
186
grow , osym = list_effect_size (output_effects )
189
- diff + = grow - shrink
187
+ diff = grow - shrink
190
188
if isym and isym != osym :
191
189
self .emit (f"STACK_SHRINK({ isym } );" )
192
190
if diff < 0 :
@@ -355,7 +353,6 @@ def write(self, out: Formatter) -> None:
355
353
356
354
# Write net stack growth/shrinkage
357
355
out .stack_adjust (
358
- 0 ,
359
356
[ieff for ieff in self .input_effects ],
360
357
[oeff for oeff in self .output_effects ],
361
358
)
@@ -848,9 +845,14 @@ def stack_analysis(
848
845
849
846
Ignore cache effects.
850
847
851
- Return the list of variable names and the initial stack pointer.
848
+ Return the list of variables (as StackEffects) and the initial stack pointer.
852
849
"""
853
850
lowest = current = highest = 0
851
+ conditions : dict [int , str ] = {} # Indexed by 'current'.
852
+ last_instr : Instruction | None = None
853
+ for thing in components :
854
+ if isinstance (thing , Instruction ):
855
+ last_instr = thing
854
856
for thing in components :
855
857
match thing :
856
858
case Instruction () as instr :
@@ -863,9 +865,24 @@ def stack_analysis(
863
865
"which are not supported in macro instructions" ,
864
866
instr .inst , # TODO: Pass name+location of macro
865
867
)
868
+ if any (eff .cond for eff in instr .input_effects ):
869
+ self .error (
870
+ f"Instruction { instr .name !r} has conditional input stack effect, "
871
+ "which are not supported in macro instructions" ,
872
+ instr .inst , # TODO: Pass name+location of macro
873
+ )
874
+ if any (eff .cond for eff in instr .output_effects ) and instr is not last_instr :
875
+ self .error (
876
+ f"Instruction { instr .name !r} has conditional output stack effect, "
877
+ "but is not the last instruction in a macro" ,
878
+ instr .inst , # TODO: Pass name+location of macro
879
+ )
866
880
current -= len (instr .input_effects )
867
881
lowest = min (lowest , current )
868
- current += len (instr .output_effects )
882
+ for eff in instr .output_effects :
883
+ if eff .cond :
884
+ conditions [current ] = eff .cond
885
+ current += 1
869
886
highest = max (highest , current )
870
887
case parser .CacheEffect ():
871
888
pass
@@ -874,9 +891,9 @@ def stack_analysis(
874
891
# At this point, 'current' is the net stack effect,
875
892
# and 'lowest' and 'highest' are the extremes.
876
893
# Note that 'lowest' may be negative.
877
- # TODO: Reverse the numbering.
878
894
stack = [
879
- StackEffect (f"_tmp_{ i + 1 } " , "" ) for i in reversed (range (highest - lowest ))
895
+ StackEffect (f"_tmp_{ i } " , "" , conditions .get (highest - i , "" ))
896
+ for i in reversed (range (1 , highest - lowest + 1 ))
880
897
]
881
898
return stack , - lowest
882
899
@@ -908,15 +925,17 @@ def effect_str(effects: list[StackEffect]) -> str:
908
925
low = 0
909
926
sp = 0
910
927
high = 0
928
+ pushed_symbolic : list [str ] = []
911
929
for comp in parts :
912
930
for effect in comp .instr .input_effects :
913
931
assert not effect .cond , effect
914
932
assert not effect .size , effect
915
933
sp -= 1
916
934
low = min (low , sp )
917
935
for effect in comp .instr .output_effects :
918
- assert not effect .cond , effect
919
936
assert not effect .size , effect
937
+ if effect .cond :
938
+ pushed_symbolic .append (maybe_parenthesize (f"{ maybe_parenthesize (effect .cond )} ? 1 : 0" ))
920
939
sp += 1
921
940
high = max (sp , high )
922
941
if high != max (0 , sp ):
@@ -926,7 +945,8 @@ def effect_str(effects: list[StackEffect]) -> str:
926
945
# calculations to use the micro ops.
927
946
self .error ("Macro has virtual stack growth" , thing )
928
947
popped = str (- low )
929
- pushed = str (sp - low )
948
+ pushed_symbolic .append (str (sp - low - len (pushed_symbolic )))
949
+ pushed = " + " .join (pushed_symbolic )
930
950
case parser .Pseudo ():
931
951
instr = self .pseudo_instrs [thing .name ]
932
952
popped = pushed = None
@@ -1203,16 +1223,23 @@ def wrap_macro(self, mac: MacroInstruction):
1203
1223
with self .out .block (f"TARGET({ mac .name } )" ):
1204
1224
if mac .predicted :
1205
1225
self .out .emit (f"PREDICTED({ mac .name } );" )
1206
- for i , var in reversed (list (enumerate (mac .stack ))):
1226
+
1227
+ # The input effects should have no conditionals.
1228
+ # Only the output effects do (for now).
1229
+ ieffects = [
1230
+ StackEffect (eff .name , eff .type ) if eff .cond else eff
1231
+ for eff in mac .stack
1232
+ ]
1233
+
1234
+ for i , var in reversed (list (enumerate (ieffects ))):
1207
1235
src = None
1208
1236
if i < mac .initial_sp :
1209
1237
src = StackEffect (f"stack_pointer[-{ mac .initial_sp - i } ]" , "" )
1210
1238
self .out .declare (var , src )
1211
1239
1212
1240
yield
1213
1241
1214
- # TODO: Use slices of mac.stack instead of numeric values
1215
- self .out .stack_adjust (mac .final_sp - mac .initial_sp , [], [])
1242
+ self .out .stack_adjust (ieffects [:mac .initial_sp ], mac .stack [:mac .final_sp ])
1216
1243
1217
1244
for i , var in enumerate (reversed (mac .stack [: mac .final_sp ]), 1 ):
1218
1245
dst = StackEffect (f"stack_pointer[-{ i } ]" , "" )
0 commit comments