mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[qfcc] Delay conversion of nil in assignments
It's not possible to take the address of constants (at this stage) and trying to use a move instruction with .zero as source would result in the VM complaining about null pointer access when bounds checking is on. Thus, don't convert a nil source expression until it is known to be safe, and use memset when it is not.
This commit is contained in:
parent
be5f11f33a
commit
5d349efe78
3 changed files with 33 additions and 11 deletions
|
@ -595,6 +595,7 @@ int is_logic (int op) __attribute__((const));
|
|||
|
||||
int has_function_call (expr_t *e) __attribute__((pure));
|
||||
|
||||
int is_nil (expr_t *e) __attribute__((pure));
|
||||
int is_string_val (expr_t *e) __attribute__((pure));
|
||||
int is_float_val (expr_t *e) __attribute__((pure));
|
||||
int is_vector_val (expr_t *e) __attribute__((pure));
|
||||
|
|
|
@ -882,6 +882,12 @@ constant_expr (expr_t *e)
|
|||
return new;
|
||||
}
|
||||
|
||||
int
|
||||
is_nil (expr_t *e)
|
||||
{
|
||||
return e->type == ex_nil;
|
||||
}
|
||||
|
||||
int
|
||||
is_string_val (expr_t *e)
|
||||
{
|
||||
|
|
|
@ -345,21 +345,22 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
}
|
||||
src_type = get_type (src);
|
||||
}
|
||||
if (!is_void (dst_type) && src->type == ex_nil) {
|
||||
if (!is_struct (dst_type) && is_nil (src)) {
|
||||
// nil is a type-agnostic 0
|
||||
// FIXME: assignment to compound types? error or memset?
|
||||
src_type = dst_type;
|
||||
convert_nil (src, src_type);
|
||||
}
|
||||
|
||||
if ((expr = check_types_compatible (dst, src))) {
|
||||
// expr might be a valid expression, but if so, check_types_compatible
|
||||
// will take care of everything
|
||||
return expr;
|
||||
}
|
||||
|
||||
if ((expr = assign_vector_expr (dst, src))) {
|
||||
return expr;
|
||||
if (!is_nil (src)) {
|
||||
if ((expr = check_types_compatible (dst, src))) {
|
||||
// expr might be a valid expression, but if so,
|
||||
// check_types_compatible will take care of everything
|
||||
return expr;
|
||||
}
|
||||
if ((expr = assign_vector_expr (dst, src))) {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_indirect (dst) && is_indirect (src)) {
|
||||
|
@ -381,8 +382,18 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
debug (dst, "here");
|
||||
if (is_struct (dst_type)) {
|
||||
dst = address_expr (dst, 0, 0);
|
||||
src = address_expr (src, 0, 0);
|
||||
return new_move_expr (dst, src, dst_type, 1);
|
||||
if (is_nil (src)) {
|
||||
int size = type_size (dst_type);
|
||||
return new_memset_expr (dst, new_integer_expr (0),
|
||||
new_integer_expr (size));
|
||||
} else {
|
||||
src = address_expr (src, 0, 0);
|
||||
return new_move_expr (dst, src, dst_type, 1);
|
||||
}
|
||||
}
|
||||
if (is_nil (src)) {
|
||||
src_type = dst_type;
|
||||
convert_nil (src, src_type);
|
||||
}
|
||||
if (dst->type == ex_expr) {
|
||||
if (get_type (dst->e.expr.e1) == &type_entity) {
|
||||
|
@ -420,6 +431,10 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
}
|
||||
}
|
||||
|
||||
if (is_nil (src)) {
|
||||
src_type = dst_type;
|
||||
convert_nil (src, src_type);
|
||||
}
|
||||
if (is_struct (dst_type)) {
|
||||
return new_move_expr (dst, src, dst_type, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue