-
Notifications
You must be signed in to change notification settings - Fork 0
/
tiger.py
executable file
·133 lines (124 loc) · 4.75 KB
/
tiger.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
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
124
125
126
127
128
129
130
131
132
133
#! /usr/bin/env python
#
# Do not modify
from optparse import OptionParser
from parser.parser import parse
import sys
parser = OptionParser()
parser.add_option("-b", "--bind",
help="invoke the binder",
action="store_true", default=False,
dest="bind")
parser.add_option("-c", "--canon",
help="canonicalize the IR tree",
action="store_true", default=False,
dest="canon")
parser.add_option("-d", "--dump",
help="dump input file to output",
action="store_true", default=False,
dest="dump")
parser.add_option("-E", "--expression",
help="use expression instead of file",
action="store", default=None,
dest="expression")
parser.add_option("-e", "--eval",
help="evaluate input file to output",
action="store_true", default=False,
dest="eval")
parser.add_option("-g", "--gen",
help="generate assembly code",
action="store_true", default=False,
dest="gen")
parser.add_option("-i", "--ir",
help="invoke IR translator",
action="store_true", default=False,
dest="ir")
parser.add_option("-I", "--irvm",
help="use IRVM target (default: ARM)",
action="store_true", default=False,
dest="irvm")
parser.add_option("-l", "--liveness",
help="perform liveness analysis",
action="store_true", default=False,
dest="liveness")
parser.add_option("-r", "--registers",
help="allocate registers",
action="store_true", default=False,
dest="registers")
parser.add_option("-t", "--type",
help="invoke the typer",
action="store_true", default=False,
dest="type")
parser.add_option("-v", "--verbose",
help="be verbose",
action="store_true", default=False,
dest="verbose")
parser.usage = """%prog [options] [file]"""
parser.description = "Compile a Tiger program (or standard input)"
(options, args) = parser.parse_args()
options.liveness |= options.registers
options.gen |= options.liveness
options.canon |= options.gen
if options.irvm and options.gen:
print("Error: IRVM cannot be selected for code generation", file=sys.stderr)
sys.exit(1)
options.irvm &= not options.gen
options.ir |= options.canon | options.irvm
options.type |= options.ir
if len(args) > 1 or (options.expression and len(args) > 0):
parser.print_help(file=sys.stderr)
sys.exit(1)
if options.expression:
content = options.expression
else:
fd = open(args[0]) if args else sys.stdin
content = fd.read()
fd.close()
tree = parse(content)
if options.bind or options.type:
from semantics.binder import Binder
tree.accept(Binder())
if options.type:
from typer.typer import Typer
Typer().run(tree, True)
if options.ir:
if options.irvm:
from irvm.frame import IrvmFrame as Frame
else:
from arm.frame import ArmFrame as Frame
from ir.translate import Translator
funcs = Translator(Frame).run(tree)
if options.canon:
from ir.canonical import canon
from ir.hoist import HoistCalls
from ir.blocks import reorder_blocks
H = HoistCalls()
for (f, (frame, stm)) in funcs.items():
funcs[f] = (frame, reorder_blocks(canon(stm.accept(H)), frame))
if options.gen:
from arm.gen import Gen
assembly = {}
for (f, (frame, seq)) in funcs.items():
assembly[f] = (frame, seq.accept(Gen(frame)))
if options.liveness and not options.registers:
# This is useful for testing only, the register allocation
# will take care of calling liveness analysis itself.
from codegen.liveness import liveness_analysis
liveness_analysis(frame, assembly[f][1])
if options.registers:
from codegen.alloc import allocate_registers
assembly[f] = (frame, allocate_registers(frame, assembly[f][1]))
if options.dump:
for (f, (frame, code)) in assembly.items():
for i in code:
print(i.dump(options.verbose))
elif options.dump:
from ir.dumper import Dumper
for (frame, stm) in funcs.values():
print(stm.accept(Dumper()))
elif options.dump:
from parser.dumper import Dumper
print(tree.accept(Dumper(options.bind)))
if options.eval:
from ast.evaluator import Evaluator
print("Evaluating: %s" % tree.accept(Evaluator()))