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, ¯o->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, ¯o->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