diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index ac91860a4..ccdcdae9e 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -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. diff --git a/tools/qfcc/source/expr_call.c b/tools/qfcc/source/expr_call.c index 843fb3747..478c6c021 100644 --- a/tools/qfcc/source/expr_call.c +++ b/tools/qfcc/source/expr_call.c @@ -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; diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index 1fbb3afce..2d7965e71 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -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 {