glsl: add ARB_shading_language_include support to #line
authorTimothy Arceri <tarceri@itsqueeze.com>
Wed, 14 Aug 2019 04:24:31 +0000 (14:24 +1000)
committerTimothy Arceri <tarceri@itsqueeze.com>
Wed, 20 Nov 2019 05:05:55 +0000 (05:05 +0000)
From the ARB_shading_language_include spec:

   "#line must have, after macro substitution, one of the following
    forms:

       #line <line>
       #line <line> <source-string-number>
       #line <line> "<path>"

    where <line> and <source-string-number> are constant integer
    expressions and <path> is a valid string for a path supplied in the
    #include directive. After processing this directive (including its
    new-line), the implementation will behave as if it is compiling at
    line number <line> and source string number <source-string-number>
    or <path> path. Subsequent source strings will be numbered
    sequentially, until another #line directive overrides that
    numbering."

Reviewed-by: Witold Baryluk <witold.baryluk@gmail.com>
src/compiler/glsl/ast.h
src/compiler/glsl/glcpp/glcpp-lex.l
src/compiler/glsl/glcpp/glcpp-parse.y
src/compiler/glsl/glsl_lexer.ll
src/compiler/glsl/glsl_parser.yy
src/compiler/glsl/glsl_parser_extras.cpp
src/compiler/glsl/glsl_parser_extras.h

index f07a14bce8f07789e2346b0c122331d2c92a5d98..67b258ce5386249199c8c80180551d72441b09f2 100644 (file)
@@ -77,6 +77,7 @@ public:
    {
       struct YYLTYPE locp;
 
+      locp.path = this->location.path;
       locp.source = this->location.source;
       locp.first_line = this->location.first_line;
       locp.first_column = this->location.first_column;
@@ -93,6 +94,7 @@ public:
     */
    void set_location(const struct YYLTYPE &locp)
    {
+      this->location.path = locp.path;
       this->location.source = locp.source;
       this->location.first_line = locp.first_line;
       this->location.first_column = locp.first_column;
@@ -107,6 +109,7 @@ public:
     */
    void set_location_range(const struct YYLTYPE &begin, const struct YYLTYPE &end)
    {
+      this->location.path = begin.path;
       this->location.source = begin.source;
       this->location.first_line = begin.first_line;
       this->location.last_line = end.last_line;
@@ -118,6 +121,7 @@ public:
     * Source location of the AST node.
     */
    struct {
+      char *path;               /**< GLSL shader include path. */
       unsigned source;          /**< GLSL source number. */
       unsigned first_line;      /**< First line number within the source string. */
       unsigned first_column;    /**< First column in the first line. */
index f7003da0cc84372dd425919e9fcf6a23eb89cbb4..47ecb7b55b1e9f89e70293e05487bc1ef724ff5d 100644 (file)
@@ -202,6 +202,7 @@ DIGITS                      [0-9][0-9]*
 DECIMAL_INTEGER                [1-9][0-9]*[uU]?
 OCTAL_INTEGER          0[0-7]*[uU]?
 HEXADECIMAL_INTEGER    0[xX][0-9a-fA-F]+[uU]?
+PATH                   ["][]^./ _A-Za-z0-9+*%[(){}|&~=!:;,?-]*["]
 
 %%
 
@@ -558,6 +559,10 @@ HEXADECIMAL_INTEGER        0[xX][0-9a-fA-F]+[uU]?
        }
 }
 
+{PATH} {
+       RETURN_STRING_TOKEN (PATH);
+}
+
        /* We preserve all newlines, even between #if 0..#endif, so no
        skipping.. */
 <*>{NEWLINE} {
index 51bc85dcee74ac8ee676411f0d503261abd6f679..b975e8b3f40d1f77fef4ee8b6e144d0aa3ed1482 100644 (file)
@@ -174,11 +174,11 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
         /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to
          * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols,
          * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
-%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS
+%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS PATH
 %token PASTE
 %type <ival> INTEGER operator SPACE integer_constant version_constant
 %type <expression_value> expression
-%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA
+%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA PATH
 %type <string_list> identifier_list
 %type <token> preprocessing_token
 %type <token_list> pp_tokens replacement_list text_line
@@ -238,6 +238,13 @@ expanded_line:
                                           "#line %" PRIiMAX " %" PRIiMAX "\n",
                                            $2, $3);
        }
+|      LINE_EXPANDED integer_constant PATH NEWLINE {
+               parser->has_new_line_number = 1;
+               parser->new_line_number = $2;
+               _mesa_string_buffer_printf(parser->output,
+                                          "#line %" PRIiMAX " %s\n",
+                                           $2, $3);
+       }
 ;
 
 define:
@@ -706,6 +713,10 @@ preprocessing_token:
                $$ = _token_create_str (parser, INTEGER_STRING, $1);
                $$->location = yylloc;
        }
+|      PATH {
+               $$ = _token_create_str (parser, PATH, $1);
+               $$->location = yylloc;
+       }
 |      operator {
                $$ = _token_create_ival (parser, $1, $1);
                $$->location = yylloc;
index 43bd2b23ec4c82efc65f2a96ad6d11f9145c6aef..8c59e1d748fa9f9236b3d87ee43013fd00149399 100644 (file)
@@ -45,7 +45,8 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *,
       yylloc->last_column = yycolumn + 1;                      \
    } while(0);
 
-#define YY_USER_INIT yylineno = 0; yycolumn = 0; yylloc->source = 0;
+#define YY_USER_INIT yylineno = 0; yycolumn = 0; yylloc->source = 0; \
+   yylloc->path = NULL;
 
 /* A macro for handling reserved words and keywords across language versions.
  *
@@ -226,6 +227,7 @@ INT         ({DEC_INT}|{HEX_INT}|{OCT_INT})
 SPC            [ \t]*
 SPCP           [ \t]+
 HASH           ^{SPC}#{SPC}
+PATH           ["][./ _A-Za-z0-9]*["]
 %%
 
 [ \r\t]+               ;
@@ -257,7 +259,50 @@ HASH               ^{SPC}#{SPC}
                                       yylineno--;
 
                                   yylloc->source = strtol(ptr, NULL, 0);
+                                   yylloc->path = NULL;
                                }
+{HASH}line{SPCP}{INT}{SPCP}{PATH}{SPC}$ {
+                                   if (!yyextra->ARB_shading_language_include_enable) {
+                                      struct _mesa_glsl_parse_state *state = yyextra;
+                                      _mesa_glsl_error(yylloc, state,
+                                                       "ARB_shading_language_include required "
+                                                       "to use #line <line> \"<path>\"");
+                                   }
+
+                                   /* Eat characters until the first digit is
+                                    * encountered
+                                    */
+                                   char *ptr = yytext;
+                                   while (!isdigit(*ptr))
+                                      ptr++;
+
+                                   /* Subtract one from the line number because
+                                    * yylineno is zero-based instead of
+                                    * one-based.
+                                    */
+                                   yylineno = strtol(ptr, &ptr, 0) - 1;
+
+                                   /* From GLSL 3.30 and GLSL ES on, after processing the
+                                    * line directive (including its new-line), the implementation
+                                    * will behave as if it is compiling at the line number passed
+                                    * as argument. It was line number + 1 in older specifications.
+                                    */
+                                   if (yyextra->is_version(330, 100))
+                                      yylineno--;
+
+                                   while (isspace(*ptr))
+                                      ptr++;
+
+                                   /* Skip over leading " */
+                                   ptr++;
+
+                                   char *end = strrchr(ptr, '"');
+                                   int path_len = (end - ptr) + 1;
+                                   void *mem_ctx = yyextra->linalloc;
+                                   yylloc->path = (char *) linear_alloc_child(mem_ctx, path_len);
+                                   memcpy(yylloc->path, ptr, path_len);
+                                   yylloc->path[path_len - 1] = '\0';
+                                }
 {HASH}line{SPCP}{INT}{SPC}$    {
                                   /* Eat characters until the first digit is
                                    * encountered
index edf421d9053ecbdd22081581aab119b5474d1b69..048af1f085747b5e4a42dcc5f1290b188f66ec00 100644 (file)
@@ -91,6 +91,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
    @$.last_line = 1;
    @$.last_column = 1;
    @$.source = 0;
+   @$.path = NULL;
 }
 
 %lex-param   {struct _mesa_glsl_parse_state *state}
index e457d63b988556e4bde2c1d965e868788ef35835..b1573460080cf57873e3b207f3f0889058c6c1f0 100644 (file)
@@ -495,11 +495,15 @@ _mesa_glsl_msg(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
    /* Get the offset that the new message will be written to. */
    int msg_offset = strlen(state->info_log);
 
-   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): %s: ",
-                                           locp->source,
-                                           locp->first_line,
-                                           locp->first_column,
-                                           error ? "error" : "warning");
+   if (locp->path) {
+      ralloc_asprintf_append(&state->info_log, "\"%s\"", locp->path);
+   } else {
+      ralloc_asprintf_append(&state->info_log, "%u", locp->source);
+   }
+   ralloc_asprintf_append(&state->info_log, ":%u(%u): %s: ",
+                          locp->first_line, locp->first_column,
+                          error ? "error" : "warning");
+
    ralloc_vasprintf_append(&state->info_log, fmt, ap);
 
    const char *const msg = &state->info_log[msg_offset];
index 33db8b5b656593f7013f1bea92fbd2fc05095a84..444a51dfdb55d39b8bf5906f84edb2fa7fa2d9fc 100644 (file)
@@ -68,6 +68,8 @@ typedef struct YYLTYPE {
    int last_line;
    int last_column;
    unsigned source;
+   /* Path for ARB_shading_language_include include source */
+   char *path;
 } YYLTYPE;
 # define YYLTYPE_IS_DECLARED 1
 # define YYLTYPE_IS_TRIVIAL 1