@@ -220,13 +220,14 @@ def __init__(self, extract_bits: bool=True, cast_type: str = "uintptr_t") -> Non
220220 self .extract_bits = extract_bits
221221 self .cast_type = cast_type
222222
223- def drop (self , var : StackItem ):
223+ def drop (self , var : StackItem , check_liveness : bool ):
224224 self .top_offset .pop (var )
225225 if self .variables :
226226 popped = self .variables .pop ()
227227 if popped .is_dead () or not var .used :
228228 return
229- raise StackError (f"Dropping live value '{ var .name } '" )
229+ if check_liveness :
230+ raise StackError (f"Dropping live value '{ var .name } '" )
230231
231232 def pop (self , var : StackItem ) -> tuple [str , Local ]:
232233 self .top_offset .pop (var )
@@ -415,6 +416,7 @@ class Storage:
415416 stack : Stack
416417 inputs : list [Local ]
417418 outputs : list [Local ]
419+ check_liveness : bool
418420 spilled : int = 0
419421
420422 @staticmethod
@@ -438,11 +440,11 @@ def is_live(var: Local) -> bool:
438440 def clear_inputs (self , reason :str ) -> None :
439441 while self .inputs :
440442 tos = self .inputs .pop ()
441- if self .is_live (tos ):
443+ if self .is_live (tos ) and self . check_liveness :
442444 raise StackError (
443445 f"Input '{ tos .name } ' is still live { reason } "
444446 )
445- self .stack .drop (tos .item )
447+ self .stack .drop (tos .item , self . check_liveness )
446448
447449 def clear_dead_inputs (self ) -> None :
448450 live = ""
@@ -452,7 +454,7 @@ def clear_dead_inputs(self) -> None:
452454 live = tos .name
453455 break
454456 self .inputs .pop ()
455- self .stack .drop (tos .item )
457+ self .stack .drop (tos .item , self . check_liveness )
456458 for var in self .inputs :
457459 if not self .is_live (var ):
458460 raise StackError (
@@ -516,7 +518,7 @@ def reload(self, out: CWriter) -> None:
516518 out .emit_reload ()
517519
518520 @staticmethod
519- def for_uop (stack : Stack , uop : Uop ) -> tuple [list [str ], "Storage" ]:
521+ def for_uop (stack : Stack , uop : Uop , check_liveness = True ) -> tuple [list [str ], "Storage" ]:
520522 code_list : list [str ] = []
521523 inputs : list [Local ] = []
522524 peeks : list [Local ] = []
@@ -542,7 +544,7 @@ def for_uop(stack: Stack, uop: Uop) -> tuple[list[str], "Storage"]:
542544 for var in inputs :
543545 stack .push (var )
544546 outputs = [ Local .undefined (var ) for var in uop .stack .outputs if not var .peek ]
545- return code_list , Storage (stack , inputs , outputs )
547+ return code_list , Storage (stack , inputs , outputs , check_liveness )
546548
547549 @staticmethod
548550 def copy_list (arg : list [Local ]) -> list [Local ]:
@@ -554,8 +556,8 @@ def copy(self) -> "Storage":
554556 inputs = [ variables [var .name ] for var in self .inputs ]
555557 assert [v .name for v in inputs ] == [v .name for v in self .inputs ], (inputs , self .inputs )
556558 return Storage (
557- new_stack , inputs ,
558- self .copy_list ( self . outputs ) , self .spilled
559+ new_stack , inputs , self . copy_list ( self . outputs ),
560+ self .check_liveness , self .spilled
559561 )
560562
561563 def sanity_check (self ) -> None :
@@ -586,7 +588,7 @@ def merge(self, other: "Storage", out: CWriter) -> None:
586588 if len (self .inputs ) != len (other .inputs ):
587589 self .clear_dead_inputs ()
588590 other .clear_dead_inputs ()
589- if len (self .inputs ) != len (other .inputs ):
591+ if len (self .inputs ) != len (other .inputs ) and self . check_liveness :
590592 diff = self .inputs [- 1 ] if len (self .inputs ) > len (other .inputs ) else other .inputs [- 1 ]
591593 raise StackError (f"Unmergeable inputs. Differing state of '{ diff .name } '" )
592594 for var , other_var in zip (self .inputs , other .inputs ):
@@ -605,7 +607,7 @@ def push_outputs(self) -> None:
605607 if self .spilled :
606608 raise StackError (f"Unbalanced stack spills" )
607609 self .clear_inputs ("at the end of the micro-op" )
608- if self .inputs :
610+ if self .inputs and self . check_liveness :
609611 raise StackError (f"Input variable '{ self .inputs [- 1 ].name } ' is still live" )
610612 self ._push_defined_outputs ()
611613 if self .outputs :
@@ -682,7 +684,7 @@ def close_variable(var: Local, overwrite: str) -> None:
682684 self .stack .push (output )
683685 self .stack .flush (out )
684686 close_variable (self .inputs [0 ], "" )
685- self .stack .drop (output .item )
687+ self .stack .drop (output .item , self . check_liveness )
686688 self .inputs = []
687689 return
688690 if var_size (lowest ) != var_size (output ):
@@ -696,7 +698,7 @@ def close_variable(var: Local, overwrite: str) -> None:
696698 close_variable (self .inputs [0 ], "PyStackRef_NULL" )
697699 for input in reversed (self .inputs [1 :]):
698700 input .kill ()
699- self .stack .drop (input .item )
701+ self .stack .drop (input .item , self . check_liveness )
700702 self .stack .pop (self .inputs [0 ].item )
701703 output_in_place = self .outputs and output is self .outputs [0 ] and lowest .memory_offset is not None
702704 if output_in_place :
0 commit comments