xref: /llvm-project/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/StepIR.py (revision f98ee40f4b5d7474fc67e82824bf6abbaedb7b1c)
1# DExTer : Debugging Experience Tester
2# ~~~~~~   ~         ~~         ~   ~~
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7"""Classes which are used to represent debugger steps."""
8
9import json
10
11from collections import OrderedDict
12from typing import List
13from enum import Enum
14from dex.dextIR.FrameIR import FrameIR
15from dex.dextIR.LocIR import LocIR
16from dex.dextIR.ProgramState import ProgramState
17
18
19class StopReason(Enum):
20    BREAKPOINT = 0
21    STEP = 1
22    PROGRAM_EXIT = 2
23    ERROR = 3
24    OTHER = 4
25
26
27class StepKind(Enum):
28    FUNC = 0
29    FUNC_EXTERNAL = 1
30    FUNC_UNKNOWN = 2
31    VERTICAL_FORWARD = 3
32    SAME = 4
33    VERTICAL_BACKWARD = 5
34    UNKNOWN = 6
35    HORIZONTAL_FORWARD = 7
36    HORIZONTAL_BACKWARD = 8
37
38
39class StepIR:
40    """A debugger step.
41
42    Args:
43        watches (OrderedDict): { expression (str), result (ValueIR) }
44    """
45
46    def __init__(
47        self,
48        step_index: int,
49        stop_reason: StopReason,
50        frames: List[FrameIR],
51        step_kind: StepKind = None,
52        watches: OrderedDict = None,
53        program_state: ProgramState = None,
54    ):
55        self.step_index = step_index
56        self.step_kind = step_kind
57        self.stop_reason = stop_reason
58        self.program_state = program_state
59
60        if frames is None:
61            frames = []
62        self.frames = frames
63
64        if watches is None:
65            watches = {}
66        self.watches = watches
67
68    def __str__(self):
69        try:
70            frame = self.current_frame
71            frame_info = (
72                frame.function,
73                frame.loc.path,
74                frame.loc.lineno,
75                frame.loc.column,
76            )
77        except AttributeError:
78            frame_info = (None, None, None, None)
79
80        step_info = (
81            (self.step_index,)
82            + frame_info
83            + (str(self.stop_reason), str(self.step_kind), [w for w in self.watches])
84        )
85
86        return "{}{}".format(".   " * (self.num_frames - 1), json.dumps(step_info))
87
88    @property
89    def num_frames(self):
90        return len(self.frames)
91
92    @property
93    def current_frame(self):
94        if not len(self.frames):
95            return None
96        return self.frames[0]
97
98    @property
99    def current_function(self):
100        try:
101            return self.current_frame.function
102        except AttributeError:
103            return None
104
105    @property
106    def current_location(self):
107        try:
108            return self.current_frame.loc
109        except AttributeError:
110            return LocIR(path=None, lineno=None, column=None)
111