[qfcc] Improve support for matrix types

Their size is now calculated correctly, they can be assigned,
initialized using block initializers (vectors too!), and columns can be
indexed as vector lvalues.
This commit is contained in:
Bill Currie 2024-09-05 14:06:30 +09:00
parent e9d5bac369
commit 24a48ad703
5 changed files with 32 additions and 9 deletions

View file

@ -1309,7 +1309,7 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src,
operand_t *operands[3] = {0, 0, 0};
daglabel_t *var;
if (is_structural (type) || type->width > 4) {
if (is_structural (type) || is_matrix (type) || type->width > 4) {
operands[0] = fix_op_type (src, type);
operands[1] = short_operand (type_size (type), src->expr);
for ( ; var_iter; var_iter = set_next (var_iter)) {

View file

@ -2830,11 +2830,16 @@ array_expr (const expr_t *array, const expr_t *index)
|| ind - array_type->array.base >= array_type->array.size)) {
return error (index, "array index out of bounds");
}
if (is_nonscalar (array_type)
if (is_nonscalar (array_type) && !is_matrix (array_type)
&& is_constant (index)
&& (ind < 0 || ind >= array_type->width)) {
return error (index, "array index out of bounds");
}
if (is_matrix (array_type)
&& is_constant (index)
&& (ind < 0 || ind >= array_type->columns)) {
return error (index, "array index out of bounds");
}
if (is_array (array_type)) {
ele_type = dereference_type (array_type);
base = new_int_expr (array_type->array.base, false);
@ -2842,7 +2847,10 @@ array_expr (const expr_t *array, const expr_t *index)
ele_type = array_type->fldptr.type;
base = new_int_expr (0, false);
} else {
ele_type = ev_types[array_type->type];
ele_type = base_type (array_type);
if (is_matrix (array_type)) {
ele_type = vector_type (ele_type, array_type->width);
}
if (array->type == ex_uexpr && array->expr.op == '.') {
auto vec = offset_pointer_expr (array->expr.e1, index);
vec = cast_expr (pointer_type (ele_type), vec);

View file

@ -229,6 +229,10 @@ build_element_chain (element_chain_t *element_chain, const type_t *type,
state.type = state.field->type;
state.offset = state.field->offset;
}
} else if (is_matrix (type)) {
state.type = vector_type (base_type (type), type->width);
} else if (is_nonscalar (type)) {
state.type = base_type (type);
} else if (is_array (type)) {
state.type = dereference_type (type);
} else {

View file

@ -967,7 +967,8 @@ expr_assign (sblock_t *sblock, const expr_t *e, operand_t **op)
if (src_expr->type == ex_assign) {
sblock = statement_subexpr (sblock, src_expr, &src);
if (is_structural (dst_type) || dst_type->width > 4) {
if (is_structural (dst_type) || is_matrix (dst_type)
|| dst_type->width > 4) {
return expr_assign_copy (sblock, e, op, src);
}
if (is_indirect (dst_expr)) {
@ -976,7 +977,8 @@ expr_assign (sblock_t *sblock, const expr_t *e, operand_t **op)
sblock = statement_subexpr (sblock, dst_expr, &dst);
}
} else {
if (is_structural (dst_type) || dst_type->width > 4) {
if (is_structural (dst_type) || is_matrix (dst_type)
|| dst_type->width > 4) {
return expr_assign_copy (sblock, e, op, src);
}

View file

@ -987,9 +987,18 @@ print_type_str (dstring_t *str, const type_t *type)
case ev_short:
case ev_ushort:
case ev_double:
dasprintf (str, " %s%s", pr_type_name[type->type],
type->width > 1 ? va (0, "{%d}", type->width)
: "");
{
const char *name = pr_type_name[type->type];
int width = type->width;
int cols = type->columns;
if (cols > 1) {
dasprintf (str, " %s{%d,%d}", name, cols, width);
} else if (type->width > 1) {
dasprintf (str, " %s{%d}", name, width);
} else {
dasprintf (str, " %s", name);
}
}
return;
case ev_invalid:
case ev_type_count:
@ -1504,7 +1513,7 @@ type_size (const type_t *type)
internal_error (0, "%s:%d:%d", pr_type_name[type->type],
type->columns, type->width);
}
return pr_type_size[type->type] * type->width;
return pr_type_size[type->type] * type->width * type->columns;
case ty_struct:
case ty_union:
if (!type->symtab)