mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
[qfcc] Improve handling of nil assignments
Especially when they result in using memset.
This commit is contained in:
parent
0d4c7ba10f
commit
21a8559674
3 changed files with 16 additions and 13 deletions
|
@ -147,6 +147,7 @@ typedef struct ex_memset_s {
|
|||
struct expr_s *dst;
|
||||
struct expr_s *val;
|
||||
struct expr_s *count;
|
||||
struct type_s *type;
|
||||
} ex_memset_t;
|
||||
|
||||
/** State expression used for think function state-machines.
|
||||
|
@ -649,7 +650,7 @@ expr_t *new_param_expr (struct type_s *type, int num);
|
|||
expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type,
|
||||
int indirect);
|
||||
|
||||
expr_t *new_memset_expr (expr_t *dst, expr_t *val, expr_t *count);
|
||||
expr_t *new_memset_expr (expr_t *dst, expr_t *val, struct type_s *type);
|
||||
|
||||
|
||||
/** Convert a name to an expression of the appropriate type.
|
||||
|
|
|
@ -214,8 +214,9 @@ get_type (expr_t *e)
|
|||
convert_name (e);
|
||||
switch (e->type) {
|
||||
case ex_labelref:
|
||||
case ex_memset:
|
||||
return &type_void;
|
||||
case ex_memset:
|
||||
return e->e.memset.type;
|
||||
case ex_label:
|
||||
case ex_error:
|
||||
case ex_compound:
|
||||
|
@ -1186,7 +1187,7 @@ new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect)
|
|||
}
|
||||
|
||||
expr_t *
|
||||
new_memset_expr (expr_t *dst, expr_t *val, expr_t *count)
|
||||
new_memset_expr (expr_t *dst, expr_t *val, type_t *type)
|
||||
{
|
||||
expr_t *e;
|
||||
if (!is_pointer (get_type (dst))) {
|
||||
|
@ -1195,14 +1196,12 @@ new_memset_expr (expr_t *dst, expr_t *val, expr_t *count)
|
|||
if (!is_scalar (get_type (val))) {
|
||||
return error (val, "memset value must be a scalar");
|
||||
}
|
||||
if (!is_integral (get_type (count))) {
|
||||
return error (val, "memset count must be integral");
|
||||
}
|
||||
e = new_expr ();
|
||||
e->type = ex_memset;
|
||||
e->e.memset.dst = dst;
|
||||
e->e.memset.val = val;
|
||||
e->e.memset.count = count;
|
||||
e->e.memset.count = new_integer_expr (type_size (type));
|
||||
e->e.memset.type = type;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -286,6 +286,12 @@ is_indirect (expr_t *e)
|
|||
return is_const_ptr (e->e.expr.e1);
|
||||
}
|
||||
|
||||
static __attribute__((pure)) int
|
||||
is_memset (expr_t *e)
|
||||
{
|
||||
return e->type == ex_memset;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
assign_expr (expr_t *dst, expr_t *src)
|
||||
{
|
||||
|
@ -305,7 +311,7 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
internal_error (dst, "dst_type broke in assign_expr");
|
||||
}
|
||||
|
||||
if (src) {
|
||||
if (src && !is_memset (src)) {
|
||||
convert_name (src);
|
||||
if (src->type == ex_error) {
|
||||
return src;
|
||||
|
@ -316,7 +322,7 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
return expr;
|
||||
}
|
||||
} else {
|
||||
if (is_scalar (dst_type)) {
|
||||
if (!is_memset (src) && is_scalar (dst_type)) {
|
||||
return error (dst, "empty scalar initializer");
|
||||
}
|
||||
src = new_nil_expr ();
|
||||
|
@ -347,7 +353,6 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
@ -383,9 +388,7 @@ assign_expr (expr_t *dst, expr_t *src)
|
|||
if (is_struct (dst_type)) {
|
||||
dst = address_expr (dst, 0, 0);
|
||||
if (is_nil (src)) {
|
||||
int size = type_size (dst_type);
|
||||
return new_memset_expr (dst, new_integer_expr (0),
|
||||
new_integer_expr (size));
|
||||
return new_memset_expr (dst, new_integer_expr (0), dst_type);
|
||||
} else {
|
||||
src = address_expr (src, 0, 0);
|
||||
return new_move_expr (dst, src, dst_type, 1);
|
||||
|
|
Loading…
Reference in a new issue