diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 0b4127e12..0b1e0bc62 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -71,8 +71,10 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_ statement->b = var_b ? var_b->ofs : 0; if (op->type_c == ev_void || op->right_associative) { // ifs, gotos, and assignments don't need vars allocated - var_c = NULL; - statement->c = 0; + if (op->type_c == ev_void) { + var_c = NULL; + statement->c = 0; + } ret = var_a; } else { // allocate result space if (!var_c) { @@ -154,7 +156,7 @@ emit_function_call (expr_t *e, def_t *dest) def_t * emit_assign_expr (expr_t *e) { - def_t *def_a, *def_b; + def_t *def_a, *def_b, *def_c; opcode_t *op; expr_t *e1 = e->e.expr.e1; expr_t *e2 = e->e.expr.e2; @@ -163,30 +165,40 @@ emit_assign_expr (expr_t *e) e1->e.temp.users--; return 0; } - def_a = emit_sub_expr (e1, 0); - if (def_a->type->type == ev_pointer) { - def_b = emit_sub_expr (e2, 0); - op = PR_Opcode_Find ("=", def_b, def_a, &def_void); - emit_statement (e->line, op, def_b, def_a, 0); + if (e1->type == ex_expr && e1->e.expr.op == '.' + && extract_type (e1->e.expr.e1) == ev_pointer) { + def_a = emit_sub_expr (e2, 0); + def_c = emit_sub_expr (e1->e.expr.e2, 0); + def_b = emit_sub_expr (e1->e.expr.e1, 0); + op = PR_Opcode_Find ("=", def_a, def_b, def_c); + emit_statement (e->line, op, def_a, def_b, def_c); } else { - if (def_a->constant) { - if (options.code.cow) { - int size = pr_type_size [def_a->type->type]; - int ofs = PR_NewLocation (def_a->type); - - memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size); - def_a->ofs = ofs; - def_a->constant = 0; - if (options.warnings.cow) - warning (e1, "assignment to constant %s (Moooooooo!)", def_a->name); - } else { - error (e1, "assignment to constant %s", def_a->name); - } - } - def_b = emit_sub_expr (e2, def_a); - if (def_b != def_a) { + def_a = emit_sub_expr (e1, 0); + if (def_a->type->type == ev_pointer) { + def_b = emit_sub_expr (e2, 0); op = PR_Opcode_Find ("=", def_b, def_a, &def_void); emit_statement (e->line, op, def_b, def_a, 0); + } else { + if (def_a->constant) { + if (options.code.cow) { + int size = pr_type_size [def_a->type->type]; + int ofs = PR_NewLocation (def_a->type); + + memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size); + def_a->ofs = ofs; + def_a->constant = 0; + if (options.warnings.cow) + warning (e1, "assignment to constant %s (Moooooooo!)", + def_a->name); + } else { + error (e1, "assignment to constant %s", def_a->name); + } + } + def_b = emit_sub_expr (e2, def_a); + if (def_b != def_a) { + op = PR_Opcode_Find ("=", def_b, def_a, &def_void); + emit_statement (e->line, op, def_b, def_a, 0); + } } } if (def_a->type->type != ev_pointer) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 024f984aa..4feb91c4f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -988,14 +988,13 @@ type_mismatch: type = &type_float; } if (op == '=' && e1->type == ex_expr && e1->e.expr.op == '.') { - if (t1 == &type_entity) { + if (get_type(e1->e.expr.e1) == &type_entity) { type_t new; memset (&new, 0, sizeof (new)); new.type = ev_pointer; type = new.aux_type = e1->e.expr.type; e1->e.expr.type = PR_FindType (&new); - } else { } } if (!type) diff --git a/tools/qfcc/source/pr_opcode.c b/tools/qfcc/source/pr_opcode.c index 09f7c3db7..80c5b30a4 100644 --- a/tools/qfcc/source/pr_opcode.c +++ b/tools/qfcc/source/pr_opcode.c @@ -117,10 +117,7 @@ PR_Opcode_Find (const char *name, def_t *var_a, def_t *var_b, def_t *var_c) op.type_a = var_a->type->type; op.type_b = var_b->type->type; op.type_c = var_c->type->type; - if (op.type_c == ev_void) - tab = &opcode_type_table_ab; - else - tab = &opcode_type_table_abc; + tab = &opcode_type_table_abc; } else if (var_a && var_b) { op.type_a = var_a->type->type; op.type_b = var_b->type->type;