[qfcc] Support the new memset instructions

This commit is contained in:
Bill Currie 2020-03-11 22:57:20 +09:00
parent 6ca85d770d
commit be5f11f33a
4 changed files with 73 additions and 1 deletions

View file

@ -56,6 +56,7 @@ typedef enum {
ex_nil, ///< umm, nil, null. nuff said (0 of any type)
ex_value, ///< constant value (::ex_value_t)
ex_compound, ///< compound initializer
ex_memset, ///< memset needs three params...
} expr_type;
/** Binary and unary expressions.
@ -142,6 +143,12 @@ typedef struct {
struct expr_s *e;
} ex_bool_t;
typedef struct ex_memset_s {
struct expr_s *dst;
struct expr_s *val;
struct expr_s *count;
} ex_memset_t;
/** State expression used for think function state-machines.
State expressions are of the form <code>[framenum, nextthink]</code>
@ -225,6 +232,7 @@ typedef struct expr_s {
ex_vector_t vector; ///< vector expression list
ex_value_t *value; ///< constant value
element_chain_t compound; ///< compound initializer
ex_memset_t memset; ///< memset expr params
} e;
} expr_t;
@ -640,6 +648,9 @@ 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);
/** Convert a name to an expression of the appropriate type.
Converts the expression in-place. If the exprssion is not a name

View file

@ -214,6 +214,7 @@ get_type (expr_t *e)
convert_name (e);
switch (e->type) {
case ex_labelref:
case ex_memset:
return &type_void;
case ex_label:
case ex_error:
@ -436,6 +437,13 @@ copy_expr (expr_t *e)
append_element (n, new_element (i->expr, i->symbol));
}
return n;
case ex_memset:
n = new_expr ();
*n = *e;
n->e.memset.dst = copy_expr (e->e.memset.dst);
n->e.memset.val = copy_expr (e->e.memset.val);
n->e.memset.count = copy_expr (e->e.memset.count);
return n;
}
internal_error (e, "invalid expression");
}
@ -1171,6 +1179,27 @@ new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect)
return e;
}
expr_t *
new_memset_expr (expr_t *dst, expr_t *val, expr_t *count)
{
expr_t *e;
if (!is_pointer (get_type (dst))) {
return error (dst, "incorrect destination type for memset");
}
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;
return e;
}
expr_t *
append_expr (expr_t *block, expr_t *e)
{
@ -1508,6 +1537,7 @@ unary_expr (int op, expr_t *e)
case ex_labelref:
case ex_state:
case ex_compound:
case ex_memset:
internal_error (e, 0);
case ex_uexpr:
if (e->e.expr.op == '-')
@ -1575,6 +1605,7 @@ unary_expr (int op, expr_t *e)
case ex_labelref:
case ex_state:
case ex_compound:
case ex_memset:
internal_error (e, 0);
case ex_bool:
return new_bool_expr (e->e.bool.false_list,
@ -1641,6 +1672,7 @@ unary_expr (int op, expr_t *e)
case ex_labelref:
case ex_state:
case ex_compound:
case ex_memset:
internal_error (e, 0);
case ex_uexpr:
if (e->e.expr.op == '~')

View file

@ -123,6 +123,7 @@ check_valid_lvalue (expr_t *expr)
return check_valid_lvalue (expr->e.expr.e1);
}
break;
case ex_memset:
case ex_compound:
case ex_state:
case ex_bool:

View file

@ -1438,6 +1438,32 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
return sblock;
}
static sblock_t *
statement_memset (sblock_t *sblock, expr_t *e)
{
expr_t *dst = e->e.memset.dst;
expr_t *val = e->e.memset.val;
expr_t *count = e->e.memset.count;
const char *opcode = "<MEMSET>";
statement_t *s;
if (is_constant (count)) {
if (is_integer (get_type (count))
&& (unsigned) expr_integer (count) < 0x10000) {
count = new_short_expr (expr_integer (count));
}
if (is_uinteger (get_type (count)) && expr_integer (count) < 0x10000) {
count = new_short_expr (expr_uinteger (count));
}
}
s = new_statement (st_move, opcode, e);
sblock = statement_subexpr (sblock, dst, &s->opc);
sblock = statement_subexpr (sblock, count, &s->opb);
sblock = statement_subexpr (sblock, val, &s->opa);
sblock_add_statement (sblock, s);
return sblock;
}
static sblock_t *
statement_nonexec (sblock_t *sblock, expr_t *e)
{
@ -1463,10 +1489,12 @@ statement_slist (sblock_t *sblock, expr_t *e)
statement_nonexec, // ex_vector
statement_nonexec, // ex_nil
statement_nonexec, // ex_value
0, // ex_compound
statement_memset,
};
for (/**/; e; e = e->next) {
if (e->type > ex_value)
if (e->type > ex_memset)
internal_error (e, "bad expression type");
sblock = sfuncs[e->type] (sblock, e);
}