mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/preproc: Store argument values per expansion, not per macro.
This commit is contained in:
parent
e7c4867359
commit
aa79bfa681
Notes:
Henri Verbeet
2024-10-07 17:53:30 +02:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1147
@ -60,6 +60,7 @@ struct preproc_expansion
|
||||
{
|
||||
struct preproc_buffer buffer;
|
||||
const struct preproc_text *text;
|
||||
struct preproc_text *arg_values;
|
||||
/* Back-pointer to the macro, if this expansion a macro body. This is
|
||||
* necessary so that argument tokens can be correctly replaced. */
|
||||
struct preproc_macro *macro;
|
||||
@ -72,7 +73,6 @@ struct preproc_macro
|
||||
|
||||
char **arg_names;
|
||||
size_t arg_count;
|
||||
struct preproc_text *arg_values;
|
||||
|
||||
struct preproc_text body;
|
||||
};
|
||||
@ -117,6 +117,7 @@ struct preproc_ctx
|
||||
STATE_ARGS,
|
||||
} state;
|
||||
unsigned int paren_depth;
|
||||
struct preproc_text *arg_values;
|
||||
} text_func, directive_func;
|
||||
|
||||
int current_directive;
|
||||
|
@ -29,11 +29,11 @@
|
||||
|
||||
#define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner)
|
||||
|
||||
static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx)
|
||||
static struct preproc_expansion *preproc_get_top_expansion(struct preproc_ctx *ctx)
|
||||
{
|
||||
if (!ctx->expansion_count)
|
||||
return NULL;
|
||||
return ctx->expansion_stack[ctx->expansion_count - 1].macro;
|
||||
return &ctx->expansion_stack[ctx->expansion_count - 1];
|
||||
}
|
||||
|
||||
static void update_location(struct preproc_ctx *ctx);
|
||||
@ -132,14 +132,14 @@ INT_SUFFIX [uUlL]{0,2}
|
||||
|
||||
if (!ctx->last_was_newline)
|
||||
{
|
||||
struct preproc_macro *macro;
|
||||
struct preproc_expansion *exp;
|
||||
|
||||
/* Stringification is only done for function-like macro bodies.
|
||||
* Anywhere else, we need to parse it as two separate tokens.
|
||||
* We could use a state for this, but yyless() is easier and cheap.
|
||||
*/
|
||||
|
||||
if ((macro = preproc_get_top_macro(ctx)) && macro->arg_count)
|
||||
if ((exp = preproc_get_top_expansion(ctx)) && exp->macro && exp->macro->arg_count)
|
||||
return T_HASHSTRING;
|
||||
|
||||
yyless(1);
|
||||
@ -258,6 +258,12 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx)
|
||||
|
||||
yy_delete_buffer(exp->buffer.lexer_buffer, ctx->scanner);
|
||||
|
||||
if (exp->macro)
|
||||
{
|
||||
for (unsigned int i = 0; i < exp->macro->arg_count; ++i)
|
||||
vkd3d_string_buffer_cleanup(&exp->arg_values[i].text);
|
||||
free(exp->arg_values);
|
||||
}
|
||||
--ctx->expansion_count;
|
||||
TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count);
|
||||
}
|
||||
@ -310,15 +316,15 @@ static int return_token(int token, YYSTYPE *lval, const char *text)
|
||||
|
||||
static const struct preproc_text *find_arg_expansion(struct preproc_ctx *ctx, const char *s)
|
||||
{
|
||||
struct preproc_macro *macro;
|
||||
struct preproc_expansion *exp;
|
||||
unsigned int i;
|
||||
|
||||
if ((macro = preproc_get_top_macro(ctx)))
|
||||
if ((exp = preproc_get_top_expansion(ctx)) && exp->macro)
|
||||
{
|
||||
for (i = 0; i < macro->arg_count; ++i)
|
||||
for (i = 0; i < exp->macro->arg_count; ++i)
|
||||
{
|
||||
if (!strcmp(s, macro->arg_names[i]))
|
||||
return ¯o->arg_values[i];
|
||||
if (!strcmp(s, exp->macro->arg_names[i]))
|
||||
return &exp->arg_values[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -330,7 +336,7 @@ static void preproc_text_add(struct preproc_text *text, const char *string)
|
||||
}
|
||||
|
||||
static bool preproc_push_expansion(struct preproc_ctx *ctx,
|
||||
const struct preproc_text *text, struct preproc_macro *macro)
|
||||
const struct preproc_text *text, struct preproc_macro *macro, struct preproc_text *arg_values)
|
||||
{
|
||||
struct preproc_expansion *exp;
|
||||
|
||||
@ -342,6 +348,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx,
|
||||
exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner);
|
||||
exp->buffer.location = text->location;
|
||||
exp->macro = macro;
|
||||
exp->arg_values = arg_values;
|
||||
TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count);
|
||||
return true;
|
||||
}
|
||||
@ -542,7 +549,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
|
||||
if ((expansion = find_arg_expansion(ctx, text)))
|
||||
{
|
||||
preproc_push_expansion(ctx, expansion, NULL);
|
||||
preproc_push_expansion(ctx, expansion, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -550,7 +557,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
{
|
||||
if (!macro->arg_count)
|
||||
{
|
||||
preproc_push_expansion(ctx, ¯o->body, macro);
|
||||
preproc_push_expansion(ctx, ¯o->body, macro, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -616,16 +623,19 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
case STATE_IDENTIFIER:
|
||||
if (token == '(')
|
||||
{
|
||||
struct preproc_text *first_arg = &func_state->macro->arg_values[0];
|
||||
unsigned int i;
|
||||
struct preproc_text *arg_values;
|
||||
|
||||
if (!(arg_values = calloc(func_state->macro->arg_count, sizeof(*arg_values))))
|
||||
return 0;
|
||||
|
||||
for (unsigned int i = 0; i < func_state->macro->arg_count; ++i)
|
||||
vkd3d_string_buffer_init(&arg_values[i].text);
|
||||
arg_values[0].location = *lloc;
|
||||
|
||||
func_state->arg_count = 0;
|
||||
func_state->paren_depth = 1;
|
||||
func_state->state = STATE_ARGS;
|
||||
for (i = 0; i < func_state->macro->arg_count; ++i)
|
||||
func_state->macro->arg_values[i].text.content_size = 0;
|
||||
|
||||
first_arg->location = *lloc;
|
||||
func_state->arg_values = arg_values;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -649,7 +659,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
VKD3D_ASSERT(func_state->macro->arg_count);
|
||||
|
||||
if (func_state->arg_count < func_state->macro->arg_count)
|
||||
current_arg = &func_state->macro->arg_values[func_state->arg_count];
|
||||
current_arg = &func_state->arg_values[func_state->arg_count];
|
||||
|
||||
switch (token)
|
||||
{
|
||||
@ -664,7 +674,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
|
||||
if ((expansion = find_arg_expansion(ctx, text)))
|
||||
{
|
||||
preproc_push_expansion(ctx, expansion, NULL);
|
||||
preproc_push_expansion(ctx, expansion, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -700,7 +710,8 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
|
||||
{
|
||||
if (++func_state->arg_count == func_state->macro->arg_count)
|
||||
{
|
||||
preproc_push_expansion(ctx, &func_state->macro->body, func_state->macro);
|
||||
preproc_push_expansion(ctx, &func_state->macro->body,
|
||||
func_state->macro, func_state->arg_values);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -91,7 +91,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati
|
||||
size_t arg_count, const struct vkd3d_shader_location *body_loc, struct vkd3d_string_buffer *body)
|
||||
{
|
||||
struct preproc_macro *macro;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if ((macro = preproc_find_macro(ctx, name)))
|
||||
@ -108,14 +107,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati
|
||||
macro->name = name;
|
||||
macro->arg_names = arg_names;
|
||||
macro->arg_count = arg_count;
|
||||
macro->arg_values = NULL;
|
||||
if (arg_count && !(macro->arg_values = vkd3d_calloc(arg_count, sizeof(*macro->arg_values))))
|
||||
{
|
||||
vkd3d_free(macro);
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < arg_count; ++i)
|
||||
vkd3d_string_buffer_init(¯o->arg_values[i].text);
|
||||
macro->body.text = *body;
|
||||
macro->body.location = *body_loc;
|
||||
ret = rb_put(&ctx->macros, name, ¯o->entry);
|
||||
@ -129,12 +120,8 @@ void preproc_free_macro(struct preproc_macro *macro)
|
||||
|
||||
vkd3d_free(macro->name);
|
||||
for (i = 0; i < macro->arg_count; ++i)
|
||||
{
|
||||
vkd3d_string_buffer_cleanup(¯o->arg_values[i].text);
|
||||
vkd3d_free(macro->arg_names[i]);
|
||||
}
|
||||
vkd3d_free(macro->arg_names);
|
||||
vkd3d_free(macro->arg_values);
|
||||
vkd3d_string_buffer_cleanup(¯o->body.text);
|
||||
vkd3d_free(macro);
|
||||
}
|
||||
|
@ -375,3 +375,7 @@ key1
|
||||
[preproc]
|
||||
#define key1 ::key2 pass
|
||||
key1
|
||||
|
||||
[preproc]
|
||||
#define KEY(a, b) a b
|
||||
KEY(KEY(x, y), pass)
|
||||
|
Loading…
Reference in New Issue
Block a user