mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader: Partially implement #define.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Matteo Bruni <mbruni@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6b75fb7b9c
commit
9a1317ff0f
@ -243,6 +243,7 @@ XFAIL_TESTS = \
|
|||||||
tests/hlsl-vector-indexing.shader_test \
|
tests/hlsl-vector-indexing.shader_test \
|
||||||
tests/hlsl-vector-indexing-uniform.shader_test \
|
tests/hlsl-vector-indexing-uniform.shader_test \
|
||||||
tests/math.shader_test \
|
tests/math.shader_test \
|
||||||
|
tests/preproc-if.shader_test \
|
||||||
tests/preproc-ifdef.shader_test \
|
tests/preproc-ifdef.shader_test \
|
||||||
tests/preproc-if-expr.shader_test \
|
tests/preproc-if-expr.shader_test \
|
||||||
tests/preproc-invalid.shader_test \
|
tests/preproc-invalid.shader_test \
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define __VKD3D_SHADER_PREPROC_H
|
#define __VKD3D_SHADER_PREPROC_H
|
||||||
|
|
||||||
#include "vkd3d_shader_private.h"
|
#include "vkd3d_shader_private.h"
|
||||||
|
#include "rbtree.h"
|
||||||
|
|
||||||
struct preproc_if_state
|
struct preproc_if_state
|
||||||
{
|
{
|
||||||
@ -33,6 +34,12 @@ struct preproc_if_state
|
|||||||
bool seen_else;
|
bool seen_else;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct preproc_macro
|
||||||
|
{
|
||||||
|
struct rb_entry entry;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
struct preproc_ctx
|
struct preproc_ctx
|
||||||
{
|
{
|
||||||
void *scanner;
|
void *scanner;
|
||||||
@ -44,6 +51,8 @@ struct preproc_ctx
|
|||||||
struct preproc_if_state *if_stack;
|
struct preproc_if_state *if_stack;
|
||||||
size_t if_count, if_stack_size;
|
size_t if_count, if_stack_size;
|
||||||
|
|
||||||
|
struct rb_tree macros;
|
||||||
|
|
||||||
int current_directive;
|
int current_directive;
|
||||||
|
|
||||||
bool last_was_newline;
|
bool last_was_newline;
|
||||||
@ -52,6 +61,7 @@ struct preproc_ctx
|
|||||||
bool error;
|
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,
|
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;
|
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
@ -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><<EOF>> {yy_pop_state(yyscanner);}
|
||||||
<C_COMMENT,CXX_COMMENT>. {}
|
<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. */
|
/* 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)
|
for (p = yytext + 1; strchr(" \t", *p); ++p)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (!strcmp(p, "define"))
|
||||||
|
return T_DEFINE;
|
||||||
if (!strcmp(p, "elif"))
|
if (!strcmp(p, "elif"))
|
||||||
return T_ELIF;
|
return T_ELIF;
|
||||||
if (!strcmp(p, "else"))
|
if (!strcmp(p, "else"))
|
||||||
@ -154,6 +156,7 @@ static int return_token(int token, YYSTYPE *lval, const char *text)
|
|||||||
{
|
{
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
|
case T_IDENTIFIER:
|
||||||
case T_INTEGER:
|
case T_INTEGER:
|
||||||
case T_TEXT:
|
case T_TEXT:
|
||||||
if (!(lval->string = vkd3d_strdup(text)))
|
if (!(lval->string = vkd3d_strdup(text)))
|
||||||
@ -191,6 +194,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
|||||||
{
|
{
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
|
case T_DEFINE:
|
||||||
case T_ELIF:
|
case T_ELIF:
|
||||||
case T_ELSE:
|
case T_ELSE:
|
||||||
case T_ENDIF:
|
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",
|
TRACE("Parsing token %d, line %d, in directive %d, string %s.\n",
|
||||||
token, lloc->line, ctx->current_directive, debugstr_a(text));
|
token, lloc->line, ctx->current_directive, debugstr_a(text));
|
||||||
|
|
||||||
if (!ctx->current_directive && !preproc_is_writing(ctx))
|
switch (ctx->current_directive)
|
||||||
continue;
|
{
|
||||||
|
case T_ELIF:
|
||||||
|
case T_ELSE:
|
||||||
|
case T_ENDIF:
|
||||||
|
case T_IF:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!preproc_is_writing(ctx))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->current_directive)
|
if (ctx->current_directive)
|
||||||
return return_token(token, lval, text);
|
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,
|
int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
|
||||||
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
|
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;
|
void *output_code;
|
||||||
|
|
||||||
vkd3d_string_buffer_init(&ctx.buffer);
|
vkd3d_string_buffer_init(&ctx.buffer);
|
||||||
|
rb_init(&ctx.macros, preproc_macro_compare);
|
||||||
ctx.message_context = message_context;
|
ctx.message_context = message_context;
|
||||||
ctx.location.source_name = compile_info->source_name;
|
ctx.location.source_name = compile_info->source_name;
|
||||||
ctx.location.line = 1;
|
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);
|
vkd3d_free(ctx.if_stack);
|
||||||
|
rb_destroy(&ctx.macros, preproc_macro_rb_free, NULL);
|
||||||
|
|
||||||
if (ctx.error)
|
if (ctx.error)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
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)
|
static bool preproc_was_writing(struct preproc_ctx *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->if_count < 2)
|
if (ctx->if_count < 2)
|
||||||
@ -135,17 +172,20 @@ static uint32_t preproc_parse_integer(const char *s)
|
|||||||
uint32_t integer;
|
uint32_t integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%token <string> T_IDENTIFIER
|
||||||
%token <string> T_INTEGER
|
%token <string> T_INTEGER
|
||||||
%token <string> T_TEXT
|
%token <string> T_TEXT
|
||||||
|
|
||||||
%token T_NEWLINE
|
%token T_NEWLINE
|
||||||
|
|
||||||
|
%token T_DEFINE "#define"
|
||||||
%token T_ELIF "#elif"
|
%token T_ELIF "#elif"
|
||||||
%token T_ELSE "#else"
|
%token T_ELSE "#else"
|
||||||
%token T_ENDIF "#endif"
|
%token T_ENDIF "#endif"
|
||||||
%token T_IF "#if"
|
%token T_IF "#if"
|
||||||
|
|
||||||
%type <integer> expr
|
%type <integer> expr
|
||||||
|
%type <string> body_token
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -156,8 +196,25 @@ shader_text
|
|||||||
vkd3d_string_buffer_printf(&ctx->buffer, "\n");
|
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
|
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))
|
if (!preproc_push_if(ctx, !!$2))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@ -82,6 +82,7 @@ enum vkd3d_shader_error
|
|||||||
|
|
||||||
VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX = 4000,
|
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_INVALID_DIRECTIVE = 4301,
|
||||||
VKD3D_SHADER_WARNING_PP_UNKNOWN_DIRECTIVE = 4303,
|
VKD3D_SHADER_WARNING_PP_UNKNOWN_DIRECTIVE = 4303,
|
||||||
VKD3D_SHADER_WARNING_PP_UNTERMINATED_IF = 4305,
|
VKD3D_SHADER_WARNING_PP_UNTERMINATED_IF = 4305,
|
||||||
|
@ -349,7 +349,7 @@ static void test_preprocess(void)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(tests); ++i)
|
for (i = 0; i < ARRAY_SIZE(tests); ++i)
|
||||||
{
|
{
|
||||||
if (i == 43)
|
if (i == 6)
|
||||||
continue;
|
continue;
|
||||||
vkd3d_test_set_context("Source \"%s\"", tests[i].source);
|
vkd3d_test_set_context("Source \"%s\"", tests[i].source);
|
||||||
todo_if (i <= 4 || (i >= 9 && i <= 14))
|
todo_if (i <= 4 || (i >= 9 && i <= 14))
|
||||||
|
Loading…
Reference in New Issue
Block a user