""" Classes for φ nodes in a RiscV CFG :py:class:`CFG ` under SSA Form: :py:class:`PhiNode` for a statement of the form temp_x = φ(temp_0, ..., temp_n). These particular kinds of statements are expected to be in the field b._phis for a :py:class:`Block ` b. """ from dataclasses import dataclass from typing import List, Dict from Lib.Operands import Operand, Temporary, DataLocation, Renamer from Lib.Statement import Statement, Label @dataclass class PhiNode(Statement): """ A φ node is a renaming in the CFG, of the form temp_x = φ(temp_0, ..., temp_n). The field var contains the variable temp_x. The field srcs relies for each precedent block in the CFG, identified with its label, the variable temp_i of the φ node. """ var: DataLocation srcs: Dict[Label, Operand] def defined(self) -> List[Operand]: """Return the variable defined by the φ node.""" return [self.var] def get_srcs(self) -> Dict[Label, Operand]: """ Return the dictionnary associating for each previous block the corresponding variable. """ return self.srcs def used(self) -> List[Operand]: """Return the variables used by the statement.""" return list(self.srcs.values()) def rename(self, renamer: Renamer) -> None: """Rename the variable defined by the φ node with a fresh name.""" if isinstance(self.var, Temporary): self.var = renamer.fresh(self.var) def rename_from(self, renamer: Renamer, label: Label) -> None: """Rename the variable associated to the block identified by `label`.""" if label in self.srcs: t = self.srcs[label] if isinstance(t, Temporary): if renamer.defined(t): self.srcs[label] = renamer.replace(t) else: del self.srcs[label] def __str__(self): return "{} = φ({})".format(self.var, self.srcs) def __hash__(self): return hash((self.var, *self.srcs.items())) def printIns(self, stream): print(' # ' + str(self), file=stream)