From cc34e5954fdb4616972103e542a4ba296f45e343 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Dec 2001 08:39:47 +0000 Subject: [PATCH] lots of work on better array/pointer/struct handline. doesn't quite work yet --- libs/gamecode/engine/pr_opcode.c | 49 ++-- tools/qfcc/include/expr.h | 10 +- tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/emit.c | 74 ++++- tools/qfcc/source/expr.c | 464 ++++++++++++++++++++++--------- tools/qfcc/source/pr_def.c | 3 +- tools/qfcc/source/pr_imm.c | 2 +- tools/qfcc/source/qc-parse.y | 15 +- tools/qfcc/source/switch.c | 2 +- tools/qwaq/main.c | 1 + 10 files changed, 445 insertions(+), 177 deletions(-) diff --git a/libs/gamecode/engine/pr_opcode.c b/libs/gamecode/engine/pr_opcode.c index cd254daa2..41e755b01 100644 --- a/libs/gamecode/engine/pr_opcode.c +++ b/libs/gamecode/engine/pr_opcode.c @@ -40,6 +40,7 @@ static const char rcsid[] = # include "strings.h" #endif +#include "QF/cvar.h" #include "QF/hash.h" #include "QF/pr_comp.h" #include "QF/progs.h" @@ -134,31 +135,31 @@ opcode_t pr_opcodes[] = { {"=", "store.i", OP_STORE_I, true, ev_integer, ev_integer, ev_void, PROG_VERSION}, {"=", "store.p", OP_STORE_P, true, ev_pointer, ev_pointer, ev_void, PROG_VERSION}, - {"=", "storep.f", OP_STOREP_F, true, ev_float, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.v", OP_STOREP_V, true, ev_vector, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.s", OP_STOREP_S, true, ev_string, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.ent", OP_STOREP_ENT, true, ev_entity, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.fld", OP_STOREP_FLD, true, ev_field, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.fnc", OP_STOREP_FNC, true, ev_func, ev_pointer, ev_void, PROG_ID_VERSION}, - {"=", "storep.i", OP_STOREP_I, true, ev_integer, ev_pointer, ev_void, PROG_VERSION}, + {".=", "storep.f", OP_STOREP_F, true, ev_float, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.v", OP_STOREP_V, true, ev_vector, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.s", OP_STOREP_S, true, ev_string, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.ent", OP_STOREP_ENT, true, ev_entity, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.fld", OP_STOREP_FLD, true, ev_field, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.fnc", OP_STOREP_FNC, true, ev_func, ev_pointer, ev_void, PROG_ID_VERSION}, + {".=", "storep.i", OP_STOREP_I, true, ev_integer, ev_pointer, ev_void, PROG_VERSION}, - {"=", "storeb.f", OP_STOREB_F, true, ev_float, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.v", OP_STOREB_V, true, ev_vector, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.s", OP_STOREB_S, true, ev_string, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.ent", OP_STOREB_ENT, true, ev_entity, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.fld", OP_STOREB_FLD, true, ev_field, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.fnc", OP_STOREB_FNC, true, ev_func, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.i", OP_STOREB_I, true, ev_integer, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storeb.p", OP_STOREB_P, true, ev_pointer, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.f", OP_STOREB_F, true, ev_float, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.v", OP_STOREB_V, true, ev_vector, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.s", OP_STOREB_S, true, ev_string, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.ent", OP_STOREB_ENT, true, ev_entity, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.fld", OP_STOREB_FLD, true, ev_field, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.fnc", OP_STOREB_FNC, true, ev_func, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.i", OP_STOREB_I, true, ev_integer, ev_pointer, ev_integer, PROG_VERSION}, + {".=", "storeb.p", OP_STOREB_P, true, ev_pointer, ev_pointer, ev_integer, PROG_VERSION}, - {"=", "storebi.f", OP_STOREBI_F, true, ev_float, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.v", OP_STOREBI_V, true, ev_vector, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.s", OP_STOREBI_S, true, ev_string, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.ent", OP_STOREBI_ENT, true, ev_entity, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.fld", OP_STOREBI_FLD, true, ev_field, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.fnc", OP_STOREBI_FNC, true, ev_func, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.i", OP_STOREBI_I, true, ev_integer, ev_pointer, ev_short, PROG_VERSION}, - {"=", "storebi.p", OP_STOREBI_P, true, ev_pointer, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.f", OP_STOREBI_F, true, ev_float, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.v", OP_STOREBI_V, true, ev_vector, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.s", OP_STOREBI_S, true, ev_string, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.ent", OP_STOREBI_ENT, true, ev_entity, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.fld", OP_STOREBI_FLD, true, ev_field, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.fnc", OP_STOREBI_FNC, true, ev_func, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.i", OP_STOREBI_I, true, ev_integer, ev_pointer, ev_short, PROG_VERSION}, + {".=", "storebi.p", OP_STOREBI_P, true, ev_pointer, ev_pointer, ev_short, PROG_VERSION}, {"", "return", OP_RETURN, false, ev_void, ev_void, ev_void, PROG_ID_VERSION}, @@ -313,6 +314,8 @@ PR_Check_Opcodes (progs_t *pr) opcode_t *op; dstatement_t *st; + if (!pr_boundscheck->int_val) + return; for (st = pr->pr_statements; st - pr->pr_statements < pr->progs->numstatements; st++) { diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 8a4de108f..33c080bda 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -75,6 +75,12 @@ typedef struct { int users; } temp_t; +typedef struct { + int val; + type_t *type; + int abs; +} pointer_t; + typedef struct expr_s { struct expr_s *next; expr_type type; @@ -99,7 +105,7 @@ typedef struct expr_s { int entity_val; int field_val; int func_val; - int pointer_val; + pointer_t pointer; float quaternion_val[4]; int integer_val; unsigned int uinteger_val; @@ -140,6 +146,8 @@ expr_t *return_expr (function_t *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); +expr_t *address_expr (expr_t *e1, expr_t *e2, type_t *t); +expr_t *assign_expr (expr_t *e1, expr_t *e2); def_t *emit_statement (int line, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c); void emit_expr (expr_t *e); diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 04ceabe5e..2679b0258 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -33,5 +33,5 @@ YFLAGS = -d bin_PROGRAMS= qfcc -qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c struct.c switch.c getopt.c getopt1.c +qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c struct.c switch.c getopt.c getopt1.c type.c qfcc_LDADD= -lQFgamecode -lQFutil diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 2c5cce9dd..6f873cd41 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -89,6 +89,12 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, statement->c = var_c->ofs; ret = var_c; } +#if 0 + printf ("%s %s(%d) %s(%d) %s(%d)\n", op->opname, + var_a ? var_a->name : "", statement->a, + var_b ? var_b->name : "", statement->b, + var_c ? var_c->name : "", statement->c); +#endif PR_AddStatementRef (var_a, statement, 0); PR_AddStatementRef (var_b, statement, 1); @@ -160,7 +166,7 @@ emit_function_call (expr_t *e, def_t *dest) } def_t * -emit_assign_expr (expr_t *e) +emit_assign_expr (const char *operator, expr_t *e) { def_t *def_a, *def_b, *def_c; opcode_t *op; @@ -176,14 +182,26 @@ emit_assign_expr (expr_t *e) 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); + op = PR_Opcode_Find (operator, def_a, def_b, def_c); emit_statement (e->line, op, def_a, def_b, def_c); } else { def_a = emit_sub_expr (e1, 0); - if (def_a->type->type == ev_pointer) { + if (def_a->type->type == ev_pointer + && e2->type != ex_uexpr + && e2->e.expr.op != '&') { 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 (def_b->type->type == ev_pointer) { + expr_t *zero = new_expr (); + def_t *z; + + zero->type = ex_short; + z = emit_sub_expr (zero, 0); + op = PR_Opcode_Find (operator, def_b, def_a, z); + emit_statement (e->line, op, def_b, def_a, z); + } else { + op = PR_Opcode_Find (operator, 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) { @@ -200,9 +218,19 @@ emit_assign_expr (expr_t *e) error (e1, "assignment to constant %s", def_a->name); } } - def_b = emit_sub_expr (e2, def_a); + if (e2->type == ex_expr && e2->e.expr.type->type == ev_pointer + && e2->e.expr.op == '&') { + //def_b = emit_sub_expr (e2->e.expr.e1, 0); + //e2 = e2->e.expr.e2; + //operator = "."; + //def_b = emit_sub_expr (e2, def_b); + e2->e.expr.op = '.'; + def_b = emit_sub_expr (e2, def_a); + } else { + def_b = emit_sub_expr (e2, def_a); + } if (def_b != def_a) { - op = PR_Opcode_Find ("=", def_b, def_a, &def_void); + op = PR_Opcode_Find (operator, def_b, def_a, &def_void); emit_statement (e->line, op, def_b, def_a, 0); } } @@ -262,7 +290,7 @@ emit_sub_expr (expr_t *e, def_t *dest) break; } if (e->e.expr.op == '=') { - d = emit_assign_expr (e); + d = emit_assign_expr ("=", e); break; } if (e->e.expr.e1->type == ex_block @@ -313,13 +341,27 @@ emit_sub_expr (expr_t *e, def_t *dest) && e->e.expr.e1->e.expr.op == '.') { tmp = PR_GetTempDef (e->e.expr.type, pr_scope); tmp->users += 2; + def_b = emit_sub_expr (&zero, 0); + } else { + def_b = &def_void; } def_a = emit_sub_expr (e->e.expr.e1, tmp); - def_b = emit_sub_expr (&zero, 0); if (!dest) { dest = PR_GetTempDef (e->e.expr.type, pr_scope); dest->users += 2; } + } if (e->e.expr.op == '.') { + if (!dest + && (e->e.expr.e1->type != ex_pointer + || !(e->e.expr.e1->e.pointer.val > 0 + && e->e.expr.e1->e.pointer.val < 65536))) { + dest = PR_GetTempDef (e->e.expr.type, pr_scope); + dest->users += 2; + } + d = emit_sub_expr (e->e.expr.e1, dest); + if (!d->name) + d->type = e->e.expr.type; + return d; } else { abort (); } @@ -340,13 +382,22 @@ emit_sub_expr (expr_t *e, def_t *dest) } d = e->e.temp.def; break; + case ex_pointer: + if (e->e.pointer.val > 0 && e->e.pointer.val < 65536 + && e->e.pointer.type->type != ev_struct) { + d = PR_NewDef (e->e.pointer.type, 0, pr_scope); + d->ofs = e->e.short_val; + d->absolute = e->e.pointer.abs; + d->users = 1; + break; + } + // fall through case ex_string: case ex_float: case ex_vector: case ex_entity: case ex_field: case ex_func: - case ex_pointer: case ex_quaternion: case ex_integer: case ex_uinteger: @@ -401,8 +452,9 @@ emit_expr (expr_t *e) break; case ex_expr: switch (e->e.expr.op) { + case PAS: case '=': - emit_assign_expr (e); + emit_assign_expr (get_op_string (e->e.expr.op), e); break; case 'n': emit_branch (e->line, op_ifnot, e->e.expr.e1, e->e.expr.e2); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 19fe2efe1..a78728e8e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -39,6 +39,7 @@ static const char rcsid[] = #include "qfcc.h" #include "scope.h" #include "struct.h" +#include "type.h" #include "qc-parse.h" @@ -134,6 +135,15 @@ get_type (expr_t *e) return e->e.def->type; case ex_temp: return e->e.temp.type; + case ex_pointer: + { + type_t new; + + memset (&new, 0, sizeof (new)); + new.type = ev_pointer; + new.aux_type = e->e.pointer.type; + return PR_FindType (&new); + } case ex_integer: if (options.code.progsversion == PROG_ID_VERSION) { e->type = ex_float; @@ -146,7 +156,6 @@ get_type (expr_t *e) case ex_entity: case ex_field: case ex_func: - case ex_pointer: case ex_quaternion: case ex_uinteger: case ex_short: @@ -218,6 +227,7 @@ const char * get_op_string (int op) { switch (op) { + case PAS: return ".="; case OR: return "||"; case AND: return "&&"; case EQ: return "=="; @@ -524,10 +534,13 @@ print_expr (expr_t *e) printf (" %g", e->e.quaternion_val[2]); printf (" %g'", e->e.quaternion_val[3]); break; + case ex_pointer: + printf ("(%s)[%d]", type_name[e->e.pointer.type->type], + e->e.pointer.val); + break; case ex_entity: case ex_field: case ex_func: - case ex_pointer: case ex_integer: printf ("%d", e->e.integer_val); break; @@ -780,6 +793,82 @@ do_op_integer (int op, expr_t *e1, expr_t *e2) return e1; } +static expr_t * +do_op_uinteger (int op, expr_t *e1, expr_t *e2) +{ + unsigned int i1, i2; + + i1 = e1->e.uinteger_val; + i2 = e2->e.uinteger_val; + + switch (op) { + case '+': + e1->e.uinteger_val += i2; + break; + case '-': + e1->e.uinteger_val -= i2; + break; + case '*': + e1->e.uinteger_val *= i2; + break; + case '/': + warning (e2, "%d / %d == %d", i1, i2, i1 / i2); + e1->e.uinteger_val /= i2; + break; + case '&': + e1->e.uinteger_val = i1 & i2; + break; + case '|': + e1->e.uinteger_val = i1 | i2; + break; + case '^': + e1->e.uinteger_val = i1 ^ i2; + break; + case '%': + e1->e.uinteger_val = i1 % i2; + break; + case SHL: + e1->e.uinteger_val = i1 << i2; + break; + case SHR: + e1->e.uinteger_val = i1 >> i2; + break; + case AND: + e1->e.uinteger_val = i1 && i2; + break; + case OR: + e1->e.uinteger_val = i1 || i2; + break; + case LT: + e1->type = ex_integer; + e1->e.integer_val = i1 < i2; + break; + case GT: + e1->type = ex_integer; + e1->e.integer_val = i1 > i2; + break; + case LE: + e1->type = ex_integer; + e1->e.integer_val = i1 <= i2; + break; + case GE: + e1->type = ex_integer; + e1->e.integer_val = i1 >= i2; + break; + case EQ: + e1->type = ex_integer; + e1->e.integer_val = i1 == i2; + break; + case NE: + e1->type = ex_integer; + e1->e.integer_val = i1 != i2; + break; + default: + return error (e1, "invalid operand for uinteger"); + } + return e1; +} + static expr_t * do_op_huh (int op, expr_t *e1, expr_t *e2) { @@ -787,16 +876,19 @@ do_op_huh (int op, expr_t *e1, expr_t *e2) } static expr_t *(*do_op[]) (int op, expr_t *e1, expr_t *e2) = { - do_op_huh, - do_op_string, - do_op_float, - do_op_vector, - do_op_huh, - do_op_huh, - do_op_huh, - do_op_huh, - do_op_huh, - do_op_integer, + do_op_huh, // ev_void + do_op_string, // ev_string + do_op_float, // ev_float + do_op_vector, // ev_vector + do_op_huh, // ev_entity + do_op_huh, // ev_field + do_op_huh, // ev_func + do_op_huh, // ev_pointer + do_op_huh, // ev_quaternion + do_op_integer, // ev_integer + do_op_uinteger, // ev_uinteger + do_op_huh, // ev_short + do_op_huh, // ev_struct }; static expr_t * @@ -817,53 +909,65 @@ binary_const (int op, expr_t *e1, expr_t *e2) static expr_t * field_expr (expr_t *e1, expr_t *e2) { - etype_t t1, t2; + type_t *t1, *t2; expr_t *e; - type_t *strct; struct_field_t *field; - t1 = extract_type (e1); - if (t1 == ev_struct) { - strct = get_type (e1); - if (e2->type != ex_name) - return error (e2, "structure field name expected"); - field = struct_find_field (strct, e2->e.string_val); - if (!field) - return error (e2, "structure has no field %s", e2->e.string_val); - e2->type = ex_short; - e2->e.short_val = field->offset; - e = new_binary_expr ('.', unary_expr ('&', e1), e2); - e->e.expr.type = field->type; - return e; - } - if (t1 == ev_pointer - && (strct = get_type(e1)->aux_type)->type == ev_struct) { - if (e2->type == ex_name) { - field = struct_find_field (strct, e2->e.string_val); + t1 = get_type (e1); + switch (t1->type) { + case ev_struct: + if (e2->type != ex_name) + return error (e2, "structure field name expected"); + field = struct_find_field (t1, e2->e.string_val); if (!field) return error (e2, "structure has no field %s", - e2->e.string_val); + e2->e.string_val); e2->type = ex_short; e2->e.short_val = field->offset; - e = new_binary_expr ('.', e1, e2); - e->e.expr.type = field->type; + e = unary_expr ('.', address_expr (e1, e2, field->type)); return e; - } + case ev_pointer: + if (t1->aux_type->type == ev_struct) { + if (e2->type == ex_name) { + field = struct_find_field (t1->aux_type, e2->e.string_val); + if (!field) + return error (e2, "structure has no field %s", + e2->e.string_val); + e2->type = ex_short; + e2->e.short_val = field->offset; + t1 = pointer_type (field->type); + } + } + if (e1->type == ex_pointer) { + if (e2->type == ex_short) { + e1->e.pointer.val += e2->e.short_val; + } else if (e2->type == ex_integer) { + e1->e.pointer.val += e2->e.integer_val; + } else if (e2->type == ex_uinteger) { + e1->e.pointer.val += e2->e.uinteger_val; + } else { + break; + } + e1->e.pointer.type = t1->aux_type; + return unary_expr ('.', e1); + } else { + e = new_binary_expr ('&', e1, e2); + e->e.expr.type = t1; + return unary_expr ('.', e); + } + break; + case ev_entity: + t2 = get_type (e2); + if (t2->type == ev_field) { + e = new_binary_expr ('.', e1, e2); + e->e.expr.type = t2->aux_type; + return e; + } + break; + default: + break; } - t2 = extract_type (e2); - - if ((t1 != ev_entity || t2 != ev_field) - && (t1 != ev_pointer - || (t2 != ev_integer && t2 != ev_uinteger && t2 != ev_short))) { - return error (e1, "type missmatch for ."); - } - - e = new_binary_expr ('.', e1, e2); - if (t1 == ev_pointer) - e->e.expr.type = get_type (e1)->aux_type; - else - e->e.expr.type = get_type (e2)->aux_type; - return e; + return type_mismatch (e1, e2, '.'); } expr_t * @@ -946,17 +1050,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_t *e; convert_name (e1); - if (op != '=') - check_initialized (e1); - - if (op == '=' && e1->type == ex_def) - PR_DefInitialized (e1->e.def); + check_initialized (e1); if (e1->type == ex_block && e1->e.block.is_call && e2->type == ex_block && e2->e.block.is_call && e1->e.block.result) { e = new_temp_def_expr (e1->e.block.result->e.def->type); inc_users (e); // for the block itself - e1 = binary_expr ('=', e, e1); + e1 = assign_expr (e, e1); } if (op == '.') @@ -1000,11 +1100,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) "expressions involving ! and %c", op); } - if (op == '=' && t1->type != ev_void && e2->type == ex_nil) { - t2 = t1; - e2->type = expr_types[t2->type]; - } - if (t1 != t2) { switch (t1->type) { case ev_float: @@ -1052,17 +1147,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) } else if (op == '*' && t1 == &type_vector && t2 == &type_vector) { type = &type_float; } - if (op == '=' && e1->type == ex_expr && e1->e.expr.op == '.') { - 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); - e1->e.expr.op = '&'; - } - } if (!type) error (e1, "internal error"); @@ -1077,7 +1161,7 @@ asx_expr (int op, expr_t *e1, expr_t *e2) expr_t *e = new_expr (); *e = *e1; - return binary_expr ('=', e, binary_expr (op, e1, e2)); + return assign_expr (e, binary_expr (op, e1, e2)); } expr_t * @@ -1244,55 +1328,12 @@ unary_expr (int op, expr_t *e) return error (e, "invalid type for unary ~"); } break; - case '&': - switch (e->type) { - case ex_label: - case ex_name: - error (e, "internal error"); - abort (); - case ex_def: - { - type_t new; - expr_t *n = new_unary_expr (op, e); - - memset (&new, 0, sizeof (new)); - new.type = ev_pointer; - new.aux_type = e->e.def->type; - n->e.expr.type = PR_FindType (&new); - return n; - } - case ex_expr: - if (e->e.expr.op == '.') { - expr_t *e1 = e->e.expr.e1; - etype_t t1 = extract_type (e1); - if (t1 == ev_entity || t1 == ev_pointer) { - type_t new; - - memset (&new, 0, sizeof (new)); - new.type = ev_pointer; - new.aux_type = e->e.expr.type; - e->e.expr.type = PR_FindType (&new); - return e; - } - } - case ex_uexpr: - case ex_block: - case ex_temp: - case ex_short: - case ex_integer: - case ex_uinteger: - case ex_float: - case ex_nil: - case ex_string: - case ex_vector: - case ex_quaternion: - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: - return error (e, "invalid type for unary &"); - } - break; + case '.': + if (extract_type (e) != ev_pointer) + return error (e, "invalid type for unary ."); + e = new_unary_expr ('.', e); + e->e.expr.type = get_type (e->e.expr.e1)->aux_type; + return e; } error (e, "internal error"); abort (); @@ -1414,7 +1455,7 @@ function_expr (expr_t *e1, expr_t *e2) a = &(*a)->next; } for (i = 0; i < arg_expr_count - 1; i++) { - append_expr (call, binary_expr ('=', arg_exprs[i][1], arg_exprs[i][0])); + append_expr (call, assign_expr (arg_exprs[i][1], arg_exprs[i][0])); } if (arg_expr_count) { e = new_bind_expr (arg_exprs[arg_expr_count - 1][0], @@ -1479,13 +1520,13 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2) block->e.block.result = (type1 == type2) ? new_temp_def_expr (type1) : 0; append_expr (block, new_binary_expr ('i', test_expr (cond, 1), tlabel)); if (block->e.block.result) - append_expr (block, new_binary_expr ('=', block->e.block.result, e2)); + append_expr (block, assign_expr (block->e.block.result, e2)); else append_expr (block, e2); append_expr (block, new_unary_expr ('g', elabel)); append_expr (block, tlabel); if (block->e.block.result) - append_expr (block, new_binary_expr ('=', block->e.block.result, e1)); + append_expr (block, assign_expr (block->e.block.result, e1)); else append_expr (block, e1); append_expr (block, elabel); @@ -1507,7 +1548,7 @@ incop_expr (int op, expr_t *e, int postop) expr_t *block = new_block_expr (); temp = new_temp_def_expr (type); - append_expr (block, binary_expr ('=', temp, e)); + append_expr (block, assign_expr (temp, e)); append_expr (block, incop); block->e.block.result = temp; return block; @@ -1521,6 +1562,7 @@ array_expr (expr_t *array, expr_t *index) type_t *array_type = get_type (array); type_t *index_type = get_type (index); expr_t *scale; + expr_t *e; int size; if (array_type->type != ev_pointer || array_type->num_parms < 1) @@ -1543,5 +1585,173 @@ array_expr (expr_t *array, expr_t *index) && index->e.uinteger_val < 32768)) { index->type = ex_short; } - return binary_expr ('.', array, index); + e = new_binary_expr ('.', array, index); + e->e.expr.type = pointer_type (array_type->aux_type); + return unary_expr ('.', e); +} + +expr_t * +address_expr (expr_t *e1, expr_t *e2, type_t *t) +{ + expr_t *e; + type_t *type = 0; + + if (!t) + t = get_type (e1); + +// print_expr (e1);puts(""); + switch (e1->type) { + case ex_def: + type = e1->e.def->type; + if (type->type == ev_struct) { + int abs = !e1->e.def->scope; + def_t *def = e1->e.def; + + e = e1; + e->type = ex_pointer; + e->e.pointer.val = def->ofs; + e->e.pointer.type = t; + e->e.pointer.abs = abs; + } else { + e = new_unary_expr ('&', e1); + e->e.expr.type = pointer_type (type); + } + break; + case ex_expr: + if (e1->e.expr.op == '.') { + expr_t *e = e1->e.expr.e1; + + type = get_type (e); + if (type->type == ev_entity || type->type == ev_pointer) { + e->e.expr.type = pointer_type (type); + e->e.expr.op = '&'; + return e; + } + } + return error (e, "invalid type for unary &"); + case ex_uexpr: + if (e1->e.expr.op == '.') { + e = e1->e.expr.e1; + type = get_type (e)->aux_type; + if (e->type == ex_expr && e->e.expr.op == '.') { + e->e.expr.type = pointer_type (e->e.expr.type); + e->e.expr.op = '&'; + } + break; + } + return error (e, "invalid type for unary &"); + default: + return error (e, "invalid type for unary &"); + } + if (e2) { + if (e->type == ex_pointer && e2->type == ex_short) { + e->e.pointer.val += e2->e.short_val; + } else { +// print_expr (e); puts(""); +// print_expr (e2); puts(""); + if (e2->type != ex_short || e2->e.short_val) { +// print_expr (e2);puts(""); + e = new_binary_expr ('&', e, e2); + } + if (e->type == ex_expr || e->type == ex_uexpr) + e->e.expr.type = pointer_type (t); + } + } +// print_expr (e);puts(""); +// puts(""); + return e; +} + +static inline int +is_indirect (expr_t *e) +{ + if (e->type == ex_expr && e->e.expr.op == '.') + return 1; + if (!(e->type == ex_uexpr && e->e.expr.op == '.')) + return 0; + e = e->e.expr.e1; + if (e->type != ex_pointer + || !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) + return 1; + return 0; +} + +expr_t * +assign_expr (expr_t *e1, expr_t *e2) +{ + int op = '='; + type_t *t1, *t2, *type; + expr_t *e; + + convert_name (e1); + if (e1->type == ex_def) + PR_DefInitialized (e1->e.def); + //XXX func = func + convert_name (e2); + check_initialized (e2); + t1 = get_type (e1); + t2 = get_type (e2); + if (!t1 || !t2) { + error (e1, "internal error"); + abort (); + } + if (e2->type == ex_integer + && (t1 == &type_float + || t1 == &type_vector + || t1 == &type_quaternion)) { + convert_int (e2); + t2 = &type_float; + } + + if (t1->type != ev_void && e2->type == ex_nil) { + t2 = t1; + e2->type = expr_types[t2->type]; + } + + if (t1 != t2) + return type_mismatch (e1, e2, op); + else + type = t1; +//print_expr (e1); printf(" %d\n", e1->line); +//print_expr (e2); printf("\n"); +//printf ("%s %s\n", type_name[t1->type], type_name[t2->type]); + if (is_indirect (e1) && is_indirect (e2)) { + expr_t *temp = new_temp_def_expr (t1); + + e = new_block_expr (); + append_expr (e, assign_expr (temp, e2)); + append_expr (e, assign_expr (e1, temp)); + return e; + } else if (is_indirect (e1)) { + if (e1->type == ex_expr) { + if (get_type (e1->e.expr.e1) == &type_entity) { + type = e1->e.expr.type; + e1->e.expr.type = pointer_type (type); + e1->e.expr.op = '&'; + } + op = PAS; + } else { + e = e1->e.expr.e1; + if (e->type != ex_pointer + || !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) { + e1 = e; + op = PAS; + } + } + } else if (is_indirect (e2)) { + if (e2->type == ex_uexpr) { + e = e2->e.expr.e1; + if (e->type != ex_pointer + || !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) { + e2 = e; + op = PAS; + } + } + } + if (!type) + error (e1, "internal error"); + + e = new_binary_expr (op, e1, e2); + e->e.expr.type = type; + return e; } diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c index 45b30199a..c93a0f020 100644 --- a/tools/qfcc/source/pr_def.c +++ b/tools/qfcc/source/pr_def.c @@ -189,7 +189,8 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate) } else if (type->type == ev_pointer) { size = PR_GetTypeSize (type->aux_type); *allocate += type->num_parms * size; - def->initialized = def->constant = 1; + if (type->num_parms) + def->initialized = def->constant = 1; } return def; diff --git a/tools/qfcc/source/pr_imm.c b/tools/qfcc/source/pr_imm.c index 6943341aa..b82f47320 100644 --- a/tools/qfcc/source/pr_imm.c +++ b/tools/qfcc/source/pr_imm.c @@ -136,7 +136,7 @@ PR_ReuseConstant (expr_t *expr, def_t *def) break; case ex_pointer: snprintf (rep, sizeof (rep), "\001pointer:%08X\001", - e.e.integer_val); + e.e.pointer.val); tab = pointer_imm_defs; type = &type_pointer; break; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index d22ea4eac..bc70e2f5c 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -92,7 +92,7 @@ typedef struct { struct switch_block_s *switch_block; } -%right '=' ASX +%right '=' ASX PAS /* pointer assign */ %right '?' ':' %left OR AND %left EQ NE LE GE LT GT @@ -320,7 +320,7 @@ opt_var_initializer expr_t *e = new_expr (); e->type = ex_def; e->e.def = current_def; - append_expr (local_expr, binary_expr ('=', e, $2)); + append_expr (local_expr, assign_expr (e, $2)); PR_DefInitialized (current_def); } else { if ($2->type >= ex_string) { @@ -676,7 +676,7 @@ opt_expr } expr - : expr '=' expr { $$ = binary_expr ('=', $1, $3); } + : expr '=' expr { $$ = assign_expr ($1, $3); } | expr ASX expr { $$ = asx_expr ($2, $1, $3); } | expr '?' expr ':' expr { $$ = conditional_expr ($1, $3, $5); } | expr AND expr { $$ = binary_expr (AND, $1, $3); } @@ -705,6 +705,7 @@ expr | '-' expr %prec UNARY { $$ = unary_expr ('-', $2); } | '!' expr %prec UNARY { $$ = unary_expr ('!', $2); } | '~' expr %prec UNARY { $$ = unary_expr ('~', $2); } + | '&' expr %prec UNARY { $$ = address_expr ($2, 0, 0); } | INCOP expr { $$ = incop_expr ($1, $2, 0); } | expr INCOP { $$ = incop_expr ($2, $1, 1); } | NAME @@ -828,14 +829,6 @@ build_type (int is_field, type_t *type) new.type = ev_field; new.aux_type = type; return PR_FindType (&new); - } else if (type->type == ev_struct) { - type_t new; - - memset (&new, 0, sizeof (new)); - new.type = ev_pointer; - new.aux_type = type; - new.num_parms = 1; - return PR_FindType (&new); } else { return type; } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 750400785..a4b697dc2 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -258,7 +258,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, test->line = sw_val->line; test->file = sw_val->file; - test = binary_expr ('=', temp, test); + test = assign_expr (temp, test); test->line = sw_val->line; test->file = sw_val->file; append_expr (sw, test); diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index d0a7a7d7d..125436495 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -72,6 +72,7 @@ main () Cmd_Init (); Cvar_Get ("pr_debug", "1", 0, 0, 0); + Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); Cvar_Get ("fs_basegame", ".", 0, 0, 0); Cvar_Get ("fs_userpath", ".", 0, 0, 0); Cvar_Get ("fs_sharepath", ".", 0, 0, 0);