[qfcc] Emit spir-v global variables

This required adding a `var` symbol type. For now, it holds just the
storage class, but it might be good for the initializer, too.

Also, clean up some pointer/reference inconsistencies.
This commit is contained in:
Bill Currie 2024-11-14 00:41:07 +09:00
parent ae4d87b969
commit 698430630d
5 changed files with 49 additions and 8 deletions

View file

@ -35,6 +35,7 @@
#endif
SY_TYPE(name) ///< just a name (referent tbd)
SY_TYPE(var) ///< symbol refers to a variable
SY_TYPE(offset) ///< symbol refers to a variable (struct member)
SY_TYPE(def) ///< symbol refers to a variable
SY_TYPE(const) ///< symbol refers to a constant

View file

@ -59,6 +59,10 @@ typedef struct symconv_s {
void *data;
} symconv_t;
typedef struct var_s {
enum storage_class_e storage;
} var_t;
typedef struct symbol_s {
struct symbol_s *next; ///< chain of symbols in symbol table
struct symtab_s *table; ///< symbol table that owns this symbol
@ -73,6 +77,7 @@ typedef struct symbol_s {
bool is_constexpr:1;
struct attribute_s *attributes;
union {
var_t var; ///< sy_var
int offset; ///< sy_offset
struct def_s *def; ///< sy_def
struct ex_value_s *value; ///< sy_const

View file

@ -99,6 +99,9 @@ convert_name (const expr_t *e)
&& current_func) {
return new_string_expr (GETSTR (e->loc.file));
}
if (sym->sy_type == sy_var) {
return e;
}
if (!sym->table) {
e = error (e, "%s undefined", sym->name);
sym->type = type_default;

View file

@ -241,6 +241,9 @@ build_args (const expr_t *(*arg_exprs)[2], int *arg_expr_count,
if (param_qual & pq_out) {
auto inout = new_expr ();
inout->type = ex_inout;
if (is_reference(get_type (e))) {
e = pointer_deref (e);
}
if (param_qual == pq_inout) {
inout->inout.in = cast_expr (arg_types[i], e);
}

View file

@ -39,6 +39,7 @@
#include "tools/qfcc/include/defspace.h"
#include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/function.h"
#include "tools/qfcc/include/glsl-lang.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/spirv.h"
#include "tools/qfcc/include/statements.h"
@ -323,7 +324,7 @@ spirv_TypeFunction (symbol_t *fsym, spirvctx_t *ctx)
for (auto p = fsym->params; p; p = p->next) {
auto ptype = p->type;
if (p->qual != pq_const) {
ptype = pointer_type (ptype);
ptype = reference_type (ptype);
}
param_types[num_params++] = type_id (ptype, ctx);
}
@ -434,14 +435,38 @@ spirv_FunctionParameter (const char *name, const type_t *type, spirvctx_t *ctx)
}
static unsigned
spirv_variable (symbol_t *sym, SpvStorageClass storage_class, spirvctx_t *ctx)
spirv_variable (symbol_t *sym, spirvctx_t *ctx)
{
if (sym->sy_type != sy_var) {
internal_error (0, "unexpected variable symbol type");
}
auto interface = glsl_iftype_from_sc (sym->var.storage);
SpvStorageClass storage;
if (interface < glsl_num_interfaces) {
static SpvStorageClass iface_storage[glsl_num_interfaces] = {
[glsl_in] = SpvStorageClassInput,
[glsl_out] = SpvStorageClassOutput,
[glsl_uniform] = SpvStorageClassUniform,
[glsl_buffer] = SpvStorageClassStorageBuffer,
};
storage = iface_storage[interface];
} else if (sym->var.storage < sc_count) {
static SpvStorageClass sc_storage[sc_count] = {
[sc_static] = SpvStorageClassPrivate,
[sc_local] = SpvStorageClassFunction,
};
storage = sc_storage[sym->var.storage];
}
auto space = ctx->module->globals;
if (storage == SpvStorageClassFunction) {
space = ctx->decl_space;
}
unsigned id = spirv_id (ctx);
//FIXME init value
auto insn = spirv_new_insn (SpvOpVariable, 4, ctx->decl_space);
INSN (insn, 1) = type_id (sym->type, ctx);
auto insn = spirv_new_insn (SpvOpVariable, 4, space);
INSN (insn, 1) = type_id (reference_type (sym->type), ctx);
INSN (insn, 2) = id;
INSN (insn, 3) = storage_class;
INSN (insn, 3) = storage;
spirv_Name (id, sym->name, ctx);
return id;
}
@ -479,7 +504,7 @@ spirv_function (function_t *func, spirvctx_t *ctx)
for (auto p = func->sym->params; p; p = p->next) {
auto ptype = p->type;
if (p->qual != pq_const) {
ptype = pointer_type (ptype);
ptype = reference_type (ptype);
}
unsigned pid = spirv_FunctionParameter (p->name, ptype, ctx);
if (func->parameters) {
@ -496,7 +521,7 @@ spirv_function (function_t *func, spirvctx_t *ctx)
if (func->locals) {
spirv_DeclLabel (ctx);
for (auto sym = func->locals->symbols; sym; sym = sym->next) {
sym->id = spirv_variable (sym, SpvStorageClassFunction, ctx);
sym->id = spirv_variable (sym, ctx);
}
} else {
spirv_Label (ctx);
@ -780,6 +805,8 @@ spirv_symbol (const expr_t *e, spirvctx_t *ctx)
} else if (sym->sy_type == sy_func) {
auto func = sym->metafunc->func;
sym->id = spirv_function_ref (func, ctx);
} else if (sym->sy_type == sy_var) {
sym->id = spirv_variable (sym, ctx);
} else {
internal_error (e, "unexpected symbol type: %s for %s",
symtype_str (sym->sy_type), sym->name);
@ -1002,7 +1029,7 @@ spirv_field (const expr_t *e, spirvctx_t *ctx)
auto acc_type = res_type;
bool literal_ind = true;
if (is_pointer (base_type) || is_reference (base_type)) {
acc_type = pointer_type (res_type);
acc_type = reference_type (res_type);
op = SpvOpAccessChain;
literal_ind = false;
}
@ -1251,6 +1278,8 @@ spirv_declare_sym (specifier_t spec, const expr_t *init, symtab_t *symtab,
sym->type = reference_type (sym->type);
}
sym->lvalue = !spec.is_const;
sym->sy_type = sy_var;
sym->var.storage = spec.storage;
symtab_addsymbol (symtab, sym);
if (symtab->type == stab_local) {
if (init) {