diff options
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 236 |
1 files changed, 142 insertions, 94 deletions
diff --git a/translate.cxx b/translate.cxx index 8c17c7cb..ebfd619e 100644 --- a/translate.cxx +++ b/translate.cxx @@ -7,10 +7,25 @@ #include "elaborate.h" #include "translate.h" #include <iostream> +#include <sstream> using namespace std; + +// little utility function + +template <typename T> +static string +stringify(T t) +{ + ostringstream s; + s << t; + return s.str (); +} + + + // ------------------------------------------------------------------------ // toy provider/unparser pair @@ -66,6 +81,9 @@ struct c_unparser: public unparser, public visitor string c_typename (exp_type e); string c_varname (const string& e); + void c_assign (const string& lvalue, expression* rvalue, const string& msg); + void c_assign (const string& lvalue, const string& rvalue, exp_type type, + const string& msg, const token* tok); void visit_block (block *s); void visit_null_statement (null_statement *s); @@ -410,6 +428,7 @@ c_unparser::emit_function (functiondecl* v) this->current_probe = 0; this->current_probenum = 0; this->current_function = v; + this->tmpvar_counter = 0; o->newline() << "struct function_" << c_varname (v->name) << "_locals * " @@ -480,6 +499,7 @@ c_unparser::emit_probe (derived_probe* v, unsigned i) this->current_function = 0; this->current_probe = v; this->current_probenum = i; + this->tmpvar_counter = 0; v->body->visit (this); this->current_probe = 0; this->current_probenum = 0; // not essential @@ -518,6 +538,51 @@ c_unparser::c_varname (const string& e) } +void +c_unparser::c_assign (const string& lvalue, expression* rvalue, + const string& msg) +{ + if (rvalue->type == pe_long) + { + o->newline() << lvalue << " = "; + rvalue->visit (this); + o->line() << ";"; + } + else if (rvalue->type == pe_string) + { + o->newline() << "strncpy (" << lvalue << ", "; + rvalue->visit (this); + o->line() << ", MAXSTRINGLEN);"; + } + else + { + string fullmsg = msg + " type unsupported"; + throw semantic_error (fullmsg, rvalue->tok); + } +} + + +void +c_unparser::c_assign (const string& lvalue, const string& rvalue, + exp_type type, const string& msg, const token* tok) +{ + if (type == pe_long) + { + o->newline() << lvalue << " = " << rvalue << ";"; + } + else if (type == pe_string) + { + o->newline() << "strncpy (" << lvalue << ", " + << rvalue << ", MAXSTRINGLEN);"; + } + else + { + string fullmsg = msg + " type unsupported"; + throw semantic_error (fullmsg, tok); + } +} + + void c_unparser::visit_block (block *s) @@ -624,21 +689,7 @@ c_unparser::visit_return_statement (return_statement* s) "vs", s->tok); o->newline() << "/* " << *s->tok << " */"; - if (s->value->type == pe_long) - { - o->newline() << "l->__retvalue = "; - s->value->visit (this); - o->line() << ";"; - } - else if (s->value->type == pe_string) - { - o->newline() << "strncpy (l->__retvalue, "; - s->value->visit (this); - o->line() << ", MAXSTRINGLEN);"; - o->line() << ";"; - } - else - throw semantic_error ("return type unsupported", s->tok); + c_assign ("l->__retvalue", s->value, "return value"); o->newline() << "goto out;"; } @@ -820,6 +871,7 @@ c_unparser::visit_symbol (symbol* e) } else if (current_function) { + // check locals for (unsigned i=0; i<current_function->locals.size(); i++) { vardecl* rr = current_function->locals[i]; @@ -829,6 +881,17 @@ c_unparser::visit_symbol (symbol* e) return; } } + + // check formal args + for (unsigned i=0; i<current_function->formal_args.size(); i++) + { + vardecl* rr = current_function->formal_args[i]; + if (rr == r) // comparison of pointers is sufficient + { + o->line() << "l->" << c_varname (r->name); + return; + } + } } // it better be a global @@ -850,8 +913,11 @@ c_unparser::visit_symbol (symbol* e) void c_tmpcounter_assignment::visit_symbol (symbol *e) { - parent->parent->o->newline() << parent->parent->c_typename (e->type) - << " __tmp" << parent->tmpvar_counter ++ << ";"; + parent->parent->o->newline() + << parent->parent->c_typename (e->type) + << " __tmp" << parent->tmpvar_counter ++ << ";" + << " /* " << e->name << " rvalue */"; + rvalue->visit (parent); } @@ -883,16 +949,7 @@ c_unparser_assignment::visit_symbol (symbol *e) o->line() << "({ "; o->indent(1); - if (e->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << tmp_base << tmpidx; - o->line() << (e->type == pe_long ? " = " : ", "); - rvalue->visit (parent); - if (e->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + parent->c_assign (tmp_base + stringify (tmpidx), rvalue, "assignment"); // XXX: strings may be passed safely via a char*, without // a full copy in tmpNNN @@ -905,16 +962,11 @@ c_unparser_assignment::visit_symbol (symbol *e) vardecl* rr = current_probe->locals[i]; if (rr == r) // comparison of pointers is sufficient { - if (e->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << "l->" << parent->c_varname (r->name); - o->line() << (e->type == pe_long ? " = " : ", ") - << tmp_base << tmpidx; - if (e->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + parent->c_assign ("l->" + parent->c_varname (r->name), + tmp_base + stringify (tmpidx), + rvalue->type, + "local variable assignment", rvalue->tok); + o->newline() << tmp_base << tmpidx << ";"; o->newline(-1) << "})"; return; @@ -928,16 +980,27 @@ c_unparser_assignment::visit_symbol (symbol *e) vardecl* rr = current_function->locals[i]; if (rr == r) // comparison of pointers is sufficient { - if (e->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << "l->" << parent->c_varname (r->name); - o->line() << (e->type == pe_long ? " = " : ", ") - << tmp_base << tmpidx; - if (e->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + parent->c_assign ("l->" + parent->c_varname (r->name), + tmp_base + stringify (tmpidx), + rvalue->type, + "local variable assignment", rvalue->tok); + + o->newline() << tmp_base << tmpidx << ";"; + o->newline(-1) << "})"; + return; + } + } + + for (unsigned i=0; i<current_function->formal_args.size(); i++) + { + vardecl* rr = current_function->formal_args[i]; + if (rr == r) // comparison of pointers is sufficient + { + parent->c_assign ("l->" + parent->c_varname (r->name), + tmp_base + stringify (tmpidx), + rvalue->type, + "formal argument assignment", rvalue->tok); + o->newline() << tmp_base << tmpidx << ";"; o->newline(-1) << "})"; return; @@ -951,16 +1014,12 @@ c_unparser_assignment::visit_symbol (symbol *e) if (session->globals[i] == r) { // XXX: acquire write lock on global - if (e->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << "global_" << parent->c_varname (r->name); - o->line() << (e->type == pe_long ? " = " : ", ") - << tmp_base << tmpidx; - if (e->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + + parent->c_assign ("global_" + parent->c_varname (r->name), + tmp_base + stringify (tmpidx), + rvalue->type, + "global variable assignment", rvalue->tok); + o->newline() << tmp_base << tmpidx << ";"; o->newline(-1) << "})"; return; @@ -979,11 +1038,16 @@ c_tmpcounter::visit_arrayindex (arrayindex *e) for (unsigned i=0; i<r->index_types.size(); i++) parent->o->newline() << parent->c_typename (r->index_types[i]) - << " __tmp" << tmpvar_counter ++ << ";"; + << " __tmp" << tmpvar_counter ++ << ";" + << " /* " << e->base << " idx #" << i << " */"; // now the result parent->o->newline() << parent->c_typename (r->type) - << " __tmp" << tmpvar_counter ++ << ";"; + << " __tmp" << tmpvar_counter ++ << ";" + << " /* " << e->base << "value */"; + + for (unsigned i=0; i<e->indexes.size(); i++) + e->indexes[i]->visit (this); } @@ -1020,16 +1084,9 @@ c_unparser::visit_arrayindex (arrayindex* e) throw semantic_error ("array index type mismatch", e->indexes[i]->tok); unsigned tmpidx = tmpidx_base + i; - if (e->indexes[i]->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << tmp_base << tmpidx; - o->line() << (e->indexes[i]->type == pe_long ? " = " : ", "); - e->indexes[i]->visit (this); - if (e->indexes[i]->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + + c_assign (tmp_base + stringify (tmpidx), + e->indexes[i], "array index copy"); } o->newline() << "if (errorcount)"; @@ -1078,7 +1135,11 @@ c_tmpcounter::visit_functioncall (functioncall *e) for (unsigned i=0; i<r->formal_args.size(); i++) parent->o->newline() << parent->c_typename (r->formal_args[i]->type) - << " __tmp" << tmpvar_counter ++ << ";"; + << " __tmp" << tmpvar_counter ++ << ";" + << " /* " << e->function << " arg #" << i << " */"; + + for (unsigned i=0; i<e->args.size(); i++) + e->args[i]->visit (this); } @@ -1110,17 +1171,9 @@ c_unparser::visit_functioncall (functioncall* e) if (r->formal_args[i]->type != e->args[i]->type) throw semantic_error ("function argument type mismatch", e->args[i]->tok, "vs", r->formal_args[i]->tok); - - if (e->args[i]->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << tmp_base << tmpidx; - o->line() << (e->args[i]->type == pe_long ? " = " : ", "); - e->args[i]->visit (this); - if (e->args[i]->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + + c_assign (tmp_base + stringify(tmpidx), + e->args[i], "function actual argument evaluation"); } o->newline() << "if (c->nesting+2 >= MAXNESTING)"; @@ -1140,19 +1193,14 @@ c_unparser::visit_functioncall (functioncall* e) if (r->formal_args[i]->type != e->args[i]->type) throw semantic_error ("function argument type mismatch", e->args[i]->tok, "vs", r->formal_args[i]->tok); - - if (e->args[i]->type == pe_string) - o->newline() << "strncpy ("; - else - o->newline(); - o->line() << "c->locals[c->nesting+1]" - << ".function_" << c_varname (r->name) - << "." << c_varname (r->formal_args[i]->name); - o->line() << (e->args[i]->type == pe_long ? " = " : ", "); - o->line() << tmp_base << tmpidx; - if (e->args[i]->type == pe_string) - o->line() << ", MAXSTRINGLEN)"; - o->line() << ";"; + + c_assign ("c->locals[c->nesting+1].function_" + + c_varname (r->name) + "." + + c_varname (r->formal_args[i]->name), + tmp_base + stringify (tmpidx), + e->args[i]->type, + "function actual argument copy", + e->args[i]->tok); } // call function |