Module: wine Branch: master Commit: 84509acb166387e5877066a39a56d4be54cdd9e0 URL: https://gitlab.winehq.org/wine/wine/-/commit/84509acb166387e5877066a39a56d4b...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Apr 15 16:15:08 2024 +0200
widl: Correctly align stack parameters on ARM.
---
tools/widl/typegen.c | 61 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 16 deletions(-)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 86d4354573e..7284e0531bc 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -417,20 +417,35 @@ static int get_padding(const var_list_t *fields) return ROUNDING(offset, salign); }
-static unsigned int get_stack_size( const var_t *var, int *by_value ) +static unsigned int get_stack_size( const var_t *var, unsigned int *stack_align, int *by_value ) { - unsigned int stack_size; + unsigned int stack_size, align = 0; int by_val;
switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES )) { case TGT_BASIC: + if (target.cpu == CPU_ARM) + { + switch (type_basic_get_type( var->declspec.type )) + { + case TYPE_BASIC_FLOAT: + case TYPE_BASIC_DOUBLE: + case TYPE_BASIC_INT64: + case TYPE_BASIC_HYPER: + align = 8; + break; + default: + break; + } + } + /* fall through */ case TGT_ENUM: case TGT_RANGE: case TGT_STRUCT: case TGT_UNION: case TGT_USER_TYPE: - stack_size = type_memsize( var->declspec.type ); + stack_size = type_memsize_and_alignment( var->declspec.type, &align ); switch (target.cpu) { case CPU_x86_64: @@ -439,7 +454,11 @@ static unsigned int get_stack_size( const var_t *var, int *by_value ) case CPU_ARM64: by_val = (stack_size <= 2 * pointer_size); break; + case CPU_ARM: + by_val = 1; + break; default: + align = pointer_size; by_val = 1; break; } @@ -448,9 +467,12 @@ static unsigned int get_stack_size( const var_t *var, int *by_value ) by_val = 0; break; } - if (!by_val) stack_size = pointer_size; + if (align < pointer_size) align = pointer_size; + if (!by_val) stack_size = align = pointer_size; + if (by_value) *by_value = by_val; - return ROUND_SIZE( stack_size, pointer_size ); + if (stack_align) *stack_align = align; + return ROUND_SIZE( stack_size, align ); }
static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs, @@ -1035,7 +1057,8 @@ int decl_indirect(const type_t *t) }
static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned short *flags, - unsigned int *stack_size, unsigned int *typestring_offset ) + unsigned int *stack_size, unsigned int *stack_align, + unsigned int *typestring_offset ) { unsigned int alignment, server_size = 0, buffer_size = 0; unsigned char fc = 0; @@ -1047,7 +1070,7 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned else if (!is_in && !is_out) is_in = TRUE;
*flags = 0; - *stack_size = get_stack_size( var, &is_byval ); + *stack_size = get_stack_size( var, stack_align, &is_byval ); *typestring_offset = var->typestring_offset;
if (is_in) *flags |= IsIn; @@ -1203,11 +1226,11 @@ static unsigned char get_func_oi2_flags( const var_t *func ) var_t *retval = type_function_get_retval( func->declspec.type ); unsigned char oi2_flags = 0x40; /* HasExtensions */ unsigned short flags; - unsigned int stack_size, typestring_offset; + unsigned int stack_size, stack_align, typestring_offset;
if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) { - get_parameter_fc( var, 0, &flags, &stack_size, &typestring_offset ); + get_parameter_fc( var, 0, &flags, &stack_size, &stack_align, &typestring_offset ); if (flags & MustSize) { if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */ @@ -1218,7 +1241,7 @@ static unsigned char get_func_oi2_flags( const var_t *func ) if (!is_void( retval->declspec.type )) { oi2_flags |= 0x04; /* HasRet */ - get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset ); + get_parameter_fc( retval, 1, &flags, &stack_size, &stack_align, &typestring_offset ); if (flags & MustSize) oi2_flags |= 0x01; /* ServerMustSize */ } return oi2_flags; @@ -1228,10 +1251,11 @@ static unsigned int write_new_procformatstring_type(FILE *file, int indent, cons int is_return, unsigned int *stack_offset) { char buffer[128]; - unsigned int stack_size, typestring_offset; + unsigned int stack_size, stack_align, typestring_offset; unsigned short flags; - unsigned char fc = get_parameter_fc( var, is_return, &flags, &stack_size, &typestring_offset ); + unsigned char fc = get_parameter_fc( var, is_return, &flags, &stack_size, &stack_align, &typestring_offset );
+ *stack_offset = ROUND_SIZE( *stack_offset, stack_align ); strcpy( buffer, "/* flags:" ); if (flags & MustSize) strcat( buffer, " must size," ); if (flags & MustFree) strcat( buffer, " must free," ); @@ -1255,7 +1279,7 @@ static unsigned int write_new_procformatstring_type(FILE *file, int indent, cons else print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", typestring_offset, typestring_offset ); - *stack_offset += max( stack_size, pointer_size ); + *stack_offset += stack_size; return 6; }
@@ -1313,7 +1337,7 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons else print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
- size = get_stack_size( var, NULL ); + size = get_stack_size( var, NULL, NULL ); print_file(file, indent, "0x%02x,\n", size / pointer_size ); print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset); size = 4; /* includes param type prefix */ @@ -1365,6 +1389,7 @@ static void write_proc_func_interp( FILE *file, int indent, const type_t *iface, unsigned int nb_args = 0; unsigned int stack_size = 0; unsigned int stack_offset = 0; + unsigned int stack_align; unsigned short param_num = 0; unsigned short handle_stack_offset = 0; unsigned short handle_param_num = 0; @@ -1385,7 +1410,9 @@ static void write_proc_func_interp( FILE *file, int indent, const type_t *iface, handle_stack_offset = stack_size; handle_param_num = param_num; } - stack_size += get_stack_size( var, NULL ); + size = get_stack_size( var, &stack_align, NULL ); + stack_size = ROUND_SIZE( stack_size, stack_align ); + stack_size += size; param_num++; nb_args++; } @@ -1773,13 +1800,15 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, if (is_object( iface )) offset += pointer_size; if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) { + unsigned int align, size = get_stack_size( var, &align, NULL ); + offset = ROUND_SIZE( offset, align ); if (var->name && !strcmp(var->name, subexpr->u.sval)) { expr_loc.v = var; correlation_variable = var->declspec.type; break; } - offset += get_stack_size( var, NULL ); + offset += size; if (var == current_arg) robust_flags &= ~RobustEarly; } }