[qfcc] Create glsl block before parsing members

This allows attributes to be put on the block before members are
declared thus giving member attributes to override block attributes when
appropriate.
This commit is contained in:
Bill Currie 2024-09-12 12:02:18 +09:00
parent f7f2790937
commit db39fdbe37
5 changed files with 71 additions and 37 deletions

View file

@ -69,8 +69,9 @@ extern const char *glsl_interface_names[glsl_num_interfaces];
typedef struct glsl_block_s {
struct glsl_block_s *next;
const char *name;
attribute_t *attributes;
symbol_t *name;
glsl_interface_t interface;
symtab_t *attributes;
symtab_t *members;
symbol_t *instance_name;
} glsl_block_t;
@ -88,8 +89,9 @@ extern glsl_sublang_t glsl_geom_sublanguage;
extern glsl_sublang_t glsl_frag_sublanguage;
void glsl_block_clear (void);
void glsl_declare_block (specifier_t spec, symbol_t *block_sym,
symbol_t *instance_name);
glsl_block_t *glsl_create_block (specifier_t spec, symbol_t *block_sym);
void glsl_finish_block (glsl_block_t *block);
void glsl_declare_block_instance (glsl_block_t *block, symbol_t *instance_name);
glsl_block_t *glsl_get_block (const char *name, glsl_interface_t interface);
symtab_t *glsl_optimize_attributes (attribute_t *attributes);
void glsl_apply_attributes (symtab_t *attributes, specifier_t spec);

View file

@ -110,6 +110,8 @@ typedef union rua_val_s {
struct symtab_s *symtab;
struct attribute_s *attribute;
struct designator_s *designator;
struct glsl_block_s *block;
} rua_val_t;
#include "tools/qfcc/source/qc-parse.h"

View file

@ -104,6 +104,7 @@ typedef struct symtab_s {
struct class_s *class; ///< owning class if ivar scope
symbol_t *(*procsymbol) (const char *name, struct symtab_s *symtab);
void *procsymbol_data;
void *data;
} symtab_t;
const char *symtype_str (sy_type_e type) __attribute__((const));

View file

@ -48,7 +48,7 @@ static const char *
block_get_key (const void *_b, void *)
{
auto b = (const glsl_block_t *) _b;
return b->name;
return b->name->name;
}
void
@ -68,12 +68,17 @@ glsl_block_clear (void)
static const expr_t *
block_sym_ref (symbol_t *sym, void *data)
{
return new_symbol_expr (data);
sym = data;
glsl_block_t *block = sym->table->data;
auto interface = new_name_expr (glsl_interface_names[block->interface]);
auto blk = new_symbol_expr (block->name);
auto expr = field_expr (interface, blk);
expr = field_expr (expr, new_symbol_expr (sym));
return expr;
}
void
glsl_declare_block (specifier_t spec, symbol_t *block_sym,
symbol_t *instance_name)
glsl_block_t *
glsl_create_block (specifier_t spec, symbol_t *block_sym)
{
auto interface = glsl_iftype_from_sc(spec.storage);
hashtab_t *block_tab = nullptr;
@ -81,17 +86,18 @@ glsl_declare_block (specifier_t spec, symbol_t *block_sym,
block_tab = interfaces[interface];
}
if (!block_tab) {
error (0, "invalid storage for block: %d", spec.storage);
return;
error (0, "invalid interface for block: %d", spec.storage);
return nullptr;
}
glsl_block_t *block;
ALLOC (64, glsl_block_t, blocks, block);
*block = (glsl_block_t) {
.name = save_string (block_sym->name),
.attributes = spec.attributes,
.members = block_sym->namespace,
.instance_name = instance_name,
.name = new_symbol (block_sym->name),
.interface = interface,
.attributes = glsl_optimize_attributes (spec.attributes),
.members = new_symtab (current_symtab, stab_struct),
};
block->members->data = block;
Hash_Add (block_tab, block);
for (auto sym = block->members->symbols; sym; sym = sym->next) {
auto def = new_def (sym->name, nullptr, nullptr, spec.storage);
@ -99,11 +105,27 @@ glsl_declare_block (specifier_t spec, symbol_t *block_sym,
sym->sy_type = sy_var;
sym->def = def;
}
return block;
}
void
glsl_finish_block (glsl_block_t *block)
{
}
void
glsl_declare_block_instance (glsl_block_t *block, symbol_t *instance_name)
{
if (!block) {
// error recovery
return;
}
if (instance_name) {
block->instance_name = instance_name;
auto type = new_type ();
*type = (type_t) {
.type = ev_invalid,
.name = save_string (block_sym->name),
.name = save_string (block->name->name),
.alignment = 4,
.width = 1,
.columns = 1,
@ -113,7 +135,8 @@ glsl_declare_block (specifier_t spec, symbol_t *block_sym,
instance_name->type = append_type (instance_name->type, type);
instance_name->type = find_type (instance_name->type);
auto space = current_symtab->space;// FIXME
initialize_def (instance_name, nullptr, space, spec.storage,
initialize_def (instance_name, nullptr, space,
glsl_sc_from_iftype (block->interface),
current_symtab);
} else {
for (auto sym = block->members->symbols; sym; sym = sym->next) {

View file

@ -167,7 +167,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%token <spec> DISCARD COHERENT
%type <symbol> variable_identifier
%type <symbol> block_declaration
%type <block> block_declaration
%type <expr> constant_expression
%type <expr> expression primary_exprsssion assignment_expression
%type <expr> for_init_statement conditionopt expressionopt else
@ -576,24 +576,21 @@ declaration
}
| type_qualifier block_declaration ';'
{
auto spec = $1;
auto block = $2;
glsl_declare_block (spec, block, nullptr);
auto block = $block_declaration;
glsl_declare_block_instance (block, nullptr);
}
| type_qualifier block_declaration IDENTIFIER ';'
{
auto spec = $1;
auto block = $2;
auto instance_name = $3;
glsl_declare_block (spec, block, instance_name);
auto block = $block_declaration;
auto instance_name = $IDENTIFIER;
glsl_declare_block_instance (block, instance_name);
}
| type_qualifier block_declaration IDENTIFIER array_specifier ';'
{
auto spec = $1;
auto block = $2;
auto instance_name = $3;
instance_name->type = $4;
glsl_declare_block (spec, block, instance_name);
auto block = $block_declaration;
auto instance_name = $IDENTIFIER;
instance_name->type = $array_specifier;
glsl_declare_block_instance (block, instance_name);
}
| type_qualifier ';'
{
@ -621,16 +618,25 @@ declaration
block_declaration
: IDENTIFIER '{'
{
auto block = new_symtab (current_symtab, stab_struct);
current_symtab = block;
auto spec = $<spec>0;
auto block_sym = $IDENTIFIER;
auto block = glsl_create_block (spec, block_sym);
if (block) {
current_symtab = block->members;
}
$<block>$ = block;
}
struct_declaration_list '}'
{
auto sym = $1;
sym->sy_type = sy_namespace;
sym->namespace = current_symtab;
current_symtab = sym->namespace->parent;
$$ = sym;
auto block = $<block>3;
if (block) {
current_symtab = block->members->parent;
auto sym = $IDENTIFIER;
glsl_finish_block (block);
sym->sy_type = sy_namespace;
sym->namespace = current_symtab;
}
$$ = block;
}
;