From c5613ba1e42e42b8ecb07d86ec200b9135a38de2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 14 Nov 2024 18:37:38 +0900 Subject: [PATCH] [qfcc] Use tagged references for spir-v storage The tags might have other uses thus the generic term, but this allows spir-v variables to be declared with the correct pointer storage classes. Now spirv-val is complaining about my interfaces, so progress :) --- tools/qfcc/include/type.h | 3 ++ tools/qfcc/source/target_spirv.c | 55 ++++++++++++++++++++------------ tools/qfcc/source/type.c | 54 +++++++++++++++++++++---------- 3 files changed, 74 insertions(+), 38 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 34fc519d4..87ff6cb40 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -53,6 +53,7 @@ typedef struct ty_func_s { typedef struct ty_fldptr_s { const struct type_s *type; + unsigned tag; bool deref; ///< automatic dereference for pointers (C++ &) } ty_fldptr_t; @@ -159,7 +160,9 @@ const type_t *find_type (const type_t *new); void new_typedef (const char *name, type_t *type); const type_t *field_type (const type_t *aux); const type_t *pointer_type (const type_t *aux); +const type_t *tagged_pointer_type (unsigned tag, const type_t *aux); const type_t *reference_type (const type_t *aux); +const type_t *tagged_reference_type (unsigned tag, const type_t *aux); const type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure)); const type_t *matrix_type (const type_t *ele_type, int cols, int rows) __attribute__((pure)); const type_t *base_type (const type_t *vec_type) __attribute__((pure)); diff --git a/tools/qfcc/source/target_spirv.c b/tools/qfcc/source/target_spirv.c index 16dc2fad2..7a0de08e0 100644 --- a/tools/qfcc/source/target_spirv.c +++ b/tools/qfcc/source/target_spirv.c @@ -269,7 +269,7 @@ spirv_TypePointer (const type_t *type, spirvctx_t *ctx) auto globals = ctx->module->globals; auto insn = spirv_new_insn (SpvOpTypePointer, 4, globals); INSN (insn, 1) = spirv_id (ctx); - INSN (insn, 2) = SpvStorageClassFunction;//FIXME + INSN (insn, 2) = type->fldptr.tag; INSN (insn, 3) = rid; return INSN (insn, 1); } @@ -322,7 +322,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 = reference_type (ptype); + ptype = tagged_reference_type (SpvStorageClassFunction, ptype); } param_types[num_params++] = type_id (ptype, ctx); } @@ -432,14 +432,11 @@ spirv_FunctionParameter (const char *name, const type_t *type, spirvctx_t *ctx) return id; } -static unsigned -spirv_variable (symbol_t *sym, spirvctx_t *ctx) +static SpvStorageClass +spirv_storage_class (unsigned storage) { - if (sym->sy_type != sy_var) { - internal_error (0, "unexpected variable symbol type"); - } - auto interface = glsl_iftype_from_sc (sym->var.storage); - SpvStorageClass storage; + auto interface = glsl_iftype_from_sc (storage); + SpvStorageClass sc = 0; if (interface < glsl_num_interfaces) { static SpvStorageClass iface_storage[glsl_num_interfaces] = { [glsl_in] = SpvStorageClassInput, @@ -447,22 +444,39 @@ spirv_variable (symbol_t *sym, spirvctx_t *ctx) [glsl_uniform] = SpvStorageClassUniform, [glsl_buffer] = SpvStorageClassStorageBuffer, }; - storage = iface_storage[interface]; - } else if (sym->var.storage < sc_count) { + sc = iface_storage[interface]; + } else if (storage < sc_count) { static SpvStorageClass sc_storage[sc_count] = { + [sc_global] = SpvStorageClassPrivate, [sc_static] = SpvStorageClassPrivate, [sc_local] = SpvStorageClassFunction, + [sc_inout] = SpvStorageClassFunction, }; - storage = sc_storage[sym->var.storage]; + sc = sc_storage[storage]; + } + if (!sc) { + internal_error (0, "invalid storage class: %d", storage); + } + return sc; +} + +static unsigned +spirv_variable (symbol_t *sym, spirvctx_t *ctx) +{ + if (sym->sy_type != sy_var) { + internal_error (0, "unexpected variable symbol type"); } auto space = ctx->module->globals; + auto storage = spirv_storage_class (sym->var.storage); if (storage == SpvStorageClassFunction) { space = ctx->decl_space; } + auto type = sym->type; + unsigned tid = type_id (type, ctx); unsigned id = spirv_id (ctx); //FIXME init value auto insn = spirv_new_insn (SpvOpVariable, 4, space); - INSN (insn, 1) = type_id (reference_type (sym->type), ctx); + INSN (insn, 1) = tid; INSN (insn, 2) = id; INSN (insn, 3) = storage; spirv_Name (id, sym->name, ctx); @@ -514,7 +528,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 = reference_type (ptype); + ptype = tagged_reference_type (SpvStorageClassFunction, ptype); } unsigned pid = spirv_FunctionParameter (p->name, ptype, ctx); if (func->parameters) { @@ -939,7 +953,7 @@ spirv_call (const expr_t *call, spirvctx_t *ctx) arg_ids[i] = spirv_emit_expr (a, ctx); } else { auto psym = new_symbol ("param"); - psym->type = reference_type (get_type (a)); + psym->type = tagged_reference_type (SpvStorageClassFunction, get_type (a)); psym->sy_type = sy_var; psym->var.storage = SpvStorageClassFunction; psym->id = spirv_variable (psym, ctx); @@ -1071,7 +1085,8 @@ 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 = reference_type (res_type); + unsigned storage = base_type->fldptr.tag; + acc_type = tagged_reference_type (storage, res_type); op = SpvOpAccessChain; literal_ind = false; } @@ -1273,7 +1288,7 @@ spirv_create_param (symtab_t *parameters, symbol_t *param, param_qual_t qual) auto type = param->type; if (qual != pq_const) { param->lvalue = true; - type = reference_type (type); + type = tagged_reference_type (SpvStorageClassFunction, type); } param->type = type; } @@ -1315,10 +1330,8 @@ 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); - } + auto storage = spirv_storage_class (spec.storage); + sym->type = tagged_reference_type (storage, sym->type); sym->lvalue = !spec.is_const; sym->sy_type = sy_var; sym->var.storage = spec.storage; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index b765e7ffe..babafe543 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -688,7 +688,7 @@ field_type (const type_t *aux) } const type_t * -pointer_type (const type_t *aux) +tagged_pointer_type (unsigned tag, const type_t *aux) { type_t _new; type_t *new = &_new; @@ -701,6 +701,7 @@ pointer_type (const type_t *aux) new->alignment = 1; new->width = 1; new->columns = 1; + new->fldptr.tag = tag; new->fldptr.deref = false; if (aux) { return find_type (append_type (new, aux)); @@ -708,25 +709,38 @@ pointer_type (const type_t *aux) return new; } +const type_t * +pointer_type (const type_t *aux) +{ + return tagged_pointer_type (0, aux); +} + +const type_t * +tagged_reference_type (unsigned tag, const type_t *aux) +{ + type_t _new; + type_t *new = &_new; + + if (aux) + memset (&_new, 0, sizeof (_new)); + else + new = new_type (); + new->type = ev_ptr; + new->alignment = 1; + new->width = 1; + new->columns = 1; + new->fldptr.tag = tag; + new->fldptr.deref = true; + if (aux) { + return find_type (append_type (new, aux)); + } + return new; +} + const type_t * reference_type (const type_t *aux) { - type_t _new; - type_t *new = &_new; - - if (aux) - memset (&_new, 0, sizeof (_new)); - else - new = new_type (); - new->type = ev_ptr; - new->alignment = 1; - new->width = 1; - new->columns = 1; - new->fldptr.deref = true; - if (aux) { - return find_type (append_type (new, aux)); - } - return new; + return tagged_reference_type (0, aux); } const type_t * @@ -1040,6 +1054,9 @@ print_type_str (dstring_t *str, const type_t *type) } } dasprintf (str, "(%c", type->fldptr.deref ? '&' : '*'); + if (type->fldptr.tag) { + dasprintf (str, "%d", type->fldptr.tag); + } print_type_str (str, type->fldptr.type); dasprintf (str, ")"); return; @@ -1266,6 +1283,9 @@ encode_type (dstring_t *encoding, const type_t *type) return; } dasprintf (encoding, type->fldptr.deref ? "&" : "^"); + if (type->fldptr.tag) { + dasprintf (encoding, "%d", type->fldptr.tag); + } type = type->fldptr.type; encode_type (encoding, type); return;