mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 05:01:24 +00:00
[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:
parent
393ef8f455
commit
c48fe5e7f5
4 changed files with 65 additions and 15 deletions
|
@ -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 *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 *params);
|
||||
const expr_t *params, rua_ctx_t *ctx);
|
||||
const expr_t *function_expr (const expr_t *e1, const expr_t *e2,
|
||||
rua_ctx_t *ctx);
|
||||
const expr_t *get_column (const expr_t *e, int i);
|
||||
|
|
|
@ -1672,8 +1672,9 @@ class_finish_module (rua_ctx_t *ctx)
|
|||
module_expr = address_expr (new_symbol_expr (module_sym), 0);
|
||||
module_expr = new_list_expr (module_expr);
|
||||
|
||||
add_ctor_expr (build_function_call (new_symbol_expr (exec_class_sym),
|
||||
exec_class_sym->type, module_expr));
|
||||
auto class_sym_expr = new_symbol_expr (exec_class_sym);
|
||||
add_ctor_expr (build_function_call (class_sym_expr, exec_class_sym->type,
|
||||
module_expr, ctx));
|
||||
}
|
||||
|
||||
protocol_t *
|
||||
|
|
|
@ -206,20 +206,68 @@ check_arg_types (const expr_t **arguments, const type_t **arg_types,
|
|||
}
|
||||
|
||||
static expr_t *
|
||||
build_intrinsic_call (const expr_t *expr, const type_t *ftype,
|
||||
const expr_t **arguments, int arg_count)
|
||||
build_intrinsic_call (const expr_t *expr, symbol_t *fsym, const type_t *ftype,
|
||||
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);
|
||||
call->intrinsic.opcode = expr->intrinsic.opcode;
|
||||
call->intrinsic.res_type = ftype->func.ret_type;
|
||||
list_append_list (&call->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;
|
||||
}
|
||||
|
||||
|
@ -389,7 +437,7 @@ build_args (const expr_t *(*arg_exprs)[2], int *arg_expr_count,
|
|||
|
||||
const expr_t *
|
||||
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;
|
||||
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 expr = metafunc->expr;
|
||||
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) {
|
||||
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]);
|
||||
}
|
||||
|
||||
return build_function_call (fexpr, ftype, args);
|
||||
return build_function_call (fexpr, ftype, args, ctx);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
|
|
|
@ -250,7 +250,7 @@ message_expr (const expr_t *receiver, keywordarg_t *message, rua_ctx_t *ctx)
|
|||
return err;
|
||||
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)
|
||||
return receiver;
|
||||
|
|
Loading…
Reference in a new issue