mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 01:42:04 +00:00
[qfcc] Handle return
in inline functions
The code is pretty lousy in that it assumes there's only one `return` and it's the end of the function, and the generated code is even worse (too many load/store ops in the spir-v), but it looks like it at least works. It does pass validation.
This commit is contained in:
parent
21eed88da5
commit
626680f22f
3 changed files with 33 additions and 0 deletions
|
@ -155,6 +155,10 @@ typedef struct function_s {
|
|||
int pseudo_addr;///< pseudo address space for flow analysis
|
||||
struct pseudoop_s *pseudo_ops;///< pseudo operands used by this function
|
||||
const expr_t *exprs;
|
||||
|
||||
const expr_t *(*return_imp) (function_t *func, const expr_t *val);
|
||||
const expr_t *return_val;
|
||||
const expr_t *return_label;
|
||||
} function_t;
|
||||
|
||||
/** Represent an overloading of a function.
|
||||
|
|
|
@ -223,6 +223,25 @@ build_intrinsic_call (const expr_t *expr, const type_t *ftype,
|
|||
return call;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
inline_return_expr (function_t *func, const expr_t *val)
|
||||
{
|
||||
if (!func->return_val && val) {
|
||||
return error (val, "returning a value for a void function");
|
||||
}
|
||||
if (func->return_val && !val) {
|
||||
return error (val, "return from non-void function without a value");
|
||||
}
|
||||
auto ret = new_block_expr (nullptr);
|
||||
if (val) {
|
||||
append_expr (ret, assign_expr (func->return_val, val));
|
||||
}
|
||||
if (func->return_label) {
|
||||
append_expr (ret, goto_expr (func->return_label));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
build_inline_call (symbol_t *fsym, const type_t *ftype,
|
||||
const expr_t **arguments, int arg_count)
|
||||
|
@ -278,12 +297,19 @@ build_inline_call (symbol_t *fsym, const type_t *ftype,
|
|||
append_expr (call, decl);
|
||||
call->block.result = new_symbol_expr (ret);
|
||||
}
|
||||
func->return_val = call->block.result;
|
||||
|
||||
auto expr = metafunc->expr;
|
||||
if (expr->type == ex_block) {
|
||||
expr->block.scope->parent = locals;
|
||||
}
|
||||
append_expr (call, expr);
|
||||
|
||||
func->return_label = nullptr;//new_label_expr ();
|
||||
//append_expr (call, func->return_label);
|
||||
|
||||
func->return_imp = inline_return_expr;
|
||||
|
||||
auto proc = new_process_expr (call);
|
||||
proc->process.function = func;
|
||||
|
||||
|
|
|
@ -511,6 +511,9 @@ proc_return (const expr_t *expr, rua_ctx_t *ctx)
|
|||
if (ret_val) {
|
||||
ret_val = expr_process (ret_val, ctx);
|
||||
}
|
||||
if (current_func->return_imp) {
|
||||
return current_func->return_imp (current_func, ret_val);
|
||||
}
|
||||
if (expr->retrn.at_return) {
|
||||
return at_return_expr (current_func, ret_val);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue