mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 21:21:14 +00:00
[qfcc] Support references in expressions
While a reference var can't be initialized yet, using them seems to work in that they get dereferenced when the value needs to be read or written (though I haven't seen any generated code for them yet).
This commit is contained in:
parent
164c949796
commit
af42b8e221
5 changed files with 60 additions and 19 deletions
|
@ -979,6 +979,7 @@ const expr_t *conditional_expr (const expr_t *cond, const expr_t *e1,
|
||||||
const expr_t *incop_expr (int op, const expr_t *e, int postop);
|
const expr_t *incop_expr (int op, const expr_t *e, int postop);
|
||||||
const expr_t *array_expr (const expr_t *array, const expr_t *index);
|
const expr_t *array_expr (const expr_t *array, const expr_t *index);
|
||||||
const expr_t *deref_pointer_expr (const expr_t *pointer);
|
const expr_t *deref_pointer_expr (const expr_t *pointer);
|
||||||
|
const expr_t *pointer_deref (const expr_t *pointer);
|
||||||
const expr_t *offset_pointer_expr (const expr_t *pointer, const expr_t *offset);
|
const expr_t *offset_pointer_expr (const expr_t *pointer, const expr_t *offset);
|
||||||
const expr_t *address_expr (const expr_t *e1, const type_t *t);
|
const expr_t *address_expr (const expr_t *e1, const type_t *t);
|
||||||
const expr_t *build_if_statement (int not, const expr_t *test, const expr_t *s1,
|
const expr_t *build_if_statement (int not, const expr_t *test, const expr_t *s1,
|
||||||
|
|
|
@ -254,6 +254,13 @@ param_mismatch (const expr_t *e, int param, const char *fn,
|
||||||
get_type_string (t2));
|
get_type_string (t2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const expr_t *
|
||||||
|
reference_error (const expr_t *e, const type_t *dst, const type_t *src)
|
||||||
|
{
|
||||||
|
return error (e, "cannot bind reference of type %s to %s",
|
||||||
|
get_type_string (dst), get_type_string (src));
|
||||||
|
}
|
||||||
|
|
||||||
const expr_t *
|
const expr_t *
|
||||||
test_error (const expr_t *e, const type_t *t)
|
test_error (const expr_t *e, const type_t *t)
|
||||||
{
|
{
|
||||||
|
@ -1988,7 +1995,8 @@ vararg_integer (const expr_t *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const expr_t *
|
const expr_t *
|
||||||
build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *params)
|
build_function_call (const expr_t *fexpr, const type_t *ftype,
|
||||||
|
const expr_t *params)
|
||||||
{
|
{
|
||||||
int param_count = 0;
|
int param_count = 0;
|
||||||
expr_t *call;
|
expr_t *call;
|
||||||
|
@ -2010,7 +2018,6 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ftype->func.num_params < -1) {
|
if (ftype->func.num_params < -1) {
|
||||||
if (options.code.max_params >= 0
|
if (options.code.max_params >= 0
|
||||||
&& arg_count > options.code.max_params) {
|
&& arg_count > options.code.max_params) {
|
||||||
|
@ -2066,15 +2073,24 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
||||||
}
|
}
|
||||||
if (i < param_count) {
|
if (i < param_count) {
|
||||||
auto param_type = ftype->func.param_types[i];
|
auto param_type = ftype->func.param_types[i];
|
||||||
if (e->type == ex_nil)
|
|
||||||
e = convert_nil (e, t = param_type);
|
|
||||||
if (e->type == ex_bool)
|
|
||||||
e = convert_from_bool (e, param_type);
|
|
||||||
if (e->type == ex_error) {
|
|
||||||
err = e;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto param_qual = ftype->func.param_quals[i];
|
auto param_qual = ftype->func.param_quals[i];
|
||||||
|
|
||||||
|
if (is_reference (param_type) && param_qual != pq_in) {
|
||||||
|
internal_error (e, "qualified reference param (not yet)");
|
||||||
|
}
|
||||||
|
if (is_reference (param_type) && !is_reference (t)) {
|
||||||
|
if (!is_lvalue (e)) {
|
||||||
|
err = error (e, "cannot pass non-lvalue by reference");
|
||||||
|
}
|
||||||
|
if (!err && dereference_type (param_type) != t) {
|
||||||
|
err = reference_error (e, param_type, t);
|
||||||
|
}
|
||||||
|
} else if (!is_reference (param_type) && is_reference (t)) {
|
||||||
|
t = dereference_type (t);
|
||||||
|
}
|
||||||
|
if (e->type == ex_nil) {
|
||||||
|
t = param_type;
|
||||||
|
}
|
||||||
if (param_qual == pq_out || param_qual == pq_inout) {
|
if (param_qual == pq_out || param_qual == pq_inout) {
|
||||||
//FIXME should be able to use something like *foo() as
|
//FIXME should be able to use something like *foo() as
|
||||||
//an out or inout arg
|
//an out or inout arg
|
||||||
|
@ -2102,13 +2118,9 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
||||||
}
|
}
|
||||||
t = param_type;
|
t = param_type;
|
||||||
} else {
|
} else {
|
||||||
if (e->type == ex_nil)
|
if (e->type == ex_nil) {
|
||||||
e = convert_nil (e, t = type_nil);
|
t = type_nil;
|
||||||
if (e->type == ex_bool)
|
}
|
||||||
e = convert_from_bool (e, get_type (e));
|
|
||||||
if (is_int_val (e)
|
|
||||||
&& options.code.progsversion == PROG_ID_VERSION)
|
|
||||||
e = cast_expr (&type_float, e);
|
|
||||||
if (options.code.promote_float) {
|
if (options.code.promote_float) {
|
||||||
if (is_scalar (get_type (e)) && is_float (get_type (e))) {
|
if (is_scalar (get_type (e)) && is_float (get_type (e))) {
|
||||||
t = &type_double;
|
t = &type_double;
|
||||||
|
@ -2180,8 +2192,19 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
||||||
inout->inout.out = e;
|
inout->inout.out = e;
|
||||||
e = inout;
|
e = inout;
|
||||||
} else {
|
} else {
|
||||||
|
if (is_reference (arg_types[i])) {
|
||||||
|
if (is_reference (get_type (e))) {
|
||||||
|
// just copy the param, so no op
|
||||||
|
} else {
|
||||||
|
e = address_expr (e, nullptr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_reference (get_type (e))) {
|
||||||
|
e = pointer_deref (e);
|
||||||
|
}
|
||||||
e = cast_expr (arg_types[i], e);
|
e = cast_expr (arg_types[i], e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
expr_prepend_expr (args, e);
|
expr_prepend_expr (args, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,6 +320,9 @@ assign_expr (const expr_t *dst, const expr_t *src)
|
||||||
if ((expr = check_valid_lvalue (dst))) {
|
if ((expr = check_valid_lvalue (dst))) {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
if (is_reference (get_type (dst))) {
|
||||||
|
dst = pointer_deref (dst);
|
||||||
|
}
|
||||||
dst_type = get_type (dst);
|
dst_type = get_type (dst);
|
||||||
if (!dst_type) {
|
if (!dst_type) {
|
||||||
internal_error (dst, "dst_type broke in assign_expr");
|
internal_error (dst, "dst_type broke in assign_expr");
|
||||||
|
@ -347,6 +350,9 @@ assign_expr (const expr_t *dst, const expr_t *src)
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_reference (get_type (src))) {
|
||||||
|
src = pointer_deref (src);
|
||||||
|
}
|
||||||
src_type = get_type (src);
|
src_type = get_type (src);
|
||||||
if (!src_type) {
|
if (!src_type) {
|
||||||
internal_error (src, "src_type broke in assign_expr");
|
internal_error (src, "src_type broke in assign_expr");
|
||||||
|
|
|
@ -1333,6 +1333,13 @@ binary_expr (int op, const expr_t *e1, const expr_t *e2)
|
||||||
if ((e = check_precedence (op, e1, e2)))
|
if ((e = check_precedence (op, e1, e2)))
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
|
if (is_reference (get_type (e1))) {
|
||||||
|
e1 = pointer_deref (e1);
|
||||||
|
}
|
||||||
|
if (is_reference (get_type (e2))) {
|
||||||
|
e2 = pointer_deref (e2);
|
||||||
|
}
|
||||||
|
|
||||||
auto t1 = get_type (e1);
|
auto t1 = get_type (e1);
|
||||||
auto t2 = get_type (e2);
|
auto t2 = get_type (e2);
|
||||||
if (!t1 || !t2)
|
if (!t1 || !t2)
|
||||||
|
|
|
@ -119,7 +119,7 @@ quat_negate (const expr_t *e)
|
||||||
return new_vector_expr (q);
|
return new_vector_expr (q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const expr_t *
|
const expr_t *
|
||||||
pointer_deref (const expr_t *e)
|
pointer_deref (const expr_t *e)
|
||||||
{
|
{
|
||||||
scoped_src_loc (e);
|
scoped_src_loc (e);
|
||||||
|
@ -440,6 +440,10 @@ unary_expr (int op, const expr_t *e)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_reference (get_type (e))) {
|
||||||
|
e = pointer_deref (e);
|
||||||
|
}
|
||||||
|
|
||||||
unary_type_t *unary_type = nullptr;
|
unary_type_t *unary_type = nullptr;
|
||||||
auto t = get_type (e);
|
auto t = get_type (e);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue