[qfcc] Add an intrinsic expression type

This will be fore generating specific SPIR-V instructions via function
calls, and could be useful for Ruamoko, too.
This commit is contained in:
Bill Currie 2024-11-22 22:25:47 +09:00
parent 0dfe81bce8
commit 1893df34a3
7 changed files with 55 additions and 0 deletions

View file

@ -373,6 +373,12 @@ typedef struct {
bool not;
} ex_select_t;
typedef struct {
const expr_t *opcode;
const type_t *res_type;
ex_list_t operands;
} ex_intrinsic_t;
typedef struct expr_s {
expr_t *next;
rua_loc_t loc; ///< source location of expression
@ -421,6 +427,7 @@ typedef struct expr_s {
ex_decl_t decl; ///< variable declaration expression
ex_loop_t loop; ///< loop construct expression
ex_select_t select; ///< selection construct expression
ex_intrinsic_t intrinsic; ///< intrinsic intruction expression
};
} expr_t;

View file

@ -76,6 +76,7 @@ EX_EXPR(array) ///< array index expression (::ex_array_t)
EX_EXPR(decl) ///< delcaration expression (::ex_array_t)
EX_EXPR(loop) ///< loop construct expression (::ex_loop_t)
EX_EXPR(select) ///< select construct expression (::ex_select_t)
EX_EXPR(intrinsic) ///< intrinsic instruction expression (::ex_intrinsic_t)
#undef EX_EXPR

View file

@ -399,6 +399,22 @@ print_array (dstring_t *dstr, const expr_t *e, int level, int id,
"[]", e->loc.line);
}
static void
print_intrinsic (dstring_t *dstr, const expr_t *e, int level, int id,
const expr_t *next)
{
int indent = level * 2 + 2;
_print_expr (dstr, e->intrinsic.opcode, level, id, next);
for (auto l = e->intrinsic.operands.head; l; l = l->next) {
_print_expr (dstr, l->expr, level, id, next);
}
for (auto l = e->intrinsic.operands.head; l; l = l->next) {
dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"b\"];\n", indent, "", e,
l->expr);
}
}
static void
print_subexpr (dstring_t *dstr, const expr_t *e, int level, int id, const expr_t *next)
{
@ -854,6 +870,9 @@ _print_expr (dstring_t *dstr, const expr_t *e, int level, int id,
[ex_field] = print_field,
[ex_array] = print_array,
[ex_decl] = nullptr,
[ex_loop] = nullptr,
[ex_select] = nullptr,
[ex_intrinsic] = print_intrinsic,
};
int indent = level * 2 + 2;

View file

@ -224,6 +224,9 @@ get_type (const expr_t *e)
return e->field.type;
case ex_array:
return e->array.type;
case ex_intrinsic:
type = e->intrinsic.res_type;
break;
case ex_count:
internal_error (e, "invalid expression");
}
@ -1990,6 +1993,7 @@ has_function_call (const expr_t *e)
case ex_decl:
case ex_loop:
case ex_select:
case ex_intrinsic:
return false;
case ex_multivec:
for (auto c = e->multivec.components.head; c; c = c->next) {

View file

@ -136,6 +136,7 @@ is_lvalue (const expr_t *expr)
case ex_decl:
case ex_loop:
case ex_select:
case ex_intrinsic:
break;
case ex_cond:
return (is_lvalue (expr->cond.true_expr)

View file

@ -82,6 +82,7 @@ edag_add_expr (const expr_t *expr)
case ex_decl:
case ex_loop:
case ex_select:
case ex_intrinsic:
// these are never put in the dag
return expr;
case ex_list:

View file

@ -414,6 +414,27 @@ proc_select (const expr_t *expr)
return select;
}
static const expr_t *
proc_intrinsic (const expr_t *expr)
{
int count = list_count (&expr->intrinsic.operands);
const expr_t *operands[count + 1];
list_scatter (&expr->intrinsic.operands, operands);
auto opcode = expr_process (expr->intrinsic.opcode);
for (int i = 0; i < count; i++) {
operands[i] = expr_process (operands[i]);
}
scoped_src_loc (expr);
auto e = new_expr ();
e->type = ex_intrinsic;
e->intrinsic = (ex_intrinsic_t) {
.opcode = opcode,
.res_type = expr->intrinsic.res_type,
};
list_gather (&e->intrinsic.operands, operands, count);
return e;
}
const expr_t *
expr_process (const expr_t *expr)
{
@ -438,6 +459,7 @@ expr_process (const expr_t *expr)
[ex_decl] = proc_decl,
[ex_loop] = proc_loop,
[ex_select] = proc_select,
[ex_intrinsic] = proc_intrinsic,
};
if (expr->type >= ex_count) {