mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 21:21:14 +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;
|
const symbol_t *sym;
|
||||||
} ex_type_t;
|
} 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)
|
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||||
|
|
||||||
typedef struct expr_s {
|
typedef struct expr_s {
|
||||||
|
@ -364,6 +376,8 @@ typedef struct expr_s {
|
||||||
ex_extend_t extend; ///< vector extend operation
|
ex_extend_t extend; ///< vector extend operation
|
||||||
ex_multivec_t multivec; ///< geometric algebra multivector
|
ex_multivec_t multivec; ///< geometric algebra multivector
|
||||||
ex_type_t typ; ///< type expression
|
ex_type_t typ; ///< type expression
|
||||||
|
ex_incop_t incop; ///< incop expression
|
||||||
|
ex_cond_t cond; ///< ?: conditional expression
|
||||||
};
|
};
|
||||||
} expr_t;
|
} 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_return_expr (const expr_t *ret_val);
|
||||||
expr_t *new_adjstk_expr (int mode, int offset);
|
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_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
|
/** Create an expression of the correct type that references the specified
|
||||||
parameter slot.
|
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 *gather_factors (const type_t *type, int op,
|
||||||
const expr_t **factors, int count);
|
const expr_t **factors, int count);
|
||||||
|
|
||||||
|
const expr_t *expr_process (const expr_t *expr);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
#endif//__expr_h
|
#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(multivec) ///< geometric algebra multivector (::ex_multivec_t)
|
||||||
EX_EXPR(list) ///< non-invasive list of expressions (::ex_list_t)
|
EX_EXPR(list) ///< non-invasive list of expressions (::ex_list_t)
|
||||||
EX_EXPR(type) ///< type expression for generics
|
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
|
#undef EX_EXPR
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ qfcc_SOURCES = \
|
||||||
tools/qfcc/source/expr_dag.c \
|
tools/qfcc/source/expr_dag.c \
|
||||||
tools/qfcc/source/expr_obj.c \
|
tools/qfcc/source/expr_obj.c \
|
||||||
tools/qfcc/source/expr_optimize.c \
|
tools/qfcc/source/expr_optimize.c \
|
||||||
|
tools/qfcc/source/expr_process.c \
|
||||||
tools/qfcc/source/expr_type.c \
|
tools/qfcc/source/expr_type.c \
|
||||||
tools/qfcc/source/expr_unary.c \
|
tools/qfcc/source/expr_unary.c \
|
||||||
tools/qfcc/source/expr_vector.c \
|
tools/qfcc/source/expr_vector.c \
|
||||||
|
|
|
@ -206,6 +206,12 @@ get_type (const expr_t *e)
|
||||||
return 0;
|
return 0;
|
||||||
case ex_type:
|
case ex_type:
|
||||||
return nullptr;
|
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:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
}
|
}
|
||||||
|
@ -1934,6 +1940,12 @@ has_function_call (const expr_t *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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:
|
case ex_count:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2463,6 +2475,34 @@ conditional_expr (const expr_t *cond, const expr_t *e1, const expr_t *e2)
|
||||||
return block;
|
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 *
|
const expr_t *
|
||||||
incop_expr (int op, const expr_t *e, int postop)
|
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_multivec:
|
||||||
case ex_list:
|
case ex_list:
|
||||||
case ex_type:
|
case ex_type:
|
||||||
|
case ex_incop:
|
||||||
break;
|
break;
|
||||||
|
case ex_cond:
|
||||||
|
return (is_lvalue (expr->cond.true_expr)
|
||||||
|
&& is_lvalue (expr->cond.false_expr));
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (expr, "invalid expression");
|
internal_error (expr, "invalid expression");
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ edag_add_expr (const expr_t *expr)
|
||||||
case ex_with:
|
case ex_with:
|
||||||
case ex_args:
|
case ex_args:
|
||||||
case ex_type:
|
case ex_type:
|
||||||
|
case ex_incop:
|
||||||
// these are never put in the dag
|
// these are never put in the dag
|
||||||
return expr;
|
return expr;
|
||||||
case ex_list:
|
case ex_list:
|
||||||
|
@ -181,6 +182,13 @@ edag_add_expr (const expr_t *expr)
|
||||||
break;
|
break;
|
||||||
case ex_multivec:
|
case ex_multivec:
|
||||||
return expr; //FIXME ?
|
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);
|
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 = append_type (array, spec.type);
|
||||||
spec.type = find_type (spec.type);
|
spec.type = find_type (spec.type);
|
||||||
}
|
}
|
||||||
|
if (init) {
|
||||||
|
init = expr_process (init);
|
||||||
|
}
|
||||||
auto attributes = glsl_optimize_attributes (spec.attributes);
|
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||||
if (sym && sym->sy_type == sy_expr) {
|
if (sym && sym->sy_type == sy_expr) {
|
||||||
auto id_list = sym->expr;
|
auto id_list = sym->expr;
|
||||||
|
|
|
@ -403,7 +403,7 @@ function_identifier
|
||||||
unary_expression
|
unary_expression
|
||||||
: postfix_expression
|
: postfix_expression
|
||||||
| INCOP unary_expression { $$ = incop_expr ($1, $2, 0); }
|
| 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
|
unary_operator
|
||||||
|
@ -417,15 +417,15 @@ multiplicative_expression
|
||||||
: unary_expression
|
: unary_expression
|
||||||
| multiplicative_expression '*' unary_expression
|
| multiplicative_expression '*' unary_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr ('*', $1, $3);
|
$$ = new_binary_expr ('*', $1, $3);
|
||||||
}
|
}
|
||||||
| multiplicative_expression '/' unary_expression
|
| multiplicative_expression '/' unary_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr ('/', $1, $3);
|
$$ = new_binary_expr ('/', $1, $3);
|
||||||
}
|
}
|
||||||
| multiplicative_expression '%' unary_expression
|
| multiplicative_expression '%' unary_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr ('%', $1, $3);
|
$$ = new_binary_expr ('%', $1, $3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -433,11 +433,11 @@ additive_expression
|
||||||
: multiplicative_expression
|
: multiplicative_expression
|
||||||
| additive_expression '+' multiplicative_expression
|
| additive_expression '+' multiplicative_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr ('+', $1, $3);
|
$$ = new_binary_expr ('+', $1, $3);
|
||||||
}
|
}
|
||||||
| additive_expression '-' multiplicative_expression
|
| additive_expression '-' multiplicative_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr ('-', $1, $3);
|
$$ = new_binary_expr ('-', $1, $3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -445,11 +445,11 @@ shift_expression
|
||||||
: additive_expression
|
: additive_expression
|
||||||
| shift_expression SHL 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
|
| 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
|
: shift_expression
|
||||||
| relational_expression LT 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
|
| relational_expression GT shift_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr (QC_GT, $1, $3);
|
$$ = new_binary_expr (QC_GT, $1, $3);
|
||||||
}
|
}
|
||||||
| relational_expression LE shift_expression
|
| relational_expression LE shift_expression
|
||||||
{
|
{
|
||||||
$$ = binary_expr (QC_LE, $1, $3);
|
$$ = new_binary_expr (QC_LE, $1, $3);
|
||||||
}
|
}
|
||||||
| relational_expression GE shift_expression
|
| 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
|
: relational_expression
|
||||||
| equality_expression EQ 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
|
| 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
|
: equality_expression
|
||||||
| 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
|
: and_expression
|
||||||
| 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
|
: exclusive_or_expression
|
||||||
| 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
|
: conditional_expression
|
||||||
| unary_expression assignment_operator assignment_expression
|
| unary_expression assignment_operator assignment_expression
|
||||||
{
|
{
|
||||||
if ($2 == '=') {
|
auto expr = $3;
|
||||||
$$ = assign_expr ($1, $3);
|
if ($2 != '=') {
|
||||||
} else {
|
expr = paren_expr (expr);
|
||||||
$$ = asx_expr ($2, $1, $3);
|
expr = new_binary_expr ($2, $1, expr);
|
||||||
}
|
}
|
||||||
|
$$ = new_assign_expr ($1, expr);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue