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 *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);
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue