mesa: implement grammar/parsing for precision/invariant syntax

Plus, fix some issues with pre-defined preprocessor symbols and version checking.
This commit is contained in:
Brian Paul 2008-07-16 14:27:50 -06:00
parent 7a0b79fe36
commit ebcdbff6f1
4 changed files with 251 additions and 10 deletions

View file

@ -51,10 +51,17 @@
/* revision number - increment after each change affecting emitted output */
.emtcode REVISION 3
/* external declaration */
/* external declaration (or precision or invariant stmt) */
.emtcode EXTERNAL_NULL 0
.emtcode EXTERNAL_FUNCTION_DEFINITION 1
.emtcode EXTERNAL_DECLARATION 2
.emtcode DEFAULT_PRECISION 3
.emtcode INVARIANT_STMT 4
/* precision */
.emtcode PRECISION_LOW 0
.emtcode PRECISION_MEDIUM 1
.emtcode PRECISION_HIGH 2
/* declaration */
.emtcode DECLARATION_FUNCTION_PROTOTYPE 1
@ -240,6 +247,9 @@
.errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found."
.errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found."
.errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found."
.errtext INVALID_PRECISION "2006: Invalid precision specifier '$err_token$'."
.errtext INVALID_PRECISION_TYPE "2007: Invalid precision type '$err_token$'."
/* tells whether the shader that is being parsed is a built-in shader or not */
/* 0 - normal behaviour */
@ -1226,23 +1236,70 @@ asm_argument
var_with_field
variable_identifier .and dot .and field_selection .emit OP_FIELD;
/*
<translation_unit> ::= <external_declaration>
| <translation_unit> <external_declaration>
*/
* <translation_unit> ::= <external_declaration>
* | <translation_unit> <external_declaration>
*/
translation_unit
optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and
.loop external_declaration .and optional_space .and
'\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;
/*
<external_declaration> ::= <function_definition>
| <declaration>
*/
* <external_declaration> ::= <function_definition>
* | <declaration>
*/
external_declaration
precision_stmt .emit DEFAULT_PRECISION .or
invariant_stmt .emit INVARIANT_STMT .or
function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or
declaration .emit EXTERNAL_DECLARATION;
/*
* <precision_stmt> ::= "precision" <precision> <prectype>
*/
precision_stmt
"precision" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;
/*
* <precision> ::= "lowp"
* | "mediump"
* | "highp"
*/
precision
"lowp" .emit PRECISION_LOW .or
"mediump" .emit PRECISION_MEDIUM .or
"highp" .emit PRECISION_HIGH;
/*
* <prectype> ::= "int"
* | "float"
* | "a sampler type"
*/
prectype
"int" .emit TYPE_SPECIFIER_INT .or
"float" .emit TYPE_SPECIFIER_FLOAT .or
"sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or
"sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or
"sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or
"samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or
"sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or
"sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or
"sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or
"sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;
/*
* <invariant_stmt> ::= "invariant" identifier;
*/
invariant_stmt
"invariant" .and space .and identifier .and semicolon;
/*
<function_definition> :: <function_prototype> <compound_statement_no_new_scope>
*/

View file

@ -6,6 +6,11 @@
".emtcode EXTERNAL_NULL 0\n"
".emtcode EXTERNAL_FUNCTION_DEFINITION 1\n"
".emtcode EXTERNAL_DECLARATION 2\n"
".emtcode DEFAULT_PRECISION 3\n"
".emtcode INVARIANT_STMT 4\n"
".emtcode PRECISION_LOW 0\n"
".emtcode PRECISION_MEDIUM 1\n"
".emtcode PRECISION_HIGH 2\n"
".emtcode DECLARATION_FUNCTION_PROTOTYPE 1\n"
".emtcode DECLARATION_INIT_DECLARATOR_LIST 2\n"
".emtcode FUNCTION_ORDINARY 0\n"
@ -41,6 +46,7 @@
".emtcode TYPE_QUALIFIER_UNIFORM 4\n"
".emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5\n"
".emtcode TYPE_QUALIFIER_FIXEDINPUT 6\n"
".emtcode TYPE_QUALIFIER_INVARIANT_VARYING 7\n"
".emtcode TYPE_SPECIFIER_VOID 0\n"
".emtcode TYPE_SPECIFIER_BOOL 1\n"
".emtcode TYPE_SPECIFIER_BVEC2 2\n"
@ -137,6 +143,8 @@
".errtext LBRACE_EXPECTED \"2003: '{' expected but '$err_token$' found.\"\n"
".errtext LPAREN_EXPECTED \"2004: '(' expected but '$err_token$' found.\"\n"
".errtext RPAREN_EXPECTED \"2005: ')' expected but '$err_token$' found.\"\n"
".errtext INVALID_PRECISION \"2006: Invalid precision specifier '$err_token$'.\"\n"
".errtext INVALID_PRECISION_TYPE \"2007: Invalid precision type '$err_token$'.\"\n"
".regbyte parsing_builtin 0\n"
".regbyte shader_type 0\n"
"variable_identifier\n"
@ -597,8 +605,29 @@
" .loop external_declaration .and optional_space .and\n"
" '\\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;\n"
"external_declaration\n"
" precision_stmt .emit DEFAULT_PRECISION .or\n"
" invariant_stmt .emit INVARIANT_STMT .or\n"
" function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or\n"
" declaration .emit EXTERNAL_DECLARATION;\n"
"precision_stmt\n"
" \"precision\" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;\n"
"precision\n"
" \"lowp\" .emit PRECISION_LOW .or\n"
" \"mediump\" .emit PRECISION_MEDIUM .or\n"
" \"highp\" .emit PRECISION_HIGH;\n"
"prectype\n"
" \"int\" .emit TYPE_SPECIFIER_INT .or\n"
" \"float\" .emit TYPE_SPECIFIER_FLOAT .or\n"
" \"sampler1D\" .emit TYPE_SPECIFIER_SAMPLER1D .or\n"
" \"sampler2D\" .emit TYPE_SPECIFIER_SAMPLER2D .or\n"
" \"sampler3D\" .emit TYPE_SPECIFIER_SAMPLER3D .or\n"
" \"samplerCube\" .emit TYPE_SPECIFIER_SAMPLERCUBE .or\n"
" \"sampler1DShadow\" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or\n"
" \"sampler2DShadow\" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or\n"
" \"sampler2DRect\" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or\n"
" \"sampler2DRectShadow\" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;\n"
"invariant_stmt\n"
" \"invariant\" .and space .and identifier .and semicolon;\n"
"function_definition\n"
" function_prototype .and compound_statement_no_new_scope;\n"
"digit_oct\n"

View file

@ -56,6 +56,9 @@
*/
/** re-defined below, should be the same though */
#define TYPE_SPECIFIER_COUNT 32
/**
* Allocate storage for a variable of 'size' bytes from given pool.
@ -129,6 +132,7 @@ typedef struct slang_parse_ctx_
GLboolean global_scope; /**< Is object being declared a global? */
slang_atom_pool *atoms;
slang_unit_type type; /**< Vertex vs. Fragment */
GLuint version; /**< user-specified (or default) #version */
} slang_parse_ctx;
/* slang_output_ctx */
@ -141,6 +145,7 @@ typedef struct slang_output_ctx_
slang_var_pool *global_pool;
struct gl_program *program;
slang_var_table *vartable;
GLuint default_precision[TYPE_SPECIFIER_COUNT];
} slang_output_ctx;
/* _slang_compile() */
@ -525,7 +530,7 @@ parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
#define TYPE_SPECIFIER_MAT42 29
#define TYPE_SPECIFIER_MAT34 30
#define TYPE_SPECIFIER_MAT43 31
#define TYPE_SPECIFIER_COUNT 32
static int
parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
@ -1817,10 +1822,111 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
return 1;
}
/* external declaration */
#define PRECISION_LOW 0
#define PRECISION_MEDIUM 1
#define PRECISION_HIGH 2
static int
parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
{
#if FEATURE_es2_glsl
int precision, type;
precision = *C->I++;
switch (precision) {
case PRECISION_LOW:
case PRECISION_MEDIUM:
case PRECISION_HIGH:
/* OK */
break;
default:
_mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
precision, __FILE__, __LINE__);
return 0;
}
type = *C->I++;
switch (type) {
case TYPE_SPECIFIER_FLOAT:
case TYPE_SPECIFIER_INT:
case TYPE_SPECIFIER_SAMPLER1D:
case TYPE_SPECIFIER_SAMPLER2D:
case TYPE_SPECIFIER_SAMPLER3D:
case TYPE_SPECIFIER_SAMPLERCUBE:
case TYPE_SPECIFIER_SAMPLER1DSHADOW:
case TYPE_SPECIFIER_SAMPLER2DSHADOW:
case TYPE_SPECIFIER_SAMPLER2DRECT:
case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
/* OK */
break;
default:
_mesa_problem(NULL, "unexpected type %d at %s:%d\n",
type, __FILE__, __LINE__);
return 0;
}
assert(type < TYPE_SPECIFIER_COUNT);
O->default_precision[type] = precision;
return 1;
#else
slang_info_log_error(C->L, "syntax error at \"precision\"");
return 0;
#endif
}
/**
* Initialize the default precision for all types.
* XXX this info isn't used yet.
*/
static void
init_default_precision(slang_output_ctx *O, slang_unit_type type)
{
GLuint i;
for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
#if FEATURE_es2_glsl
O->default_precision[i] = PRECISION_LOW;
#else
O->default_precision[i] = PRECISION_HIGH;
#endif
}
#if FEATURE_es2_glsl
if (type == SLANG_UNIT_VERTEX_SHADER) {
O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
}
else {
O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
}
#endif
}
static int
parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
{
if (C->version >= 120 || FEATURE_es2_glsl) {
slang_atom *a = parse_identifier(C);
/* XXX not doing anything with this var yet */
/*printf("ID: %s\n", (char*) a);*/
return a ? 1 : 0;
}
else {
slang_info_log_error(C->L, "syntax error at \"invariant\"");
return 0;
}
}
/* external declaration or default precision specifier */
#define EXTERNAL_NULL 0
#define EXTERNAL_FUNCTION_DEFINITION 1
#define EXTERNAL_DECLARATION 2
#define DEFAULT_PRECISION 3
#define INVARIANT_STMT 4
static GLboolean
parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
@ -1843,6 +1949,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
}
/* setup output context */
init_default_precision(&o, unit->type);
o.funs = &unit->funs;
o.structs = &unit->structs;
o.vars = &unit->vars;
@ -1868,6 +1975,12 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
case EXTERNAL_DECLARATION:
success = parse_declaration(C, &o);
break;
case DEFAULT_PRECISION:
success = parse_default_precision(C, &o);
break;
case INVARIANT_STMT:
success = parse_invariant(C, &o);
break;
default:
success = GL_FALSE;
}
@ -1904,6 +2017,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
static GLboolean
compile_binary(const byte * prod, slang_code_unit * unit,
GLuint version,
slang_unit_type type, slang_info_log * infolog,
slang_code_unit * builtin, slang_code_unit * downlink,
struct gl_program *program)
@ -1919,6 +2033,7 @@ compile_binary(const byte * prod, slang_code_unit * unit,
C.global_scope = GL_TRUE;
C.atoms = &unit->object->atompool;
C.type = type;
C.version = version;
if (!check_revision(&C))
return GL_FALSE;
@ -1946,6 +2061,8 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
#if FEATURE_ARB_shading_language_120
maxVersion = 120;
#elif FEATURE_es2_glsl
maxVersion = 100;
#else
maxVersion = 110;
#endif
@ -1995,7 +2112,7 @@ compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
slang_string_free(&preprocessed);
/* Syntax is okay - translate it to internal representation. */
if (!compile_binary(prod, unit, type, infolog, builtin,
if (!compile_binary(prod, unit, version, type, infolog, builtin,
&builtin[SLANG_BUILTIN_TOTAL - 1],
program)) {
grammar_alloc_free(prod);
@ -2039,6 +2156,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
struct gl_program *program)
{
slang_code_unit *builtins = NULL;
GLuint base_version = 110;
/* load GLSL grammar */
*id = grammar_load_from_text((const byte *) (slang_shader_syn));
@ -2066,6 +2184,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
/* compile core functionality first */
if (!compile_binary(slang_core_gc,
&object->builtin[SLANG_BUILTIN_CORE],
base_version,
SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
NULL, NULL, NULL))
return GL_FALSE;
@ -2073,6 +2192,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
#if FEATURE_ARB_shading_language_120
if (!compile_binary(slang_120_core_gc,
&object->builtin[SLANG_BUILTIN_120_CORE],
120,
SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
return GL_FALSE;
@ -2081,6 +2201,11 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
/* compile common functions and variables, link to core */
if (!compile_binary(slang_common_builtin_gc,
&object->builtin[SLANG_BUILTIN_COMMON],
#if FEATURE_ARB_shading_language_120
120,
#else
base_version,
#endif
SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
#if FEATURE_ARB_shading_language_120
&object->builtin[SLANG_BUILTIN_120_CORE],
@ -2094,12 +2219,14 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
if (type == SLANG_UNIT_FRAGMENT_SHADER) {
if (!compile_binary(slang_fragment_builtin_gc,
&object->builtin[SLANG_BUILTIN_TARGET],
base_version,
SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
&object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
#if FEATURE_ARB_shading_language_120
if (!compile_binary(slang_120_fragment_gc,
&object->builtin[SLANG_BUILTIN_TARGET],
120,
SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
&object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
@ -2108,6 +2235,7 @@ compile_object(grammar * id, const char *source, slang_code_object * object,
else if (type == SLANG_UNIT_VERTEX_SHADER) {
if (!compile_binary(slang_vertex_builtin_gc,
&object->builtin[SLANG_BUILTIN_TARGET],
base_version,
SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
&object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;

View file

@ -729,6 +729,14 @@ expand (expand_state *e, pp_symbols *symbols)
slang_string_pushi (e->output, e->state->version);
slang_string_pushc (e->output, ' ');
}
#if FEATURE_es2_glsl
else if (_mesa_strcmp (id, "GL_ES") == 0 ||
_mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) {
slang_string_pushc (e->output, ' ');
slang_string_pushi (e->output, '1');
slang_string_pushc (e->output, ' ');
}
#endif
else {
pp_symbol *symbol;
@ -829,6 +837,16 @@ static GLboolean
preprocess_source (slang_string *output, const char *source, grammar pid, grammar eid,
slang_info_log *elog)
{
static const char *predefined[] = {
"__FILE__",
"__LINE__",
"__VERSION__",
#if FEATURE_es2_glsl
"GL_ES",
"GL_FRAGMENT_PRECISION_HIGH",
#endif
NULL
};
byte *prod;
GLuint size, i;
pp_state state;
@ -840,6 +858,15 @@ preprocess_source (slang_string *output, const char *source, grammar pid, gramma
pp_state_init (&state, elog);
/* add the predefined symbols to the symbol table */
for (i = 0; predefined[i]; i++) {
pp_symbol *symbol = NULL;
symbol = pp_symbols_push(&state.symbols);
assert(symbol);
slang_string_pushs(&symbol->name,
predefined[i], _mesa_strlen(predefined[i]));
}
i = 0;
while (i < size) {
if (prod[i] != ESCAPE_TOKEN) {