void c_mod() { CHECK_TYPES(sp - 1, T_NUMBER, 1, F_MOD); CHECK_TYPES(sp, T_NUMBER, 2, F_MOD); if ((sp--)->u.number == 0) error("Modulus by zero.\n"); sp->u.number %= (sp+1)->u.number; }
void zu::postfix_writer::do_zuidentifier_node(zu::zuidentifier_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->accept(this,lvl); CHECK_TYPES(_compiler, _symtab, node); // simplified generation: all variables are global _pf.ADDR(node->id()); }
void c_foreach P3(int, flags, int, idx1, int, idx2) { IF_DEBUG(stack_in_use_as_temporary++); if (flags & 4) { CHECK_TYPES(sp, T_MAPPING, 2, F_FOREACH); push_refed_array(mapping_indices(sp->u.map)); (++sp)->type = T_NUMBER; sp->u.lvalue = (sp-1)->u.arr->item; sp->subtype = (sp-1)->u.arr->size; (++sp)->type = T_LVALUE; if (flags & 2) sp->u.lvalue = ¤t_object->variables[idx1 + variable_index_offset]; else sp->u.lvalue = fp + idx1; } else if (sp->type == T_STRING) { (++sp)->type = T_NUMBER; sp->u.lvalue_byte = (unsigned char *)((sp-1)->u.string); sp->subtype = SVALUE_STRLEN(sp - 1); } else { CHECK_TYPES(sp, T_ARRAY, 2, F_FOREACH); (++sp)->type = T_NUMBER; sp->u.lvalue = (sp-1)->u.arr->item; sp->subtype = (sp-1)->u.arr->size; } (++sp)->type = T_LVALUE; if (flags & 1) sp->u.lvalue = ¤t_object->variables[idx2 + variable_index_offset]; else sp->u.lvalue = fp + idx2; }
void c_foreach(int flags, int idx1, int idx2) { IF_DEBUG(stack_in_use_as_temporary++); if (flags & FOREACH_MAPPING) { CHECK_TYPES(sp, T_MAPPING, 2, F_FOREACH); push_refed_array(mapping_indices(sp->u.map)); STACK_INC; sp->type = T_NUMBER; sp->u.lvalue = (sp-1)->u.arr->item; sp->subtype = (sp-1)->u.arr->size; STACK_INC; sp->type = T_LVALUE; if (flags & FOREACH_LEFT_GLOBAL) { sp->u.lvalue = ¤t_object->variables[idx1 + variable_index_offset]; } else { sp->u.lvalue = fp + idx1; } } else if (sp->type == T_STRING) { STACK_INC; sp->type = T_NUMBER; sp->u.lvalue_byte = (unsigned char *)((sp-1)->u.string); sp->subtype = SVALUE_STRLEN(sp - 1); } else { CHECK_TYPES(sp, T_ARRAY, 2, F_FOREACH); STACK_INC; sp->type = T_NUMBER; sp->u.lvalue = (sp-1)->u.arr->item; sp->subtype = (sp-1)->u.arr->size; } if (flags & FOREACH_RIGHT_GLOBAL) { STACK_INC; sp->type = T_LVALUE; sp->u.lvalue = ¤t_object->variables[idx2 + variable_index_offset]; } else if (flags & FOREACH_REF) { ref_t *ref = make_ref(); svalue_t *loc = fp + idx2; /* foreach guarantees our target remains valid */ ref->lvalue = 0; ref->sv.type = T_NUMBER; STACK_INC; sp->type = T_REF; sp->u.ref = ref; DEBUG_CHECK(loc->type != T_NUMBER && loc->type != T_REF, "Somehow a reference in foreach acquired a value before coming into scope"); loc->type = T_REF; loc->u.ref = ref; ref->ref++; } else { STACK_INC; sp->type = T_LVALUE; sp->u.lvalue = fp + idx2; } }
void c_parse_command(int num_arg) { svalue_t *arg; svalue_t *fp; int i; /* * type checking on first three required parameters to parse_command() */ arg = sp - 2; CHECK_TYPES(&arg[0], T_STRING, 1, F_PARSE_COMMAND); CHECK_TYPES(&arg[1], T_OBJECT | T_ARRAY, 2, F_PARSE_COMMAND); CHECK_TYPES(&arg[2], T_STRING, 3, F_PARSE_COMMAND); /* * allocate stack frame for rvalues and return value (number of matches); * perform some stack manipulation; */ fp = sp; CHECK_STACK_OVERFLOW(num_arg + 1); sp += num_arg + 1; arg = sp; *(arg--) = *(fp--); /* move pattern to top of stack */ *(arg--) = *(fp--); /* move source object or array to just below the pattern */ *(arg) = *(fp); /* move source string just below the object */ fp->type = T_NUMBER; /* * prep area for rvalues */ for (i = 1; i <= num_arg; i++) fp[i].type = T_INVALID; /* * do it... */ i = parse(arg[0].u.string, &arg[1], arg[2].u.string, &fp[1], num_arg); /* * remove mandatory parameters */ pop_3_elems(); /* * save return value on stack */ fp->u.number = i; }
void pwn::postfix_writer::do_simple_lvalue_node(pwn::simple_lvalue_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); std::string id = fix_id(node->value()); std::shared_ptr<pwn::symbol> symbol = _symtab.find(id); if ( ! _current_function) { // global context if ( ! symbol->is_var()) { throw "Error: assigning a value to a function"; } _pf.ADDR(id); } else { // local context bool is_return_symbol = ( ! symbol->is_var()) // the symbol is a function && (_current_function->name() == symbol->name()) // the symbol has the same name as the current function && ( ! is_void(_current_function->type())); // the function doesnt "return" void if (is_return_symbol) { if (is_double(_current_function->type())) { _pf.LOCAL(-8); // double @ -8 } else { _pf.LOCAL(-4); // int, string, pointer @ -4 } } else if (symbol->is_var() && symbol->name() != _current_function->name()) { _pf.LOCAL(symbol->offset()); } else { throw "Error: invalid left value"; } } }
void pwn::postfix_writer::do_add_node(cdk::add_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); if (is_pointer(node->type())) { if (is_int(node->left()->type())) { node->right()->accept(this, lvl + 1); // load the pointer node->left()->accept(this, lvl + 1); // load the shift } else { node->left()->accept(this, lvl + 1); // load the pointer node->right()->accept(this, lvl + 1); // load the shift } _pf.INT(4); // pointer size _pf.MUL(); // pointer arithmetics shift calculation _pf.ADD(); return; } node->left()->accept(this, lvl); if (is_double(node->type()) && is_int(node->left()->type())) { _pf.I2D(); } node->right()->accept(this, lvl); if (is_double(node->type()) && is_int(node->right()->type())) { _pf.I2D(); } if (is_int(node->type())) { _pf.ADD(); } else if (is_double(node->type())) { _pf.DADD(); } }
void zu::postfix_writer::do_var_declaration_node(zu::var_declaration_node * const node, int lvl){ CHECK_TYPES(_compiler, _symtab, node); std::string identifier = *(node->identifier()->identifier()); std::shared_ptr<zu::symbol> symbol = _symtab.find(identifier); if(node->ext()){ _pf.EXTERN(identifier); }else if(!_am_I_in_function){ if(node->visibility()){ _pf.GLOBAL(identifier, _pf.OBJ()); symbol->is_global(true); } _pf.BSS(); _pf.ALIGN(); _pf.LABEL(identifier); _pf.BYTE(node->type()->size()); _pf.TEXT(); _pf.ALIGN(); }else{ if(_is_arg){ symbol->offset(_arg_offset); _arg_offset += symbol->type()->size(); symbol->is_global(false); }else { symbol->offset(-_max_offset); _max_offset -= symbol->type()->size(); symbol->is_global(false); } } }
void zu::postfix_writer::do_div_node(cdk::div_node * const node, int lvl) { //debug(node, lvl); CHECK_TYPES(_compiler, _symtab, node); node->left()->accept(this, lvl+2); node->right()->accept(this, lvl+2); _pf.DIV(); }
void zu::postfix_writer::do_functioninvocation_node(zu::functioninvocation_node * const node, int lvl) { CHECK_TYPES(_compiler,_symtab,node); int remove_bits = 0; if(node->args() != NULL){ for(size_t i = 0; i < node->args()->size(); i++){ node->args()->node(i)->accept(this, lvl+2); remove_bits +=((cdk::expression_node *) node->args()->node(i))->type()->size(); } } _pf.CALL(node->identifier()->name()); _pf.TRASH(remove_bits); //find symbol of function to call std::shared_ptr<zu::symbol> sym = _symtab.find(node->identifier()->name()); if(sym == nullptr) std::cerr << "ERROR: function '"<< node->identifier()->name() <<"' not found " << std::endl; if(sym->type()->name() == basic_type::TYPE_POINTER || sym->type()->name() == basic_type::TYPE_INT || sym->type()->name() == basic_type::TYPE_STRING) _pf.PUSH(); else _pf.DPUSH(); }
void pwn::postfix_writer::do_print_node(pwn::print_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->argument()->accept(this, lvl); // determine the value to print if (is_int(node->argument()->type())) { _pf.CALL("printi"); _pf.TRASH(4); // delete the printed value std::string *f_name = new std::string("printi"); _declared_functions.push_back(f_name); _called_functions.push_back(f_name); } else if (is_string(node->argument()->type())) { _pf.CALL("prints"); _pf.TRASH(4); // delete the printed value's address std::string *f_name = new std::string("prints"); _declared_functions.push_back(f_name); _called_functions.push_back(f_name); } else if (is_double(node->argument()->type())) { _pf.CALL("printd"); _pf.TRASH(8); // delete double printed value std::string *f_name = new std::string("printd"); _declared_functions.push_back(f_name); _called_functions.push_back(f_name); } else { std::cerr << "ERROR: Trying to print invalid type." << std::endl; exit(1); } if (node->new_line()) { _pf.CALL("println"); // print a newline std::string *f_name = new std::string("println"); _declared_functions.push_back(f_name); _called_functions.push_back(f_name); } }
void zu::postfix_writer::do_and_node(zu::and_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->left()->accept(this, lvl); node->right()->accept(this, lvl); _pf.AND(); }
void zu::postfix_writer::do_lvalue_node(zu::lvalue_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); // simplified generation: all variables are global //_pf.ADDR(node->value()); LVALUE CHANGES }
void zu::postfix_writer::do_print_node(zu::print_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->argument()->accept(this, lvl); // determine the value to print if (node->argument()->type()->name() == basic_type::TYPE_INT) { _pf.EXTERN("printi"); _pf.CALL("printi"); _pf.TRASH(4); // delete the printed value } if (node->argument()->type()->name() == basic_type::TYPE_STRING) { _pf.EXTERN("prints"); _pf.CALL("prints"); _pf.TRASH(4); // delete the printed value's address } if (node->argument()->type()->name() == basic_type::TYPE_DOUBLE) { _pf.EXTERN("printd"); _pf.CALL("printd"); _pf.TRASH(8); // delete the printed value's address } /*else { std::cerr << "ERROR: CANNOT HAPPEN!" << std::endl; exit(1); }*/ if (node->nl()){ _pf.EXTERN("println"); _pf.CALL("println"); // print a newline } }
void zu::postfix_writer::do_read_node(zu::read_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); _pf.CALL("readi"); _pf.PUSH(); node->accept(this, lvl); _pf.STORE(); }
void zu::xml_writer::do_println_node(zu::println_node * const node, int lvl) { // FIXME CHECK_TYPES(_compiler, _symtab, node); openTag(node, lvl); node->argument()->accept(this, lvl + 2); closeTag(node, lvl); }
void pwn::postfix_writer::do_function_declaration_node(pwn::function_declaration_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); std::string id = fix_id(node->name()); // add this function to declared functions _declared_functions.push_back(new std::string(id)); }
void pwn::postfix_writer::do_function_call_node(pwn::function_call_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); std::string id = fix_id(node->name()); std::shared_ptr<pwn::symbol> symbol = _symtab.find(id); // put arguments in stack (reverse order) int args_size = 0; if (node->arguments()) { for (int i = node->arguments()->size() - 1; i >= 0; i--) { node->arguments()->node(i)->accept(this, lvl); args_size += ((cdk::expression_node *) node->arguments()->node(i))->type()->size(); } } // call function _pf.CALL(id); // remove arguments from stack _pf.TRASH(args_size); // put return value in the stack if (is_int(symbol->type()) || is_pointer(symbol->type()) || is_string(symbol->type())) { _pf.PUSH(); } else if (is_double(symbol->type())) { _pf.DPUSH(); } // add this function to called functions _called_functions.push_back(new std::string(id)); }
void zu::postfix_writer::do_assignment_node(zu::assignment_node * const node, int lvl) { //debug(node, lvl); CHECK_TYPES(_compiler, _symtab, node); /* // DAVID: horrible hack! // (this is caused by Zu not having explicit variable declarations) const std::string &id = node->lvalue()->value(); std::shared_ptr<zu::symbol> symbol = _symtab.find(id); if (symbol->value() == -1) { _pf.DATA(); // variables are all global and live in DATA _pf.ALIGN(); // make sure we are aligned //_pf.LABEL(id); // name variable location _pf.CONST(0); // initialize it to 0 (zero) _pf.TEXT(); // return to the TEXT segment symbol->value(0); }*/ node->rvalue()->accept(this, lvl+2); // determine the new value if(node->rvalue()->type()->name() == basic_type::TYPE_DOUBLE) _pf.DDUP(); else _pf.DUP(); node->lvalue()->accept(this, lvl+2); // where to store the value if(node->rvalue()->type()->name() == basic_type::TYPE_DOUBLE){ _pf.DSTORE(); }else{ _pf.STORE(); // store the value at address } }
void zu::postfix_writer::do_rvalue_node(zu::rvalue_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->lvalue()->accept(this, lvl); if(node->lvalue()->type()->name() == basic_type::TYPE_DOUBLE) _pf.DLOAD(); else _pf.LOAD(); }
void zu::postfix_writer::do_mem_alloc_node(zu::mem_alloc_node * const node, int lvl){ CHECK_TYPES(_compiler, _symtab, node); node->total_elements()->accept(this, lvl + 2); _pf.INT(4); // size of integer _pf.MUL(); // size of integer * #posicoes _pf.ALLOC(); _pf.SP(); }
void pwn::postfix_writer::do_assignment_node(pwn::assignment_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->rvalue()->accept(this, lvl); // determine the new value _pf.DUP(); node->lvalue()->accept(this, lvl); // where to store the value _pf.STORE(); // store the value at address }
void pwn::postfix_writer::do_neg_node(cdk::neg_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->argument()->accept(this, lvl); // determine the value if (node->type()->name() == basic_type::TYPE_DOUBLE) _pf.DNEG(); if (node->type()->name() == basic_type::TYPE_INT) _pf.NEG(); // 2-complement }
void pwn::postfix_writer::do_index_node(pwn::index_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->expression()->accept(this, lvl); // get base address _pf.INT(node->shift()); _pf.INT(8); // size of double _pf.MUL(); _pf.ADD(); }
inline void zu::xml_writer::processBinaryExpression(cdk::binary_expression_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); openTag(node, lvl); if(node->left() != nullptr) node->left()->accept(this, lvl + 2); if(node->right() != nullptr) node->right()->accept(this, lvl + 2); closeTag(node, lvl); }
// Done void pwn::postfix_writer::do_block_node(pwn::block_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); _symtab.push(); if (node->declarations()) node->declarations()->accept(this, lvl); if (node->statements()) node->statements()->accept(this, lvl); _symtab.pop(); }
void zu::xml_writer::do_assignment_node(zu::assignment_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); openTag(node, lvl); node->lvalue()->accept(this, lvl + 2); openTag("rvalue", lvl + 2); node->rvalue()->accept(this, lvl + 4); closeTag("rvalue", lvl + 2); closeTag(node, lvl); }
void pwn::postfix_writer::do_memory_allocation_node(pwn::memory_allocation_node * const node, int lvl) { CHECK_TYPES(_compiler, _symtab, node); node->size()->accept(this, lvl); // get number of doubles to alloc _pf.INT(8); // size of double _pf.MUL(); _pf.ALLOC(); _pf.SP(); // leaves the stack pointer - address of array }
void zu::xml_writer::do_mem_alloc_node(zu::mem_alloc_node * const node, int lvl){ // FIXME CHECK_TYPES(_compiler, _symtab, node); openTag(node, lvl); openTag("total_elements", lvl + 2); node->total_elements()->accept(this, lvl + 4); closeTag("total_elements", lvl + 2); closeTag(node, lvl); }
// 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)); }