2024-10-06 19:58:11 +02:00
|
|
|
"""
|
|
|
|
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.
|
2024-11-03 18:04:44 +01:00
|
|
|
The field srcs links each corresponding predecessor in the CFG
|
|
|
|
---identified by its label---, to the variable temp_i of the φ
|
|
|
|
node.
|
2024-10-06 19:58:11 +02:00
|
|
|
"""
|
|
|
|
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)
|