mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Switch to deferred expressions for glsl
I plan to do this eventually for Ruamoko, but I need it to keep working for now; it's rather nice having multiple languages. I expect this will open up a lot of options for inlining, generic/template function instantiation, etc. Right now, it's helping with specialization constants in glsl.
This commit is contained in:
parent
a97fc8154a
commit
fc4e8cb350
9 changed files with 214 additions and 21 deletions
|
@ -321,6 +321,18 @@ typedef struct {
|
|||
const symbol_t *sym;
|
||||
} ex_type_t;
|
||||
|
||||
typedef struct {
|
||||
int op;
|
||||
bool postop;
|
||||
const expr_t *expr;
|
||||
} ex_incop_t;
|
||||
|
||||
typedef struct {
|
||||
const expr_t *test;
|
||||
const expr_t *true_expr;
|
||||
const expr_t *false_expr;
|
||||
} ex_cond_t;
|
||||
|
||||
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||
|
||||
typedef struct expr_s {
|
||||
|
@ -364,6 +376,8 @@ typedef struct expr_s {
|
|||
ex_extend_t extend; ///< vector extend operation
|
||||
ex_multivec_t multivec; ///< geometric algebra multivector
|
||||
ex_type_t typ; ///< type expression
|
||||
ex_incop_t incop; ///< incop expression
|
||||
ex_cond_t cond; ///< ?: conditional expression
|
||||
};
|
||||
} expr_t;
|
||||
|
||||
|
@ -872,6 +886,9 @@ expr_t *new_assign_expr (const expr_t *dst, const expr_t *src);
|
|||
expr_t *new_return_expr (const expr_t *ret_val);
|
||||
expr_t *new_adjstk_expr (int mode, int offset);
|
||||
expr_t *new_with_expr (int mode, int reg, const expr_t *val);
|
||||
expr_t *new_incop_expr (int op, const expr_t *e, bool postop);
|
||||
expr_t *new_cond_expr (const expr_t *test, const expr_t *true_expr,
|
||||
const expr_t *false_expr);
|
||||
|
||||
/** Create an expression of the correct type that references the specified
|
||||
parameter slot.
|
||||
|
@ -1003,6 +1020,8 @@ void scatter_factors (const expr_t *prod, const expr_t **factors);
|
|||
const expr_t *gather_factors (const type_t *type, int op,
|
||||
const expr_t **factors, int count);
|
||||
|
||||
const expr_t *expr_process (const expr_t *expr);
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__expr_h
|
||||
|
|
|
@ -69,6 +69,8 @@ EX_EXPR(extend) ///< vector extend operation (::ex_extend_t)
|
|||
EX_EXPR(multivec) ///< geometric algebra multivector (::ex_multivec_t)
|
||||
EX_EXPR(list) ///< non-invasive list of expressions (::ex_list_t)
|
||||
EX_EXPR(type) ///< type expression for generics
|
||||
EX_EXPR(incop) ///< pre or post increment/decrement (::ex_incop_t)
|
||||
EX_EXPR(cond) ///< ?: conditional expression (::ex_cond_t)
|
||||
|
||||
#undef EX_EXPR
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ qfcc_SOURCES = \
|
|||
tools/qfcc/source/expr_dag.c \
|
||||
tools/qfcc/source/expr_obj.c \
|
||||
tools/qfcc/source/expr_optimize.c \
|
||||
tools/qfcc/source/expr_process.c \
|
||||
tools/qfcc/source/expr_type.c \
|
||||
tools/qfcc/source/expr_unary.c \
|
||||
tools/qfcc/source/expr_vector.c \
|
||||
|
|
|
@ -206,6 +206,12 @@ get_type (const expr_t *e)
|
|||
return 0;
|
||||
case ex_type:
|
||||
return nullptr;
|
||||
case ex_incop:
|
||||
return get_type (e->incop.expr);
|
||||
case ex_cond:
|
||||
//FIXME true_expr and false_expr need to have the same type,
|
||||
//unless one is nil
|
||||
return get_type (e->cond.true_expr);
|
||||
case ex_count:
|
||||
internal_error (e, "invalid expression");
|
||||
}
|
||||
|
@ -1934,6 +1940,12 @@ has_function_call (const expr_t *e)
|
|||
}
|
||||
}
|
||||
return 0;
|
||||
case ex_incop:
|
||||
return has_function_call (e->incop.expr);
|
||||
case ex_cond:
|
||||
return (has_function_call (e->cond.test)
|
||||
|| has_function_call (e->cond.true_expr)
|
||||
|| has_function_call (e->cond.false_expr));
|
||||
case ex_count:
|
||||
break;
|
||||
}
|
||||
|
@ -2463,6 +2475,34 @@ conditional_expr (const expr_t *cond, const expr_t *e1, const expr_t *e2)
|
|||
return block;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_incop_expr (int op, const expr_t *e, bool postop)
|
||||
{
|
||||
auto incop = new_expr ();
|
||||
incop->type = ex_incop;
|
||||
incop->incop = (ex_incop_t) {
|
||||
.op = op,
|
||||
.postop = postop,
|
||||
.expr = e,
|
||||
};
|
||||
return incop;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_cond_expr (const expr_t *test, const expr_t *true_expr,
|
||||
const expr_t *false_expr)
|
||||
{
|
||||
auto cond = new_expr ();
|
||||
cond->type = ex_cond;
|
||||
cond->cond = (ex_cond_t) {
|
||||
.test = test,
|
||||
.true_expr = true_expr,
|
||||
.false_expr = false_expr,
|
||||
};
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
const expr_t *
|
||||
incop_expr (int op, const expr_t *e, int postop)
|
||||
{
|
||||
|
|
|
@ -131,7 +131,11 @@ is_lvalue (const expr_t *expr)
|
|||
case ex_multivec:
|
||||
case ex_list:
|
||||
case ex_type:
|
||||
case ex_incop:
|
||||
break;
|
||||
case ex_cond:
|
||||
return (is_lvalue (expr->cond.true_expr)
|
||||
&& is_lvalue (expr->cond.false_expr));
|
||||
case ex_count:
|
||||
internal_error (expr, "invalid expression");
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ edag_add_expr (const expr_t *expr)
|
|||
case ex_with:
|
||||
case ex_args:
|
||||
case ex_type:
|
||||
case ex_incop:
|
||||
// these are never put in the dag
|
||||
return expr;
|
||||
case ex_list:
|
||||
|
@ -181,6 +182,13 @@ edag_add_expr (const expr_t *expr)
|
|||
break;
|
||||
case ex_multivec:
|
||||
return expr; //FIXME ?
|
||||
case ex_cond:
|
||||
if (e->cond.test == expr->cond.test
|
||||
&& e->cond.true_expr == expr->cond.true_expr
|
||||
&& e->cond.false_expr == expr->cond.false_expr) {
|
||||
return e;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DARRAY_APPEND (&expr_dag, expr);
|
||||
|
|
115
tools/qfcc/source/expr_process.c
Normal file
115
tools/qfcc/source/expr_process.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
expr_process.c
|
||||
|
||||
expression processing
|
||||
|
||||
Copyright (C) 2024 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/fbsearch.h"
|
||||
#include "QF/heapsort.h"
|
||||
#include "QF/math/bitop.h"
|
||||
|
||||
#include "tools/qfcc/include/algebra.h"
|
||||
#include "tools/qfcc/include/diagnostic.h"
|
||||
#include "tools/qfcc/include/expr.h"
|
||||
#include "tools/qfcc/include/rua-lang.h"
|
||||
#include "tools/qfcc/include/symtab.h"
|
||||
#include "tools/qfcc/include/type.h"
|
||||
#include "tools/qfcc/include/value.h"
|
||||
|
||||
typedef const expr_t *(*process_f) (const expr_t *expr);
|
||||
|
||||
static const expr_t *
|
||||
proc_expr (const expr_t *expr)
|
||||
{
|
||||
auto e1 = expr_process (expr->expr.e1);
|
||||
auto e2 = expr_process (expr->expr.e2);
|
||||
if (is_error (e1)) {
|
||||
return e1;
|
||||
}
|
||||
if (is_error (e2)) {
|
||||
return e2;
|
||||
}
|
||||
|
||||
return binary_expr (expr->expr.op, e1, e2);
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_uexpr (const expr_t *expr)
|
||||
{
|
||||
auto e1 = expr_process (expr->expr.e1);
|
||||
if (is_error (e1)) {
|
||||
return e1;
|
||||
}
|
||||
|
||||
return unary_expr (expr->expr.op, e1);
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_symbol (const expr_t *expr)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_value (const expr_t *expr)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_compound (const expr_t *expr)
|
||||
{
|
||||
auto comp = new_compound_init ();
|
||||
for (auto ele = expr->compound.head; ele; ele = ele->next) {
|
||||
append_element (comp, new_element (expr_process (ele->expr),
|
||||
ele->designator));
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
expr_process (const expr_t *expr)
|
||||
{
|
||||
static process_f funcs[ex_count] = {
|
||||
[ex_expr] = proc_expr,
|
||||
[ex_uexpr] = proc_uexpr,
|
||||
[ex_value] = proc_value,
|
||||
[ex_compound] = proc_compound,
|
||||
[ex_symbol] = proc_symbol,
|
||||
};
|
||||
|
||||
if (expr->type >= ex_count) {
|
||||
internal_error (expr, "bad sub-expression type: %d", expr->type);
|
||||
}
|
||||
if (!funcs[expr->type]) {
|
||||
internal_error (expr, "unexpected sub-expression type: %s",
|
||||
expr_names[expr->type]);
|
||||
}
|
||||
|
||||
return funcs[expr->type] (expr);
|
||||
}
|
|
@ -52,6 +52,9 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const type_t *array,
|
|||
spec.type = append_type (array, spec.type);
|
||||
spec.type = find_type (spec.type);
|
||||
}
|
||||
if (init) {
|
||||
init = expr_process (init);
|
||||
}
|
||||
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||
if (sym && sym->sy_type == sy_expr) {
|
||||
auto id_list = sym->expr;
|
||||
|
|
|
@ -403,7 +403,7 @@ function_identifier
|
|||
unary_expression
|
||||
: postfix_expression
|
||||
| INCOP unary_expression { $$ = incop_expr ($1, $2, 0); }
|
||||
| unary_operator unary_expression { $$ = unary_expr ($1, $2); }
|
||||
| unary_operator unary_expression { $$ = new_unary_expr ($1, $2); }
|
||||
;
|
||||
|
||||
unary_operator
|
||||
|
@ -417,15 +417,15 @@ multiplicative_expression
|
|||
: unary_expression
|
||||
| multiplicative_expression '*' unary_expression
|
||||
{
|
||||
$$ = binary_expr ('*', $1, $3);
|
||||
$$ = new_binary_expr ('*', $1, $3);
|
||||
}
|
||||
| multiplicative_expression '/' unary_expression
|
||||
{
|
||||
$$ = binary_expr ('/', $1, $3);
|
||||
$$ = new_binary_expr ('/', $1, $3);
|
||||
}
|
||||
| multiplicative_expression '%' unary_expression
|
||||
{
|
||||
$$ = binary_expr ('%', $1, $3);
|
||||
$$ = new_binary_expr ('%', $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -433,11 +433,11 @@ additive_expression
|
|||
: multiplicative_expression
|
||||
| additive_expression '+' multiplicative_expression
|
||||
{
|
||||
$$ = binary_expr ('+', $1, $3);
|
||||
$$ = new_binary_expr ('+', $1, $3);
|
||||
}
|
||||
| additive_expression '-' multiplicative_expression
|
||||
{
|
||||
$$ = binary_expr ('-', $1, $3);
|
||||
$$ = new_binary_expr ('-', $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -445,11 +445,11 @@ shift_expression
|
|||
: additive_expression
|
||||
| shift_expression SHL additive_expression
|
||||
{
|
||||
$$ = binary_expr (QC_SHL, $1, $3);
|
||||
$$ = new_binary_expr (QC_SHL, $1, $3);
|
||||
}
|
||||
| shift_expression SHR additive_expression
|
||||
{
|
||||
$$ = binary_expr (QC_SHR, $1, $3);
|
||||
$$ = new_binary_expr (QC_SHR, $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -457,19 +457,19 @@ relational_expression
|
|||
: shift_expression
|
||||
| relational_expression LT shift_expression
|
||||
{
|
||||
$$ = binary_expr (QC_LT, $1, $3);
|
||||
$$ = new_binary_expr (QC_LT, $1, $3);
|
||||
}
|
||||
| relational_expression GT shift_expression
|
||||
{
|
||||
$$ = binary_expr (QC_GT, $1, $3);
|
||||
$$ = new_binary_expr (QC_GT, $1, $3);
|
||||
}
|
||||
| relational_expression LE shift_expression
|
||||
{
|
||||
$$ = binary_expr (QC_LE, $1, $3);
|
||||
$$ = new_binary_expr (QC_LE, $1, $3);
|
||||
}
|
||||
| relational_expression GE shift_expression
|
||||
{
|
||||
$$ = binary_expr (QC_GE, $1, $3);
|
||||
$$ = new_binary_expr (QC_GE, $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -477,11 +477,11 @@ equality_expression
|
|||
: relational_expression
|
||||
| equality_expression EQ relational_expression
|
||||
{
|
||||
$$ = binary_expr (QC_EQ, $1, $3);
|
||||
$$ = new_binary_expr (QC_EQ, $1, $3);
|
||||
}
|
||||
| relational_expression NE relational_expression
|
||||
{
|
||||
$$ = binary_expr (QC_NE, $1, $3);
|
||||
$$ = new_binary_expr (QC_NE, $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -489,7 +489,7 @@ and_expression
|
|||
: equality_expression
|
||||
| and_expression '&' equality_expression
|
||||
{
|
||||
$$ = binary_expr ('&', $1, $3);
|
||||
$$ = new_binary_expr ('&', $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -497,7 +497,7 @@ exclusive_or_expression
|
|||
: and_expression
|
||||
| exclusive_or_expression '^' and_expression
|
||||
{
|
||||
$$ = binary_expr ('^', $1, $3);
|
||||
$$ = new_binary_expr ('^', $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -505,7 +505,7 @@ inclusive_or_expression
|
|||
: exclusive_or_expression
|
||||
| inclusive_or_expression '|' exclusive_or_expression
|
||||
{
|
||||
$$ = binary_expr ('|', $1, $3);
|
||||
$$ = new_binary_expr ('|', $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -545,11 +545,12 @@ assignment_expression
|
|||
: conditional_expression
|
||||
| unary_expression assignment_operator assignment_expression
|
||||
{
|
||||
if ($2 == '=') {
|
||||
$$ = assign_expr ($1, $3);
|
||||
} else {
|
||||
$$ = asx_expr ($2, $1, $3);
|
||||
auto expr = $3;
|
||||
if ($2 != '=') {
|
||||
expr = paren_expr (expr);
|
||||
expr = new_binary_expr ($2, $1, expr);
|
||||
}
|
||||
$$ = new_assign_expr ($1, expr);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
Loading…
Reference in a new issue