lots of work on better array/pointer/struct handline. doesn't quite work yet

This commit is contained in:
Bill Currie 2001-12-12 08:39:47 +00:00
parent 05da8d2af0
commit cc34e5954f
10 changed files with 445 additions and 177 deletions

View file

@ -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++) {

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);