summaryrefslogtreecommitdiffstats
path: root/src/glsl/glcpp/glcpp.h
Commit message (Collapse)AuthorAgeFilesLines
* util: Move ralloc to a new src/util directory.Kenneth Graunke2014-08-041-1/+1
| | | | | | | | | | | | | | | | | | For a long time, we've wanted a place to put utility code which isn't directly tied to Mesa or Gallium internals. This patch creates a new src/util directory for exactly that purpose, and builds the contents as libmesautil.la. ralloc seemed like a good first candidate. These days, it's directly used by mesa/main, i965, i915, and r300g, so keeping it in src/glsl didn't make much sense. Signed-off-by: Kenneth Graunke <[email protected]> v2 (Jason Ekstrand): More realloc uses and some scons fixes Signed-off-by: Jason Ekstrand <[email protected]> Reviewed-by: Marek Olšák <[email protected]>
* glsl/glcpp: Correctly parse directives with intervening commentsCarl Worth2014-07-291-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It's legal (though highly bizarre) for a pre-processor directive to look like this: # /* why? */ define FOO bar This behavior comes about since the specification defines separate logical phases in a precise order, and comment-removal occurs in a phase before the identification of directives. Our implementation does not use an actual separate phase for comment removal, so some extra care is necessary to correctly parse this. What we want is for '#' to introduce a directive iff it is the first token on a line, (ignoring whitespace and comments). Previously, we had a lexical rule that worked only for whitespace (not comments) with the following regular expression to find a directive-introducing '#' at the beginning of a line: HASH ^{HSPACE}*#{HSPACE}* In this commit, we switch to instead use a simple literal match of '#' to return a HASH_TOKEN token and add a new <HASH> start condition for whenever the HASH_TOKEN is the first non-space token of a line. This requires the addition of the new bit of state: first_non_space_token_this_line. This approach has a couple of implications on the glcpp parser: 1. The parser now sees two separate tokens, (such as HASH_TOKEN and HASH_DEFINE) where it previously saw one token (HASH_DEFINE) for the sequence "#define". This is a straightforward change throughout the grammar. 2. The parser may now see a SPACE token before the HASH_TOKEN token of a directive. Previously the lexical regular expression for {HASH} would eat up the space and there would be no SPACE token. This second implication is a bit of a nuisance for the parser. It causes a SPACE token to appear in a production of the grammar with the following two definitions of a control_line: control_line SPACE control_line This is really ugly, since normally a space would simply be a token separator, so it wouldn't appear in the tokens of a production. This leads to a further problem with interleaved spaces and comments: /* ... */ /* ... */ #define /* ..*/ For this, we must not return several consecutive SPACE tokens, or else we would need an arbitrary number of new productions: SPACE SPACE control_line SPACE SPACE SPACE control_line ad nauseam To avoid this problem, in this commit we also change the lexer to emit only a single SPACE token for any series of consecutive spaces, (whether from actual whitespace or comments). For this compression, we add a new bit of parser state: last_token_was_space. And we also update the expected results of all necessary test cases for the new compression of space tokens. Fortunately, the compression of spaces should not lead to any semantic changes in terms of what the eventual GLSL compiler sees. So there's a lot happening in this commit, (particularly for such a tiny feature). But fortunately, the lexer itself is looking cleaner than ever. The only ugly bit is all the state updating, but it is at least isolated to a single shared function. Of course, a new "make check" test is added for the new feature, (directives with comments and whitespace interleaved in many combinations). And this commit fixes the following Khronos GLES3 CTS tests: function_definition_with_comments_vertex function_definition_with_comments_fragment Reviewed-by: Jordan Justen <[email protected]>
* glsl/glcpp: Stop using a lexer start condition (<SKIP>) for token skipping.Carl Worth2014-07-291-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Here, "skipping" refers to the lexer not emitting any tokens for portions of the file within an #if condition (or similar) that evaluates to false. Previously, the lexer had a special <SKIP> start condition used to control this skipping. This start condition was not handled like a normal start condition. Instead, there was a particularly ugly block of code set to be included at the top of the generated lexing loop that would change from <INITIAL> to <SKIP> or from <SKIP> to <INITIAL> depending on various pieces of parser state, (such as parser->skip_state and parser->lexing_directive). Not only was that an ugly approach, but the <SKIP> start condition was complicating several glcpp bug fixes I attempted recently that want to use start conditions for other purposes, (such as a new <HASH> start condition). The recently added RETURN_TOKEN macro gives us a convenient way to implement skipping without using a lexer start condition. Now, at the top of the generated lexer, we examine all the necessary parser state and set a new parser->skipping bit. Then, in RETURN_TOKEN, we examine parser->skipping to determine whether to actually emit the token or not. Besides this, there are only a couple of other places where we need to examine the skipping bit (other than when returning a token): * To avoid emitting an error for #error if skipped. * To avoid entering the <DEFINE> start condition for a #define that is skipped. With all of this in place in the present commit, there are hopefully no behavioral changes with this patch, ("make check" still passes all of the glcpp tests at least). Reviewed-by: Jordan Justen <[email protected]>
* glsl/glcpp: Drop extra, final newline from most outputCarl Worth2014-07-291-0/+1
| | | | | | | | | | | | | | | | | | | | The glcpp parser is line-based, so it needs to see a NEWLINE token at the end of each line. This causes a trick for files that end without a final newline. Previously, the lexer for glcpp punted in this case by unconditionally returning a NEWLINE token at end-of-file, (causing most files to have an extra blank line at the end). Here, we refine this by lexing end-of-file as a NEWLINE token only if the immediately preceding token was not a NEWLINE token. The patch is a minor change that only looks huge for two reasons: 1. Almost all glcpp test result ".expected" files are updated to drop the extra newline. 2. All return statements from the lexer are adjusted to use a new RETURN_TOKEN macro that tracks the last-token-was-a-newline state. Reviewed-by: Jordan Justen <[email protected]>
* glsl/glcpp: Once again report undefined macro name in error message.Carl Worth2014-07-091-1/+1
| | | | | | | | | | | While writing the previous commit message, I just felt bad documenting the shortcoming of the change, (that undefined macro names would not be reported in error messages). Fix this by preserving the first-encounterd undefined macro name and reporting that in any resulting error message. Reviewed-by: Kenneth Graunke <[email protected]>
* glsl/glcpp: Add short-circuiting for || and && in #if/#elif for OpenGL ES.Carl Worth2014-07-091-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The GLSL ES Specification 3.00.4 says: #if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate as for C++ except for the following: ... • Undefined identifiers not consumed by the defined operator do not default to '0'. Use of such identifiers causes an error. [Page 11 (page 127 of the PDF file)] as well as: The semantics of applying operators in the preprocessor match those standard in the C++ preprocessor with the following exceptions: • The 2nd operand in a logical and ('&&') operation is evaluated if and only if the 1st operand evaluates to non-zero. • The 2nd operand in a logical or ('||') operation is evaluated if and only if the 1st operand evaluates to zero. If an operand is not evaluated, the presence of undefined identifiers in the operand will not cause an error. (Note that neither of these deviations from C++ preprocessor behavior apply to non-ES GLSL, at least as of specfication version 4.30.6). The first portion of this, (generating an error for an undefined macro in an (short-circuiting to squelch errors), was not implemented previously, but is implemented in this commit. A test is added for "make check" to ensure this behavior. Note: The change as implemented does make the error message a bit less precise, (it just states that an undefined macro was encountered, but not the name of the macro). This commit fixes the following Khronos GLES3 conformance test: undefined_identifiers.valid_undefined_identifier_1_vertex undefined_identifiers.valid_undefined_identifier_1_fragment undefined_identifiers.valid_undefined_identifier_2_vertex undefined_identifiers.valid_undefined_identifier_2_fragment Reviewed-by: Kenneth Graunke <[email protected]>
* glsl/glcpp: Fix glcpp to catch garbage after #if 1 ... #elseCarl Worth2014-07-091-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, a line such as: #else garbage would flag an error if it followed "#if 0", but not if it followed "#if 1". We fix this by setting a new bit of state (lexing_else) that allows the lexer to defer switching to the <SKIP> start state until after the NEWLINE following the #else directive. A new test case is added for: #if 1 #else garbage #endif which was untested before, (and did not generate the desired error). This fixes the following Khronos GLES3 CTS tests: tokens_after_else_vertex tokens_after_else_fragment Reviewed-by: Matt Turner <[email protected]> Reviewed-by: Anuj Phogat <[email protected]>
* glcpp: Resolve implicit GLSL version to 100 if the API is ES.Matt Turner2014-01-271-1/+2
| | | | | | | | | | Fixes a regression since b2d1c579 where ES shaders without a #version declaration would fail to compile if their precision declaration was wrapped in the standard #ifdef GL_ES check. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74066 Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glcpp: Check version_resolved in the proper place.Matt Turner2014-01-271-1/+1
| | | | | | | | | | | | | | | | | | The check was in the wrong place, such that if a shader incorrectly put a preprocessor token before the #version declaration, the version would be resolved twice, leading to a segmentation fault when attempting to redefine the __VERSION__ macro. #extension GL_ARB_sample_shading: require #version 130 void main() {} Also, rename glcpp_parser_resolve_version to glcpp_parser_resolve_implicit_version to avoid confusion. Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Carl Worth <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glcpp: Set extension defines after resolving the GLSL version.Matt Turner2014-01-231-1/+6
| | | | | | | | | | | | | | | | | | | | | | Instead of defining preprocessor macros in glcpp_parser_create based on the GL API, wait until the shader version has been resolved. Doing this allows us to correctly set (and not set) preprocessor macros for extensions allowed by the API but not the shader, as in the case of ARB_ES3_compatibility. The shader version has been resolved when the preprocessor encounters the first preprocessor token, since the GLSL spec says "The #version directive must occur in a shader before anything else, except for comments and white space." Specifically, if a #version token is found the version is known explicitly, and if any other preprocessor token is found then the GLSL version is implicitly 1.10. Cc: [email protected] Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71630 Reviewed-by: Ian Romanick <[email protected]>
* glcpp: error on multiple #else/#elif directivesErik Faye-Lund2014-01-021-0/+1
| | | | | | | | | | | | | | | | | | | | | The preprocessor currently accepts multiple else/elif-groups per if-section. The GLSL-preprocessor is defined by the C++ specification, which defines the following parse-rule: if-section: if-group elif-groups(opt) else-group(opt) endif-line This clearly only allows a single else-group, that has to come after any elif-groups. So let's modify the code to follow the specification. Add test to prevent regressions. Reviewed-by: Ian Romanick <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Carl Worth <[email protected]> Cc: 10.0 <[email protected]>
* glcpp: Replace multi-line comment with a space (even as part of macro ↵Carl Worth2014-01-021-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | definition) The preprocessor has always replaced multi-line comments with a single space character, (as required by the specification), but as of commit bd55ba568b301d0f764cd1ca015e84e1ae932c8b the lexer also emitted a NEWLINE token for each newline within the comment, (in order to preserve line numbers). The emitting of NEWLINE tokens within the comment broke the rule of "replace a multi-line comment with a single space" as could be exposed by code like the following: #define FOO a/* */b FOO Prior to commit bd55ba568b301d0f764cd1ca015e84e1ae932c8b, this code defined the macro FOO as "a b" as desired. Since that commit, this code instead defines FOO as "a" and leaves a stray "b" in the output. In this commit, we fix this by not emitting the NEWLINE tokens while lexing the comment, but instead merely counting them in the commented_newlines variable. Then, when the lexer next encounters a non-commented newline it switches to a NEWLINE_CATCHUP state to emit as many NEWLINE tokens as necessary (so that subsequent parsing stages still generate correct line numbers). Of course, it would have been more clear if we could have written a loop to emit all the newlines, but flex conventions prevent that, (we must use "return" for each token we emit). It similarly would have been clear to have a new rule restricted to the <NEWLINE_CATCHUP> state with an action much like the body of this if condition. The problem with that is that this rule must not consume any characters. It might be possible to write a rule that matches a single lookahead of any character, but then we would also need an additional rule to ensure for the <EOF> case where there are no additional characters available for the lookahead to match. Given those considerations, and given that the SKIP-state manipulation already involves a code block at the top of the lexer function, before any rules, it seems best to me to go with the implementation here which adds a similar pre-rule code block for the NEWLINE_CATCHUP. Finally, this commit also changes the expected output of a few, existing glcpp tests. The change here is that the space character resulting from the multi-line comment is now emitted before the newlines corresponding to that comment. (Previously, the newlines were emitted first, and the space character afterward.) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72686 Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glcpp: Accept pointer to GL context rather than just the API versionCarl Worth2013-01-111-1/+3
| | | | | | | | | As the preprocessor becomes more sophisticated and gains more optional behavior, it's easiest to just pass the GL context pointer to it so that it can examine any fields there that it needs to (such as API version, or the state of any driconf options, etc.). Reviewed-by: Kenneth Graunke <[email protected]>
* glcpp: Add a flag to the parser state to indicate GLES.Carl Worth2013-01-111-0/+1
| | | | | | | | | | | | This can be triggered either by creation of a GLES context (with api == API_OPENGLES2) or else by a #version directive with version value 100 or with a string of "es" following the version value. There's no behavioral change with this commit—just preparation for ES-specific behavior in the preprocessor in the future. Reviewed-by: Matt Turner <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* mesa/glsl: rename preprocess to glcpp_preprocessDave Airlie2012-09-151-1/+1
| | | | | | | | | | This symbol with dricore escapes into the namespace, its too generic, we should prefix it with something just to be nice. Should be applied to stable + 9.0 Acked-by: Kenneth Graunke <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
* glsl: glcpp: Move handling of #line directives from lexer to parser.Carl Worth2012-06-261-0/+5
| | | | | | | | | | | | | | | | | | | The GLSL specification requires that #line directives be interpreted after macro expansion. Our existing implementation of #line macros in the lexer prevents conformance on this point. Moving the handling of #line from the lexer to the parser gives us the macro expansion we need. An additional benefit is that the preprocessor also now supports comments on the same line as #line directives. Finally, the preprocessor now emits the (fully-macro-expanded) #line directives into the output. This allows the full GLSL compiler to also see and interpret these directives so it can also generate correct line numbers in error messages. Signed-off-by: Carl Worth <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
* glcpp: Don't strlen() the output for every token being printed.Kenneth Graunke2012-02-281-0/+2
| | | | | | | | | | | | | The ralloc string appending functions were originally intended for simple, non-hot-path uses like printing to an info log. Cuts Unigine Tropics load time by around 20% (6 seconds). v2: Avoid strlen() on every newline, too. Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Ian Romanick <[email protected]> [v1] Acked-by: José Fonseca <[email protected]> [v1]
* Convert everything from the talloc API to the ralloc API.Kenneth Graunke2011-01-311-2/+2
|
* glsl: Define GL_ES preprocessor macro if API is OpenGL ES 2.0.Kenneth Graunke2010-09-071-2/+2
| | | | Also define it if #version 100 is encountered.
* glcpp: Remove xtalloc wrappers in favor of plain talloc.Kenneth Graunke2010-08-041-24/+0
| | | | | | Calling exit() on a memory failure probably made sense for the standalone preprocessor, but doesn't seem too appealing as part of the GL library. Also, we don't use it in the main compiler.
* glsl2: Give the path within src/mesa/ for headers instead of relying on -I.Aras Pranckevicius2010-08-021-1/+1
|
* glsl: Fix missing initialization of yylloc.sourceCarl Worth2010-07-211-0/+19
| | | | | | | | | | | | In both the preprocessor and in the compiler proper, we use a custom yyltype struct to allow tracking the source-string number in addition to line and column. However, we were previously relying on bison's default initialization of the yyltype struct which of course is not aware of the source field and leaves it uninitialized. We fix this by defining our own YYLLOC_DEFAULT macro expanding on the default version (as appears in the bison manual) and adding initialization of yylloc.source.
* glsl2: Conditionally define preprocessor tokens for optional extensionsIan Romanick2010-07-011-2/+5
| | | | | The only optional extension currently supported by the compiler is GL_EXT_texture_array.
* glsl2: Move the compiler to the subdirectory it will live in in Mesa.Eric Anholt2010-06-241-0/+224