forked from sampsyo/bril
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathform_blocks.py
71 lines (54 loc) · 2.09 KB
/
form_blocks.py
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
"""Create and print out the basic blocks in a Bril function.
"""
import json
import sys
# Instructions that terminate a basic block.
TERMINATORS = 'br', 'jmp', 'ret'
def form_blocks(instrs):
"""Given a list of Bril instructions, generate a sequence of
instruction lists representing the basic blocks in the program.
Every instruction in `instr` will show up in exactly one block. Jump
and branch instructions may only appear at the end of a block, and
control can transfer only to the top of a basic block---so labels
can only appear at the *start* of a basic block. Basic blocks may
not be empty.
"""
# Start with an empty block.
cur_block = []
for instr in instrs:
if 'op' in instr: # It's an instruction.
# Add the instruction to the currently-being-formed block.
cur_block.append(instr)
# If this is a terminator (branching instruction), it's the
# last instruction in the block. Finish this block and
# start a new one.
if instr['op'] in TERMINATORS:
yield cur_block
cur_block = []
else: # It's a label.
# End the block here (if it contains anything).
if cur_block:
yield cur_block
# Start a new block with the label.
cur_block = [instr]
# Produce the final block, if any.
if cur_block:
yield cur_block
def print_blocks(bril):
"""Given a Bril program, print out its basic blocks.
"""
import briltxt
func = bril['functions'][0] # We only process one function.
for block in form_blocks(func['instrs']):
# Mark the block.
leader = block[0]
if 'label' in leader:
print('block "{}":'.format(leader['label']))
block = block[1:] # Hide the label, for concision.
else:
print('anonymous block:')
# Print the instructions.
for instr in block:
print(' {}'.format(briltxt.instr_to_string(instr)))
if __name__ == '__main__':
print_blocks(json.load(sys.stdin))