[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 :)
This commit is contained in:
Bill Currie 2024-11-14 18:37:38 +09:00
parent fa42478af6
commit c5613ba1e4
3 changed files with 74 additions and 38 deletions

View file

@ -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));

View file

@ -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;

View file

@ -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;