[qfcc] Use a separate enum for glsl interfaces

While technically storage classes, they shouldn't pollute other
languages. It's a bit hacky mixing enums in one value, but having some
macros helps.
This commit is contained in:
Bill Currie 2024-09-09 11:34:51 +09:00
parent c4c4b9f5b4
commit 7a2027276b
6 changed files with 57 additions and 64 deletions

View file

@ -45,6 +45,18 @@ extern language_t lang_glsl_tese;
extern language_t lang_glsl_geom;
extern language_t lang_glsl_frag;
typedef enum glsl_interface_e : unsigned {
glsl_in,
glsl_out,
glsl_uniform,
glsl_buffer,
glsl_shared,
glsl_num_interfaces
} glsl_interface_t;
#define glsl_iftype_from_sc(sc) ((glsl_interface_t)((sc) - sc_in))
#define glsl_sc_from_iftype(it) (((storage_class_t)(it)) + sc_in)
typedef struct glsl_block_s {
struct glsl_block_s *next;
const char *name;

View file

@ -38,7 +38,7 @@ typedef struct symtab_s symtab_t;
/** Specify the storage class of a def.
*/
typedef enum storage_class_e {
typedef enum storage_class_e : unsigned {
sc_global, ///< def is globally visible across units
sc_system, ///< def may be redefined once
sc_extern, ///< def is externally allocated
@ -47,14 +47,15 @@ typedef enum storage_class_e {
sc_local, ///< def is local to the current function
sc_argument, ///< def is a function argument
sc_inout,
sc_in,
sc_out,
sc_inout,
sc_uniform,
sc_buffer,
sc_shared,
sc_count
} storage_class_t;
extern const char *storage_class_names[sc_count];
typedef struct specifier_s {
const type_t *type;
const expr_t *type_expr;

View file

@ -70,22 +70,12 @@ set_storage_bits (def_t *def, storage_class_t storage)
{
def->storage_bits = 0;
switch (storage) {
case sc_out:
case sc_buffer:
case sc_shared:
def->global = true;
break;
case sc_system:
def->system = true;
// fall through
case sc_global:
def->global = true;
break;
case sc_in:
case sc_uniform:
def->global = true;
def->readonly = true;
break;
case sc_extern:
def->global = true;
def->external = true;
@ -96,6 +86,8 @@ set_storage_bits (def_t *def, storage_class_t storage)
def->local = true;
break;
case sc_inout:
case sc_in:
case sc_out:
case sc_param:
def->local = true;
def->param = true;
@ -104,13 +96,15 @@ set_storage_bits (def_t *def, storage_class_t storage)
def->local = true;
def->argument = true;
break;
case sc_count:
break;
}
}
static bool
deferred_size (storage_class_t storage)
{
if (storage == sc_in || storage == sc_uniform || storage == sc_buffer) {
if (storage >= sc_in) {
return true;
}
return false;

View file

@ -42,11 +42,7 @@
ALLOC_STATE (glsl_block_t, blocks);
static hashtab_t *input_blocks;
static hashtab_t *output_blocks;
static hashtab_t *uniform_blocks;
static hashtab_t *buffer_blocks;
static hashtab_t *shared_blocks;
static hashtab_t *interfaces[glsl_num_interfaces];
static const char *
block_get_key (const void *_b, void *)
@ -58,18 +54,14 @@ block_get_key (const void *_b, void *)
void
glsl_block_clear (void)
{
if (input_blocks) {
Hash_FlushTable (input_blocks);
Hash_FlushTable (output_blocks);
Hash_FlushTable (uniform_blocks);
Hash_FlushTable (buffer_blocks);
Hash_FlushTable (shared_blocks);
if (interfaces[glsl_in]) {
for (auto i = glsl_in; i < glsl_num_interfaces; i++) {
Hash_FlushTable (interfaces[i]);
}
} else {
input_blocks = Hash_NewTable (127, block_get_key, 0, 0, 0);
output_blocks = Hash_NewTable (127, block_get_key, 0, 0, 0);
uniform_blocks = Hash_NewTable (127, block_get_key, 0, 0, 0);
buffer_blocks = Hash_NewTable (127, block_get_key, 0, 0, 0);
shared_blocks = Hash_NewTable (127, block_get_key, 0, 0, 0);
for (auto i = glsl_in; i < glsl_num_interfaces; i++) {
interfaces[i] = Hash_NewTable (127, block_get_key, 0, 0, 0);
}
}
}
@ -83,32 +75,10 @@ void
glsl_declare_block (specifier_t spec, symbol_t *block_sym,
symbol_t *instance_name)
{
auto interface = glsl_iftype_from_sc(spec.storage);
hashtab_t *block_tab = nullptr;
switch (spec.storage) {
case sc_in:
block_tab = input_blocks;
break;
case sc_out:
block_tab = output_blocks;
break;
case sc_uniform:
block_tab = uniform_blocks;
break;
case sc_buffer:
block_tab = buffer_blocks;
break;
case sc_shared:
block_tab = shared_blocks;
break;
case sc_global:
case sc_system:
case sc_extern:
case sc_static:
case sc_param:
case sc_local:
case sc_argument:
case sc_inout:
break;
if (interface < glsl_num_interfaces) {
block_tab = interfaces[interface];
}
if (!block_tab) {
error (0, "invalid storage for block: %d", spec.storage);

View file

@ -1133,12 +1133,18 @@ jump_statement
%%
#define GLSL_INTERFACE(bt) .spec = { .storage = glsl_sc_from_iftype (bt) }
static keyword_t glsl_keywords[] = {
{"const", GLSL_CONST, .spec = { .is_const = true }},
{"uniform", GLSL_UNIFORM, .spec = { .storage = sc_uniform }},
{"buffer", GLSL_BUFFER, .spec = { .storage = sc_buffer }},
{"shared", GLSL_SHARED, .spec = { .storage = sc_shared }},
{"uniform", GLSL_UNIFORM, GLSL_INTERFACE (glsl_uniform)},
{"buffer", GLSL_BUFFER, GLSL_INTERFACE (glsl_buffer)},
{"shared", GLSL_SHARED, GLSL_INTERFACE (glsl_shared)},
// in and out are both parameter qualifiers (sc_in and sc_out) and
// glsl interface types (glsl_in and glsl_out). Assume interface type
// here.
{"in", GLSL_IN, GLSL_INTERFACE (glsl_in )},
{"out", GLSL_OUT, GLSL_INTERFACE (glsl_out )},
{"inout", GLSL_INOUT, .spec = { .storage = sc_inout }},
{"attribute", GLSL_RESERVED},
{"varying", GLSL_RESERVED},
{"coherent", GLSL_COHERENT},
@ -1167,9 +1173,6 @@ static keyword_t glsl_keywords[] = {
{"if", GLSL_IF},
{"else", GLSL_ELSE},
{"subroutine", GLSL_RESERVED},
{"in", GLSL_IN, .spec = { .storage = sc_in }},
{"out", GLSL_OUT, .spec = { .storage = sc_out }},
{"inout", GLSL_INOUT},
{"int", GLSL_TYPE_SPEC, .spec = {.type = &type_int}},
{"void", GLSL_VOID, .spec = {.type = &type_void}},
{"bool", GLSL_TYPE_SPEC, .spec = {.type = &type_bool}},

View file

@ -40,6 +40,19 @@
#include "tools/qfcc/include/symtab.h"
#include "tools/qfcc/include/type.h"
const char *storage_class_names[sc_count] = {
"global",
"system",
"extern",
"static",
"param",
"local",
"argument",
"inout",
"in",
"out",
};
language_t current_language;
function_t *current_func;
class_type_t *current_class;