Zebediah Figura : vkd3d-shader: Partially implement #define.

Alexandre Julliard julliard at winehq.org
Tue Jan 12 15:00:33 CST 2021


Module: vkd3d
Branch: master
Commit: 9a1317ff0f274dda4d56af20e42f17d2af5a08c4
URL:    https://source.winehq.org/git/vkd3d.git/?a=commit;h=9a1317ff0f274dda4d56af20e42f17d2af5a08c4

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Thu Jan  7 11:48:06 2021 -0600

vkd3d-shader: Partially implement #define.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 Makefile.am                              |  1 +
 libs/vkd3d-shader/preproc.h              | 10 ++++++
 libs/vkd3d-shader/preproc.l              | 35 +++++++++++++++++--
 libs/vkd3d-shader/preproc.y              | 59 +++++++++++++++++++++++++++++++-
 libs/vkd3d-shader/vkd3d_shader_private.h |  1 +
 tests/hlsl_d3d12.c                       |  2 +-
 6 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 514f050..bf1d7bf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -243,6 +243,7 @@ XFAIL_TESTS = \
 	tests/hlsl-vector-indexing.shader_test \
 	tests/hlsl-vector-indexing-uniform.shader_test \
 	tests/math.shader_test \
+	tests/preproc-if.shader_test \
 	tests/preproc-ifdef.shader_test \
 	tests/preproc-if-expr.shader_test \
 	tests/preproc-invalid.shader_test \
diff --git a/libs/vkd3d-shader/preproc.h b/libs/vkd3d-shader/preproc.h
index effcd99..7f77d27 100644
--- a/libs/vkd3d-shader/preproc.h
+++ b/libs/vkd3d-shader/preproc.h
@@ -22,6 +22,7 @@
 #define __VKD3D_SHADER_PREPROC_H
 
 #include "vkd3d_shader_private.h"
+#include "rbtree.h"
 
 struct preproc_if_state
 {
@@ -33,6 +34,12 @@ struct preproc_if_state
     bool seen_else;
 };
 
+struct preproc_macro
+{
+    struct rb_entry entry;
+    char *name;
+};
+
 struct preproc_ctx
 {
     void *scanner;
@@ -44,6 +51,8 @@ struct preproc_ctx
     struct preproc_if_state *if_stack;
     size_t if_count, if_stack_size;
 
+    struct rb_tree macros;
+
     int current_directive;
 
     bool last_was_newline;
@@ -52,6 +61,7 @@ struct preproc_ctx
     bool error;
 };
 
+void preproc_free_macro(struct preproc_macro *macro) DECLSPEC_HIDDEN;
 void preproc_warning(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc,
         enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5) DECLSPEC_HIDDEN;
 
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l
index 47ad1f1..89c205f 100644
--- a/libs/vkd3d-shader/preproc.l
+++ b/libs/vkd3d-shader/preproc.l
@@ -67,7 +67,7 @@ IDENTIFIER      [A-Za-z_][A-Za-z0-9_]*
 <C_COMMENT,CXX_COMMENT><<EOF>>      {yy_pop_state(yyscanner);}
 <C_COMMENT,CXX_COMMENT>.            {}
 
-<INITIAL>{IDENTIFIER}               {return T_TEXT;}
+<INITIAL>{IDENTIFIER}               {return T_IDENTIFIER;}
 
     /* We have no use for floats, but shouldn't parse them as integers. */
 
@@ -100,6 +100,8 @@ IDENTIFIER      [A-Za-z_][A-Za-z0-9_]*
         for (p = yytext + 1; strchr(" \t", *p); ++p)
             ;
 
+        if (!strcmp(p, "define"))
+            return T_DEFINE;
         if (!strcmp(p, "elif"))
             return T_ELIF;
         if (!strcmp(p, "else"))
@@ -154,6 +156,7 @@ static int return_token(int token, YYSTYPE *lval, const char *text)
 {
     switch (token)
     {
+        case T_IDENTIFIER:
         case T_INTEGER:
         case T_TEXT:
             if (!(lval->string = vkd3d_strdup(text)))
@@ -191,6 +194,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
         {
             switch (token)
             {
+                case T_DEFINE:
                 case T_ELIF:
                 case T_ELSE:
                 case T_ENDIF:
@@ -208,8 +212,18 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
         TRACE("Parsing token %d, line %d, in directive %d, string %s.\n",
                 token, lloc->line, ctx->current_directive, debugstr_a(text));
 
-        if (!ctx->current_directive && !preproc_is_writing(ctx))
-            continue;
+        switch (ctx->current_directive)
+        {
+            case T_ELIF:
+            case T_ELSE:
+            case T_ENDIF:
+            case T_IF:
+                break;
+
+            default:
+                if (!preproc_is_writing(ctx))
+                    continue;
+        }
 
         if (ctx->current_directive)
             return return_token(token, lval, text);
@@ -218,6 +232,19 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
     }
 }
 
+static int preproc_macro_compare(const void *key, const struct rb_entry *entry)
+{
+    const struct preproc_macro *macro = RB_ENTRY_VALUE(entry, struct preproc_macro, entry);
+    const char *name = key;
+
+    return strcmp(name, macro->name);
+}
+
+static void preproc_macro_rb_free(struct rb_entry *entry, void *ctx)
+{
+    preproc_free_macro(RB_ENTRY_VALUE(entry, struct preproc_macro, entry));
+}
+
 int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
         struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
 {
@@ -226,6 +253,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
     void *output_code;
 
     vkd3d_string_buffer_init(&ctx.buffer);
+    rb_init(&ctx.macros, preproc_macro_compare);
     ctx.message_context = message_context;
     ctx.location.source_name = compile_info->source_name;
     ctx.location.line = 1;
@@ -248,6 +276,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
     }
 
     vkd3d_free(ctx.if_stack);
+    rb_destroy(&ctx.macros, preproc_macro_rb_free, NULL);
 
     if (ctx.error)
     {
diff --git a/libs/vkd3d-shader/preproc.y b/libs/vkd3d-shader/preproc.y
index 647bb45..45cad44 100644
--- a/libs/vkd3d-shader/preproc.y
+++ b/libs/vkd3d-shader/preproc.y
@@ -66,6 +66,43 @@ static void yyerror(const YYLTYPE *loc, void *scanner, struct preproc_ctx *ctx,
     preproc_error(ctx, loc, VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX, "%s", string);
 }
 
+static struct preproc_macro *preproc_find_macro(struct preproc_ctx *ctx, const char *name)
+{
+    struct rb_entry *entry;
+
+    if ((entry = rb_get(&ctx->macros, name)))
+        return RB_ENTRY_VALUE(entry, struct preproc_macro, entry);
+    return NULL;
+}
+
+static bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc, char *name)
+{
+    struct preproc_macro *macro;
+    int ret;
+
+    if ((macro = preproc_find_macro(ctx, name)))
+    {
+        preproc_warning(ctx, loc, VKD3D_SHADER_WARNING_PP_ALREADY_DEFINED, "Redefinition of %s.", name);
+        rb_remove(&ctx->macros, &macro->entry);
+        preproc_free_macro(macro);
+    }
+
+    TRACE("Defining new macro %s.\n", debugstr_a(name));
+
+    if (!(macro = vkd3d_malloc(sizeof(*macro))))
+        return false;
+    macro->name = name;
+    ret = rb_put(&ctx->macros, name, &macro->entry);
+    assert(!ret);
+    return true;
+}
+
+void preproc_free_macro(struct preproc_macro *macro)
+{
+    vkd3d_free(macro->name);
+    vkd3d_free(macro);
+}
+
 static bool preproc_was_writing(struct preproc_ctx *ctx)
 {
     if (ctx->if_count < 2)
@@ -135,17 +172,20 @@ static uint32_t preproc_parse_integer(const char *s)
     uint32_t integer;
 }
 
+%token <string> T_IDENTIFIER
 %token <string> T_INTEGER
 %token <string> T_TEXT
 
 %token T_NEWLINE
 
+%token T_DEFINE "#define"
 %token T_ELIF "#elif"
 %token T_ELSE "#else"
 %token T_ENDIF "#endif"
 %token T_IF "#if"
 
 %type <integer> expr
+%type <string> body_token
 
 %%
 
@@ -156,8 +196,25 @@ shader_text
             vkd3d_string_buffer_printf(&ctx->buffer, "\n");
         }
 
+body_text
+    : %empty
+    | body_text body_token
+        {
+            vkd3d_free($2);
+        }
+
+body_token
+    : T_IDENTIFIER
+    | T_INTEGER
+    | T_TEXT
+
 directive
-    : T_IF expr T_NEWLINE
+    : T_DEFINE T_IDENTIFIER body_text T_NEWLINE
+        {
+            if (!preproc_add_macro(ctx, &@$, $2))
+                YYABORT;
+        }
+    | T_IF expr T_NEWLINE
         {
             if (!preproc_push_if(ctx, !!$2))
                 YYABORT;
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index b89d20e..1011be2 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -82,6 +82,7 @@ enum vkd3d_shader_error
 
     VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX                = 4000,
 
+    VKD3D_SHADER_WARNING_PP_ALREADY_DEFINED             = 4300,
     VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE           = 4301,
     VKD3D_SHADER_WARNING_PP_UNKNOWN_DIRECTIVE           = 4303,
     VKD3D_SHADER_WARNING_PP_UNTERMINATED_IF             = 4305,
diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c
index 77a7ea1..38c1ab2 100644
--- a/tests/hlsl_d3d12.c
+++ b/tests/hlsl_d3d12.c
@@ -349,7 +349,7 @@ static void test_preprocess(void)
 
     for (i = 0; i < ARRAY_SIZE(tests); ++i)
     {
-        if (i == 43)
+        if (i == 6)
             continue;
         vkd3d_test_set_context("Source \"%s\"", tests[i].source);
         todo_if (i <= 4 || (i >= 9 && i <= 14))




More information about the wine-cvs mailing list