-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcfg.py
More file actions
124 lines (94 loc) · 3.22 KB
/
Copy pathcfg.py
File metadata and controls
124 lines (94 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'''
This file will detect leaders, build basic blocks and build CFG (Control Flow Graph)
'''
from ir import Instr
class BasicBlock:
def __init__(self, id):
self.id = id
self.instructions = []
self.successors = []
self.predecessors = []
def add_instruction(self, instr):
self.instructions.append(instr)
def __repr__(self):
lines = [f"Block {self.id}:"]
for instr in self.instructions:
lines.append(f" {instr.raw}")
return "\n".join(lines)
#leader detection
def find_leaders(instructions):
leaders = set()
# Rule 1: first instruction
leaders.add(0)
label_to_index = {}
# First pass: map labels
for i, instr in enumerate(instructions):
if instr.raw.endswith(":"):
label = instr.raw[:-1]
label_to_index[label] = i
leaders.add(i)
# Second pass: jumps
for i, instr in enumerate(instructions):
text = instr.raw
if text.startswith("if"):
parts = text.split()
target = parts[-1]
if target in label_to_index:
leaders.add(label_to_index[target])
if i + 1 < len(instructions):
leaders.add(i + 1)
elif text.startswith("goto"):
target = text.split()[1]
if target in label_to_index:
leaders.add(label_to_index[target])
if i + 1 < len(instructions):
leaders.add(i + 1)
return sorted(leaders), label_to_index
#build basic blocks
def build_basic_blocks(instructions):
leaders, label_map = find_leaders(instructions)
blocks = []
leader_to_block = {}
for i, leader in enumerate(leaders):
block = BasicBlock(i)
leader_to_block[leader] = block
#until next leader -1
end = leaders[i + 1] if i + 1 < len(leaders) else len(instructions)
for j in range(leader, end):
block.add_instruction(instructions[j])
blocks.append(block)
return blocks, label_map, leader_to_block, leaders
#build cfg
def build_cfg(blocks, label_map):
# Map label → block
label_to_block = {}
for block in blocks:
first_instr = block.instructions[0]
if first_instr.raw.endswith(":"):
label = first_instr.raw[:-1]
label_to_block[label] = block
for i, block in enumerate(blocks):
last_instr = block.instructions[-1].raw
# IF
if last_instr.startswith("if"):
parts = last_instr.split()
target = parts[-1]
if target in label_to_block:
block.successors.append(label_to_block[target])
# fall-through
if i + 1 < len(blocks):
block.successors.append(blocks[i + 1])
# GOTO
elif last_instr.startswith("goto"):
target = last_instr.split()[1]
if target in label_to_block:
block.successors.append(label_to_block[target])
# NORMAL FLOW
else:
if i + 1 < len(blocks):
block.successors.append(blocks[i + 1])
# Fill predecessors
for block in blocks:
for succ in block.successors:
succ.predecessors.append(block)
return blocks