mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
lots of work on better array/pointer/struct handline. doesn't quite work yet
This commit is contained in:
parent
05da8d2af0
commit
cc34e5954f
10 changed files with 445 additions and 177 deletions
|
@ -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>", "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++) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -92,7 +92,7 @@ typedef struct {
|
|||
struct switch_block_s *switch_block;
|
||||
}
|
||||
|
||||
%right <op> '=' ASX
|
||||
%right <op> '=' 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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue