mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Ensure final block is terminated
Which for a function means return or unreachable (though I suppose branches might work).
This commit is contained in:
parent
5033dc9a12
commit
fa42478af6
1 changed files with 34 additions and 10 deletions
|
@ -48,7 +48,7 @@
|
||||||
#include "tools/qfcc/include/target.h"
|
#include "tools/qfcc/include/target.h"
|
||||||
#include "tools/qfcc/include/type.h"
|
#include "tools/qfcc/include/type.h"
|
||||||
|
|
||||||
#define INSN(i,o) D_var_o(int,&(i),o)
|
#define INSN(i,o) D_var_o(int,(i),o)
|
||||||
#define ADD_DATA(d,s) defspace_add_data((d), (s)->data, (s)->size)
|
#define ADD_DATA(d,s) defspace_add_data((d), (s)->data, (s)->size)
|
||||||
|
|
||||||
typedef struct spirvctx_s {
|
typedef struct spirvctx_s {
|
||||||
|
@ -83,19 +83,17 @@ spirv_add_type_id (const type_t *type, unsigned id, spirvctx_t *ctx)
|
||||||
ctx->type_ids.a[type->id] = id;
|
ctx->type_ids.a[type->id] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static def_t
|
static def_t *
|
||||||
spirv_new_insn (int op, int size, defspace_t *space)
|
spirv_new_insn (int op, int size, defspace_t *space)
|
||||||
{
|
{
|
||||||
def_t insn = {
|
auto insn = new_def (nullptr, nullptr, space, sc_static);
|
||||||
.space = space,
|
insn->offset = defspace_alloc_highwater (space, size);
|
||||||
.offset = defspace_alloc_highwater (space, size),
|
|
||||||
};
|
|
||||||
|
|
||||||
INSN (insn, 0) = (op & SpvOpCodeMask) | (size << SpvWordCountShift);
|
INSN (insn, 0) = (op & SpvOpCodeMask) | (size << SpvWordCountShift);
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static def_t
|
static def_t *
|
||||||
spirv_str_insn (int op, int offs, int extra, const char *str, defspace_t *space)
|
spirv_str_insn (int op, int offs, int extra, const char *str, defspace_t *space)
|
||||||
{
|
{
|
||||||
int len = strlen (str) + 1;
|
int len = strlen (str) + 1;
|
||||||
|
@ -473,6 +471,17 @@ spirv_variable (symbol_t *sym, spirvctx_t *ctx)
|
||||||
|
|
||||||
static unsigned spirv_emit_expr (const expr_t *e, spirvctx_t *ctx);
|
static unsigned spirv_emit_expr (const expr_t *e, spirvctx_t *ctx);
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
spirv_undef (const type_t *type, spirvctx_t *ctx)
|
||||||
|
{
|
||||||
|
unsigned type_id = spirv_type_id (type, ctx);
|
||||||
|
unsigned id = spirv_id (ctx);
|
||||||
|
auto insn = spirv_new_insn (SpvOpUndef, 3, ctx->module->globals);
|
||||||
|
INSN (insn, 1) = type_id;
|
||||||
|
INSN (insn, 2) = id;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
spirv_function_ref (function_t *func, spirvctx_t *ctx)
|
spirv_function_ref (function_t *func, spirvctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
@ -492,10 +501,11 @@ spirv_function (function_t *func, spirvctx_t *ctx)
|
||||||
defspace_reset (ctx->code_space);
|
defspace_reset (ctx->code_space);
|
||||||
defspace_reset (ctx->decl_space);
|
defspace_reset (ctx->decl_space);
|
||||||
|
|
||||||
|
auto ret_type = func->type->func.ret_type;
|
||||||
unsigned func_id = spirv_function_ref (func, ctx);
|
unsigned func_id = spirv_function_ref (func, ctx);
|
||||||
|
|
||||||
auto insn = spirv_new_insn (SpvOpFunction, 5, ctx->decl_space);
|
auto insn = spirv_new_insn (SpvOpFunction, 5, ctx->decl_space);
|
||||||
INSN (insn, 1) = type_id (func->type->func.ret_type, ctx);
|
INSN (insn, 1) = type_id (ret_type, ctx);
|
||||||
INSN (insn, 2) = func_id;
|
INSN (insn, 2) = func_id;
|
||||||
INSN (insn, 3) = 0;
|
INSN (insn, 3) = 0;
|
||||||
INSN (insn, 4) = ft_id;
|
INSN (insn, 4) = ft_id;
|
||||||
|
@ -529,8 +539,22 @@ spirv_function (function_t *func, spirvctx_t *ctx)
|
||||||
int start_size = ctx->code_space->size;
|
int start_size = ctx->code_space->size;
|
||||||
if (func->exprs) {
|
if (func->exprs) {
|
||||||
spirv_emit_expr (func->exprs, ctx);
|
spirv_emit_expr (func->exprs, ctx);
|
||||||
|
}
|
||||||
|
def_t *last_insn = nullptr;
|
||||||
|
if (ctx->code_space->def_tail != &ctx->code_space->defs) {
|
||||||
|
last_insn = (def_t *) ctx->code_space->def_tail;
|
||||||
|
}
|
||||||
|
if (!last_insn
|
||||||
|
|| ((INSN(last_insn, 0) & SpvOpCodeMask) != SpvOpReturn
|
||||||
|
&& (INSN(last_insn, 0) & SpvOpCodeMask) != SpvOpReturnValue
|
||||||
|
&& (INSN(last_insn, 0) & SpvOpCodeMask) != SpvOpUnreachable)) {
|
||||||
|
if (is_void (ret_type)) {
|
||||||
|
spirv_new_insn (SpvOpReturn, 1, ctx->code_space);
|
||||||
} else {
|
} else {
|
||||||
spirv_Unreachable (ctx);
|
unsigned ret_id = spirv_undef (ret_type, ctx);
|
||||||
|
auto insn = spirv_new_insn (SpvOpReturnValue, 2, ctx->code_space);
|
||||||
|
INSN (insn, 1) = ret_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ctx->code_space->size == start_size) {
|
if (ctx->code_space->size == start_size) {
|
||||||
spirv_Unreachable (ctx);
|
spirv_Unreachable (ctx);
|
||||||
|
|
Loading…
Reference in a new issue