9 #define MAX(A,B) (A > B ? A : B)
13 %token STRUCT END METHOD VAR IF THEN ELSE WHILE DO RETURN NOT OR THIS IDENT NUM ASSIGN
16 @i xx = @Statement.sin@;
20 @i @Statement.sout@ = @Statement.sin@;
22 *> xxputsin(@Statement.sout@,)
23 * geht nicht, weil verschachtelte macros deaktiviert sind */
26 @macro lblcountinout()
27 @i @Statement.lblcnt_out@ = @Statement.lblcnt_in@;
31 @i @Statement.vars_out@ = @Statement.vars_in@;
34 /* beschreibung der attribute
36 * f: symboltabelle fuer quirks mit structur und parameter
37 * gparamges: anzahl der parameter in einer methode
38 * parms: parametercounter
39 * node: baum fuer iburg
40 * sin: symboltabelle fuer statement ("eingabe")
41 * sout: symboltabelle die aus einem statement wieder rauskommt ("ausgabe")
42 * lblcnt_{in,out}: label counter
43 * vars_{in,out}: counter fuer lokale variablen
44 * call: enthaelt block einen call? (sonst kann man sich stack setup sparen)
45 * imm: fuer ein paar quirks mit immediates im ast
46 * paramcount: zum zaehlen der paramter eines methodenaufrufes
48 @autoinh s gparamges vars_in
49 @autosyn node imm call
51 @attributes { char *name; } IDENT
52 @attributes { long val; } NUM
53 @attributes { struct symbol *f; int paramges; int parms; } Parms
54 @attributes { struct symbol *f; } Program Structdef;
55 @attributes { struct symbol *f; int offsetcount; } FeldID
56 @attributes { struct symbol *s; } Methoddef
57 @attributes { struct symbol *s; int gparamges; int vars_in; int cnt; int paramcount; struct treenode *node; } Exprs
58 @attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int vars_in; int vars_out; int call; } Statseq
59 @attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int reallblcnt; int vars_in; int vars_out; int call; } Elsestat
60 @attributes { struct symbol *s; int gparamges; int vars_in; struct treenode *node; short imm; int call; } Expr Minusterm Multerm Orterm Feld Term
61 @attributes { struct symbol *s; int gparamges; int vars_in; struct treenode *node; } Lexpr IdentCommon
62 @attributes { struct symbol *sin; int gparamges; struct symbol *sout; struct treenode *node; int vars_in; int vars_out; int lblcnt_in; int lblcnt_out; int call; } Statement
64 @traversal @postorder c
65 @traversal @preorder reg
66 @traversal @preorder gen
72 @i @Program.f@ = tab_new();
73 @gen printf("\t.text\n");
80 @i @Methoddef.s@ = @Program.0.f@;
81 @i @Program.1.f@ = @Program.0.f@;
84 | Structdef ';' Program
86 @i @Program.1.f@ = tab_merge(@Program.0.f@, @Structdef.f@, 1);
92 METHOD IDENT '(' Parms ')' Statseq END
95 @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.f@, 0);
96 @i @Statseq.vars_in@ = 0;
97 @i @Statseq.gparamges@ = @Parms.paramges@;
98 @i @Statseq.lblcnt_in@ = 0;
99 @gen func_header(@IDENT.name@, @Statseq.vars_out@, @Parms.paramges@, @Statseq.call@);
106 @i @Structdef.f@ = @FeldID.f@;
107 @i @FeldID.offsetcount@ = 0;
112 /* lokale Vars werden in Statement in die tabelle eingefuegt */
115 @i @Parms.1.parms@ = @Parms.0.parms@ + 1;
116 @i @Parms.0.paramges@ = @Parms.1.paramges@;
117 @i @Parms.0.f@ = tab_add_symbol(@Parms.1.f@, @IDENT.name@, S_PARM, 1, @Parms.parms@, -1);
122 @i @Parms.f@ = tab_new();
123 @i @Parms.paramges@ = @Parms.parms@;
130 @i @FeldID.1.offsetcount@ = @FeldID.0.offsetcount@ + 1;
131 @i @FeldID.0.f@ = tab_add_symbol(@FeldID.1.f@, @IDENT.name@, S_FIELD, 1, -1, @FeldID.0.offsetcount@);
136 @i @FeldID.f@ = tab_new();
141 Statement ';' Statseq
143 @i @Statement.sin@ = @Statseq.0.s@;
144 @i @Statement.lblcnt_in@ = @Statseq.0.lblcnt_in@;
146 @i @Statseq.1.s@ = @Statement.sout@;
147 @i @Statseq.1.lblcnt_in@ = @Statement.lblcnt_out@;
148 @i @Statseq.1.gparamges@ = @Statseq.0.gparamges@;
150 @i @Statement.vars_in@ = @Statseq.0.vars_in@;
151 @i @Statseq.1.vars_in@ = @Statement.vars_out@;
153 @i @Statseq.0.lblcnt_out@ = @Statseq.1.lblcnt_out@;
154 @i @Statseq.0.vars_out@ = @Statseq.1.vars_out@;
156 @i @Statseq.0.call@ = @Statement.call@ || @Statseq.1.call@;
161 @i @Statseq.0.lblcnt_out@ = @Statseq.0.lblcnt_in@;
162 @i @Statseq.0.vars_out@ = @Statseq.0.vars_in@;
163 @i @Statseq.0.call@ = 0;
175 @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, @Lexpr.node@);
176 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
177 @reg @Lexpr.node@->reg = next_reg(@Expr.node@->reg, @Expr.gparamges@);
179 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
182 | VAR IDENT ASSIGN Expr
184 /* tab_clone ist hier noetig, vgl. folgendes statement
185 * > var x := x - 1; */
186 @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1, @Statement.gparamges@ + @Statement.vars_in@, -1);
189 @i @Statement.vars_out@ = @Statement.vars_in@ + 1;
193 @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, @Statement.gparamges@ + @Statement.vars_in@));
194 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
196 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
205 @i @Statement.node@ = new_node(O_EXPR, @Expr.node@, TREENULL);
206 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
209 just_calls(@Statement.node@);
213 | IF Expr THEN Statseq END
216 @i @Statseq.lblcnt_in@ = @Statement.lblcnt_in@ + 1;
217 @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@;
219 @i @Statseq.vars_in@ = @Statement.vars_in@;
220 @i @Statement.vars_out@ = @Statseq.vars_out@;
222 @i @Statement.call@ = @Expr.call@ || @Statseq.call@;
225 xxputsin(@Statseq.s@,)
227 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
229 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
231 printf(".%s_ifstart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
232 write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
233 printf("\tjz .%s_ifend_%d\n", get_func_name(), @Statement.lblcnt_in@);
235 @gen @revorder(1) printf(".%s_ifend_%d:\n", get_func_name(), @Statement.lblcnt_in@);
238 | IF Expr THEN Statseq Elsestat END
241 @i @Statseq.0.lblcnt_in@ = @Statement.lblcnt_in@ + 1;
242 @i @Elsestat.lblcnt_in@ = @Statseq.lblcnt_out@;
243 @i @Statement.lblcnt_out@ = @Elsestat.lblcnt_out@;
245 /* im Elsestat muss noch ein label numeriert werden */
246 @i @Elsestat.reallblcnt@ = @Statement.lblcnt_in@;
248 @i @Statseq.vars_in@ = @Statement.vars_in@;
249 @i @Elsestat.vars_in@ = @Statement.vars_in@;
250 @i @Statement.vars_out@ = MAX(@Statseq.vars_out@, @Elsestat.vars_out@);
252 @i @Statement.call@ = @Expr.call@ || @Statseq.call@ || @Elsestat.call@;
255 xxputsin(@Statseq.0.s@,)
256 xxputsin(@Elsestat.s@,)
258 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
260 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
262 printf(".%s_ifstart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
263 write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
264 printf("\tjz .%s_ifelse_%d\n", get_func_name(), @Statement.lblcnt_in@);
266 @gen @revorder(1) printf(".%s_ifend_%d:\n", get_func_name(), @Statement.lblcnt_in@);
269 | WHILE Expr DO Statseq END
272 @i @Statseq.lblcnt_in@ = @Statement.lblcnt_in@ + 1;
273 @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@;
275 @i @Statseq.vars_in@ = @Statement.vars_in@;
276 @i @Statement.vars_out@ = @Statseq.vars_out@;
278 @i @Statement.call@ = @Expr.call@ || @Statseq.call@;
281 xxputsin(@Statseq.s@,)
283 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
285 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
287 printf(".%s_whilestart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
288 write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
289 printf("\tjz .%s_whileend_%d\n", get_func_name(), @Statement.lblcnt_in@);
291 @gen @revorder(1) printf("\tjmp .%s_whilestart_%d\n.%s_whileend_%d:\n", get_func_name(), @Statement.lblcnt_in@, get_func_name(), @Statement.lblcnt_in@);
301 @i @Statement.node@ = new_node(O_RET, @Expr.node@, TREENULL);
302 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
304 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1); func_footer();
311 @i @Statseq.lblcnt_in@ = @Elsestat.lblcnt_in@;
312 @i @Elsestat.lblcnt_out@ = @Statseq.lblcnt_out@;
314 @i @Statseq.vars_in@ = @Elsestat.vars_in@;
315 @i @Elsestat.vars_out@ = @Statseq.vars_out@;
317 @gen printf("\tjmp .%s_ifend_%d\n.%s_ifelse_%d:\n", get_func_name(), @Elsestat.reallblcnt@, get_func_name(), @Elsestat.reallblcnt@);
328 @c check(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM);
331 @IdentCommon.node@ = TREENULL;
332 if(tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
333 /* es handelt sich um ein feldzugriff auf this */
334 @IdentCommon.node@ = new_field(@IDENT.name@, new_param(O_ID, "this", TREENULL, TREENULL, 0), TREENULL, tab_lookup(@IdentCommon.s@, @IDENT.name@, S_FIELD) == SYMNULL ? -1 : tab_lookup(@IdentCommon.s@, @IDENT.name@, S_FIELD)->soffset);
335 } else { /* param oder var */
336 int tmp = tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL ? -1 : tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM)->param_index;
337 @IdentCommon.node@ = new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, tmp);
341 @reg if(tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
342 /* TODO: kein schoener hack? */
343 @IdentCommon.node@->kids[0]->reg = @IdentCommon.node@->reg;
351 @c check(@Feld.s@, @IDENT.name@, S_FIELD);
352 @i @Feld.node@ = new_field(@IDENT.name@, @Term.node@, TREENULL, tab_lookup(@Feld.s@, @IDENT.name@, S_FIELD) == SYMNULL ? -1 : tab_lookup(@Feld.s@, @IDENT.name@, S_FIELD)->soffset);
354 @reg @Term.node@->reg = next_reg(@Feld.node@->reg, @Term.gparamges@);
361 @reg @Term.node@->reg = @Expr.node@->reg;
366 @i @Expr.node@ = new_node(O_BOOL, new_node(O_EQ, @Term.node@, new_node(O_NULL, TREENULL, TREENULL)), TREENULL);
368 @reg @Term.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
373 @i @Expr.node@ = new_node(O_SUB, @Term.node@, @Minusterm.node@);
374 @i @Expr.imm@ = @Term.imm@ && @Minusterm.imm@;
375 @i @Expr.call@ = @Term.call@ || @Minusterm.call@;
378 if(!(@Expr.node@->kids[0] == TREENULL && @Expr.node@->kids[1] == TREENULL)) {
379 @Term.node@->reg = @Expr.node@->reg;
380 if(@Minusterm.imm@) {
381 @Minusterm.node@->reg = @Expr.node@->reg;
383 @Minusterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
391 @i @Expr.node@ = new_node(O_MUL, @Term.node@, @Multerm.node@);
392 @i @Expr.imm@ = @Term.imm@ && @Multerm.imm@;
393 @i @Expr.call@ = @Term.call@ || @Multerm.call@;
396 @Term.node@->reg = @Expr.node@->reg;
398 @Multerm.node@->reg = @Expr.node@->reg;
400 @Multerm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
407 @i @Expr.node@ = new_node(O_OR, @Term.node@, @Orterm.node@);
408 @i @Expr.imm@ = @Term.imm@ && @Orterm.imm@;
409 @i @Expr.call@ = @Term.call@ || @Orterm.call@;
412 @Term.node@->reg = @Expr.node@->reg;
413 @Orterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
419 @i @Expr.node@ = new_node(O_BOOL, new_node(O_LESS, @Term.0.node@, @Term.1.node@), TREENULL);
420 @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@;
421 @i @Expr.call@ = @Term.0.call@ || @Term.1.call@;
424 @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
425 @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
431 @i @Expr.node@ = new_node(O_BOOL, new_node(O_EQ, @Term.0.node@, @Term.1.node@), TREENULL);
432 @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@;
433 @i @Expr.call@ = @Term.0.call@ || @Term.1.call@;
436 @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
437 @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
445 @i @Minusterm.node@ = new_node(O_ADD, @Minusterm.1.node@, @Term.node@);
446 @i @Minusterm.0.imm@ = @Term.imm@ && @Minusterm.1.imm@;
447 @i @Minusterm.0.call@ = @Term.call@ || @Minusterm.1.call@;
450 @Minusterm.1.node@->reg = @Minusterm.node@->reg;
451 if(@Minusterm.1.imm@) {
452 @Term.node@->reg = @Minusterm.node@->reg;
454 @Term.node@->reg = next_reg(@Minusterm.1.node@->reg, @Minusterm.gparamges@);
461 @reg @Term.node@->reg = @Minusterm.node@->reg;
468 @i @Multerm.node@ = new_node(O_MUL, @Multerm.1.node@, @Term.node@);
469 @i @Multerm.0.imm@ = @Term.imm@ && @Multerm.1.imm@;
470 @i @Multerm.0.call@ = @Term.call@ || @Multerm.1.call@;
473 @Multerm.1.node@->reg = @Multerm.node@->reg;
474 if(@Multerm.1.imm@) {
475 @Term.node@->reg = @Multerm.node@->reg;
477 @Term.node@->reg = next_reg(@Multerm.1.node@->reg, @Multerm.gparamges@);
484 @reg @Term.node@->reg = @Multerm.node@->reg;
491 @i @Orterm.node@ = new_node(O_OR, @Orterm.1.node@, @Term.node@);
492 @i @Orterm.0.imm@ = @Term.imm@ && @Orterm.1.imm@;
493 @i @Orterm.0.call@ = @Term.call@ || @Orterm.1.call@;
496 @Orterm.1.node@->reg = @Orterm.node@->reg;
498 @Term.node@->reg = @Orterm.node@->reg;
500 @Term.node@->reg = next_reg(@Orterm.1.node@->reg, @Orterm.gparamges@);
506 @reg @Term.node@->reg = @Orterm.node@->reg;
514 @i @Term.node@ = @Expr.node@;
519 @i @Term.node@ = new_number(@NUM.val@);
526 @i @Term.node@ = new_number(-1 * (@NUM.val@));
533 @i @Term.node@ = new_param(O_ID, "this", TREENULL, TREENULL, 0);
546 @i @Term.node@ = @Feld.node@;
550 | IDENT '(' Exprs ')'
553 @Term.node@ = new_call(@IDENT.name@, new_arg(@Exprs.node@, new_nothing(), 0) /*this*/,
554 TREENULL, @Term.gparamges@, @Term.vars_in@);
555 @Term.node@->soffset = MAX(@Exprs.paramcount@, @Term.gparamges@);
560 @reg @Exprs.node@->reg = @Term.node@->reg;
563 | Term '.' IDENT '(' Exprs ')'
566 @Term.node@ = new_call(@IDENT.name@, new_arg(@Exprs.node@, @Term.1.node@, 0) /*this*/,
567 TREENULL, @Term.gparamges@, @Term.vars_in@);
568 @Term.node@->soffset = MAX(@Exprs.paramcount@, @Term.gparamges@);
573 @reg @Exprs.node@->reg = @Term.1.node@->reg = @Term.node@->kids[0]->reg = @Term.node@->reg;
581 @i @Exprs.0.node@ = new_arg(@Expr.0.node@, @Exprs.1.node@, @Exprs.0.cnt@);
582 @i @Exprs.0.paramcount@ = @Exprs.1.paramcount@;
583 @i @Exprs.1.cnt@ = @Exprs.0.cnt@ + 1;
585 @Expr.node@->reg = @Exprs.0.node@->reg;
586 @Exprs.1.node@->reg = next_reg(@Exprs.0.node@->reg, @Exprs.gparamges@);
591 @i @Exprs.0.node@ = new_arg(@Expr.0.node@, new_nothing(), @Exprs.cnt@);
592 @i @Exprs.paramcount@ = @Exprs.cnt@ + 1;
593 @reg @Expr.node@->reg = @Exprs.0.node@->reg;
597 @i @Exprs.0.node@ = new_nothing();
598 @i @Exprs.paramcount@ = @Exprs.cnt@;
606 int yyerror(char *error_text)
608 fprintf(stderr,"Zeile %i: %s\n", yylineno, error_text);
612 int main(int argc, char **argv)