[qfcc] Handle explicit arguments to intrinsics

There are problems with symbol lookup (eg, generic type names, image
operand names) but the system seems to be working: texelFetch ->
OpImageFetch (which uses explicit arguments even though it doesn't need
to) seems to set the arguments to OpImageFetch correctly.
This commit is contained in:
Bill Currie 2025-01-17 18:14:21 +09:00
parent 393ef8f455
commit c48fe5e7f5
4 changed files with 65 additions and 15 deletions

View file

@ -1075,7 +1075,7 @@ const expr_t *field_expr (const expr_t *e1, const expr_t *e2);
const expr_t *asx_expr (int op, const expr_t *e1, const expr_t *e2); const expr_t *asx_expr (int op, const expr_t *e1, const expr_t *e2);
const expr_t *unary_expr (int op, const expr_t *e); const expr_t *unary_expr (int op, const expr_t *e);
const expr_t *build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *build_function_call (const expr_t *fexpr, const type_t *ftype,
const expr_t *params); const expr_t *params, rua_ctx_t *ctx);
const expr_t *function_expr (const expr_t *e1, const expr_t *e2, const expr_t *function_expr (const expr_t *e1, const expr_t *e2,
rua_ctx_t *ctx); rua_ctx_t *ctx);
const expr_t *get_column (const expr_t *e, int i); const expr_t *get_column (const expr_t *e, int i);

View file

@ -1672,8 +1672,9 @@ class_finish_module (rua_ctx_t *ctx)
module_expr = address_expr (new_symbol_expr (module_sym), 0); module_expr = address_expr (new_symbol_expr (module_sym), 0);
module_expr = new_list_expr (module_expr); module_expr = new_list_expr (module_expr);
add_ctor_expr (build_function_call (new_symbol_expr (exec_class_sym), auto class_sym_expr = new_symbol_expr (exec_class_sym);
exec_class_sym->type, module_expr)); add_ctor_expr (build_function_call (class_sym_expr, exec_class_sym->type,
module_expr, ctx));
} }
protocol_t * protocol_t *

View file

@ -206,20 +206,68 @@ check_arg_types (const expr_t **arguments, const type_t **arg_types,
} }
static expr_t * static expr_t *
build_intrinsic_call (const expr_t *expr, const type_t *ftype, build_intrinsic_call (const expr_t *expr, symbol_t *fsym, const type_t *ftype,
const expr_t **arguments, int arg_count) const expr_t **arguments, int arg_count, rua_ctx_t *ctx)
{ {
for (int i = 0; i < arg_count; i++) {
if (is_reference (get_type (arguments[i]))) {
arguments[i] = pointer_deref (arguments[i]);
}
}
auto call = new_intrinsic_expr (nullptr); auto call = new_intrinsic_expr (nullptr);
call->intrinsic.opcode = expr->intrinsic.opcode; call->intrinsic.opcode = expr->intrinsic.opcode;
call->intrinsic.res_type = ftype->func.ret_type; call->intrinsic.res_type = ftype->func.ret_type;
list_append_list (&call->intrinsic.operands, list_append_list (&call->intrinsic.operands,
&expr->intrinsic.operands); &expr->intrinsic.operands);
list_gather (&call->intrinsic.operands, arguments, arg_count); if (expr->intrinsic.extra) {
if (expr->intrinsic.extra->type != ex_list) {
internal_error (expr->intrinsic.extra, "not a list");
}
auto params = new_symtab (current_symtab, stab_param);
int i = 0;
for (auto p = fsym->params; p; p = p->next, i++) {
if (!p->selector && !p->type && !p->name) {
internal_error (0, "inline variadic not implemented");
}
if (!p->type) {
continue; // non-param selector
}
if (is_void (p->type)) {
if (p->name) {
error (0, "invalid parameter type for %s", p->name);
} else if (p != fsym->params || p->next) {
error (0, "void must be the only parameter");
continue;
} else {
continue;
}
}
if (!p->name) {
notice (0, "parameter name omitted");
continue;
}
auto psym = new_symbol (p->name);
psym->sy_type = sy_expr;
psym->expr = arguments[i];
symtab_addsymbol (params, psym);
}
auto extra = &expr->intrinsic.extra->list;
int extra_count = list_count (extra);
const expr_t *extra_args[extra_count + 1] = {};
list_scatter (extra, extra_args);
auto scope = current_symtab;
current_symtab = params;
for (int i = 0; i < extra_count; i++) {
extra_args[i] = expr_process (extra_args[i], ctx);
}
current_symtab = scope;
list_gather (&call->intrinsic.operands, extra_args, extra_count);
} else {
for (int i = 0; i < arg_count; i++) {
if (is_reference (get_type (arguments[i]))) {
arguments[i] = pointer_deref (arguments[i]);
}
}
list_gather (&call->intrinsic.operands, arguments, arg_count);
}
return call; return call;
} }
@ -389,7 +437,7 @@ build_args (const expr_t *(*arg_exprs)[2], int *arg_expr_count,
const expr_t * const expr_t *
build_function_call (const expr_t *fexpr, const type_t *ftype, build_function_call (const expr_t *fexpr, const type_t *ftype,
const expr_t *args) const expr_t *args, rua_ctx_t *ctx)
{ {
int param_count = 0; int param_count = 0;
const expr_t *err = 0; const expr_t *err = 0;
@ -421,7 +469,8 @@ build_function_call (const expr_t *fexpr, const type_t *ftype,
auto metafunc = fsym->metafunc; auto metafunc = fsym->metafunc;
auto expr = metafunc->expr; auto expr = metafunc->expr;
if (expr->type == ex_intrinsic) { if (expr->type == ex_intrinsic) {
return build_intrinsic_call (expr, ftype, arguments, arg_count); return build_intrinsic_call (expr, fsym, ftype,
arguments, arg_count, ctx);
} }
if (metafunc->can_inline) { if (metafunc->can_inline) {
return build_inline_call (fsym, ftype, arguments, arg_count); return build_inline_call (fsym, ftype, arguments, arg_count);
@ -484,7 +533,7 @@ function_expr (const expr_t *fexpr, const expr_t *args, rua_ctx_t *ctx)
PrecacheFile (expr_string (arg), fexpr->symbol->name[13]); PrecacheFile (expr_string (arg), fexpr->symbol->name[13]);
} }
return build_function_call (fexpr, ftype, args); return build_function_call (fexpr, ftype, args, ctx);
} }
const expr_t * const expr_t *

View file

@ -250,7 +250,7 @@ message_expr (const expr_t *receiver, keywordarg_t *message, rua_ctx_t *ctx)
return err; return err;
method_type = method->type; method_type = method->type;
} }
call = build_function_call (send_msg, method_type, args); call = build_function_call (send_msg, method_type, args, ctx);
if (call->type == ex_error) if (call->type == ex_error)
return receiver; return receiver;