CAP/MiniC/Lib/PhiNode.py
2024-11-03 18:04:44 +01:00

64 lines
2.1 KiB
Python

"""
Classes for φ nodes in a RiscV CFG :py:class:`CFG <Lib.CFG.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 <Lib.CFG.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 links each corresponding predecessor in the CFG
---identified by its label---, to 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)