From 7bb6dd71978ab412330029dde1a69d72a3548b3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Oct 2002 02:35:12 +0000 Subject: [PATCH] make chained structure assignments (mostly) work. found a bug in the handling of pointer immediates which needs fixing before this will work in general --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/emit.c | 29 +++++++++++++++++++++++------ tools/qfcc/source/expr.c | 19 +++++++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 1a289a56a..83c987315 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -153,6 +153,7 @@ expr_t *new_short_expr (short short_val); expr_t *new_bind_expr (expr_t *e1, expr_t *e2); expr_t *new_self_expr (void); expr_t *new_this_expr (void); +expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type); void inc_users (expr_t *e); void convert_name (expr_t *e); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index af56d5590..1780d183f 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -324,19 +324,32 @@ emit_move_expr (expr_t *e) { expr_t *e1 = e->e.expr.e1; expr_t *e2 = e->e.expr.e2; + expr_t *size_expr; def_t *size, *src, *dst; - type_t *type; + type_t *src_type, *dst_type; opcode_t *op; + dst_type = get_type (e1); + src_type = get_type (e2); src = emit_sub_expr (e2, 0); dst = emit_sub_expr (e1, 0); - type = get_type (e1); - - if (type->type == ev_struct) { - size = emit_sub_expr (new_short_expr (type_size (dst->type)), 0); + + if (dst_type->type == ev_struct && src_type->type == ev_struct) { + printf("%s:%d\n", src->name, src->ofs); + size_expr = new_short_expr (type_size (dst->type)); + } else if (dst_type->type == ev_struct) { + dst = emit_sub_expr (address_expr (new_def_expr (dst), 0, 0), 0); + size_expr = new_integer_expr (type_size (dst_type)); + } else if (src_type->type == ev_struct) { + printf("%s:%d ", src->name, src->ofs); + src = emit_sub_expr (address_expr (new_def_expr (src), 0, 0), 0); + printf("%s:%d\n", src->name, src->ofs); + size_expr = new_integer_expr (type_size (dst_type->aux_type)); } else { - size = emit_sub_expr (new_integer_expr (type_size (type->aux_type)), 0); + size_expr = new_integer_expr (type_size (dst_type->aux_type)); } + size = emit_sub_expr (size_expr, 0); + op = opcode_find ("", src, size, dst); return emit_statement (e, op, src, size, dst); } @@ -428,6 +441,10 @@ emit_sub_expr (expr_t *e, def_t *dest) error (e, "internal error"); abort (); case ex_expr: + if (e->e.expr.op == 'M') { + d = emit_move_expr (e); + break; + } if (e->e.expr.op == 'b') { d = emit_bind_expr (e->e.expr.e1, e->e.expr.e2); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a0f69439c..20bdde91f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -343,6 +343,7 @@ get_op_string (int op) case 's': return ""; case 'c': return ""; case 'C': return ""; + case 'M': return ""; default: return "unknown"; } @@ -640,6 +641,14 @@ new_this_expr (void) return new_def_expr (def); } +expr_t * +new_move_expr (expr_t *e1, expr_t *e2, type_t *type) +{ + expr_t *e = new_binary_expr ('M', e1, e2); + e->e.expr.type = type; + return e; +} + expr_t * append_expr (expr_t *block, expr_t *e) { @@ -2179,7 +2188,7 @@ assign_expr (expr_t *e1, expr_t *e2) if (extract_type (e2) == ev_struct) { e1 = address_expr (e1, 0, 0); e2 = address_expr (e2, 0, 0); - e = new_binary_expr ('M', e1, e2); + e = new_move_expr (e1, e2, get_type (e2)); } else { expr_t *temp = new_temp_def_expr (t1); @@ -2192,8 +2201,7 @@ assign_expr (expr_t *e1, expr_t *e2) } else if (is_indirect (e1)) { if (extract_type (e1) == ev_struct) { e1 = address_expr (e1, 0, 0); - e2 = address_expr (e2, 0, 0); - return new_binary_expr ('M', e1, e2); + return new_move_expr (e1, e2, get_type (e2)); } if (e1->type == ex_expr) { if (get_type (e1->e.expr.e1) == &type_entity) { @@ -2212,9 +2220,8 @@ assign_expr (expr_t *e1, expr_t *e2) } } else if (is_indirect (e2)) { if (extract_type (e1) == ev_struct) { - e1 = address_expr (e1, 0, 0); e2 = address_expr (e2, 0, 0); - return new_binary_expr ('M', e1, e2); + return new_move_expr (e1, e2, get_type (e2)); } if (e2->type == ex_uexpr) { e = e2->e.expr.e1; @@ -2230,7 +2237,7 @@ assign_expr (expr_t *e1, expr_t *e2) } } if (extract_type (e1) == ev_struct) { - return new_binary_expr ('M', e1, e2); + return new_move_expr (e1, e2, get_type (e2)); } if (!type) error (e1, "internal error");