mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-22 11:41:38 +00:00
[qfcc] Correctly implement pointer arithmetic
This commit is contained in:
parent
c5400c4581
commit
441e7b99bc
1 changed files with 56 additions and 18 deletions
|
@ -46,6 +46,7 @@ typedef struct {
|
||||||
} expr_type_t;
|
} expr_type_t;
|
||||||
|
|
||||||
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
|
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
|
||||||
|
static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
||||||
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
|
|
||||||
|
@ -176,13 +177,13 @@ static expr_type_t func_func[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t pointer_pointer[] = {
|
static expr_type_t pointer_pointer[] = {
|
||||||
{'-', &type_integer, &type_integer, &type_integer},
|
{'-', 0, 0, 0, pointer_arithmetic},
|
||||||
{EQ, &type_integer},
|
{EQ, 0, 0, 0, pointer_compare},
|
||||||
{NE, &type_integer},
|
{NE, 0, 0, 0, pointer_compare},
|
||||||
{LE, &type_integer},
|
{LE, 0, 0, 0, pointer_compare},
|
||||||
{GE, &type_integer},
|
{GE, 0, 0, 0, pointer_compare},
|
||||||
{LT, &type_integer},
|
{LT, 0, 0, 0, pointer_compare},
|
||||||
{GT, &type_integer},
|
{GT, 0, 0, 0, pointer_compare},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ static expr_type_t integer_vector[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static expr_type_t integer_pointer[] = {
|
static expr_type_t integer_pointer[] = {
|
||||||
{'+', &type_pointer, 0, &type_integer},
|
{'+', 0, 0, 0, pointer_arithmetic},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -735,21 +736,58 @@ static expr_t *
|
||||||
pointer_arithmetic (int op, expr_t *e1, expr_t *e2)
|
pointer_arithmetic (int op, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
expr_t *e;
|
expr_t *e;
|
||||||
type_t *ptype = get_type (e1);
|
type_t *t1 = get_type (e1);
|
||||||
|
type_t *t2 = get_type (e2);
|
||||||
|
expr_t *ptr;
|
||||||
|
expr_t *offset;
|
||||||
|
expr_t *psize;
|
||||||
|
type_t *ptype;
|
||||||
|
|
||||||
if (!is_pointer (ptype)) {
|
if (!is_pointer (t1) && !is_pointer (t2)) {
|
||||||
ptype = get_type (e2);
|
|
||||||
}
|
|
||||||
if (!is_pointer (ptype)) {
|
|
||||||
internal_error (e1, "pointer arithmetic on non-pointers");
|
internal_error (e1, "pointer arithmetic on non-pointers");
|
||||||
}
|
}
|
||||||
|
if (is_pointer (t1) && is_pointer (t2)) {
|
||||||
|
if (op != '-') {
|
||||||
|
return error (e2, "invalid pointer operation");
|
||||||
|
}
|
||||||
|
if (t1 != t2) {
|
||||||
|
return error (e2, "cannot use %c on pointers of different types",
|
||||||
|
op);
|
||||||
|
}
|
||||||
e1 = cast_expr (&type_integer, e1);
|
e1 = cast_expr (&type_integer, e1);
|
||||||
e2 = cast_expr (&type_integer, e2);
|
e2 = cast_expr (&type_integer, e2);
|
||||||
e = binary_expr (op, e1, e2);
|
psize = new_integer_expr (type_size (t1->t.fldptr.type));
|
||||||
|
return binary_expr ('/', binary_expr ('-', e1, e2), psize);
|
||||||
|
} else if (is_pointer (t1)) {
|
||||||
|
offset = cast_expr (&type_integer, e2);
|
||||||
|
ptr = cast_expr (&type_integer, e1);
|
||||||
|
ptype = t1;
|
||||||
|
} else if (is_pointer (t2)) {
|
||||||
|
offset = cast_expr (&type_integer, e1);
|
||||||
|
ptr = cast_expr (&type_integer, e2);
|
||||||
|
ptype = t2;
|
||||||
|
}
|
||||||
|
psize = new_integer_expr (type_size (ptype->t.fldptr.type));
|
||||||
|
e = binary_expr (op, ptr, binary_expr ('*', offset, psize));
|
||||||
return cast_expr (ptype, e);
|
return cast_expr (ptype, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static expr_t *
|
||||||
|
pointer_compare (int op, expr_t *e1, expr_t *e2)
|
||||||
|
{
|
||||||
|
type_t *t1 = get_type (e1);
|
||||||
|
type_t *t2 = get_type (e2);
|
||||||
|
expr_t *e;
|
||||||
|
|
||||||
|
if (!type_assignable (t1, t2)) {
|
||||||
|
return error (e2, "cannot use %s on pointers of different types",
|
||||||
|
get_op_string (op));
|
||||||
|
}
|
||||||
|
e = new_binary_expr (op, e1, e2);
|
||||||
|
e->e.expr.type = &type_integer;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
static expr_t *
|
static expr_t *
|
||||||
inverse_multiply (int op, expr_t *e1, expr_t *e2)
|
inverse_multiply (int op, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
|
@ -790,7 +828,7 @@ double_compare (int op, expr_t *e1, expr_t *e2)
|
||||||
e1 = cast_expr (&type_double, e1);
|
e1 = cast_expr (&type_double, e1);
|
||||||
}
|
}
|
||||||
e = new_binary_expr (op, e1, e2);
|
e = new_binary_expr (op, e1, e2);
|
||||||
e->e.expr.type = &type_double;
|
e->e.expr.type = &type_integer;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue