From d9c14178ac80ee836839015565677e951012e88a Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Mon, 13 Jul 2026 08:28:03 +0100 Subject: [PATCH] Segfault, corruption and codegen fixes --- amd64.c | 270 +++++++++++++++++++++++++++++++++++---- i386.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 612 insertions(+), 44 deletions(-) diff --git a/amd64.c b/amd64.c index 324df27..146aa82 100644 --- a/amd64.c +++ b/amd64.c @@ -136,6 +136,7 @@ static const char *postfix_copy_lvalue_tag_name = 0; static int postfix_member_offset = 0; static int postfix_member_size = 0; +static int postfix_value_is_array = 0; static int postfix_member_is_floating = 0; static int postfix_member_is_unsigned = 0; @@ -13376,6 +13377,8 @@ static void emit_load_assignment_rhs_to_pair (const char *lo, const char *hi) { if (find_global_symbol (name) >= 0) { + postfix_value_is_array = get_global_symbol_array (name); + if (get_global_symbol_kind (name) == GLOBAL_SYMBOL_FUNCTION || get_global_symbol_array (name) || (!get_global_symbol_pointer_depth (name) && @@ -13905,6 +13908,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { postfix_member_pointed_size = elem_size; postfix_member_offset = offset; postfix_member_size = size; + postfix_value_is_array = is_array; postfix_member_is_floating = is_floating; postfix_member_is_unsigned = is_unsigned; postfix_member_calling_convention = last_found_member_calling_convention; @@ -13920,6 +13924,8 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { enum token_kind assign_op; int subscript_elem_size; + postfix_value_is_array = 0; + if (!is_array && pointer_depth > 0) { emit_load_member_from_addr_reg_now (reg, reg, offset, DATA_PTR & 0x1f); } else if (state->ofp && offset != 0) { @@ -17128,6 +17134,156 @@ static int source_starts_lparen_deref_subscript_at (const char *p) { } +static int source_starts_lparen_subscript_call_at (const char *p) { + + int bracket_depth; + + if (!p || *p != '(') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) { + return 0; + } + + p++; + + while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '[') { + return 0; + } + + bracket_depth = 1; + p++; + + while (*p && bracket_depth > 0) { + + if (*p == '[') { + bracket_depth++; + } else if (*p == ']') { + bracket_depth--; + } + + p++; + + } + + if (bracket_depth != 0) { + return 0; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != ')') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + return *p == '('; + +} + +static int source_starts_lparen_deref_subscript_call_at (const char *p) { + + int bracket_depth; + + if (!p) { + return 0; + } + + if (*p == '(') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '*') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) { + return 0; + } + + p++; + + while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '[') { + return 0; + } + + bracket_depth = 1; + p++; + + while (*p && bracket_depth > 0) { + + if (*p == '[') { + bracket_depth++; + } else if (*p == ']') { + bracket_depth--; + } + + p++; + + } + + if (bracket_depth != 0) { + return 0; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != ')') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + return *p == '('; + +} + static int source_starts_lparen_deref_postfix_incdec_at (const char *p) { if (!p) { @@ -20817,6 +20973,8 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { if (src->is_array) { + postfix_value_is_array = 1; + if (src->is_static && src->static_label) { emit_load_address_to_reg_now (reg, src->static_label); } else { @@ -20917,6 +21075,8 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { if (find_global_symbol (name) >= 0) { + postfix_value_is_array = get_global_symbol_array (name); + if (get_global_symbol_kind (name) == GLOBAL_SYMBOL_FUNCTION || get_global_symbol_array (name) || (!get_global_symbol_pointer_depth (name) && @@ -23110,6 +23270,16 @@ static void emit_load_floating_rhs_expression_now (int result_size) { static void emit_load_assignment_rhs_expression_to_reg (const char *reg); +static int local_symbol_is_array_now (const struct local_symbol *sym) { + + if (!sym) { + return 0; + } + + return sym->is_array || sym->array_dimensions > 0 || sym->array_element_size > 0; + +} + static int current_argument_is_bare_identifier_now (void) { const char *p; @@ -23307,14 +23477,41 @@ static int emit_push_global_aggregate_argument_now (const char *name) { int offset; int chunk; - if (!name || get_global_symbol_kind (name) != GLOBAL_SYMBOL_OBJECT || - get_global_symbol_array (name) || get_global_symbol_pointer_depth (name) > 0 || - get_global_symbol_floating (name)) { + const char *tag_name; + + if (!name) { return 0; } - size = get_global_symbol_size (name); + if (get_global_symbol_kind (name) != GLOBAL_SYMBOL_OBJECT) { + return 0; + } + + if (get_global_symbol_array (name)) { + return 0; + } + if (get_global_symbol_pointer_depth (name) > 0) { + return 0; + } + + if (get_global_symbol_floating (name)) { + return 0; + } + + size = get_global_symbol_size (name); + tag_name = get_global_symbol_tag_name (name); + + /* + * Only tagged aggregate objects are passed by value here. Untagged + * objects include scalar values and arrays whose decay metadata was not + * visible during the self-hosting pass; those must use normal expression + * loading so arrays decay to one address instead of multiple stack words. + */ + if (!tag_name || !tag_name[0]) { + return 0; + } + if (size <= (DATA_PTR & 0x1f)) { return 0; } @@ -23485,12 +23682,13 @@ static void emit_call_pointer_in_reg_now (const char *fn_reg, const char *result } + postfix_value_is_array = 0; postfix_member_seen = 0; postfix_member_size = 0; postfix_member_pointer_depth = 0; postfix_member_pointed_size = 0; - if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && find_local_symbol (tok.ident)->is_array) { + if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && local_symbol_is_array_now (find_local_symbol (tok.ident))) { struct local_symbol *arg_sym = find_local_symbol (tok.ident); @@ -23599,12 +23797,12 @@ static void emit_call_pointer_in_reg_now (const char *fn_reg, const char *result if (state->ofp) { - if (!arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && postfix_member_size > (DATA_PTR & 0x1f)) { + if (!arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("rax", arg_bytes); - } else if (!arg_is_floating && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!arg_is_floating && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("rax", arg_bytes); @@ -25386,12 +25584,13 @@ static void emit_call_identifier_to_reg_now (const char *name, const char *reg, } + postfix_value_is_array = 0; postfix_member_seen = 0; postfix_member_size = 0; postfix_member_pointer_depth = 0; postfix_member_pointed_size = 0; - if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && find_local_symbol (tok.ident)->is_array) { + if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && local_symbol_is_array_now (find_local_symbol (tok.ident))) { struct local_symbol *arg_sym = find_local_symbol (tok.ident); @@ -25510,12 +25709,12 @@ static void emit_call_identifier_to_reg_now (const char *name, const char *reg, * slot according to the AMD64 calling convention. */ - } else if (!use_inline && !arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!use_inline && !arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("rax", arg_bytes); - } else if (!use_inline && !arg_is_floating && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!use_inline && !arg_is_floating && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("rax", arg_bytes); @@ -29995,6 +30194,15 @@ static int parse_parenthesized_deref_subscript_statement (void) { } + if (tok.kind == TOK_LPAREN) { + + get_token (); + + expect (TOK_RPAREN, ")"); + emit_call_pointer_in_reg_now ("rax", "rax"); + + } + emit_load_deref_reg_now ("rax", DATA_PTR & 0x1f); emit_handle_subscript_after_loaded_pointer_to_reg_now ("rax", pointer_depth - 1, pointed_size, src ? src->pointed_is_unsigned : get_global_symbol_pointed_is_unsigned (name)); @@ -30391,6 +30599,20 @@ static int parse_identifier_assignment_statement (void) { emit_parse_postfix_subscript_scaled_address_to_reg_now ("rdx", elem_size); } + if (tok.kind == TOK_LPAREN) { + + if (state->ofp) { + emit_load_deref_reg_now ("rdx", DATA_PTR & 0x1f); + } + + emit_call_pointer_in_reg_now ("rdx", "rax"); + expect_semi_or_recover (); + + free (name); + return 1; + + } + if (tok.kind == TOK_INCR || tok.kind == TOK_DECR) { op = tok.kind; @@ -35992,18 +36214,16 @@ static int parse_parenthesized_member_function_pointer_call_statement (void) { const char *base_tag_name = 0; - if (tok.kind != TOK_LPAREN || !source_starts_with_parenthesized_indirect_call_now ()) { + if (tok.kind != TOK_LPAREN || (!source_starts_with_parenthesized_indirect_call_now () && !source_starts_lparen_deref_subscript_call_at (tok.start) && !source_starts_lparen_deref_subscript_call_at (tok.caret) && !source_starts_lparen_subscript_call_at (tok.start) && !source_starts_lparen_subscript_call_at (tok.caret))) { return 0; } get_token (); - if (tok.kind != TOK_STAR) { - return 0; + if (tok.kind == TOK_STAR) { + get_token (); } - get_token (); - if (tok.kind == TOK_LPAREN) { wrapped_member_expr = 1; @@ -36138,6 +36358,10 @@ static void parse_statement (void) { } + if (parse_parenthesized_member_function_pointer_call_statement ()) { + return; + } + if (parse_parenthesized_deref_subscript_statement ()) { expect_semi_or_recover (); @@ -36145,10 +36369,6 @@ static void parse_statement (void) { } - if (parse_parenthesized_member_function_pointer_call_statement ()) { - return; - } - if (tok.kind == TOK_LPAREN) { int parenthesized_assignment_is_unsigned; @@ -37504,8 +37724,8 @@ static void parse_global_initializer_values (int64_s *values, char **symbols, in } -static int int64_is_zero_value (int64_s value) { - return value.low == 0 && value.high == 0; +static int int64_is_zero_value (const int64_s *value) { + return value->low == 0 && value->high == 0; } static char masm_pending_data_label[512]; @@ -37764,11 +37984,15 @@ static int global_initializer_is_all_zero (const int64_s *values, char **symbols int i; if (symbols) { + for (i = 0; i < value_count; i++) { + if (symbols[i]) { return 0; } + } + } if (!values || value_count <= 0) { @@ -37776,9 +38000,11 @@ static int global_initializer_is_all_zero (const int64_s *values, char **symbols } for (i = 0; i < value_count; i++) { - if (!int64_is_zero_value (values[i])) { + + if (!int64_is_zero_value (&values[i])) { return 0; } + } return 1; diff --git a/i386.c b/i386.c index 0bc62b7..1fc3f1f 100644 --- a/i386.c +++ b/i386.c @@ -101,6 +101,7 @@ static const char *postfix_copy_lvalue_tag_name = 0; static int postfix_member_offset = 0; static int postfix_member_size = 0; +static int postfix_value_is_array = 0; static int postfix_member_is_floating = 0; static int postfix_member_is_unsigned = 0; @@ -12884,6 +12885,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { postfix_member_pointed_size = elem_size; postfix_member_offset = offset; postfix_member_size = size; + postfix_value_is_array = is_array; postfix_member_is_floating = is_floating; postfix_member_is_unsigned = is_unsigned; postfix_member_calling_convention = last_found_member_calling_convention; @@ -12899,6 +12901,8 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) { enum token_kind assign_op; int subscript_elem_size; + postfix_value_is_array = 0; + if (!is_array && pointer_depth > 0) { emit_load_member_from_addr_reg_now (reg, reg, offset, DATA_PTR & 0x1f); } else if (state->ofp && offset != 0) { @@ -15986,6 +15990,156 @@ static int source_starts_lparen_deref_subscript_at (const char *p) { } +static int source_starts_lparen_subscript_call_at (const char *p) { + + int bracket_depth; + + if (!p || *p != '(') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) { + return 0; + } + + p++; + + while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '[') { + return 0; + } + + bracket_depth = 1; + p++; + + while (*p && bracket_depth > 0) { + + if (*p == '[') { + bracket_depth++; + } else if (*p == ']') { + bracket_depth--; + } + + p++; + + } + + if (bracket_depth != 0) { + return 0; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != ')') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + return *p == '('; + +} + +static int source_starts_lparen_deref_subscript_call_at (const char *p) { + + int bracket_depth; + + if (!p) { + return 0; + } + + if (*p == '(') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '*') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) { + return 0; + } + + p++; + + while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') { + p++; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != '[') { + return 0; + } + + bracket_depth = 1; + p++; + + while (*p && bracket_depth > 0) { + + if (*p == '[') { + bracket_depth++; + } else if (*p == ']') { + bracket_depth--; + } + + p++; + + } + + if (bracket_depth != 0) { + return 0; + } + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + if (*p != ')') { + return 0; + } + + p++; + + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { + p++; + } + + return *p == '('; + +} + static int source_starts_lparen_deref_postfix_incdec_at (const char *p) { if (!p) { @@ -19117,6 +19271,25 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { } + if (tok.kind == TOK_LPAREN) { + + /* + * Subscript parsing leaves reg holding the address of the + * selected array element. For an array of function pointers, + * load the pointer stored in that element before emitting the + * indirect call. Calling reg directly here calls the address + * of the array slot instead of the function it contains. + */ + emit_load_deref_reg_now (reg, DATA_PTR & 0x1f); + + emit_call_pointer_in_reg_now (reg, reg); + set_rhs_last_pointer_info (0, 0); + + free (name); + return; + + } + emit_apply_postfix_member_access_to_reg_now (reg); postfix_copy_lvalue_tag_name = 0; @@ -19184,6 +19357,25 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { } + if (tok.kind == TOK_LPAREN) { + + /* + * Subscript parsing leaves reg holding the address of the + * selected array element. For an array of function pointers, + * load the pointer stored in that element before emitting the + * indirect call. Calling reg directly here calls the address + * of the array slot instead of the function it contains. + */ + emit_load_deref_reg_now (reg, DATA_PTR & 0x1f); + + emit_call_pointer_in_reg_now (reg, reg); + set_rhs_last_pointer_info (0, 0); + + free (name); + return; + + } + emit_apply_postfix_member_access_to_reg_now (reg); postfix_copy_lvalue_tag_name = 0; @@ -19581,6 +19773,8 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { if (src->is_array) { + postfix_value_is_array = 1; + if (src->is_static && src->static_label) { emit_load_address_to_reg_now (reg, src->static_label); } else { @@ -19687,6 +19881,8 @@ static void emit_load_assignment_rhs_to_reg (const char *reg) { if (find_global_symbol (name) >= 0) { + postfix_value_is_array = get_global_symbol_array (name); + if (get_global_symbol_kind (name) == GLOBAL_SYMBOL_FUNCTION || get_global_symbol_array (name) || (!get_global_symbol_pointer_depth (name) && @@ -21883,6 +22079,16 @@ static void emit_load_floating_rhs_expression_now (int result_size) { static void emit_load_assignment_rhs_expression_to_reg (const char *reg); +static int local_symbol_is_array_now (const struct local_symbol *sym) { + + if (!sym) { + return 0; + } + + return sym->is_array || sym->array_dimensions > 0 || sym->array_element_size > 0; + +} + static int current_argument_is_bare_identifier_now (void) { const char *p; @@ -22023,13 +22229,39 @@ static int emit_push_global_aggregate_argument_now (const char *name) { int offset; int chunk; - if (!name || get_global_symbol_kind (name) != GLOBAL_SYMBOL_OBJECT || - get_global_symbol_array (name) || get_global_symbol_pointer_depth (name) > 0 || - get_global_symbol_floating (name)) { + const char *tag_name; + + if (!name) { + return 0; + } + + if (get_global_symbol_kind (name) != GLOBAL_SYMBOL_OBJECT) { + return 0; + } + + if (get_global_symbol_array (name)) { + return 0; + } + + if (get_global_symbol_pointer_depth (name) > 0) { + return 0; + } + + if (get_global_symbol_floating (name)) { return 0; } size = get_global_symbol_size (name); + tag_name = get_global_symbol_tag_name (name); + + /* Only tagged aggregate objects are passed by value here. Untagged + * objects include scalar values and arrays whose decay metadata was not + * visible during the self-hosting pass; those must use normal expression + * loading so arrays decay to one address instead of multiple stack words. + */ + if (!tag_name || !tag_name[0]) { + return 0; + } if (size <= (DATA_PTR & 0x1f)) { return 0; @@ -22160,12 +22392,30 @@ static void emit_call_pointer_in_reg_now (const char *fn_reg, const char *result } + postfix_value_is_array = 0; postfix_member_seen = 0; postfix_member_size = 0; postfix_member_pointer_depth = 0; postfix_member_pointed_size = 0; - if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && emit_push_aggregate_argument_now (tok.ident, find_local_symbol (tok.ident))) { + if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && local_symbol_is_array_now (find_local_symbol (tok.ident))) { + + struct local_symbol *arg_sym = find_local_symbol (tok.ident); + + if (arg_sym->is_static && arg_sym->static_label) { + emit_load_address_to_reg_now ("eax", arg_sym->static_label); + } else { + emit_load_local_address_to_reg_now ("eax", arg_sym->offset); + } + + emit_push_reg_now ("eax"); + + arg_bytes = DATA_PTR & 0x1f; + arg_is_floating = 0; + + get_token (); + + } else if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && emit_push_aggregate_argument_now (tok.ident, find_local_symbol (tok.ident))) { struct local_symbol *arg_sym = find_local_symbol (tok.ident); @@ -22174,6 +22424,18 @@ static void emit_call_pointer_in_reg_now (const char *fn_reg, const char *result get_token (); + } else if (tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && + !find_local_symbol (tok.ident) && find_global_symbol (tok.ident) >= 0 && + get_global_symbol_array (tok.ident)) { + + emit_load_address_to_reg_now ("eax", tok.ident); + emit_push_reg_now ("eax"); + + arg_bytes = DATA_PTR; + arg_is_floating = 0; + + get_token (); + } else { int arg_starts_64bit_integer = current_argument_starts_64bit_integer_now (); @@ -22199,12 +22461,12 @@ static void emit_call_pointer_in_reg_now (const char *fn_reg, const char *result emit_push_reg_now ("edx"); emit_push_reg_now ("eax"); - } else if (!arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("eax", arg_bytes); - } else if (!arg_is_floating && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!arg_is_floating && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("eax", arg_bytes); @@ -22452,6 +22714,28 @@ static int current_argument_is_bare_64bit_identifier_now (void) { } +static int call_argument_expects_by_value_aggregate_now (const char *name, int argument_index) { + + int symbol_index; + + if (!name || argument_index < 0) { + return 0; + } + + symbol_index = find_global_symbol (name); + + if (symbol_index < 0 || global_symbols[symbol_index].kind != GLOBAL_SYMBOL_FUNCTION || !global_symbols[symbol_index].has_prototype || + argument_index >= global_symbols[symbol_index].param_count || + global_symbols[symbol_index].param_pointer_depths[argument_index] > 0 || + global_symbols[symbol_index].param_floatings[argument_index] || + global_symbols[symbol_index].param_sizes[argument_index] <= (DATA_PTR & 0x1f)) { + return 0; + } + + return 1; + +} + static int current_argument_starts_64bit_integer_now (void) { if (tok.kind == TOK_CLLONG || tok.kind == TOK_CULLONG) { @@ -22580,12 +22864,30 @@ static void emit_call_identifier_to_reg_now (const char *name, const char *reg, } + postfix_value_is_array = 0; postfix_member_seen = 0; postfix_member_size = 0; postfix_member_pointer_depth = 0; postfix_member_pointed_size = 0; - if (!use_inline && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && emit_push_aggregate_argument_now (tok.ident, find_local_symbol (tok.ident))) { + if (!use_inline && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && local_symbol_is_array_now (find_local_symbol (tok.ident))) { + + struct local_symbol *arg_sym = find_local_symbol (tok.ident); + + if (arg_sym->is_static && arg_sym->static_label) { + emit_load_address_to_reg_now ("eax", arg_sym->static_label); + } else { + emit_load_local_address_to_reg_now ("eax", arg_sym->offset); + } + + emit_push_reg_now ("eax"); + + arg_bytes = DATA_PTR & 0x1f; + arg_is_floating = 0; + + get_token (); + + } else if (!use_inline && call_argument_expects_by_value_aggregate_now (name, argc) && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && find_local_symbol (tok.ident) && emit_push_aggregate_argument_now (tok.ident, find_local_symbol (tok.ident))) { struct local_symbol *arg_sym = find_local_symbol (tok.ident); @@ -22594,7 +22896,20 @@ static void emit_call_identifier_to_reg_now (const char *name, const char *reg, get_token (); - } else if (!use_inline && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && !find_local_symbol (tok.ident) && emit_push_global_aggregate_argument_now (tok.ident)) { + } else if (!use_inline && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && + !find_local_symbol (tok.ident) && find_global_symbol (tok.ident) >= 0 && + get_global_symbol_array (tok.ident) && + !call_argument_expects_by_value_aggregate_now (name, argc)) { + + emit_load_address_to_reg_now ("eax", tok.ident); + emit_push_reg_now ("eax"); + + arg_bytes = DATA_PTR; + arg_is_floating = 0; + + get_token (); + + } else if (!use_inline && call_argument_expects_by_value_aggregate_now (name, argc) && tok.kind == TOK_IDENT && tok.ident && current_argument_is_bare_identifier_now () && !find_local_symbol (tok.ident) && emit_push_global_aggregate_argument_now (tok.ident)) { arg_bytes = get_global_symbol_size (tok.ident); arg_is_floating = 0; @@ -22677,12 +22992,12 @@ static void emit_call_identifier_to_reg_now (const char *name, const char *reg, emit_push_reg_now ("edx"); emit_push_reg_now ("eax"); - } else if (!use_inline && !arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!use_inline && !arg_is_floating && postfix_member_seen && postfix_member_pointer_depth == 0 && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("eax", arg_bytes); - } else if (!use_inline && !arg_is_floating && postfix_member_size > (DATA_PTR & 0x1f)) { + } else if (!use_inline && !arg_is_floating && !postfix_value_is_array && postfix_member_size > (DATA_PTR & 0x1f)) { arg_bytes = postfix_member_size; emit_push_aggregate_from_addr_reg_now ("eax", arg_bytes); @@ -27212,6 +27527,15 @@ static int parse_parenthesized_deref_subscript_statement (void) { } + if (tok.kind == TOK_LPAREN) { + + get_token (); + + expect (TOK_RPAREN, ")"); + emit_call_pointer_in_reg_now ("eax", "eax"); + + } + emit_load_deref_reg_now ("eax", DATA_PTR & 0x1f); emit_handle_subscript_after_loaded_pointer_to_reg_now ("eax", pointer_depth - 1, pointed_size, src ? src->pointed_is_unsigned : get_global_symbol_pointed_is_unsigned (name)); @@ -27607,6 +27931,20 @@ static int parse_identifier_assignment_statement (void) { emit_parse_postfix_subscript_scaled_address_to_reg_now ("edx", elem_size); } + if (tok.kind == TOK_LPAREN) { + + if (state->ofp) { + emit_load_deref_reg_now ("edx", DATA_PTR & 0x1f); + } + + emit_call_pointer_in_reg_now ("edx", "eax"); + expect_semi_or_recover (); + + free (name); + return 1; + + } + if (tok.kind == TOK_INCR || tok.kind == TOK_DECR) { op = tok.kind; @@ -33377,18 +33715,16 @@ static int parse_parenthesized_member_function_pointer_call_statement (void) { const char *base_tag_name = 0; - if (tok.kind != TOK_LPAREN || !source_starts_with_parenthesized_indirect_call_now ()) { + if (tok.kind != TOK_LPAREN || (!source_starts_with_parenthesized_indirect_call_now () && !source_starts_lparen_deref_subscript_call_at (tok.start) && !source_starts_lparen_deref_subscript_call_at (tok.caret) && !source_starts_lparen_subscript_call_at (tok.start) && !source_starts_lparen_subscript_call_at (tok.caret))) { return 0; } get_token (); - if (tok.kind != TOK_STAR) { - return 0; + if (tok.kind == TOK_STAR) { + get_token (); } - get_token (); - if (tok.kind == TOK_LPAREN) { wrapped_member_expr = 1; @@ -33523,6 +33859,10 @@ static void parse_statement (void) { } + if (parse_parenthesized_member_function_pointer_call_statement ()) { + return; + } + if (parse_parenthesized_deref_subscript_statement ()) { expect_semi_or_recover (); @@ -33530,10 +33870,6 @@ static void parse_statement (void) { } - if (parse_parenthesized_member_function_pointer_call_statement ()) { - return; - } - if (tok.kind == TOK_LPAREN) { int parenthesized_assignment_is_unsigned; @@ -34858,8 +35194,8 @@ static void parse_global_initializer_values (int64_s *values, char **symbols, in } -static int int64_is_zero_value (int64_s value) { - return value.low == 0 && value.high == 0; +static int int64_is_zero_value (const int64_s *value) { + return value->low == 0 && value->high == 0; } static char masm_pending_data_label[512]; @@ -35118,11 +35454,15 @@ static int global_initializer_is_all_zero (const int64_s *values, char **symbols int i; if (symbols) { + for (i = 0; i < value_count; i++) { + if (symbols[i]) { return 0; } + } + } if (!values || value_count <= 0) { @@ -35130,9 +35470,11 @@ static int global_initializer_is_all_zero (const int64_s *values, char **symbols } for (i = 0; i < value_count; i++) { - if (!int64_is_zero_value (values[i])) { + + if (!int64_is_zero_value (&values[i])) { return 0; } + } return 1; -- 2.34.1