11# -*- coding: utf-8 -*-
2-
2+ from __future__ import annotations
33from typing import Iterable , Iterator , List
44
55import src .api .config
6- import src .api .utils
76import src .arch .z80 .backend .common
87from src .api .debug import __DEBUG__
9- from src .api .identityset import IdentitySet
108from src .arch .z80 .optimizer import helpers
119from src .arch .z80 .optimizer .common import JUMP_LABELS , LABELS
1210from src .arch .z80 .optimizer .cpustate import CPUState
1816from src .arch .z80 .optimizer .labelinfo import LabelInfo
1917from src .arch .z80 .optimizer .memcell import MemCell
2018from src .arch .z80 .optimizer .patterns import RE_ID_OR_NUMBER
19+ from src .api .utils import flatten_list , first
2120from src .arch .z80 .peephole import evaluator
2221
2322
@@ -33,10 +32,10 @@ def __init__(self, memory: Iterable[str]):
3332 self .next = None # Which (if any) basic block follows this one in memory
3433 self .prev = None # Which (if any) basic block precedes to this one in the code
3534 self .lock = False # True if this block is being accessed by other subroutine
36- self .comes_from = IdentitySet () # A list/tuple containing possible jumps to this block
37- self .goes_to = IdentitySet () # A list/tuple of possible block to jump from here
35+ self .comes_from : set [ BasicBlock ] = set () # A list/tuple containing possible jumps to this block
36+ self .goes_to : set [ BasicBlock ] = set () # A list/tuple of possible block to jump from here
3837 self .modified = False # True if something has been changed during optimization
39- self .calls = IdentitySet ()
38+ self .calls : set [ BasicBlock ] = set ()
4039 self .label_goes = []
4140 self .ignored = False # True if this block can be ignored (it's useless)
4241 self .id = BasicBlock .__UNIQUE_ID
@@ -162,7 +161,7 @@ def update_labels(self):
162161 for l in self .labels :
163162 LABELS [l ].basic_block = self
164163
165- def delete_comes_from (self , basic_block ) :
164+ def delete_comes_from (self , basic_block : BasicBlock ) -> None :
166165 """Removes the basic_block ptr from the list for "comes_from"
167166 if it exists. It also sets self.prev to None if it is basic_block.
168167 """
@@ -174,14 +173,14 @@ def delete_comes_from(self, basic_block):
174173
175174 self .lock = True
176175
177- for i in range ( len ( self .comes_from )) :
178- if self . comes_from [ i ] is basic_block :
179- self .comes_from .pop ( i )
176+ for elem in self .comes_from :
177+ if elem . id == basic_block . id :
178+ self .comes_from .remove ( elem )
180179 break
181180
182181 self .lock = False
183182
184- def delete_goes_to (self , basic_block ) :
183+ def delete_goes_to (self , basic_block : BasicBlock ) -> None :
185184 """Removes the basic_block ptr from the list for "goes_to"
186185 if it exists. It also sets self.next to None if it is basic_block.
187186 """
@@ -193,15 +192,15 @@ def delete_goes_to(self, basic_block):
193192
194193 self .lock = True
195194
196- for i in range ( len ( self .goes_to )) :
197- if self . goes_to [ i ] is basic_block :
198- self .goes_to .pop ( i )
195+ for elem in self .goes_to :
196+ if elem . id is basic_block . id :
197+ self .goes_to .remove ( elem )
199198 basic_block .delete_comes_from (self )
200199 break
201200
202201 self .lock = False
203202
204- def add_comes_from (self , basic_block ) :
203+ def add_comes_from (self , basic_block : BasicBlock ) -> None :
205204 """This simulates a set. Adds the basic_block to the comes_from
206205 list if not done already.
207206 """
@@ -220,12 +219,11 @@ def add_comes_from(self, basic_block):
220219 basic_block .add_goes_to (self )
221220 self .lock = False
222221
223- def add_goes_to (self , basic_block ) :
222+ def add_goes_to (self , basic_block : BasicBlock ) -> None :
224223 """This simulates a set. Adds the basic_block to the goes_to
225224 list if not done already.
226225 """
227- if basic_block is None :
228- return
226+ assert basic_block is not None
229227
230228 if self .lock :
231229 return
@@ -326,7 +324,7 @@ def update_goes_and_comes(self):
326324
327325 final_blk = self .next # The block all the final returns should go to
328326 stack = [LABELS [oper [0 ]].basic_block ]
329- bbset = IdentitySet ()
327+ bbset : set [ BasicBlock ] = set ()
330328
331329 while stack :
332330 bb = stack .pop (0 )
@@ -514,7 +512,7 @@ def get_first_non_label_instruction(self):
514512
515513 return None
516514
517- def get_next_exec_instruction (self ):
515+ def get_next_exec_instruction (self ) -> MemCell | None :
518516 """Return the first non label instruction to be executed, either
519517 in this block or in the following one. If there are more than one, return None.
520518 Also returns None if there is no instruction to be executed.
@@ -526,22 +524,22 @@ def get_next_exec_instruction(self):
526524 if len (blk .goes_to ) != 1 :
527525 return None
528526
529- blk = blk .goes_to [ 0 ]
527+ blk = next ( iter ( blk .goes_to ))
530528 result = blk .get_first_non_label_instruction ()
531529
532530 return result
533531
534- def guesses_initial_state_from_origin_blocks (self ):
532+ def guesses_initial_state_from_origin_blocks (self ) -> tuple [ dict [ str , str ], dict [ str , str ]] :
535533 """Returns two dictionaries (regs, memory) that contains the common values
536534 of the cpustates of all comes_from blocks
537535 """
538536 if not self .comes_from :
539537 return {}, {}
540538
541- regs = self .comes_from [ 0 ] .cpu .regs
542- mems = self .comes_from [ 0 ] .cpu .mem
539+ regs = first ( self .comes_from ) .cpu .regs
540+ mems = first ( self .comes_from ) .cpu .mem
543541
544- for blk in self .comes_from [1 :]:
542+ for blk in list ( self .comes_from ) [1 :]:
545543 regs = helpers .dict_intersection (regs , blk .cpu .regs )
546544 mems = helpers .dict_intersection (mems , blk .cpu .mem )
547545
0 commit comments