@@ -313,17 +313,41 @@ def write_instructions(self, filename: str) -> None:
313
313
f .write (f"{ indent } DISPATCH();\n " )
314
314
f .write (f"{ indent } }}\n " )
315
315
316
- # Write super-instructions
316
+ # Write super-instructions and macros
317
+ # TODO: Cleanup the hacks
317
318
for name , sup in self .supers .items ():
318
- components = [self .instrs [name ] for name in sup .ops ]
319
319
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 " )
320
327
for i , instr in enumerate (components ):
321
328
if i > 0 and sup .kind == "super" :
322
329
f .write (f"{ indent } NEXTOPARG();\n " )
323
330
f .write (f"{ indent } next_instr++;\n " )
324
331
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
326
344
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 " )
327
351
f .write (f"{ indent } DISPATCH();\n " )
328
352
f .write (f"{ indent } }}\n " )
329
353
@@ -333,6 +357,25 @@ def write_instructions(self, filename: str) -> None:
333
357
file = sys .stderr ,
334
358
)
335
359
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
+
336
379
337
380
def always_exits (block : parser .Block ) -> bool :
338
381
"""Determine whether a block always ends in a return/goto/etc."""
0 commit comments