diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 421c832e2..01d3f0519 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2380,6 +2380,10 @@ return_expr (function_t *f, const expr_t *e) if (e->type == ex_bool) { e = convert_from_bool (e, ret_type); } + if (is_reference (t) && !is_reference (ret_type)) { + e = pointer_deref (e); + t = dereference_type (t); + } if (is_float(ret_type) && is_int_val (e)) { e = cast_expr (&type_float, e); t = &type_float; diff --git a/tools/qfcc/source/target_spirv.c b/tools/qfcc/source/target_spirv.c index b5dddc76d..9a01a9da2 100644 --- a/tools/qfcc/source/target_spirv.c +++ b/tools/qfcc/source/target_spirv.c @@ -424,6 +424,8 @@ spirv_variable (symbol_t *sym, SpvStorageClass storage_class, spirvctx_t *ctx) return id; } +static unsigned spirv_emit_expr (const expr_t *e, spirvctx_t *ctx); + static unsigned spirv_function (function_t *func, spirvctx_t *ctx) { @@ -454,19 +456,22 @@ spirv_function (function_t *func, spirvctx_t *ctx) } } - if (func->exprs) { + if (func->locals) { spirv_Label (ctx); - } - if (0&&!func->sblock) { - spirv_Unreachable (ctx); - } - for (auto sblock = func->sblock; sblock; sblock = sblock->next) { - if (!sblock->id) { - sblock->id = spirv_Label (ctx); + for (auto sym = func->locals->symbols; sym; sym = sym->next) { + sym->id = spirv_variable (sym, SpvStorageClassFunction, ctx); } + } + int start_size = ctx->code->size; + if (func->exprs) { + spirv_emit_expr (func->exprs, ctx); + } else { spirv_Unreachable (ctx); } - if (0)spirv_FunctionEnd (ctx); + if (ctx->code->size == start_size) { + spirv_Unreachable (ctx); + } + spirv_FunctionEnd (ctx); return func_id; } @@ -616,8 +621,6 @@ spirv_find_op (const char *op_name, etype_t type1, etype_t type2) return nullptr; } -static unsigned spirv_emit_expr (const expr_t *e, spirvctx_t *ctx); - static unsigned spirv_uexpr (const expr_t *e, spirvctx_t *ctx) { @@ -813,8 +816,9 @@ static unsigned spirv_return (const expr_t *e, spirvctx_t *ctx) { if (e->retrn.ret_val) { + unsigned ret_id = spirv_emit_expr (e->retrn.ret_val, ctx); auto def = spirv_new_insn (SpvOpReturnValue, 2, ctx->current); - D_var_o(int, def, 1) = spirv_emit_expr (e->retrn.ret_val, ctx); + D_var_o(int, def, 1) = ret_id; } else { spirv_new_insn (SpvOpReturn, 1, ctx->current); } @@ -956,10 +960,6 @@ spirv_write (struct pr_info_s *pr, const char *filename) for (auto func = pr->func_head; func; func = func->next) { auto func_id = spirv_function (func, &ctx); - for (auto sym = func->locals->symbols; sym; sym = sym->next) { - sym->id = spirv_variable (sym, SpvStorageClassFunction, &ctx); - } - spirv_emit_expr (func->exprs, &ctx); if (strcmp ("main", func->o_name) == 0) { auto model = SpvExecutionModelVertex;//FIXME spirv_EntryPoint (func_id, func->o_name, model, &ctx); @@ -1080,6 +1080,10 @@ spirv_declare_sym (specifier_t spec, const expr_t *init, symtab_t *symtab) if (check && check->table == symtab) { error (0, "%s redefined", sym->name); } + if (symtab->type == stab_local) { + // spir-v locals are references + sym->type = reference_type (sym->type); + } symtab_addsymbol (symtab, sym); }