From dc9777f5c4d517c8c4f2888449250c8f187f2fa6 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sun, 6 Jun 2010 21:14:39 +0200 Subject: [PATCH] gesamt: variablen und calls 'mitzaehlen' --- gesamt/chelper.c | 14 +++++++- gesamt/chelper.h | 2 +- gesamt/code.bfe | 6 ++-- gesamt/parser.y | 89 ++++++++++++++++++++++++++++++++++++------------ gesamt/tree.c | 11 ++++++ gesamt/tree.h | 5 +-- 6 files changed, 100 insertions(+), 27 deletions(-) diff --git a/gesamt/chelper.c b/gesamt/chelper.c index b4831a7..edef844 100644 --- a/gesamt/chelper.c +++ b/gesamt/chelper.c @@ -14,10 +14,20 @@ static char *regs8l[] = {"al", "r10b", "r11b", "r9b"}; /* ja, dirty.. */ static char *akt_func_name = (char*) NULL; -void func_header(char *s) +static char need_stack = 0; + +void func_header(char *s, int vars, int parms, int call) { printf("\t.globl %1$s\n\t.type %1$s, @function\n%1$s:\n", s); + printf("\t//vars: %i, parms: %i, call(bool): %i\n", vars, parms, call); akt_func_name = s; + + need_stack = (vars || parms) && call; + if(need_stack) { + printf("\tpushq %%rbp\n" + "\tmovq %%rsp, %%rbp\n", + "\tsubq $%d, %%rsp\n", 8*(vars+parms)); + } } char *get_func_name(void) @@ -27,6 +37,8 @@ char *get_func_name(void) void func_footer(void) { + if(need_stack) + printf("\tleave\n"); printf("\tret\n"); } diff --git a/gesamt/chelper.h b/gesamt/chelper.h index 0287f94..70870ee 100644 --- a/gesamt/chelper.h +++ b/gesamt/chelper.h @@ -1,6 +1,6 @@ #ifndef __CHELPER_H #define __CHELPER_H -void func_header(char *s); +void func_header(char *s, int vars, int parms, int call); char *get_func_name(void); void func_footer(void); char *next_reg(char *s, int params); diff --git a/gesamt/code.bfe b/gesamt/code.bfe index 8615fab..15eb808 100644 --- a/gesamt/code.bfe +++ b/gesamt/code.bfe @@ -185,7 +185,7 @@ void assign_var(struct treenode *bnode) %} %start begin -%term O_RET=1 O_NULL=2 O_SUB=3 O_MUL=4 O_OR=5 O_LESS=6 O_EQ=7 O_ID=8 O_ADD=9 O_NUM=10 O_FIELD=11 O_MTWO=12 O_MFOUR=13 O_MEIGHT=14 O_MONE=15 O_ASSIGN=16 O_IF=17 O_BOOL=18 +%term O_RET=1 O_NULL=2 O_SUB=3 O_MUL=4 O_OR=5 O_LESS=6 O_EQ=7 O_ID=8 O_ADD=9 O_NUM=10 O_FIELD=11 O_MTWO=12 O_MFOUR=13 O_MEIGHT=14 O_MONE=15 O_ASSIGN=16 O_IF=17 O_BOOL=18 O_CALL=19 %% @@ -209,7 +209,7 @@ ifstat: O_IF(expr) # 2 # /* iburg beschummeln :/ */ printf("\ttest $-1, %%rax\n" ifstat: O_IF(O_BOOL(expr)) # 1 # /* dann braucht man kein test */ -ret: O_RET(retexpr) # 2 # printf("\t//o_ret(expr)\n"); move(BN_REG, "rax"); func_footer(); +ret: O_RET(retexpr) # 2 # printf("\t//o_ret(expr)\n"); move(BN_REG, "rax"); retexpr: O_ID # 1 # printf("\t//retexpr\n"); if(bnode->param_index > -1) move(param_reg(bnode->param_index), BN_REG); retexpr: expr @@ -219,6 +219,8 @@ expr: O_ID # 0 # expr: imm # 1 # moveimm(BN_VAL, BN_REG); expr: O_BOOL(expr) # 0 # +expr: O_CALL # 0 # printf("\tcall %s\n", bnode->name); + expr: O_SUB(expr,expr) # 2 # gen_e_eno(bnode, "subq"); expr: O_SUB(expr,O_FIELD(expr)) # 2 # gen_e_field(bnode, "subq"); diff --git a/gesamt/parser.y b/gesamt/parser.y index 39cc35d..9c1309d 100644 --- a/gesamt/parser.y +++ b/gesamt/parser.y @@ -27,6 +27,10 @@ @i @Statement.lblcnt_out@ = @Statement.lblcnt_in@; @end +@macro varsinout() + @i @Statement.vars_out@ = @Statement.vars_in@; +@end + /* beschreibung der attribute * s: symboltabelle * f: symboltabelle fuer quirks mit structur und parameter @@ -37,7 +41,7 @@ * sout: symboltabelle die aus einem statement wieder rauskommt ("ausgabe") */ @autoinh s gparamges -@autosyn node imm +@autosyn node imm call @attributes { char *name; } IDENT @attributes { long val; } NUM @@ -46,11 +50,11 @@ @attributes { struct symbol *f; int offsetcount; } FeldID @attributes { struct symbol *s; } Methoddef @attributes { struct symbol *s; int gparamges; } Exprs -@attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; } Statseq -@attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int reallblcnt; } Elsestat -@attributes { struct symbol *s; int gparamges; struct treenode *node; short imm; } Expr Minusterm Multerm Orterm Feld Term +@attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int vars_in; int vars_out; int call; } Statseq +@attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int reallblcnt; int vars_in; int vars_out; int call; } Elsestat +@attributes { struct symbol *s; int gparamges; struct treenode *node; short imm; int call; } Expr Minusterm Multerm Orterm Feld Term @attributes { struct symbol *s; int gparamges; struct treenode *node; } Lexpr -@attributes { struct symbol *sin; int gparamges; struct symbol *sout; struct treenode *node; int vars; int lblcnt_in; int lblcnt_out; } Statement +@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 @traversal @postorder c @traversal @preorder reg @@ -84,9 +88,10 @@ Methoddef: @{ @i @Parms.parms@ = 1; @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.f@, 0); + @i @Statseq.vars_in@ = 0; @i @Statseq.gparamges@ = @Parms.paramges@; @i @Statseq.lblcnt_in@ = 0; - @gen func_header(@IDENT.name@); + @gen func_header(@IDENT.name@, @Statseq.vars_out@, @Parms.paramges@, @Statseq.call@); @} ; @@ -135,14 +140,22 @@ Statseq: @i @Statseq.1.s@ = @Statement.sout@; @i @Statseq.1.lblcnt_in@ = @Statement.lblcnt_out@; - @i @Statseq.1.gparamges@ = @Statseq.0.gparamges@ + @Statement.vars@; + @i @Statseq.1.gparamges@ = @Statseq.0.gparamges@; + + @i @Statement.vars_in@ = @Statseq.0.vars_in@; + @i @Statseq.1.vars_in@ = @Statement.vars_out@; @i @Statseq.0.lblcnt_out@ = @Statseq.1.lblcnt_out@; + @i @Statseq.0.vars_out@ = @Statseq.1.vars_out@; + + @i @Statseq.0.call@ = @Statement.call@ || @Statseq.1.call@; @} | @{ @i @Statseq.0.lblcnt_out@ = @Statseq.0.lblcnt_in@; + @i @Statseq.0.vars_out@ = @Statseq.0.vars_in@; + @i @Statseq.0.call@ = 0; @} ; @@ -151,10 +164,10 @@ Statement: @{ statinout() lblcountinout() + varsinout() xxputsin(@Lexpr.s@,) xxputsin(@Expr.s@,) @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, @Lexpr.node@); - @i @Statement.vars@ = 0; @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); @reg @Lexpr.node@->reg = next_reg(@Expr.node@->reg, @Expr.gparamges@); @@ -165,12 +178,14 @@ Statement: @{ /* tab_clone ist hier noetig, vgl. folgendes statement * > var x := x - 1; */ - @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1, @Statement.gparamges@, -1); + @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1, @Statement.gparamges@ + @Statement.vars_in@, -1); lblcountinout() + + @i @Statement.vars_out@ = @Statement.vars_in@ + 1; + xxputsin(@Expr.s@,) - @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, @Statement.gparamges@)); - @i @Statement.vars@ = 1; + @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, @Statement.gparamges@ + @Statement.vars_in@)); @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1); @@ -179,10 +194,10 @@ Statement: | Expr @{ statinout() + varsinout() lblcountinout() xxputsin(@Expr.s@,) @i @Statement.node@ = TREENULL; - @i @Statement.vars@ = 0; @} | IF Expr THEN Statseq END @@ -190,11 +205,16 @@ Statement: statinout() @i @Statseq.lblcnt_in@ = @Statement.lblcnt_in@ + 1; @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@; + + @i @Statseq.vars_in@ = @Statement.vars_in@; + @i @Statement.vars_out@ = @Statseq.vars_out@; + + @i @Statement.call@ = @Expr.call@ || @Statseq.call@; + xxputsin(@Expr.s@,) xxputsin(@Statseq.s@,) @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL); - @i @Statement.vars@ = 0; @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); @gen { @@ -216,12 +236,17 @@ Statement: /* im Elsestat muss noch ein label numeriert werden */ @i @Elsestat.reallblcnt@ = @Statement.lblcnt_in@; + @i @Statseq.vars_in@ = @Statement.vars_in@; + @i @Elsestat.vars_in@ = @Statement.vars_in@; + @i @Statement.vars_out@ = MAX(@Statseq.vars_out@, @Elsestat.vars_out@); + + @i @Statement.call@ = @Expr.call@ || @Statseq.call@ || @Elsestat.call@; + xxputsin(@Expr.s@,) xxputsin(@Statseq.0.s@,) xxputsin(@Elsestat.s@,) @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL); - @i @Statement.vars@ = 0; @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); @gen { @@ -238,11 +263,16 @@ Statement: statinout() @i @Statseq.lblcnt_in@ = @Statement.lblcnt_in@ + 1; @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@; + + @i @Statseq.vars_in@ = @Statement.vars_in@; + @i @Statement.vars_out@ = @Statseq.vars_out@; + + @i @Statement.call@ = @Expr.call@ || @Statseq.call@; + xxputsin(@Expr.s@,) xxputsin(@Statseq.s@,) @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL); - @i @Statement.vars@ = 0; @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); @gen { @@ -258,13 +288,13 @@ Statement: @{ statinout() lblcountinout() + varsinout() xxputsin(@Expr.s@,) - @i @Statement.vars@ = 0; @i @Statement.node@ = new_node(O_RET, @Expr.node@, TREENULL); @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@); - @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1); + @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1); func_footer(); @} ; @@ -274,6 +304,9 @@ Elsestat: @i @Statseq.lblcnt_in@ = @Elsestat.lblcnt_in@; @i @Elsestat.lblcnt_out@ = @Statseq.lblcnt_out@; + @i @Statseq.vars_in@ = @Elsestat.vars_in@; + @i @Elsestat.vars_out@ = @Statseq.vars_out@; + @gen printf("\tjmp .%s_ifend_%d\n.%s_ifelse_%d:\n", get_func_name(), @Elsestat.reallblcnt@, get_func_name(), @Elsestat.reallblcnt@); @} @@ -329,6 +362,7 @@ Expr: @{ @i @Expr.node@ = new_node(O_SUB, @Term.node@, @Minusterm.node@); @i @Expr.imm@ = @Term.imm@ && @Minusterm.imm@; + @i @Expr.call@ = @Term.call@ || @Minusterm.call@; @reg { if(!(@Expr.node@->kids[0] == TREENULL && @Expr.node@->kids[1] == TREENULL)) { @@ -346,6 +380,7 @@ Expr: @{ @i @Expr.node@ = new_node(O_MUL, @Term.node@, @Multerm.node@); @i @Expr.imm@ = @Term.imm@ && @Multerm.imm@; + @i @Expr.call@ = @Term.call@ || @Multerm.call@; @reg { @Term.node@->reg = @Expr.node@->reg; @@ -361,6 +396,7 @@ Expr: @{ @i @Expr.node@ = new_node(O_OR, @Term.node@, @Orterm.node@); @i @Expr.imm@ = @Term.imm@ && @Orterm.imm@; + @i @Expr.call@ = @Term.call@ || @Orterm.call@; @reg { @Term.node@->reg = @Expr.node@->reg; @@ -371,7 +407,8 @@ Expr: | Term '<' Term @{ @i @Expr.node@ = new_node(O_BOOL, new_node(O_LESS, @Term.0.node@, @Term.1.node@), TREENULL); - @i @Expr.imm@ = @Term.0.imm@ && @Term.0.imm@; + @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@; + @i @Expr.call@ = @Term.0.call@ || @Term.1.call@; @reg { @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg; @@ -382,7 +419,8 @@ Expr: | Term '=' Term @{ @i @Expr.node@ = new_node(O_BOOL, new_node(O_EQ, @Term.0.node@, @Term.1.node@), TREENULL); - @i @Expr.imm@ = @Term.0.imm@ && @Term.0.imm@; + @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@; + @i @Expr.call@ = @Term.0.call@ || @Term.1.call@; @reg { @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg; @@ -396,6 +434,7 @@ Minusterm: @{ @i @Minusterm.node@ = new_node(O_ADD, @Minusterm.1.node@, @Term.node@); @i @Minusterm.0.imm@ = @Term.imm@ && @Minusterm.1.imm@; + @i @Minusterm.0.call@ = @Term.call@ || @Minusterm.1.call@; @reg { @Minusterm.1.node@->reg = @Minusterm.node@->reg; @@ -418,6 +457,7 @@ Multerm: @{ @i @Multerm.node@ = new_node(O_MUL, @Multerm.1.node@, @Term.node@); @i @Multerm.0.imm@ = @Term.imm@ && @Multerm.1.imm@; + @i @Multerm.0.call@ = @Term.call@ || @Multerm.1.call@; @reg { @Multerm.1.node@->reg = @Multerm.node@->reg; @@ -440,6 +480,7 @@ Orterm: @{ @i @Orterm.node@ = new_node(O_OR, @Orterm.1.node@, @Term.node@); @i @Orterm.0.imm@ = @Term.imm@ && @Orterm.1.imm@; + @i @Orterm.0.call@ = @Term.call@ || @Orterm.1.call@; @reg { @Orterm.1.node@->reg = @Orterm.node@->reg; @@ -467,18 +508,21 @@ Term: @{ @i @Term.node@ = new_number(@NUM.val@); @i @Term.imm@ = 1; + @i @Term.call@ = 0; @} | '-' NUM @{ @i @Term.node@ = new_number(-1 * (@NUM.val@)); @i @Term.imm@ = 1; + @i @Term.call@ = 0; @} | THIS @{ @i @Term.node@ = new_param(O_ID, strdup("this"), TREENULL, TREENULL, 0); @i @Term.imm@ = 0; + @i @Term.call@ = 0; @} | IDENT @@ -486,6 +530,7 @@ Term: @c check(@Term.s@, @IDENT.name@, S_VAR|S_PARM); @i @Term.imm@ = 0; + @i @Term.call@ = 0; @i { @Term.node@ = TREENULL; if(tab_lookup(@Term.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) { @@ -511,14 +556,16 @@ Term: | IDENT '(' Exprs ')' @{ - @i @Term.node@ = TREENULL; + @i @Term.node@ = new_call(@IDENT.name@, TREENULL, TREENULL); @i @Term.imm@ = 0; + @i @Term.call@ = 1; @} | Term '.' IDENT '(' Exprs ')' @{ - @i @Term.node@ = TREENULL; + @i @Term.node@ = new_node(O_CALL, TREENULL, TREENULL); @i @Term.imm@ = 0; + @i @Term.call@ = 1; @} ; diff --git a/gesamt/tree.c b/gesamt/tree.c index 593709c..4dcf0d7 100644 --- a/gesamt/tree.c +++ b/gesamt/tree.c @@ -63,6 +63,17 @@ struct treenode *new_field(char *name, struct treenode *l, struct treenode *r, i return new; } +struct treenode *new_call(char *name, struct treenode *l, struct treenode *r) +{ + struct treenode *new = new_node(O_CALL, l, r); + +#ifdef DDTREE + fprintf(stderr, "new_call\n"); +#endif + new->name = name; + return new; +} + struct treenode *new_number(long val) { struct treenode *new; diff --git a/gesamt/tree.h b/gesamt/tree.h index 8e39fe3..b99b8d2 100644 --- a/gesamt/tree.h +++ b/gesamt/tree.h @@ -13,14 +13,14 @@ enum { O_RET=1, O_NULL, O_SUB, O_MUL, O_OR=5, O_LESS, O_EQ, O_ID, O_ADD, O_NUM=10, O_FIELD, O_MTWO, O_MFOUR, O_MEIGHT, - O_MONE=15, O_ASSIGN, O_IF, O_BOOL + O_MONE=15, O_ASSIGN, O_IF, O_BOOL, O_CALL }; static char *o_names[] = { "", "O_RET", "O_NULL", "O_SUB", "O_MUL", "O_OR", "O_LESS", "O_EQ", "O_ID", "O_ADD", "O_NUM", "O_FIELD", "O_MTWO", "O_MFOUR", "O_MEIGHT", - "O_MONE", "O_ASSIGN", "O_IF", "O_BOOL" + "O_MONE", "O_ASSIGN", "O_IF", "O_BOOL", "O_CALL" }; struct treenode { @@ -48,6 +48,7 @@ struct treenode *new_node(int op, struct treenode *l, struct treenode *r); struct treenode *new_number(long val); struct treenode *new_param(int op, char *name, struct treenode *l, struct treenode *r, int param_index); struct treenode *new_field(char *name, struct treenode *l, struct treenode *r, int soffset); +struct treenode *new_call(char *name, struct treenode *l, struct treenode *r); void write_tree(struct treenode *node, int ident); #endif -- 2.25.1