From: Robert Pengelly Date: Sun, 4 Oct 2026 18:15:11 +0000 (+0100) Subject: Fix multidimensional array member indexing X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;ds=sidebyside;p=scc.git Fix multidimensional array member indexing --- diff --git a/amd64.c b/amd64.c index 8a8af56..3d6483f 100644 --- a/amd64.c +++ b/amd64.c @@ -14752,11 +14752,14 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { const char *member_caret; unsigned long member_line; - int offset = 0; + int size = DATA_INT & 0x1f; int elem_size = DATA_INT & 0x1f; + + int array_dimensions = 0; int pointer_depth = 0; + int is_array = 0; int is_floating = 0; int is_unsigned = 0; @@ -14787,6 +14790,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { } is_unsigned = last_found_member_is_unsigned; + array_dimensions = last_found_member_array_dimensions; { @@ -14890,9 +14894,11 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { } + } else if (array_dimensions > 1) { + emit_parse_postfix_subscripts_to_reg_dims_now (reg, subscript_elem_size, pointer_depth, elem_size, array_dimensions, is_unsigned, &subscript_elem_size); } else { emit_parse_postfix_subscript_scaled_address_to_reg_now (reg, subscript_elem_size); - } + } if (tok.kind == TOK_ARROW && subscript_elem_size <= (DATA_PTR & 0x1f)) { @@ -15040,7 +15046,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { postfix_member_pointer_depth--; } - if (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f)) { + if (array_dimensions <= 1 && (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f))) { emit_load_deref_reg_ex_now (reg, subscript_elem_size, is_unsigned); } diff --git a/i386.c b/i386.c index 936c1ae..3607d51 100644 --- a/i386.c +++ b/i386.c @@ -13686,11 +13686,14 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { const char *member_caret; unsigned long member_line; - int offset = 0; + int size = DATA_INT & 0x1f; int elem_size = DATA_INT & 0x1f; + + int array_dimensions = 0; int pointer_depth = 0; + int is_array = 0; int is_floating = 0; int is_unsigned = 0; @@ -13721,6 +13724,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { } is_unsigned = last_found_member_is_unsigned; + array_dimensions = last_found_member_array_dimensions; { @@ -13807,9 +13811,11 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { } + } else if (array_dimensions > 1) { + emit_parse_postfix_subscripts_to_reg_dims_now (reg, subscript_elem_size, pointer_depth, elem_size, array_dimensions, is_unsigned, &subscript_elem_size); } else { emit_parse_postfix_subscript_scaled_address_to_reg_now (reg, subscript_elem_size); - } + } if (tok.kind == TOK_ARROW && subscript_elem_size <= (DATA_PTR & 0x1f)) { @@ -13957,7 +13963,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { postfix_member_pointer_depth--; } - if (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f)) { + if (array_dimensions <= 1 && (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f))) { emit_load_deref_reg_ex_now (reg, subscript_elem_size, is_unsigned); } diff --git a/parse.c b/parse.c index 3d73089..e71f143 100644 --- a/parse.c +++ b/parse.c @@ -91,10 +91,11 @@ int parsed_field_count = 0; struct member_info_entry member_infos[MAX_MEMBER_INFOS]; int member_info_count = 0; -const char *last_found_member_tag_name = 0; +int last_found_member_array_dimensions = 0; int last_found_member_is_unsigned = 0; struct pending_param pending_params[MAX_PENDING_PARAMS]; +const char *last_found_member_tag_name = 0; int pending_param_count; int preserve_pending_params; @@ -1467,6 +1468,7 @@ int find_member_info_ex_bounded (const char *name, int max_size, const char *own last_found_member_tag_name = 0; last_found_member_is_unsigned = 0; + last_found_member_array_dimensions = 0; last_found_member_calling_convention = TOK_EOF; if (!name) { @@ -1532,6 +1534,7 @@ int find_member_info_ex_bounded (const char *name, int max_size, const char *own last_found_member_tag_name = member_infos[best].tag_name; last_found_member_is_unsigned = member_infos[best].is_unsigned ? 1 : 0; + last_found_member_array_dimensions = member_infos[best].array_dimensions; last_found_member_calling_convention = member_infos[best].calling_convention; if (offset) { @@ -2686,6 +2689,7 @@ int find_member_info_ex (const char *name, int *offset, int *size, int *elem_siz last_found_member_tag_name = 0; last_found_member_is_unsigned = 0; + last_found_member_array_dimensions = 0; last_found_member_calling_convention = TOK_EOF; if (!name) { @@ -2711,6 +2715,7 @@ int find_member_info_ex (const char *name, int *offset, int *size, int *elem_siz last_found_member_tag_name = member_infos[best].tag_name; last_found_member_is_unsigned = member_infos[best].is_unsigned ? 1 : 0; + last_found_member_array_dimensions = member_infos[best].array_dimensions; last_found_member_calling_convention = member_infos[best].calling_convention; if (offset) { @@ -2831,6 +2836,7 @@ static void remember_member_info_ex (const char *name, int offset, int size, int member_infos[member_info_count].size = size; member_infos[member_info_count].elem_size = elem_size > 0 ? elem_size : size; member_infos[member_info_count].pointer_depth = pointer_depth; + member_infos[member_info_count].array_dimensions = is_array ? declarator_array_dimensions : 0; member_infos[member_info_count].is_array = is_array; member_infos[member_info_count].is_floating = is_floating ? 1 : 0; member_infos[member_info_count].is_unsigned = parsed_type_is_unsigned ? 1 : 0; @@ -2877,6 +2883,7 @@ static void promote_anonymous_aggregate_members (const char *owner_tag_name, int dst->size = src->size; dst->elem_size = src->elem_size; dst->pointer_depth = src->pointer_depth; + dst->array_dimensions = src->array_dimensions; dst->is_array = src->is_array; dst->is_floating = src->is_floating; dst->is_unsigned = src->is_unsigned; @@ -3550,11 +3557,27 @@ void parse_type_spec (void) { if (declarator_has_array && declarator_is_pointer) { member_info_elem_size = DATA_PTR; + } else if (declarator_has_array && declarator_first_array_count > 0) { + + /* + * One subscript of a multidimensional array member + * selects the complete object after the first + * dimension. member_size already contains the + * storage for every dimension, so divide by the + * first dimension rather than recording the scalar + * base type. + * + * char segment[32][4]; + * + * segment[i] therefore has a four-byte stride. + */ + member_info_elem_size = member_size / declarator_first_array_count; + } else { member_info_elem_size = declarator_is_pointer ? (parsed_type_is_aggregate ? parsed_type_size : (parsed_type_size & 0x1f)) : - (declarator_has_array ? member_type_size : member_size); + member_size; } diff --git a/parse.h b/parse.h index bf38cd6..87f4710 100644 --- a/parse.h +++ b/parse.h @@ -141,6 +141,8 @@ struct member_info_entry { int offset; int size; int elem_size; + + int array_dimensions; int pointer_depth; int is_array; @@ -198,7 +200,9 @@ struct local_symbol { }; extern const char *last_found_member_tag_name; + extern int last_found_member_is_unsigned; +extern int last_found_member_array_dimensions; struct aggregate_tag_entry {