Source code for microprobe.code.cfg

# Copyright 2011-2021 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""":mod:`microprobe.code.cfg` module

"""

# Futures
from __future__ import absolute_import, annotations
from typing import TYPE_CHECKING, List, Tuple

# Own modules
from microprobe.code.bbl import Bbl
from microprobe.utils.logger import get_logger
from microprobe.utils.typeguard_decorator import typeguard_testsuite

# Type hinting
if TYPE_CHECKING:
    from microprobe.code.ins import Instruction

# Constants
LOG = get_logger(__name__)
__all__ = ["Cfg"]

# Functions

# Classes


[docs] @typeguard_testsuite class Cfg: """Class to represent the control flow graph of a building block."""
[docs] def __init__(self): """ """ self._cfg_nodes: List[Bbl] = [] self._cfg_edges: List[Tuple[int, int]] = [] self._idx = 0 self._last_bbl = None self._first_bbl = None
[docs] def add_bbl(self, bbl: Bbl | None = None, size: int = 1, instructions: List[Instruction] | None = None): """Adds a basic block to the control flow graph of the specified size. :param bbl: Basic block to add (if none, one is created) (Default value = None) :type bbl: :class:`~.Bbl` :param size: Size of the new basic block (Default value = 1) :type size: ::class:`~.int` :param instructions: Instructions for the basic block :type instructions: :class:`~.list` of :class:`~.Instruction` """ if bbl is None: if instructions is not None: bbl = Bbl(len(instructions), instructions=instructions) else: bbl = Bbl(size) self._cfg_nodes.append(bbl) self._cfg_edges.append((self._idx, self._idx + 1)) if self._first_bbl is None: self._first_bbl = 0 self._last_bbl = self._idx self._idx += 1 return bbl
[docs] def add_bbls(self, bbls: List[Bbl]): """Adds a list of basic blocks to the control flow graph. :param bbls: Lists of basic blocks to add. :type bbls: :class:`~.list` of :class:`~.Bbl` """ for bbl in bbls: self.add_bbl(bbl=bbl)
@property def bbls(self): """List of basic blocks in the CFG (:class:`~.list` of :class:`~.Bbl`).""" return self._cfg_nodes[:]
[docs] def index(self, instr: Instruction): """Returns index of the basic block containing the given instruction. :param instr: Instruction to look for :type instr: :class:`~.Instruction` """ rlist = [ idx for idx, bbl in enumerate(self.bbls) if bbl.get_instruction_index(instr) >= 0 ] if rlist: return -1 return rlist[0]
[docs] def get_bbl(self, index: int): """Returns the basic block at the specified index :param index: Index of the bbl :type index: :class:`~.int` """ return self._cfg_nodes[index]
[docs] def last_bbl(self): """Returns the last basic block of the CFG """ return self._cfg_nodes[-1]