void zu::postfix_writer::do_if_node(zu::if_node * const node, int lvl) { int lbl1; node->condition()->accept(this, lvl); _pf.JZ(mklbl(lbl1 = ++_lbl)); node->block()->accept(this, lvl + 2); _pf.LABEL(mklbl(lbl1)); }
void simple::postfix_writer::do_while_node(simple::while_node * const node, int lvl) { int lbl1, lbl2; _pf.LABEL(mklbl(lbl1 = ++_lbl)); node->condition()->accept(this, lvl); _pf.JZ(mklbl(lbl2 = ++_lbl)); node->block()->accept(this, lvl + 2); _pf.JMP(mklbl(lbl1)); _pf.LABEL(mklbl(lbl2)); }
// Done void pwn::postfix_writer::do_if_node(cdk::if_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1; node->condition()->accept(this, lvl); _pf.JZ(mklbl(lbl1 = ++_lbl)); node->block()->accept(this, lvl + 2); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1)); }
void zu::postfix_writer::do_double_node(cdk::double_node * const node, int lvl) { _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(++_lbl)); _pf.DOUBLE(node->value()); _pf.TEXT(); _pf.ADDR(mklbl(_lbl)); _pf.DLOAD(); }
void zu::postfix_writer::do_or_node(zu::or_node * const node, int lvl){ int lbl1; CHECK_TYPES(_compiler, _symtab, node); node->left()->accept(this, lvl); _pf.DUP(); // if it is true, then do not eval the next expression _pf.JNZ(mklbl(lbl1 = ++_lbl)); node->right()->accept(this, lvl); _pf.OR(); _pf.LABEL(mklbl(lbl1)); }
void zu::postfix_writer::do_if_else_node(zu::if_else_node * const node, int lvl) { int lbl1, lbl2; node->condition()->accept(this, lvl); _pf.JZ(mklbl(lbl1 = ++_lbl)); node->thenblock()->accept(this, lvl + 2); _pf.JMP(mklbl(lbl2 = ++_lbl)); _pf.LABEL(mklbl(lbl1)); node->elseblock()->accept(this, lvl + 2); _pf.LABEL(mklbl(lbl1 = lbl2)); }
void pwn::postfix_writer::do_or_node(pwn::or_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1; node->left()->accept(this, lvl); _pf.DUP(); _pf.JNZ(mklbl(lbl1 = ++_lbl)); // _pf.TRASH(4); node->right()->accept(this, lvl); _pf.OR(); _pf.LABEL(mklbl(lbl1)); }
void zu::postfix_writer::do_string_node(cdk::string_node * const node, int lvl) { int lbl1; /* generate the string */ _pf.RODATA(); // strings are DATA readonly _pf.ALIGN(); // make sure we are aligned _pf.LABEL(mklbl(lbl1 = ++_lbl)); // give the string a name _pf.STR(node->value()); // output string characters /* leave the address on the stack */ _pf.TEXT(); // return to the TEXT segment _pf.ADDR(mklbl(lbl1)); // the string to be printed }
//NEW NODES void pwn::postfix_writer::do_and_node(pwn::and_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1; node->left()->accept(this, lvl); _pf.INT(1); _pf.AND(); _pf.DUP(); _pf.JZ(mklbl(lbl1 = ++_lbl)); node->left()->accept(this, lvl); node->right()->accept(this, lvl); _pf.AND(); _pf.LABEL(mklbl(lbl1)); }
void pwn::postfix_writer::do_string_node(cdk::string_node * const node, int lvl) { int lbl1; if (_args || !_insidefunc) _pf.STR(node->value()); else { _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1 = ++_lbl)); _pf.STR(node->value()); _pf.TEXT(); _pf.ALIGN(); _pf.ADDR(mklbl(lbl1)); } }
void zu::postfix_writer::do_or_node(zu::or_node * const node, int lvl) { int lbl = ++_lbl; CHECK_TYPES(_compiler, _symtab, node); node->left()->accept(this, lvl+2); _pf.DUP(); _pf.JZ(mklbl(lbl)); node->right()->accept(this, lvl+2); _pf.DUP(); _pf.OR(); _pf.ALIGN(); _pf.LABEL(mklbl(lbl)); }
// Done void pwn::postfix_writer::do_not_node(pwn::not_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1 = ++_lbl; int lbl_end = ++_lbl; node->argument()->accept(this, lvl + 1); _pf.JZ(mklbl(lbl1)); _pf.INT(0); _pf.JMP(mklbl(lbl_end)); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1)); _pf.INT(1); _pf.ALIGN(); _pf.LABEL(mklbl(lbl_end)); }
Node * genlbl(Srcloc loc) { char buf[128]; genlblstr(buf, 128, ""); return mklbl(loc, buf); }
// Done void pwn::postfix_writer::do_and_node(pwn::and_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl0 = ++_lbl; int lbl_end = ++_lbl; node->left()->accept(this, lvl + 1); _pf.JZ(mklbl(lbl0)); node->right()->accept(this, lvl + 1); _pf.JZ(mklbl(lbl0)); _pf.INT(1); _pf.JMP(mklbl(lbl_end)); _pf.ALIGN(); _pf.LABEL(mklbl(lbl0)); _pf.INT(0); _pf.ALIGN(); _pf.LABEL(mklbl(lbl_end)); }
// Done void pwn::postfix_writer::do_double_node(cdk::double_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); if (_current_function) { // local scope _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(++_lbl)); _pf.DOUBLE(node->value()); _pf.TEXT(); _pf.ADDR(mklbl(_lbl)); _pf.DLOAD(); } else { // global scope _pf.ALIGN(); _pf.LABEL(*_current_id); _pf.DOUBLE(node->value()); } }
void pwn::postfix_writer::do_double_node(cdk::double_node * const node, int lvl) { int lbl1; if (!_insidefunc) { _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1 = ++_lbl)); _pf.DOUBLE(node->value()); _pf.TEXT(); _pf.ADDR(mklbl(lbl1)); } else if (_insidefunc && !_args) _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1 = ++_lbl)); _pf.DOUBLE(node->value()); _pf.TEXT(); _pf.ADDR(mklbl(lbl1)); _pf.DLOAD(); }
// Done void pwn::postfix_writer::do_string_node(cdk::string_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1; /* generate the string */ _pf.RODATA(); // strings are DATA readonly _pf.ALIGN(); // make sure we are aligned _pf.LABEL(mklbl(lbl1 = ++_lbl)); // give the string a name _pf.STR(node->value()); // output string characters if (_current_function) { // local scope _pf.TEXT(); // return to the TEXT segment _pf.ADDR(mklbl(lbl1)); // the string to be printed } else { // global scope _pf.ALIGN(); _pf.LABEL(*_current_id); _pf.ID(mklbl(lbl1)); } }
void zu::postfix_writer::do_double_node(cdk::double_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1; if (_am_I_in_function) { //Contexto local _pf.RODATA(); _pf.ALIGN(); _pf.LABEL(mklbl(lbl1 = ++_lbl)); _pf.DOUBLE(node->value()); _pf.TEXT(); _pf.ALIGN(); _pf.ADDR(mklbl(lbl1)); _pf.DLOAD(); } else { //Contexto global _pf.DATA(); _pf.ALIGN(); _pf.LABEL(_id_to_label); _pf.DOUBLE(node->value()); } }
static Bb *addlabel(Cfg *cfg, Bb *bb, Node **nl, size_t i, Srcloc loc) { /* if the current block assumes fall-through, insert an explicit jump */ if (i > 0 && nl[i - 1]->type == Nexpr) { if (exprop(nl[i - 1]) != Ocjmp && exprop(nl[i - 1]) != Ojmp) addnode(cfg, bb, mkexpr(loc, Ojmp, mklbl(loc, lblstr(nl[i])), NULL)); } if (bb->nnl) bb = mkbb(cfg); label(cfg, nl[i], bb); return bb; }
void pwn::postfix_writer::do_identity_node(pwn::identity_node * const node, int lvl) { int lbl1; CHECK_TYPES(_compiler, _symtab, node); node->argument()->accept(this, lvl); // determine the value //TODO check this function if (node->type()->name() == basic_type::TYPE_DOUBLE) { _pf.DDUP(); _pf.DOUBLE(0); _pf.LT(); _pf.JZ(mklbl(lbl1 = ++_lbl)); _pf.DNEG(); _pf.LABEL(mklbl(lbl1)); } if (node->type()->name() == basic_type::TYPE_INT) { _pf.DUP(); _pf.INT(0); _pf.LT(); _pf.JZ(mklbl(lbl1 = ++_lbl)); _pf.NEG(); // 2-complement _pf.LABEL(mklbl(lbl1)); } }
void zu::postfix_writer::do_for_node(zu::for_node * const node, int lvl) { int cond, end, inc; std::string scond = mklbl(cond = ++_lbl); std::string send = mklbl(end = ++_lbl); std::string sinc = mklbl(inc = ++_lbl); _break_labels.push_back(send); _continue_labels.push_back(sinc); if(node->init() != nullptr) node->init()->accept(this, lvl + 2); _pf.ALIGN(); _pf.LABEL(scond); if(node->condition() != nullptr){ node->condition()->accept(this, lvl +2 ); _pf.JZ(send); } node->block()->accept(this, lvl + 2); _pf.ALIGN(); _pf.LABEL(sinc); if(node->increment() != nullptr) node->increment()->accept(this, lvl + 2); _pf.JMP(scond); _pf.ALIGN(); _pf.LABEL(send); _break_labels.pop_back(); _continue_labels.pop_back(); }
// Maybe done - i think it's done but it's untested void pwn::postfix_writer::do_repeat_node(pwn::repeat_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1 = ++_lbl; int lbl2 = ++_lbl; _repeat_increment.push_back(lbl2); int lbl3 = ++_lbl; _repeat_end.push_back(lbl3); if (node->inicializations()) { node->inicializations()->accept(this, lvl); // init repeat } _pf.ALIGN(); _pf.LABEL(mklbl(lbl1)); // condition label node->conditions()->accept(this, lvl); _pf.JZ(mklbl(lbl3)); // jump if condition is false node->block()->accept(this, lvl + 2); _pf.ALIGN(); _pf.LABEL(mklbl(lbl2)); // increment label node->updates()->accept(this, lvl); _pf.JMP(mklbl(lbl1)); // go to condition label _pf.ALIGN(); _pf.LABEL(mklbl(lbl3)); // end cycle _repeat_increment.pop_back(); _repeat_end.pop_back(); }
void pwn::postfix_writer::do_stop_node(pwn::stop_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); unsigned int n = node->value(); int lbl; if (n > _repeat_end.size()) { throw std::string("Error: there are not enough active cycles"); } for (unsigned int i = 0; i < n; i++) { lbl = _repeat_end.back(); _repeat_increment.pop_back(); _repeat_end.pop_back(); } _pf.JMP(mklbl(lbl)); }
void pwn::postfix_writer::do_repeat_node(pwn::repeat_node * const node, int lvl) { int condition = ++_lbl; int increment = ++_lbl; int end = ++_lbl; _symtab.push(); _stack.push_back(mklbl(end)); _stack.push_back(mklbl(increment)); node->init()->accept(this, lvl); _pf.LABEL(mklbl(condition)); node->condition()->accept(this, lvl); _pf.JZ(mklbl(end)); node->block()->accept(this, lvl); _pf.LABEL(mklbl(increment)); node->incr()->accept(this, lvl); _pf.JMP(mklbl(condition)); _pf.LABEL(mklbl(end)); _stack.pop_back(); _stack.pop_back(); _symtab.pop(); }
void zu::postfix_writer::do_for_node(zu::for_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); int lbl1, lbl2, lbl3; if(node->init() != nullptr) node->init()->accept(this, lvl); _pf.LABEL(mklbl(lbl1 = ++_lbl)); if(node->cond() != nullptr) node->cond()->accept(this, lvl); else (new cdk::integer_node(lvl, 1))->accept(this, lvl); _pf.JZ(mklbl(lbl2 = ++_lbl)); _break_lbls.push_back(mklbl(lbl2)); _continue_lbls.push_back(mklbl(lbl3 = ++_lbl)); node->block()->accept(this, lvl + 2); _pf.LABEL(mklbl(lbl3)); if(node->incr() != nullptr) node->incr()->accept(this, lvl); _pf.JMP(mklbl(lbl1)); _pf.LABEL(mklbl(lbl2)); }
void pwn::postfix_writer::do_return_node(pwn::return_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); _pf.JMP(mklbl(_current_function_end)); }
void zu::postfix_writer::do_return_node(zu::return_node * const node, int lvl){ _pf.JMP(mklbl(_lbl_return)); }
void zu::postfix_writer::do_function_definition_node(zu::function_definition_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); std::string name = ""; if(*(node->identifier()->identifier()) == "zu") name = "_main"; else if(*(node->identifier()->identifier()) == "_main") name = "zu"; else name = *(node->identifier()->identifier()); delete_extern(name); //only removes if it exists // generate the main function (RTS mandates that its name be "_main") _pf.TEXT(); _pf.ALIGN(); if(node->visibility()) _pf.GLOBAL("_main", _pf.FUNC()); _pf.LABEL(name); declarations_counter dc(_compiler, _symtab, _pf); node->accept(&dc, lvl); size_t declars_size = dc.get_size(); size_t retsize = 0; if(node->return_type() != nullptr) retsize = node->return_type()->size(); _pf.ENTER(declars_size); _max_offset = declars_size ; _am_I_in_function = true; if(node->literal() != nullptr){ node->literal()->accept(this, lvl+2); _pf.LOCA(-retsize); } _symtab.push(); //args _arg_offset = 8; if(node->args() != nullptr){ _is_arg = true; node->args()->accept(this, lvl+2); _is_arg = false; } mklbl(_lbl_return = ++_lbl); node->body()->accept(this, lvl); _pf.LABEL(mklbl(_lbl_return)); // end of function if(node->return_type() != nullptr){ _pf.LOCAL(-retsize); //tirar o tipo de retorno (tamanho) if(node->return_type()->name() != basic_type::TYPE_DOUBLE){ _pf.LOAD(); _pf.POP(); }else{ // doubles _pf.DLOAD(); _pf.DPOP(); } } _pf.LEAVE(); _pf.RET(); _max_offset = 0; _am_I_in_function = false; _arg_offset = 8; _symtab.pop(); //args }
void pwn::postfix_writer::do_function_definition_node(pwn::function_definition_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); _current_function_end = ++_lbl; _pf.TEXT(); _pf.ALIGN(); std::string name = fix_id(node->name()); // is global ? if ( ! node->is_local()) { _pf.GLOBAL(name, _pf.FUNC()); } _pf.LABEL(name); // find space needed for local variables pwn::enter_size *visitor = new pwn::enter_size(_compiler); node->accept(visitor, 0); int size = visitor->size(); delete visitor; // reserve memory _pf.ENTER(size); // set current function _current_function = _symtab.find_local(node->name()); // create new context _symtab.push(); if (node->arguments()) { _current_offset = 8; // function arguments offset node->arguments()->accept(this, lvl + 1); } _current_offset = 0; // local variables offset // reserve space for return variable int return_size = 0; if (is_int(node->return_type()) || is_string(node->return_type()) || is_pointer(node->return_type())) { return_size = 4; // int, string, pointer } else if (is_double(node->return_type())) { return_size = 8; // double } _current_offset -= return_size; // handle default return value if (node->return_default()) { node->return_default()->accept(this, lvl + 1); if (return_size == 4) { _pf.LOCA(-4); } else if (return_size == 8) { _pf.LOCAL(-8); _pf.DSTORE(); } } else { // if no return default is specified, return 0 if int or pointer _pf.INT(0); _pf.LOCA(-4); } // function body node->block()->accept(this, lvl); _pf.ALIGN(); _pf.LABEL(mklbl(_current_function_end)); // put return value in eax if (return_size == 4) { // int string pointer _pf.LOCV(-4); _pf.POP(); } else if (return_size == 8) { // double _pf.LOCAL(-8); _pf.DLOAD(); _pf.DPOP(); } // return from function _pf.LEAVE(); _pf.RET(); // leave local context _symtab.pop(); _current_function = nullptr; // add this function to defined functions list _defined_functions.push_back(new std::string(name)); }
static void eval(Node *p) { int i, lbl1, lbl2; char *name; if (p == 0) return; switch(p->attrib) { case INTEGER: fprintf(out, pfIMM, p->value.i); /* push an integer immediate */ break; case STRING: /* generate the string */ fprintf(out, pfRODATA); /* strings are DATA readonly */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); /* name the string */ fprintf(out, pfSTR, p->value.s); /* output string characters */ /* make the call */ fprintf(out, pfTEXT); /* return to the TEXT segment */ fprintf(out, pfADDR, mklbl(lbl1)); /* the string to be printed */ fprintf(out, pfCALL, "_prints"); /* call the print rotine */ fprintf(out, pfCALL, "_println"); /* print a newline */ fprintf(out, pfTRASH, sizeof(regint)); /* remove the string address: 4/8 bytes */ break; case VARIABLE: if (IDfind(p->value.s, 0) >= 0) { fprintf(out, pfADDR, p->value.s); fprintf(out, pfLOAD); } break; case WHILE: fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); eval(p->SUB(0)); fprintf(out, pfJZ, mklbl(lbl2 = ++lbl)); eval(p->SUB(1)); fprintf(out, pfJMP, mklbl(lbl1)); fprintf(out, pfLABEL, mklbl(lbl2)); break; case IF: eval(p->SUB(0)); fprintf(out, pfJZ, mklbl(lbl1 = ++lbl)); eval(p->SUB(1)); if (p->value.sub.num > 2) { /* if else */ fprintf(out, pfJMP, mklbl(lbl2 = ++lbl)); fprintf(out, pfLABEL, mklbl(lbl1)); eval(p->SUB(2)); lbl1 = lbl2; } fprintf(out, pfLABEL, mklbl(lbl1)); break; case READ: if (IDfind(p->value.s, 0) >= 0) { fprintf(out, pfCALL, "_readi"); fprintf(out, pfPUSH); fprintf(out, pfADDR, p->value.s); fprintf(out, pfSTORE); } break; case PRINT: eval(p->SUB(0)); /* determine the value */ fprintf(out, pfCALL, "_printi"); /* call the print function */ fprintf(out, pfCALL, "_println"); /* print a newline */ fprintf(out, pfTRASH, sizeof(regint)); /* remove the printed value: 4/8 bytes */ break; case ';': for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case '=': name = p->SUB(0)->value.s; if (IDfind(name, (int*)IDtest) == -1) { /* variable not found ? */ fprintf(out, pfDATA); /* variables are DATA */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfLABEL, name); /* name variable location */ #ifdef _64bits_ fprintf(out, pfLONG, 0LL); /* initialize it to 0 (zero) */ #else fprintf(out, pfINTEGER, 0); /* initialize it to 0 (zero) */ #endif fprintf(out, pfTEXT); /* return to the TEXT segment */ IDnew(INTEGER, name, 0); /* put in the symbol table */ } eval(p->SUB(1)); /* determine the new value */ fprintf(out, pfADDR, name); /* where to store the value */ fprintf(out, pfSTORE); /* store the value at address */ break; case UMINUS: eval(p->SUB(0)); /* determine the value */ fprintf(out, pfNEG); /* make the 2-compliment */ break; default: eval(p->SUB(0)); /* evaluate first argument */ eval(p->SUB(1)); /* evaluate second argument */ switch(p->attrib) { /* make the operation ... */ case '+': fprintf(out, pfADD); break; case '-': fprintf(out, pfSUB); break; case '*': fprintf(out, pfMUL); break; case '/': fprintf(out, pfDIV); break; case '%': fprintf(out, pfMOD); break; case '<': fprintf(out, pfLT); break; case '>': fprintf(out, pfGT); break; case GE: fprintf(out, pfGE); break; case LE: fprintf(out, pfLE); break; case NE: fprintf(out, pfNE); break; case EQ: fprintf(out, pfEQ); break; default: printf("unknown %d\n", p->attrib); } } }