git.haldean.org cvm / 18b5612
Huzzah! Code generation for function calling. Will Brown 9 years ago
4 changed file(s) with 107 addition(s) and 80 deletion(s). Raw diff Collapse all Expand all
3434 'ojmp',
3535 'ldconst',
3636 'print',
37 'return',
38 'call',
3739 ]
3840
3941 opcodes = dict(zip(ops, range(len(ops))))
1111 if func == 'main':
1212 continue
1313 func_locations[func] = len(code)
14 code.extend(codeobj.code)
1415
16 code = replace_function_addresses(code, func_locations)
1517 code = static_allocate(code, glob)
16
17 print(func_locations)
18 for c in code:
19 print(c)
2018 return code
2119
2220 def is_var(term):
2321 return isinstance(term, tuple) and len(term) == 2 and term[1] == 'var'
22
23 def replace_function_addresses(code, func_locations):
24 def replace_for_instruction(instr):
25 def arg_sub(arg):
26 if isinstance(arg, tuple) and len(arg) == 2 and arg[1] == 'func':
27 return func_locations[arg[0]]
28 else: return arg
29 return tuple(map(arg_sub, instr))
30 return map(replace_for_instruction, code)
2431
2532 def static_allocate(code, glob):
2633 glob_locations = {}
2936 # spec is a 2-tuple of type, init value
3037 glob_locations[var] = next_location
3138 next_location += spec[0].bytecount
32
33 print(glob_locations)
3439
3540 gen = []
3641 for line in code:
77 init_code = []
88 for item in root:
99 if item[0] == 'fun':
10 function = translate_function(item, glob)
10 function = translate_function(item, glob, funcs)
1111 funcs[item[2][0][0]] = function
1212 elif item[0] == 'declare':
1313 for var, init in item[2]:
1515 glob[name] = (cvmtype, init)
1616 if init:
1717 init_code.extend(
18 translate_declaration(name, (cvmtype, init), glob))
18 translate_declaration(name, (cvmtype, init), glob, funcs))
1919 else:
2020 raise Exception('Only function definitions and declarations'
2121 'are allowed at top level.')
2222
2323 return glob, funcs, init_code
2424
25 def translate_function(ftree, glob):
25 def translate_function(ftree, glob, funcs):
2626 fname = ftree[2][0][0]
2727 fargs = list(map(cvmtypes.declarator, ftree[2][1]))
28 fcode, flocals = translate_compound(ftree[3], glob)
28 fcode, flocals = translate_compound(ftree[3], glob, funcs)
2929 fret = cvmtypes.typefor(ftree[1])
3030 return function(fname, fcode, fargs, fret, flocals)
3131
3434 cvmtype, name = cvmtypes.declarator((decl[1], var))
3535 loc[name] = (cvmtype, init)
3636
37 def translate_compound(ftree, glob):
37 def translate_compound(ftree, glob, funcs):
3838 if not ftree: return [], {}
3939
4040 declarations = []
5252 code = []
5353 for var, data in loc.items():
5454 if data[1]:
55 code.extend(translate_declaration(var, data, glob))
55 code.extend(translate_declaration(var, data, glob, funcs))
5656 for node in ftree[first_statement:]:
57 code.extend(translate_statement(node, glob))
57 code.extend(translate_statement(node, glob, funcs))
5858
5959 return code, loc
6060
61 def translate_declaration(var, data, glob):
62 return (
63 translate_statement(data[1], glob) +
61 def translate_declaration(var, data, glob, funcs):
62 return (
63 translate_statement(data[1], glob, funcs) +
6464 [('store', (var, 'var'))])
6565
66 def translate_statement(ftree, glob):
66 def translate_statement(ftree, glob, funcs):
6767 '''
6868 TODO:
6969
7070 BREAK
7171 CALL
7272 GOTO
73 RETURN
7473 '''
7574 # Assignment
7675 if ftree[0] == '=':
77 rhs = translate_statement(ftree[2], glob)
76 rhs = translate_statement(ftree[2], glob, funcs)
7877 return rhs + [('store', ftree[1])]
7978
8079 # Variable access
8180 if ftree[1] == 'var':
8281 return [('load', ftree)]
8382
83 # Call stack-related
84 if ftree[0] == 'call':
85 func = funcs[ftree[1][0]]
86 if len(func.args) != len(ftree[2]):
87 raise Exception('Not enough arguments to function "%s"' % ftree[1][0])
88
89 arg_evals = []
90 for arg in ftree[2]:
91 arg_evals.extend(translate_statement(arg, glob, funcs))
92 return arg_evals + [('call', (ftree[1][0], 'func'))]
93
94 if ftree[0] == 'return':
95 return translate_statement(ftree[1], glob, funcs) + [('return',)]
96
8497 # Unary operators
8598 if ftree[0] == '++':
86 return translate_unop_expression('incr', ftree, glob)
99 return translate_unop_expression('incr', ftree, glob, funcs)
87100 if ftree[0] == '--':
88 return translate_unop_expression('decr', ftree, glob)
101 return translate_unop_expression('decr', ftree, glob, funcs)
89102 if ftree[0] == '~':
90 return translate_unop_expression('not', ftree, glob)
103 return translate_unop_expression('not', ftree, glob, funcs)
91104 if ftree[0] == '!':
92 return translate_unop_expression('bnot', ftree, glob)
105 return translate_unop_expression('bnot', ftree, glob, funcs)
93106
94107 # Binary operators
95108 if ftree[0] == '*' and len(ftree) == 3:
96 return translate_binop_expression('mul', ftree, glob)
109 return translate_binop_expression('mul', ftree, glob, funcs)
97110 if ftree[0] == '+':
98 return translate_binop_expression('add', ftree, glob)
111 return translate_binop_expression('add', ftree, glob, funcs)
99112 if ftree[0] == '-':
100 return translate_binop_expression('sub', ftree, glob)
113 return translate_binop_expression('sub', ftree, glob, funcs)
101114 if ftree[0] == '/':
102 return translate_binop_expression('div', ftree, glob)
115 return translate_binop_expression('div', ftree, glob, funcs)
103116 if ftree[0] == '%':
104 return translate_binop_expression('mod', ftree, glob)
117 return translate_binop_expression('mod', ftree, glob, funcs)
105118
106119 if ftree[0] == '&' and len(ftree[0]) == 3:
107 return translate_binop_expression('and', ftree, glob)
120 return translate_binop_expression('and', ftree, glob, funcs)
108121 if ftree[0] == '|':
109 return translate_binop_expression('or', ftree, glob)
122 return translate_binop_expression('or', ftree, glob, funcs)
110123 if ftree[0] == '^':
111 return translate_binop_expression('xor', ftree, glob)
124 return translate_binop_expression('xor', ftree, glob, funcs)
112125
113126 if ftree[0] == '<<':
114 return translate_binop_expression('lsh', ftree, glob)
127 return translate_binop_expression('lsh', ftree, glob, funcs)
115128 if ftree[0] == '>>':
116 return translate_binop_expression('rsh', ftree, glob)
129 return translate_binop_expression('rsh', ftree, glob, funcs)
117130
118131 if ftree[0] == '&&':
119 return translate_binop_expression('band', ftree, glob)
132 return translate_binop_expression('band', ftree, glob, funcs)
120133 if ftree[0] == '||':
121 return translate_binop_expression('bor', ftree, glob)
134 return translate_binop_expression('bor', ftree, glob, funcs)
122135
123136 # Comparison operators
124137 if ftree[0] == '==':
125 return translate_binop_expression('eq', ftree, glob)
138 return translate_binop_expression('eq', ftree, glob, funcs)
126139 if ftree[0] == '>=':
127 return translate_binop_expression('geq', ftree, glob)
140 return translate_binop_expression('geq', ftree, glob, funcs)
128141 if ftree[0] == '<=':
129 return translate_binop_expression('leq', ftree, glob)
142 return translate_binop_expression('leq', ftree, glob, funcs)
130143 if ftree[0] == '>':
131 return translate_binop_expression('gt', ftree, glob)
144 return translate_binop_expression('gt', ftree, glob, funcs)
132145 if ftree[0] == '<':
133 return translate_binop_expression('lt', ftree, glob)
146 return translate_binop_expression('lt', ftree, glob, funcs)
134147 if ftree[0] == '!=':
135 return translate_binop_expression('neq', ftree, glob)
148 return translate_binop_expression('neq', ftree, glob, funcs)
136149
137150 # Assignment operators
138151 if ftree[0] == '+=':
139 return translate_assign_expression('add', ftree, glob)
152 return translate_assign_expression('add', ftree, glob, funcs)
140153 if ftree[0] == '-=':
141 return translate_assign_expression('sub', ftree, glob)
154 return translate_assign_expression('sub', ftree, glob, funcs)
142155 if ftree[0] == '*=':
143 return translate_assign_expression('mul', ftree, glob)
156 return translate_assign_expression('mul', ftree, glob, funcs)
144157 if ftree[0] == '/=':
145 return translate_assign_expression('div', ftree, glob)
158 return translate_assign_expression('div', ftree, glob, funcs)
146159 if ftree[0] == '%=':
147 return translate_assign_expression('mod', ftree, glob)
160 return translate_assign_expression('mod', ftree, glob, funcs)
148161
149162 if ftree[0] == '&=':
150 return translate_assign_expression('and', ftree, glob)
163 return translate_assign_expression('and', ftree, glob, funcs)
151164 if ftree[0] == '|=':
152 return translate_assign_expression('or', ftree, glob)
165 return translate_assign_expression('or', ftree, glob, funcs)
153166 if ftree[0] == '^=':
154 return translate_assign_expression('xor', ftree, glob)
167 return translate_assign_expression('xor', ftree, glob, funcs)
155168 if ftree[0] == '>>=':
156 return translate_assign_expression('rsh', ftree, glob)
169 return translate_assign_expression('rsh', ftree, glob, funcs)
157170 if ftree[0] == '<<=':
158 return translate_assign_expression('lsh', ftree, glob)
171 return translate_assign_expression('lsh', ftree, glob, funcs)
159172
160173 # Dereferencing
161174 if ftree[0] == '->':
166179 return [('addr', ftree[1])]
167180 if ftree[0] == '*':
168181 return (
169 translate_statement(ftree[1], glob) +
182 translate_statement(ftree[1], glob, funcs) +
170183 [('load', ('result', 'reg'))])
171184
172185 # Conditionals
173186 if ftree[0] == 'if':
174 code_true, ignore = translate_compound(ftree[2], glob)
175 code_false, ignore = translate_compound(ftree[3], glob)
176 return (
177 translate_statement(ftree[1], glob) +
187 code_true, ignore = translate_compound(ftree[2], glob, funcs)
188 code_false, ignore = translate_compound(ftree[3], glob, funcs)
189 return (
190 translate_statement(ftree[1], glob, funcs) +
178191 # Conditional Offset Zero JuMP --
179192 # relative jump if result register == 0
180193 [('ozjmp', len(code_true) + 2)] +
183196 code_false)
184197
185198 if ftree[0] == '?':
186 code_true = translate_statement(ftree[2], glob)
187 code_false = translate_statement(ftree[3], glob)
188 return (
189 translate_statement(ftree[1], glob) +
199 code_true = translate_statement(ftree[2], glob, funcs)
200 code_false = translate_statement(ftree[3], glob, funcs)
201 return (
202 translate_statement(ftree[1], glob, funcs) +
190203 # Conditional Offset Zero JuMP --
191204 # relative jump if result register == 0
192205 [('ozjmp', len(code_true) + 2)] +
196209 [('nop',)])
197210
198211 if ftree[0] == 'while':
199 condition = translate_statement(ftree[1], glob)
200 code_true, ignore = translate_compound(ftree[2], glob)
212 condition = translate_statement(ftree[1], glob, funcs)
213 code_true, ignore = translate_compound(ftree[2], glob, funcs)
201214 return (
202215 condition +
203216 [('ozjmp', len(code_true) + 2)] +
205218 [('ojmp', -len(code_true) - len(condition) - 1), ('nop',)])
206219
207220 if ftree[0] == 'do':
208 condition = translate_statement(ftree[1], glob)
209 code_true, ignore = translate_compound(ftree[2], glob)
221 condition = translate_statement(ftree[1], glob, funcs)
222 code_true, ignore = translate_compound(ftree[2], glob, funcs)
210223 return (
211224 code_true +
212225 condition +
215228 ('nop',)])
216229
217230 if ftree[0] == 'for':
218 body, ignore = translate_compound(ftree[4], glob)
219 condition = translate_statement(ftree[2], glob)
231 body, ignore = translate_compound(ftree[4], glob, funcs)
232 condition = translate_statement(ftree[2], glob, funcs)
220233 update = []
221234 if ftree[3]:
222 update = translate_statement(ftree[3], glob)
223
224 return (
225 translate_statement(ftree[1], glob) +
235 update = translate_statement(ftree[3], glob, funcs)
236
237 return (
238 translate_statement(ftree[1], glob, funcs) +
226239 condition +
227240 [('ozjmp', len(body) + len(update) + 2)] +
228241 body + update +
237250 print('Warning: statement tree %s could not be translated.' % (ftree,))
238251 return []
239252
240 def translate_unop_expression(op, ftree, glob):
241 return (
242 translate_statement(ftree[1], glob) +
253 def translate_unop_expression(op, ftree, glob, funcs):
254 return (
255 translate_statement(ftree[1], glob, funcs) +
243256 [(op,), ('store', ftree[1])])
244257
245 def translate_binop_expression(op, ftree, glob):
246 return (
247 translate_statement(ftree[1], glob) +
248 translate_statement(ftree[2], glob) +
258 def translate_binop_expression(op, ftree, glob, funcs):
259 return (
260 translate_statement(ftree[1], glob, funcs) +
261 translate_statement(ftree[2], glob, funcs) +
249262 [(op,)])
250263
251 def translate_assign_expression(op, ftree, glob):
252 return (
253 translate_binop_expression(op, ftree, glob) +
264 def translate_assign_expression(op, ftree, glob, funcs):
265 return (
266 translate_binop_expression(op, ftree, glob, funcs) +
254267 [('store', ftree[1])])
0 int test(int ignore) {
1 return 7;
2 }
3
4 int main() {
5 test(5);
6 }