static void gen_expr(tree *expr) { struct variable *var; switch(expr->tag) { case node_arg: var = get_global(ARG_NAME(expr)); codegen_load_file(expr, var); break; case node_call: analyze_call(expr, true, codegen_size); break; case node_constant: LOAD_CONSTANT(expr->value.constant, codegen_size); break; case node_symbol: var = get_global(SYM_NAME(expr)); if (var->tag == sym_const) { LOAD_CONSTANT(var->value, codegen_size); } else { codegen_load_file(expr, var); } break; case node_unop: gen_unop_expr(expr); break; case node_binop: if (expr->value.binop.op == op_assign) { analyze_error(expr, "assign operator = should be equal operator =="); } else if ((expr->value.binop.op == op_lsh) || (expr->value.binop.op == op_rsh)) { /* for shifts it is best to calculate the left side first */ gen_binop_expr(expr->value.binop.op, expr->value.binop.p1, expr->value.binop.p0); } else { /* for all others calculate the right side first */ gen_binop_expr(expr->value.binop.op, expr->value.binop.p0, expr->value.binop.p1); } break; default: assert(0); } }
static void gen_binop_expr(enum node_op op, tree *p0, tree *p1) { char *reg1 = NULL; char *reg2 = NULL; struct variable *var; gen_expr(p1); if (p0->tag == node_call) { reg1 = codegen_get_temp(codegen_size); STORE_FILE(reg1, codegen_size, 0, false); analyze_call(p0, true, codegen_size); CODEGEN(op, codegen_size, false, 0, reg1); } else if (p0->tag == node_constant) { CODEGEN(op, codegen_size, true, p0->value.constant, NULL); } else if (p0->tag == node_symbol) { var = get_global(SYM_NAME(p0)); if (var->tag == sym_const) { CODEGEN(op, codegen_size, true, var->value, NULL); } else if (SYM_OFST(p0)) { /* it is a complex expression, so save temp data */ reg1 = codegen_get_temp(codegen_size); reg2 = codegen_get_temp(codegen_size); STORE_FILE(reg1, codegen_size, 0, false); codegen_load_file(p0, var); STORE_FILE(reg2, codegen_size, 0, false); LOAD_FILE(reg1, codegen_size, 0, false); CODEGEN(op, codegen_size, false, 0, reg2); } else { CODEGEN(op, codegen_size, false, 0, var->name); } } else { /* it is a complex expression so save temp data */ reg1 = codegen_get_temp(codegen_size); STORE_FILE(reg1, codegen_size, 0, false); gen_expr(p0); CODEGEN(op, codegen_size, false, 0, reg1); } if (reg1) free(reg1); if (reg2) free(reg2); }
static void analyze_expr(short priority, short op_main) { short op, op_curr, op_not; short prio; short nparam; inc_level(); op_curr = op_main; op_not = RS_NONE; nparam = (op_main == RS_NONE || op_main == RS_UNARY) ? 0 : 1; if (PATTERN_is(*current, RS_NEW)) THROW("Cannot use NEW operator there"); READ_OPERAND: //analyze_expr_check_first(op_curr); analyze_single(op_curr); nparam++; if (nparam > MAX_PARAM_OP) THROW("Expression too complex. Too many operands"); READ_OPERATOR: if (!PATTERN_is_reserved(*current)) goto OPERATOR_END; op = PATTERN_index(*current); if (!RES_is_operator(op)) goto OPERATOR_END; if (op == RS_AND || op == RS_OR) if (PATTERN_is(current[1], RS_IF)) goto OPERATOR_END; current++; if (op == RS_NOT && PATTERN_is_reserved(*current)) { op_not = PATTERN_index(*current); if (RES_is_operator(op_not) && RES_can_have_not_before(op_not)) { op = op_not + 1; current++; } } if (priority) prio = priority; else if (op_curr == RS_NONE) prio = 0; else prio = RES_priority(op_curr); if (op_curr == RS_NONE) { if (RES_is_binary(op) || RES_is_n_ary(op)) { op_curr = op; goto READ_OPERAND; } } if (op_curr == op) { if (!(RES_is_binary(op) && nparam == 2)) goto READ_OPERAND; } if (RES_priority(op) > prio) { if (op == RS_LSQR) analyze_array(); else if (op == RS_LBRA) analyze_call(); else analyze_expr(RES_priority(op), op); goto READ_OPERATOR; } if (RES_priority(op) == prio) { add_operator(op_curr, nparam); if (op == RS_LSQR) { analyze_array(); goto READ_OPERATOR; } else if (op == RS_LBRA) { analyze_call(); goto READ_OPERATOR; } else { if (RES_is_only(op_curr) || RES_is_only(op)) THROW("Ambiguous expression. Please use brackets"); nparam = 1; op_curr = op; goto READ_OPERAND; } } if (RES_priority(op) < prio) { if ((op_main != RS_NONE) || (priority > 0)) { add_operator(op_curr, nparam); current--; if (op_not != RS_NONE) current--; goto END; } add_operator(op_curr, nparam); if (op == RS_LSQR) { analyze_array(); nparam = 1; op_curr = op_main; goto READ_OPERATOR; } else if (op == RS_LBRA) { analyze_call(); nparam = 1; op_curr = op_main; goto READ_OPERATOR; } else { nparam = 1; op_curr = op; goto READ_OPERAND; } } dec_level(); return; OPERATOR_END: add_operator(op_curr, nparam); END: dec_level(); return; }