27 | 27 |
class Compiler(object):
|
28 | 28 |
def __init__(self, emitter):
|
29 | 29 |
self.emitter = emitter
|
30 | |
self.routines = {}
|
31 | |
self.labels = {}
|
32 | |
self.trampolines = {} # Location -> Label
|
|
30 |
self.routines = {} # routine.name -> Routine
|
|
31 |
self.routine_statics = {} # routine.name -> { static.name -> Label }
|
|
32 |
self.labels = {} # global.name -> Label ("global" includes routines)
|
|
33 |
self.trampolines = {} # Location -> Label
|
33 | 34 |
self.current_routine = None
|
34 | 35 |
|
35 | 36 |
# helper methods
|
|
58 | 59 |
return length
|
59 | 60 |
|
60 | 61 |
def get_label(self, name):
|
61 | |
if self.current_routine and hasattr(self.current_routine, 'statics'):
|
62 | |
for static in self.current_routine.statics:
|
63 | |
if static.location.name == name:
|
64 | |
raise NotImplementedError("static " + name)
|
|
62 |
if self.current_routine:
|
|
63 |
static_label = self.routine_statics.get(self.current_routine.name, {}).get(name)
|
|
64 |
if static_label:
|
|
65 |
return static_label
|
65 | 66 |
return self.labels[name]
|
66 | 67 |
|
67 | 68 |
# visitor methods
|
|
69 | 70 |
def compile_program(self, program):
|
70 | 71 |
assert isinstance(program, Program)
|
71 | 72 |
|
|
73 |
defn_labels = []
|
|
74 |
|
72 | 75 |
for defn in program.defns:
|
73 | 76 |
length = self.compute_length_of_defn(defn)
|
74 | |
self.labels[defn.name] = Label(defn.name, addr=defn.addr, length=length)
|
|
77 |
label = Label(defn.name, addr=defn.addr, length=length)
|
|
78 |
self.labels[defn.name] = label
|
|
79 |
defn_labels.append((defn, label))
|
75 | 80 |
|
76 | 81 |
for routine in program.routines:
|
77 | 82 |
self.routines[routine.name] = routine
|
|
80 | 85 |
label.set_addr(routine.addr)
|
81 | 86 |
self.labels[routine.name] = label
|
82 | 87 |
|
|
88 |
if hasattr(routine, 'statics'):
|
|
89 |
static_labels = {}
|
|
90 |
for defn in routine.statics:
|
|
91 |
length = self.compute_length_of_defn(defn)
|
|
92 |
label = Label(defn.name, addr=defn.addr, length=length)
|
|
93 |
static_labels[defn.name] = label
|
|
94 |
defn_labels.append((defn, label))
|
|
95 |
self.routine_statics[routine.name] = static_labels
|
|
96 |
|
83 | 97 |
self.compile_routine(self.routines['main'])
|
84 | 98 |
for routine in program.routines:
|
85 | 99 |
if routine.name != 'main':
|
|
91 | 105 |
self.emitter.emit(RTS())
|
92 | 106 |
|
93 | 107 |
# initialized data
|
94 | |
for defn in program.defns:
|
|
108 |
for defn, label in defn_labels:
|
95 | 109 |
if defn.initial is not None:
|
96 | |
label = self.get_label(defn.name)
|
97 | 110 |
initial_data = None
|
98 | 111 |
type_ = defn.location.type
|
99 | 112 |
if type_ == TYPE_BYTE:
|
|
109 | 122 |
self.emitter.emit(initial_data)
|
110 | 123 |
|
111 | 124 |
# uninitialized, "BSS" data
|
112 | |
for defn in program.defns:
|
|
125 |
for defn, label in defn_labels:
|
113 | 126 |
if defn.initial is None and defn.addr is None:
|
114 | |
label = self.get_label(defn.name)
|
115 | 127 |
self.emitter.resolve_bss_label(label)
|
116 | |
|
117 | 128 |
|
118 | 129 |
def compile_routine(self, routine):
|
119 | 130 |
self.current_routine = routine
|