From 67b32190f3c953c5b7091d76ddeff95c0cbfb439 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 14 Aug 2019 14:24:31 +1000 Subject: [PATCH] glsl: add ARB_shading_language_include support to #line From the ARB_shading_language_include spec: "#line must have, after macro substitution, one of the following forms: #line #line #line "" where and are constant integer expressions and 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 and source string number or path. Subsequent source strings will be numbered sequentially, until another #line directive overrides that numbering." Reviewed-by: Witold Baryluk --- src/compiler/glsl/ast.h | 4 ++ src/compiler/glsl/glcpp/glcpp-lex.l | 5 +++ src/compiler/glsl/glcpp/glcpp-parse.y | 15 +++++++- src/compiler/glsl/glsl_lexer.ll | 47 +++++++++++++++++++++++- src/compiler/glsl/glsl_parser.yy | 1 + src/compiler/glsl/glsl_parser_extras.cpp | 14 ++++--- src/compiler/glsl/glsl_parser_extras.h | 2 + 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index f07a14bce8f..67b258ce538 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -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. */ diff --git a/src/compiler/glsl/glcpp/glcpp-lex.l b/src/compiler/glsl/glcpp/glcpp-lex.l index f7003da0cc8..47ecb7b55b1 100644 --- a/src/compiler/glsl/glcpp/glcpp-lex.l +++ b/src/compiler/glsl/glcpp/glcpp-lex.l @@ -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} { diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index 51bc85dcee7..b975e8b3f40 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -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 and 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 INTEGER operator SPACE integer_constant version_constant %type expression -%type IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA +%type IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA PATH %type identifier_list %type preprocessing_token %type 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; diff --git a/src/compiler/glsl/glsl_lexer.ll b/src/compiler/glsl/glsl_lexer.ll index 43bd2b23ec4..8c59e1d748f 100644 --- a/src/compiler/glsl/glsl_lexer.ll +++ b/src/compiler/glsl/glsl_lexer.ll @@ -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 \"\""); + } + + /* 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 diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index edf421d9053..048af1f0857 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -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} diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index e457d63b988..b1573460080 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -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]; diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index 33db8b5b656..444a51dfdb5 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -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 -- 2.30.2