[qfcc] Improve handling of nil assignments

Especially when they result in using memset.
This commit is contained in:
Bill Currie 2020-03-12 19:30:54 +09:00
parent 0d4c7ba10f
commit 21a8559674
3 changed files with 16 additions and 13 deletions

View file

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

View file

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

View file

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