[qfcc] Implement a lot of glsl semantics

Other than contructors (and problems with the `out` block) qfcc can
compile fstrianglest.vert to what looks like working ruamoko code.
There's still a lot of work to do, though.
This commit is contained in:
Bill Currie 2024-08-30 13:51:31 +09:00
parent 4b369be8c1
commit d0064c6c46
4 changed files with 189 additions and 37 deletions

View file

@ -46,6 +46,12 @@ typedef enum storage_class_e {
sc_param, ///< def is an incoming function parameter
sc_local, ///< def is local to the current function
sc_argument, ///< def is a function argument
sc_in,
sc_out,
sc_uniform,
sc_buffer,
sc_shared,
} storage_class_t;
typedef struct specifier_s {
@ -60,6 +66,7 @@ typedef struct specifier_s {
bool multi_type:1;
bool multi_store:1;
bool multi_generic:1;
bool is_const:1;
bool is_signed:1;
bool is_unsigned:1;
bool is_short:1;

View file

@ -69,6 +69,15 @@ static void
set_storage_bits (def_t *def, storage_class_t storage)
{
switch (storage) {
case sc_out:
case sc_buffer:
case sc_shared:
def->global = 1;
def->external = 0;
def->local = 0;
def->param = 0;
def->argument = 0;
break;
case sc_system:
def->system = 1;
// fall through
@ -79,6 +88,15 @@ set_storage_bits (def_t *def, storage_class_t storage)
def->param = 0;
def->argument = 0;
break;
case sc_in:
case sc_uniform:
def->global = 1;
def->constant = 1;
def->external = 0;
def->local = 0;
def->param = 0;
def->argument = 0;
break;
case sc_extern:
def->global = 1;
def->external = 1;

View file

@ -112,7 +112,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%code requires { #define glsl_yypstate rua_yypstate }
// these tokens are common between qc and qp
// these tokens are common between qc and glsl
%left LOW
%nonassoc IFX
%nonassoc ELSE
@ -162,11 +162,12 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%token <spec> LOW_PRECISION DISCARD COHERENT
%type <symbol> variable_identifier
%type <symtab> block_declaration
%type <expr> expression primary_exprsssion assignment_expression
%type <expr> for_init_statement conditionopt expressionopt else
%type <expr> conditional_expression unary_expression postfix_expression
%type <expr> function_call function_call_or_method function_call_generic
%type <expr> function_call_header_with_parameters
%type <mut_expr> function_call_header_with_parameters
%type <expr> function_call_header_no_parameters
%type <expr> function_call_header function_identifier
%type <expr> logical_or_expression logical_xor_expression
@ -201,22 +202,43 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%type <param> parameter_declaration
%type <param> parameter_declarator parameter_type_specifier
%printer { fprintf (yyo, "%s", $$->name); } <symbol>
%printer { fprintf (yyo, "%s", $$->type == ex_value ? get_value_string ($$->value) : "<expr>"); } <expr>
%printer { fprintf (yyo, "%p", $<pointer>$); } <*>
%printer { fprintf (yyo, "<>"); } <>
%{
static switch_block_t *switch_block;
static const expr_t *break_label;
static const expr_t *continue_label;
static symbol_t *
function_sym_type (specifier_t spec, symbol_t *sym)
static specifier_t
spec_merge (specifier_t spec, specifier_t new)
{
sym->type = append_type (spec.sym->type, spec.type);
set_func_type_attrs (sym->type, spec);
sym->type = find_type (sym->type);
return sym;
if (spec.type && new.type) {
if (!spec.multi_type) {
error (0, "two or more data types in declaration specifiers");
spec.multi_type = true;
}
}
if (spec.storage && new.storage) {
if (!spec.multi_store) {
error (0, "multiple storage classes in declaration specifiers");
spec.multi_store = true;
}
}
if (!spec.type) {
spec.type = new.type;
}
if (!spec.storage) {
spec.storage = new.storage;
}
spec.sym = new.sym;
spec.spec_bits |= new.spec_bits;
return spec;
}
%}
%expect 0
@ -239,17 +261,13 @@ function_definition
{
$<symtab>$ = current_symtab;
auto spec = $1;
spec.sym->type = parse_params (spec.sym->type, spec.params);
auto sym = function_sym_type (spec, spec.sym);
sym->params = spec.params;
sym = function_symbol ((specifier_t) {
.sym = sym,
.is_overload = true
});
auto sym = function_symbol (spec);
current_func = begin_function (sym, nullptr, current_symtab,
false, spec.storage);
current_symtab = current_func->locals;
current_storage = sc_local;
spec.sym = sym;
$1 = spec;
}
compound_statement_no_new_scope
{
@ -297,11 +315,26 @@ function_call
function_call_or_method
: function_call_generic
{
// pull apart the args+func list
// args are in reverse order, so f(a,b,c) <- c,b,a,f
auto list = &$1->list;
int count = list_count (list);
const expr_t *exprs[count];
list_scatter (list, exprs);
auto func = exprs[count - 1];
auto args = new_list_expr (nullptr);
list_gather (&args->list, exprs, count - 1);
$$ = function_expr (func, args);
}
;
function_call_generic
: function_call_header_with_parameters ')'
: function_call_header_with_parameters ')' { $$ = $1; }
| function_call_header_no_parameters ')'
{
$$ = new_list_expr ($1);
}
;
function_call_header_no_parameters
@ -311,7 +344,15 @@ function_call_header_no_parameters
function_call_header_with_parameters
: function_call_header assignment_expression
{
auto list = new_list_expr ($1);
$$ = expr_prepend_expr (list, $2);
}
| function_call_header_with_parameters ',' assignment_expression
{
auto list = $1;
$$ = expr_prepend_expr (list, $3);
}
;
function_call_header
@ -319,7 +360,14 @@ function_call_header
;
function_identifier
: type_specifier { }
: type_specifier
{
auto type = $1.type;
auto sym = new_symbol (type->name);
sym->sy_type = sy_type;
sym->type = type;
$$ = new_symbol_expr (sym);
}
| postfix_expression
;
@ -494,14 +542,41 @@ declaration
: function_prototype ';'
| init_declarator_list ';'
| PRECISION precision_qualifier type_specifier ';'
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' ';'
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' IDENTIFIER ';'
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' IDENTIFIER array_specifier ';'
| type_qualifier block_declaration ';'
{
auto spec = $1;
auto block = $2;
for (auto s = block->symbols; s; s = s->next) {
auto b_spec = spec_merge (spec, (specifier_t) {
.type = s->type,
.sym = new_symbol (s->name),
});
b_spec.storage = sc_extern;
declare_symbol (b_spec, nullptr, current_symtab);
}
}
| type_qualifier block_declaration IDENTIFIER ';'
| type_qualifier block_declaration IDENTIFIER array_specifier ';'
| type_qualifier ';'
| type_qualifier IDENTIFIER ';'
| type_qualifier IDENTIFIER identifier_list ';'
;
block_declaration
: IDENTIFIER '{'
{
int op = 's';//FIXME 'b' might be better (for block)
auto sym = $1;
current_symtab = start_struct (&op, sym, current_symtab);
}
struct_declaration_list '}'
{
auto block = current_symtab;
current_symtab = block->parent;
$$ = block;
}
;
identifier_list
: ',' IDENTIFIER
| identifier_list ',' IDENTIFIER
@ -509,6 +584,11 @@ identifier_list
function_prototype
: function_declarator ')'
{
auto spec = $1;
spec.sym->type = parse_params (0, spec.params);
$$ = spec;
}
;
function_declarator
@ -585,6 +665,9 @@ init_declarator_list
auto symtab = current_symtab;
auto space = symtab->space;
auto storage = current_storage;
if (storage == sc_local && !local_expr) {
local_expr = new_block_expr (nullptr);
}
initialize_def ($3, $5, space, storage, symtab);
}
;
@ -592,14 +675,34 @@ init_declarator_list
single_declaration
: fully_specified_type
| fully_specified_type IDENTIFIER
{
auto spec = $1;
spec.sym = $2;
declare_symbol (spec, nullptr, current_symtab);
}
| fully_specified_type IDENTIFIER array_specifier
{
auto spec = $1;
spec.type = append_type ($3, spec.type);
spec.type = find_type (spec.type);
spec.sym = $2;
declare_symbol (spec, nullptr, current_symtab);
}
| fully_specified_type IDENTIFIER array_specifier '=' initializer
| fully_specified_type IDENTIFIER '=' initializer
{
auto spec = $1;
spec.sym = $2;
if (current_storage == sc_local && !local_expr) {
local_expr = new_block_expr (nullptr);
}
declare_symbol (spec, $4, current_symtab);
}
;
fully_specified_type
: type_specifier
| type_qualifier type_specifier
| type_qualifier type_specifier { $$ = spec_merge ($1, $2); }
;
invariant_qualifier
@ -666,6 +769,12 @@ storage_qualifier
type_specifier
: type_specifier_nonarray
| type_specifier_nonarray array_specifier
{
auto spec = $1;
auto type = append_type ($2, spec.type);
spec.type = find_type (type);
$$ = spec;
}
;
array_specifier
@ -748,17 +857,31 @@ struct_declaration_list
struct_declaration
: type_specifier struct_declarator_list ';'
| type_qualifier type_specifier struct_declarator_list ';'
| type_qualifier type_specifier { $<spec>$ = spec_merge ($1, $2); }
struct_declarator_list ';'
;
struct_declarator_list
: struct_declarator
| struct_declarator_list ',' struct_declarator
| struct_declarator_list ',' { $<spec>$ = $<spec>0; }
struct_declarator
;
struct_declarator
: IDENTIFIER
{
auto spec = $<spec>0;
spec.sym = $1;
declare_field (spec, current_symtab);
}
| IDENTIFIER array_specifier
{
auto spec = $<spec>0;
spec.type = append_type ($2, spec.type);
spec.type = find_type (spec.type);
spec.sym = $1;
declare_field (spec, current_symtab);
}
;
initializer
@ -780,7 +903,11 @@ initializer_list
;
declaration_statement
: declaration { $$ = nullptr; }
: declaration
{
$$ = local_expr;
local_expr = nullptr;
}
;
statement
@ -830,7 +957,7 @@ statement_list
expression_statement
: ';' { $$ = nullptr; }
| expression ';' { $$ = (expr_t *) $expression; }
| expression ';' { $$ = $expression; }
;
selection_statement
@ -951,8 +1078,8 @@ iteration_statement
;
for_init_statement
: expression_statement { $$ = $1; }
| declaration_statement { $$ = $1; }
: expression_statement
| declaration_statement
;
conditionopt
@ -998,10 +1125,10 @@ jump_statement
static keyword_t glsl_keywords[] = {
{"const", GLSL_CONST},
{"uniform", GLSL_UNIFORM},
{"buffer", GLSL_BUFFER},
{"shared", GLSL_SHARED},
{"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 }},
{"attribute", GLSL_RESERVED},
{"varying", GLSL_RESERVED},
{"coherent", GLSL_COHERENT},
@ -1030,11 +1157,11 @@ static keyword_t glsl_keywords[] = {
{"if", GLSL_IF},
{"else", GLSL_ELSE},
{"subroutine", GLSL_RESERVED},
{"in", GLSL_IN},
{"out", GLSL_OUT},
{"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}},
{"void", GLSL_VOID, .spec = {.type = &type_void}},
{"bool", GLSL_TYPE_SPEC, .spec = {.type = &type_bool}},
{"true", 0},
{"false", 0},

View file

@ -217,8 +217,8 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%type <mut_expr> statements compound_statement
%type <expr> else bool_label break_label continue_label
%type <expr> unary_expr ident_expr cast_expr
%type <mut_expr> opt_arg_list arg_list
%type <expr> arg_expr
%type <mut_expr> arg_list
%type <expr> opt_arg_list arg_expr
%type <switch_block> switch_block
%type <symbol> identifier label