@@ -220,13 +220,14 @@ def __init__(self, extract_bits: bool=True, cast_type: str = "uintptr_t") -> Non
220
220
self .extract_bits = extract_bits
221
221
self .cast_type = cast_type
222
222
223
- def drop (self , var : StackItem ):
223
+ def drop (self , var : StackItem , check_liveness : bool ):
224
224
self .top_offset .pop (var )
225
225
if self .variables :
226
226
popped = self .variables .pop ()
227
227
if popped .is_dead () or not var .used :
228
228
return
229
- raise StackError (f"Dropping live value '{ var .name } '" )
229
+ if check_liveness :
230
+ raise StackError (f"Dropping live value '{ var .name } '" )
230
231
231
232
def pop (self , var : StackItem ) -> tuple [str , Local ]:
232
233
self .top_offset .pop (var )
@@ -415,6 +416,7 @@ class Storage:
415
416
stack : Stack
416
417
inputs : list [Local ]
417
418
outputs : list [Local ]
419
+ check_liveness : bool
418
420
spilled : int = 0
419
421
420
422
@staticmethod
@@ -438,11 +440,11 @@ def is_live(var: Local) -> bool:
438
440
def clear_inputs (self , reason :str ) -> None :
439
441
while self .inputs :
440
442
tos = self .inputs .pop ()
441
- if self .is_live (tos ):
443
+ if self .is_live (tos ) and self . check_liveness :
442
444
raise StackError (
443
445
f"Input '{ tos .name } ' is still live { reason } "
444
446
)
445
- self .stack .drop (tos .item )
447
+ self .stack .drop (tos .item , self . check_liveness )
446
448
447
449
def clear_dead_inputs (self ) -> None :
448
450
live = ""
@@ -452,7 +454,7 @@ def clear_dead_inputs(self) -> None:
452
454
live = tos .name
453
455
break
454
456
self .inputs .pop ()
455
- self .stack .drop (tos .item )
457
+ self .stack .drop (tos .item , self . check_liveness )
456
458
for var in self .inputs :
457
459
if not self .is_live (var ):
458
460
raise StackError (
@@ -516,7 +518,7 @@ def reload(self, out: CWriter) -> None:
516
518
out .emit_reload ()
517
519
518
520
@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" ]:
520
522
code_list : list [str ] = []
521
523
inputs : list [Local ] = []
522
524
peeks : list [Local ] = []
@@ -542,7 +544,7 @@ def for_uop(stack: Stack, uop: Uop) -> tuple[list[str], "Storage"]:
542
544
for var in inputs :
543
545
stack .push (var )
544
546
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 )
546
548
547
549
@staticmethod
548
550
def copy_list (arg : list [Local ]) -> list [Local ]:
@@ -554,8 +556,8 @@ def copy(self) -> "Storage":
554
556
inputs = [ variables [var .name ] for var in self .inputs ]
555
557
assert [v .name for v in inputs ] == [v .name for v in self .inputs ], (inputs , self .inputs )
556
558
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
559
561
)
560
562
561
563
def sanity_check (self ) -> None :
@@ -586,7 +588,7 @@ def merge(self, other: "Storage", out: CWriter) -> None:
586
588
if len (self .inputs ) != len (other .inputs ):
587
589
self .clear_dead_inputs ()
588
590
other .clear_dead_inputs ()
589
- if len (self .inputs ) != len (other .inputs ):
591
+ if len (self .inputs ) != len (other .inputs ) and self . check_liveness :
590
592
diff = self .inputs [- 1 ] if len (self .inputs ) > len (other .inputs ) else other .inputs [- 1 ]
591
593
raise StackError (f"Unmergeable inputs. Differing state of '{ diff .name } '" )
592
594
for var , other_var in zip (self .inputs , other .inputs ):
@@ -605,7 +607,7 @@ def push_outputs(self) -> None:
605
607
if self .spilled :
606
608
raise StackError (f"Unbalanced stack spills" )
607
609
self .clear_inputs ("at the end of the micro-op" )
608
- if self .inputs :
610
+ if self .inputs and self . check_liveness :
609
611
raise StackError (f"Input variable '{ self .inputs [- 1 ].name } ' is still live" )
610
612
self ._push_defined_outputs ()
611
613
if self .outputs :
@@ -682,7 +684,7 @@ def close_variable(var: Local, overwrite: str) -> None:
682
684
self .stack .push (output )
683
685
self .stack .flush (out )
684
686
close_variable (self .inputs [0 ], "" )
685
- self .stack .drop (output .item )
687
+ self .stack .drop (output .item , self . check_liveness )
686
688
self .inputs = []
687
689
return
688
690
if var_size (lowest ) != var_size (output ):
@@ -696,7 +698,7 @@ def close_variable(var: Local, overwrite: str) -> None:
696
698
close_variable (self .inputs [0 ], "PyStackRef_NULL" )
697
699
for input in reversed (self .inputs [1 :]):
698
700
input .kill ()
699
- self .stack .drop (input .item )
701
+ self .stack .drop (input .item , self . check_liveness )
700
702
self .stack .pop (self .inputs [0 ].item )
701
703
output_in_place = self .outputs and output is self .outputs [0 ] and lowest .memory_offset is not None
702
704
if output_in_place :
0 commit comments