@@ -313,17 +313,41 @@ def write_instructions(self, filename: str) -> None:
313313 f .write (f"{ indent } DISPATCH();\n " )
314314 f .write (f"{ indent } }}\n " )
315315
316- # Write super-instructions
316+ # Write super-instructions and macros
317+ # TODO: Cleanup the hacks
317318 for name , sup in self .supers .items ():
318- components = [self .instrs [name ] for name in sup .ops ]
319319 f .write (f"\n { indent } TARGET({ sup .name } ) {{\n " )
320+ components = [self .instrs [name ] for name in sup .ops ]
321+ lowest , highest = self .super_macro_analysis (name , components )
322+ current = 0
323+ for i in range (lowest , current ):
324+ f .write (f"{ indent } PyObject *_tmp_{ i - lowest + 1 } = PEEK({ - i } );\n " )
325+ for i in range (current , highest ):
326+ f .write (f"{ indent } PyObject *_tmp_{ i - lowest + 1 } ;\n " )
320327 for i , instr in enumerate (components ):
321328 if i > 0 and sup .kind == "super" :
322329 f .write (f"{ indent } NEXTOPARG();\n " )
323330 f .write (f"{ indent } next_instr++;\n " )
324331 f .write (f"{ indent } {{\n " )
325- instr .write (f , indent , dedent = - 4 )
332+ for seffect in reversed (instr .input_effects ):
333+ if seffect .name != "unused" :
334+ f .write (f"{ indent } PyObject *{ seffect .name } = _tmp_{ current - lowest } ;\n " )
335+ current -= 1
336+ for oeffect in instr .output_effects :
337+ if oeffect .name != "unused" :
338+ f .write (f"{ indent } PyObject *{ oeffect .name } ;\n " )
339+ instr .write_body (f , indent , dedent = - 4 )
340+ for oeffect in instr .output_effects :
341+ if oeffect .name != "unused" :
342+ f .write (f"{ indent } _tmp_{ current - lowest + 1 } = { oeffect .name } ;\n " )
343+ current += 1
326344 f .write (f" { indent } }}\n " )
345+ if current > 0 :
346+ f .write (f"{ indent } STACK_GROW({ current } );\n " )
347+ elif current < 0 :
348+ f .write (f"{ indent } STACK_SHRINK({ - current } );\n " )
349+ for i in range (lowest , current ):
350+ f .write (f"{ indent } POKE({ i - lowest + 1 } , _tmp_{ current - i } );\n " )
327351 f .write (f"{ indent } DISPATCH();\n " )
328352 f .write (f"{ indent } }}\n " )
329353
@@ -333,6 +357,25 @@ def write_instructions(self, filename: str) -> None:
333357 file = sys .stderr ,
334358 )
335359
360+ # TODO: Move this into analysis phase
361+ def super_macro_analysis (self , name : str , components : list [Instruction ]) -> tuple [int , int ]:
362+ """Analyze a super-instruction or macro."""
363+ lowest = current = highest = 0
364+ for instr in components :
365+ if instr .cache_effects :
366+ print (
367+ f"Super-instruction { name !r} has cache effects in { instr .name !r} " ,
368+ file = sys .stderr ,
369+ )
370+ self .errors += 1
371+ current -= len (instr .input_effects )
372+ lowest = min (lowest , current )
373+ current += len (instr .output_effects )
374+ highest = max (highest , current )
375+ # At this point, 'current' is the net stack effect,
376+ # and 'lowest' and 'highest' are the extremes.
377+ return lowest , highest
378+
336379
337380def always_exits (block : parser .Block ) -> bool :
338381 """Determine whether a block always ends in a return/goto/etc."""
0 commit comments