From 69ac558d708f79aefc220768423baca5d8ad4edb Mon Sep 17 00:00:00 2001 From: dibyendumajumdar Date: Mon, 20 Dec 2021 21:24:30 +0000 Subject: [PATCH] #169 update MIR to latest --- mir/c2mir/aarch64/caarch64-ABI-code.c | 1 - mir/c2mir/aarch64/mirc_aarch64_linux.h | 6 + mir/c2mir/aarch64/mirc_aarch64_stddef.h | 4 - mir/c2mir/aarch64/mirc_aarch64_stdint.h | 9 +- mir/c2mir/c2mir.c | 779 +++++++++++++----------- mir/c2mir/ppc64/cppc64-ABI-code.c | 5 +- mir/c2mir/ppc64/mirc_ppc64_linux.h | 2 + mir/c2mir/ppc64/mirc_ppc64_stddef.h | 2 +- mir/c2mir/ppc64/mirc_ppc64_stdint.h | 9 +- mir/c2mir/riscv64/mirc_riscv64_linux.h | 2 + mir/c2mir/riscv64/mirc_riscv64_stdint.h | 9 +- mir/c2mir/s390x/cs390x-ABI-code.c | 1 - mir/c2mir/s390x/mirc_s390x_linux.h | 2 + mir/c2mir/s390x/mirc_s390x_stddef.h | 2 +- mir/c2mir/s390x/mirc_s390x_stdint.h | 9 +- mir/c2mir/x86_64/mirc_x86_64_linux.h | 6 + mir/c2mir/x86_64/mirc_x86_64_stddef.h | 6 +- mir/c2mir/x86_64/mirc_x86_64_stdint.h | 9 +- mir/mir-aarch64.c | 27 +- mir/mir-gen-aarch64.c | 81 ++- mir/mir-gen-ppc64.c | 177 +++--- mir/mir-gen-riscv64.c | 20 +- mir/mir-gen-s390x.c | 67 +- mir/mir-gen-x86_64.c | 36 +- mir/mir-gen.c | 342 ++++++----- mir/mir-gen.h | 9 + mir/mir-hash.h | 2 +- mir/mir-htab.h | 8 + mir/mir-ppc64.c | 13 +- mir/mir-reduce.h | 2 +- mir/mir-riscv64.c | 47 +- mir/mir-s390x.c | 14 +- mir/mir-varr.h | 8 + mir/mir.c | 93 ++- mir/mir.h | 37 +- 35 files changed, 1038 insertions(+), 808 deletions(-) diff --git a/mir/c2mir/aarch64/caarch64-ABI-code.c b/mir/c2mir/aarch64/caarch64-ABI-code.c index a854b97f..5b98fcfe 100644 --- a/mir/c2mir/aarch64/caarch64-ABI-code.c +++ b/mir/c2mir/aarch64/caarch64-ABI-code.c @@ -22,7 +22,6 @@ static int reg_aggregate_size (c2m_ctx_t c2m_ctx, struct type *type) { static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types, VARR (MIR_var_t) * arg_vars) { - MIR_var_t var; int size; if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) { diff --git a/mir/c2mir/aarch64/mirc_aarch64_linux.h b/mir/c2mir/aarch64/mirc_aarch64_linux.h index a3826da7..1b79cd53 100644 --- a/mir/c2mir/aarch64/mirc_aarch64_linux.h +++ b/mir/c2mir/aarch64/mirc_aarch64_linux.h @@ -51,6 +51,12 @@ static char aarch64_mirc[] "#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n" "#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n" "#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n" +#if defined(__linux__) + "#define __WCHAR_MAX__ 0x7fffffff\n" +#else + "#define __WCHAR_MAX__ 2147483647\n" +#endif + "#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)\n" "#define __SCHAR_MAX__ __INT8_MAX__\n" "#define __SHRT_MAX__ __INT16_MAX__\n" "#define __INT_MAX__ __INT32_MAX__\n" diff --git a/mir/c2mir/aarch64/mirc_aarch64_stddef.h b/mir/c2mir/aarch64/mirc_aarch64_stddef.h index 6f2b973d..85275b1c 100644 --- a/mir/c2mir/aarch64/mirc_aarch64_stddef.h +++ b/mir/c2mir/aarch64/mirc_aarch64_stddef.h @@ -10,11 +10,7 @@ static char stddef_str[] "typedef long ptrdiff_t;\n" "typedef unsigned long size_t;\n" "typedef long double max_align_t;\n" -#if defined(__APPLE__) "typedef int wchar_t;\n" -#else - "typedef unsigned int wchar_t;\n" -#endif "\n" "#define NULL ((void *) 0)\n" "\n" diff --git a/mir/c2mir/aarch64/mirc_aarch64_stdint.h b/mir/c2mir/aarch64/mirc_aarch64_stdint.h index 995106a3..2f21f678 100644 --- a/mir/c2mir/aarch64/mirc_aarch64_stdint.h +++ b/mir/c2mir/aarch64/mirc_aarch64_stdint.h @@ -116,9 +116,12 @@ static char stdint_str[] "\n" "#define SIZE_MAX (18446744073709551615UL)\n" "\n" - "/* For signed wchar_t and wint_t: */\n" - "#define WCHAR_MIN INT32_MIN\n" - "#define WCHAR_MAX INT32_MAX\n" + "#ifndef WCHAR_MAX\n" + "#define WCHAR_MAX __WCHAR_MAX__\n" + "#endif\n" + "#ifndef WCHAR_MIN\n" + "#define WCHAR_MIN __WCHAR_MIN__\n" + "#endif\n" "#define WINT_MIN WCHAR_MIN\n" "#define WINT_MAX WCHAR_MAX\n" "\n" diff --git a/mir/c2mir/c2mir.c b/mir/c2mir/c2mir.c index ec3543dc..818d5261 100644 --- a/mir/c2mir/c2mir.c +++ b/mir/c2mir/c2mir.c @@ -483,6 +483,7 @@ expr : N_I | N_L | N_LL | N_U | N_UL | N_ULL | N_F | N_D | N_LD | N_DEREF_FIELD (expr, N_ID) | N_COND (expr, expr, expr) | N_COMPOUND_LITERAL (type_name, initializer) | N_CALL (expr, N_LIST:(expr)*) | N_GENERIC (expr, N_LIST:(N_GENERIC_ASSOC (type_name?, expr))+ ) + | N_STMTEXPR (compound_stmt) label: N_CASE(expr) | N_CASE(expr,expr) | N_DEFAULT | N_LABEL(N_ID) stmt: compound_stmt | N_IF(N_LIST:(label)*, expr, stmt, stmt?) | N_SWITCH(N_LIST:(label)*, expr, stmt) | (N_WHILE|N_DO) (N_LIST:(label)*, expr, stmt) @@ -562,7 +563,7 @@ static token_code_t FIRST_KW = T_BOOL, LAST_KW = T_WHILE; typedef enum { REP8 (NODE_EL, IGNORE, I, L, LL, U, UL, ULL, F), REP8 (NODE_EL, D, LD, CH, CH16, CH32, STR, STR16, STR32), - REP4 (NODE_EL, ID, COMMA, ANDAND, OROR), + REP5 (NODE_EL, ID, COMMA, ANDAND, OROR, STMTEXPR), REP8 (NODE_EL, EQ, NE, LT, LE, GT, GE, ASSIGN, BITWISE_NOT), REP8 (NODE_EL, NOT, AND, AND_ASSIGN, OR, OR_ASSIGN, XOR, XOR_ASSIGN, LSH), REP8 (NODE_EL, LSH_ASSIGN, RSH, RSH_ASSIGN, ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL), @@ -1100,9 +1101,10 @@ static int pre_skip_if_part_p (c2m_ctx_t c2m_ctx); static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp, int type) { int i, str_len; int64_t curr_c, last_c = -1; - int64_t max_char - = (type == 'u' ? UINT16_MAX - : type == 'U' ? UINT32_MAX : type == 'L' ? MIR_WCHAR_MAX : MIR_UCHAR_MAX); + int64_t max_char = (type == 'u' ? UINT16_MAX + : type == 'U' ? UINT32_MAX + : type == 'L' ? MIR_WCHAR_MAX + : MIR_UCHAR_MAX); int start = type == ' ' ? 0 : type == '8' ? 2 : 1; int string_p = t->repr[start] == '"'; const char *str; @@ -1116,7 +1118,7 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp, in for (i = start + 1; i < str_len - 1; i++) { if (!string_p && last_c >= 0 && !pre_skip_if_part_p (c2m_ctx)) error (c2m_ctx, t->pos, "multibyte character"); - last_c = curr_c = str[i]; + last_c = curr_c = (unsigned char) str[i]; if (curr_c != '\\') { push_str_char (c2m_ctx, temp, curr_c, type); continue; @@ -1175,8 +1177,9 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp, in first_p = FALSE; if (v <= UINT32_MAX) { v *= 16; - v += (isdigit (curr_c) ? curr_c - '0' - : islower (curr_c) ? curr_c - 'a' + 10 : curr_c - 'A' + 10); + v += (isdigit (curr_c) ? curr_c - '0' + : islower (curr_c) ? curr_c - 'a' + 10 + : curr_c - 'A' + 10); } } if (first_p) { @@ -1201,8 +1204,9 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp, in curr_c = str[i]; if (!isxdigit (curr_c)) break; v *= 16; - v += (isdigit (curr_c) ? curr_c - '0' - : islower (curr_c) ? curr_c - 'a' + 10 : curr_c - 'A' + 10); + v += (isdigit (curr_c) ? curr_c - '0' + : islower (curr_c) ? curr_c - 'a' + 10 + : curr_c - 'A' + 10); } last_c = curr_c = v; if (n < digits_num) { @@ -1622,11 +1626,21 @@ static token_t get_next_pptoken_1 (c2m_ctx_t c2m_ctx, int header_p) { VARR_PUSH (char, symbol_text, curr_c); for (curr_c = cs_get (c2m_ctx); curr_c != stop && curr_c != '\n' && curr_c != EOF; curr_c = cs_get (c2m_ctx)) { - VARR_PUSH (char, symbol_text, curr_c); + if (curr_c == '\0') { + warning (c2m_ctx, pos, "null character in %s literal ignored", + stop == '"' ? "string" : "char"); + } else { + VARR_PUSH (char, symbol_text, curr_c); + } if (curr_c != '\\') continue; curr_c = cs_get (c2m_ctx); if (curr_c == '\n' || curr_c == EOF) break; - VARR_PUSH (char, symbol_text, curr_c); + if (curr_c == '\0') { + warning (c2m_ctx, pos, "null character in %s literal ignored", + stop == '"' ? "string" : "char"); + } else { + VARR_PUSH (char, symbol_text, curr_c); + } } VARR_PUSH (char, symbol_text, curr_c); if (curr_c == stop) { @@ -2286,10 +2300,20 @@ static void define (c2m_ctx_t c2m_ctx) { } if (t->code == ' ') t = get_next_pptoken (c2m_ctx); for (; t->code != '\n'; t = get_next_pptoken (c2m_ctx)) { - if (t->code == T_DBLNO) t->code = T_RDBLNO; + if (t->code == T_DBLNO) { + if (VARR_LENGTH (token_t, repl) == 0) { + error (c2m_ctx, t->pos, "## at the beginning of a macro expansion"); + continue; + } + t->code = T_RDBLNO; + } VARR_PUSH (token_t, repl, t); } unget_next_pptoken (c2m_ctx, t); + if (VARR_LENGTH (token_t, repl) != 0 && (t = VARR_LAST (token_t, repl))->code == T_RDBLNO) { + VARR_POP (token_t, repl); + error (c2m_ctx, t->pos, "## at the end of a macro expansion"); + } name = id->repr; macro_struct.id = id; if (!HTAB_DO (macro_t, macro_tab, ¯o_struct, HTAB_FIND, m)) { @@ -2305,9 +2329,11 @@ static void define (c2m_ctx_t c2m_ctx) { if (!params_eq_p (m->params, params) || !replacement_eq_p (m->replacement, repl)) { if (c2m_options->pedantic_p) { error (c2m_ctx, id->pos, "different macro redefinition of %s", name); + error (c2m_ctx, m->id->pos, "previous definition of %s", m->id->repr); } else { VARR (token_t) * temp; warning (c2m_ctx, id->pos, "different macro redefinition of %s", name); + warning (c2m_ctx, m->id->pos, "previous definition of %s", m->id->repr); SWAP (m->params, params, temp); SWAP (m->replacement, repl, temp); } @@ -2597,7 +2623,8 @@ static void find_args (c2m_ctx_t c2m_ctx, macro_call_t mc) { /* we have just rea } } if (VARR_LENGTH (token_arr_t, args) > params_len) { - t = VARR_GET (token_t, VARR_GET (token_arr_t, args, params_len), 0); + token_arr_t arg = VARR_GET (token_arr_t, args, params_len); + if (VARR_LENGTH (token_t, arg) != 0) t = VARR_GET (token_t, arg, 0); while (VARR_LENGTH (token_arr_t, args) > params_len) { temp_arr = VARR_POP (token_arr_t, args); VARR_DESTROY (token_t, temp_arr); @@ -2623,6 +2650,7 @@ static token_t token_concat (c2m_ctx_t c2m_ctx, token_t t1, token_t t2) { set_string_stream (c2m_ctx, VARR_ADDR (char, temp_string), t1->pos, NULL); t = get_next_pptoken (c2m_ctx); next = get_next_pptoken (c2m_ctx); + while (next->code == T_EOU) next = get_next_pptoken (c2m_ctx); if (next->code != T_EOFILE) { error (c2m_ctx, t1->pos, "wrong result of ##: %s", reverse (temp_string)); remove_string_stream (c2m_ctx); @@ -3048,6 +3076,7 @@ static void process_directive (c2m_ctx_t c2m_ctx) { skip_nl (c2m_ctx, t1, temp_buffer); unget_next_pptoken (c2m_ctx, new_token (c2m_ctx, t->pos, "", T_EOP, N_IGNORE)); push_back (c2m_ctx, temp_buffer); + if (n_errors != 0) VARR_TRUNC (macro_call_t, macro_call_stack, 0); /* can be non-empty */ assert (VARR_LENGTH (macro_call_t, macro_call_stack) == 0 && !no_out_p); no_out_p = TRUE; processing (c2m_ctx, TRUE); @@ -3067,8 +3096,9 @@ static void process_directive (c2m_ctx_t c2m_ctx) { skip_nl (c2m_ctx, NULL, temp_buffer); unget_next_pptoken (c2m_ctx, new_token (c2m_ctx, t->pos, "", T_EOP, N_IGNORE)); push_back (c2m_ctx, temp_buffer); + if (n_errors != 0) VARR_TRUNC (macro_call_t, macro_call_stack, 0); /* can be non-empty */ assert (VARR_LENGTH (macro_call_t, macro_call_stack) == 0 && !no_out_p); - no_out_p = 1; + no_out_p = TRUE; processing (c2m_ctx, TRUE); no_out_p = 0; move_tokens (temp_buffer, output_buffer); @@ -3456,13 +3486,13 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { res.uns_p = eval_binop_operands (c2m_ctx, tree, &v1, &v2); if (res.uns_p) { - res.u.u_val = ((zero_p = v2.u.u_val == 0) - ? 1 - : tree->code == N_DIV ? v1.u.u_val / v2.u.u_val : v1.u.u_val % v2.u.u_val); + res.u.u_val = ((zero_p = v2.u.u_val == 0) ? 1 + : tree->code == N_DIV ? v1.u.u_val / v2.u.u_val + : v1.u.u_val % v2.u.u_val); } else { - res.u.i_val = ((zero_p = v2.u.i_val == 0) - ? 1 - : tree->code == N_DIV ? v1.u.i_val / v2.u.i_val : v1.u.i_val % v2.u.i_val); + res.u.i_val = ((zero_p = v2.u.i_val == 0) ? 1 + : tree->code == N_DIV ? v1.u.i_val / v2.u.i_val + : v1.u.i_val % v2.u.i_val); } if (zero_p) error (c2m_ctx, POS (tree), "division (%s) by zero in preporocessor", @@ -3988,6 +4018,8 @@ static node_t try_arg_f (c2m_ctx_t c2m_ctx, nonterm_arg_func_t f, node_t arg) { #define TRY(f) try_f (c2m_ctx, f) #define TRY_A(f, arg) try_arg_f (c2m_ctx, f, arg) +D (compound_stmt); + /* Expressions: */ D (type_name); D (expr); @@ -4012,7 +4044,12 @@ D (primary_expr) { if (MN (T_ID, r) || MN (T_NUMBER, r) || MN (T_CH, r) || MN (T_STR, r)) { return r; } else if (M ('(')) { - P (expr); + if (C ('{')) { + P (compound_stmt); + r = new_node1 (c2m_ctx, N_STMTEXPR, r); + } else { + P (expr); + } if (M (')')) return r; } else if (MP (T_GENERIC, pos)) { PT ('('); @@ -4444,7 +4481,7 @@ DA (type_spec) { id_p = TRUE; } if (M ('{')) { - if (!C ('}')) { + if (!C ('}') && !M (';')) { P (struct_declaration_list); } else { (c2m_options->pedantic_p ? error : warning) (c2m_ctx, pos, "empty struct/union"); @@ -4759,6 +4796,7 @@ D (param_type_list) { pos_t pos; list = new_node (c2m_ctx, N_LIST); + if (C (')')) return list; for (;;) { /* parameter-list, parameter-declaration */ PA (declaration_specs, NULL); op1 = r; @@ -4993,7 +5031,6 @@ D (st_assert) { } /* Statements: */ -D (compound_stmt); D (label) { parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; @@ -5484,11 +5521,11 @@ static void symbol_finish (c2m_ctx_t c2m_ctx) { } enum basic_type get_int_basic_type (size_t s) { - return (s == sizeof (mir_int) - ? TP_INT - : s == sizeof (mir_short) - ? TP_SHORT - : s == sizeof (mir_long) ? TP_LONG : s == sizeof (mir_schar) ? TP_SCHAR : TP_LLONG); + return (s == sizeof (mir_int) ? TP_INT + : s == sizeof (mir_short) ? TP_SHORT + : s == sizeof (mir_long) ? TP_LONG + : s == sizeof (mir_schar) ? TP_SCHAR + : TP_LLONG); } static int type_qual_eq_p (const struct type_qual *tq1, const struct type_qual *tq2) { @@ -5719,6 +5756,7 @@ struct decl { static enum basic_type get_enum_basic_type (const struct type *type) { assert (type->mode == TM_ENUM); + if (type->u.tag_type->attr == NULL) return TP_INT; /* in case of undefined enum */ return ((struct enum_type *) type->u.tag_type->attr)->enum_basic_type; } @@ -6030,7 +6068,8 @@ static void set_type_layout (c2m_ctx_t c2m_ctx, struct type *type) { } else if (type->mode == TM_ARR) { struct arr_type *arr_type = type->u.arr_type; struct expr *cexpr = arr_type->size->attr; - mir_size_t nel = (arr_type->size->code == N_IGNORE || !cexpr->const_p ? 1 : cexpr->u.i_val); + mir_size_t nel + = (arr_type->size->code == N_IGNORE || cexpr == NULL || !cexpr->const_p ? 1 : cexpr->u.i_val); set_type_layout (c2m_ctx, arr_type->el_type); overall_size = type_size (c2m_ctx, arr_type->el_type) * nel; @@ -6673,15 +6712,12 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec enum_value->u.i_val = curr_val; } enum_type->enum_basic_type - = (max_val <= MIR_INT_MAX && MIR_INT_MIN <= min_val - ? TP_INT - : max_val <= MIR_UINT_MAX && 0 <= min_val - ? TP_UINT - : max_val <= MIR_LONG_MAX && MIR_LONG_MIN <= min_val - ? TP_LONG - : max_val <= MIR_ULONG_MAX && 0 <= min_val - ? TP_ULONG - : min_val < 0 || max_val <= MIR_LLONG_MAX ? TP_LLONG : TP_ULLONG); + = (max_val <= MIR_INT_MAX && MIR_INT_MIN <= min_val ? TP_INT + : max_val <= MIR_UINT_MAX && 0 <= min_val ? TP_UINT + : max_val <= MIR_LONG_MAX && MIR_LONG_MIN <= min_val ? TP_LONG + : max_val <= MIR_ULONG_MAX && 0 <= min_val ? TP_ULONG + : min_val < 0 || max_val <= MIR_LLONG_MAX ? TP_LLONG + : TP_ULLONG); } } break; @@ -7079,28 +7115,25 @@ static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct if (!arithmetic_type_p (right) && !(left->mode == TM_BASIC && left->u.basic_type == TP_BOOL && right->mode == TM_PTR)) { if (integer_type_p (left) && right->mode == TM_PTR) { - msg - = (code == N_CALL ? "using pointer without cast for integer type parameter" - : code == N_RETURN ? "returning pointer without cast for integer result" - : "assigning pointer without cast to integer"); + msg = (code == N_CALL ? "using pointer without cast for integer type parameter" + : code == N_RETURN ? "returning pointer without cast for integer result" + : "assigning pointer without cast to integer"); (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } else { - msg = (code == N_CALL - ? "incompatible argument type for arithemtic type parameter" - : code != N_RETURN - ? "incompatible types in assignment to an arithemtic type lvalue" - : "incompatible return-expr type in function returning an arithemtic value"); + msg = (code == N_CALL ? "incompatible argument type for arithmetic type parameter" + : code != N_RETURN + ? "incompatible types in assignment to an arithmetic type lvalue" + : "incompatible return-expr type in function returning an arithmetic value"); error (c2m_ctx, POS (assign_node), "%s", msg); } } } else if (left->mode == TM_STRUCT || left->mode == TM_UNION) { if ((right->mode != TM_STRUCT && right->mode != TM_UNION) || !compatible_types_p (left, right, TRUE)) { - msg = (code == N_CALL - ? "incompatible argument type for struct/union type parameter" - : code != N_RETURN - ? "incompatible types in assignment to struct/union" - : "incompatible return-expr type in function returning a struct/union"); + msg = (code == N_CALL ? "incompatible argument type for struct/union type parameter" + : code != N_RETURN + ? "incompatible types in assignment to struct/union" + : "incompatible return-expr type in function returning a struct/union"); error (c2m_ctx, POS (assign_node), "%s", msg); } } else if (left->mode == TM_PTR) { @@ -7113,45 +7146,41 @@ static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct right->u.ptr_type, TRUE)))) { if (right->mode == TM_PTR && left->u.ptr_type->mode == TM_BASIC && right->u.ptr_type->mode == TM_BASIC) { - msg = (code == N_CALL ? "incompatible pointer types of argument and parameter" - : code == N_RETURN - ? "incompatible pointer types of return-expr and function result" + msg = (code == N_CALL ? "incompatible pointer types of argument and parameter" + : code == N_RETURN ? "incompatible pointer types of return-expr and function result" : "incompatible pointer types in assignment"); int sign_diff_p = char_type_p (left->u.ptr_type) && char_type_p (right->u.ptr_type); if (!sign_diff_p || c2m_options->pedantic_p) (c2m_options->pedantic_p && !sign_diff_p ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } else if (integer_type_p (right)) { - msg - = (code == N_CALL ? "using integer without cast for pointer type parameter" - : code == N_RETURN ? "returning integer without cast for pointer result" - : "assigning integer without cast to pointer"); + msg = (code == N_CALL ? "using integer without cast for pointer type parameter" + : code == N_RETURN ? "returning integer without cast for pointer result" + : "assigning integer without cast to pointer"); (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } else { - msg = (code == N_CALL ? "incompatible argument type for pointer type parameter" - : code == N_RETURN - ? "incompatible return-expr type in function returning a pointer" + msg = (code == N_CALL ? "incompatible argument type for pointer type parameter" + : code == N_RETURN ? "incompatible return-expr type in function returning a pointer" : "incompatible types in assignment to a pointer"); (c2m_options->pedantic_p || right->mode != TM_PTR ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } } else if (right->u.ptr_type->type_qual.atomic_p) { - msg = (code == N_CALL ? "passing a pointer of an atomic type" - : code == N_RETURN ? "returning a pointer of an atomic type" - : "assignment of pointer of an atomic type"); + msg = (code == N_CALL ? "passing a pointer of an atomic type" + : code == N_RETURN ? "returning a pointer of an atomic type" + : "assignment of pointer of an atomic type"); error (c2m_ctx, POS (assign_node), "%s", msg); } else if (!type_qual_subset_p (&right->u.ptr_type->type_qual, &left->u.ptr_type->type_qual)) { - msg = (code == N_CALL - ? "discarding type qualifiers in passing argument" - : code == N_RETURN ? "return discards a type qualifier from a pointer" - : "assignment discards a type qualifier from a pointer"); + msg = (code == N_CALL ? "discarding type qualifiers in passing argument" + : code == N_RETURN ? "return discards a type qualifier from a pointer" + : "assignment discards a type qualifier from a pointer"); (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } } else { - msg = (code == N_CALL ? "passing assign incompatible value" - : code == N_RETURN ? "returning assign incompatible value" - : "assignment of incompatible value"); + msg = (code == N_CALL ? "passing assign incompatible value" + : code == N_RETURN ? "returning assign incompatible value" + : "assignment of incompatible value"); error (c2m_ctx, POS (assign_node), "%s", msg); } } @@ -7223,7 +7252,7 @@ static int update_init_object_path (c2m_ctx_t c2m_ctx, size_t mark, struct type } VARR_SET (init_object_t, init_object_path, VARR_LENGTH (init_object_t, init_object_path) - 1, init_object); - if (list_p || scalar_type_p (el_type)) return TRUE; + if (list_p || scalar_type_p (el_type) || void_type_p (el_type)) return TRUE; assert (el_type->mode == TM_ARR || el_type->mode == TM_STRUCT || el_type->mode == TM_UNION); if (el_type->mode != TM_ARR && value_type != NULL && el_type->u.tag_type == value_type->u.tag_type) @@ -7592,7 +7621,7 @@ static void check_initializer (c2m_ctx_t c2m_ctx, decl_t member_decl, struct typ break; } else { struct type *curr_type = type; - mir_llong arr_size_val; + mir_llong arr_size_val MIR_UNUSED; int first_p = TRUE; VARR_TRUNC (init_object_t, init_object_path, mark + 1); @@ -7662,10 +7691,9 @@ static void check_initializer (c2m_ctx_t c2m_ctx, decl_t member_decl, struct typ type->u.arr_type = arr_type; size_node = type->u.arr_type->size; type->u.arr_type->size - = (max_index < MIR_INT_MAX - ? new_i_node (c2m_ctx, max_index + 1, POS (size_node)) - : max_index < MIR_LONG_MAX ? new_l_node (c2m_ctx, max_index + 1, POS (size_node)) - : new_ll_node (c2m_ctx, max_index + 1, POS (size_node))); + = (max_index < MIR_INT_MAX ? new_i_node (c2m_ctx, max_index + 1, POS (size_node)) + : max_index < MIR_LONG_MAX ? new_l_node (c2m_ctx, max_index + 1, POS (size_node)) + : new_ll_node (c2m_ctx, max_index + 1, POS (size_node))); check (c2m_ctx, type->u.arr_type->size, NULL); make_type_complete (c2m_ctx, type); } @@ -7883,13 +7911,13 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no convert_value (e2, &t); e->const_p = TRUE; if (signed_integer_type_p (&t)) - e->u.i_val = (r->code == N_AND ? e1->u.i_val & e2->u.i_val - : r->code == N_OR ? e1->u.i_val | e2->u.i_val - : e1->u.i_val ^ e2->u.i_val); + e->u.i_val = (r->code == N_AND ? e1->u.i_val & e2->u.i_val + : r->code == N_OR ? e1->u.i_val | e2->u.i_val + : e1->u.i_val ^ e2->u.i_val); else - e->u.u_val = (r->code == N_AND ? e1->u.u_val & e2->u.u_val - : r->code == N_OR ? e1->u.u_val | e2->u.u_val - : e1->u.u_val ^ e2->u.u_val); + e->u.u_val = (r->code == N_AND ? e1->u.u_val & e2->u.u_val + : r->code == N_OR ? e1->u.u_val | e2->u.u_val + : e1->u.u_val ^ e2->u.u_val); } } break; @@ -8103,7 +8131,7 @@ static void classify_node (node_t n, int *expr_attr_p, int *stmt_p) { switch (n->code) { REP8 (NODE_CASE, I, L, LL, U, UL, ULL, F, D) REP7 (NODE_CASE, LD, CH, CH16, CH32, STR, STR16, STR32) - REP5 (NODE_CASE, ID, COMMA, ANDAND, OROR, EQ) + REP6 (NODE_CASE, ID, COMMA, ANDAND, OROR, EQ, STMTEXPR) REP8 (NODE_CASE, NE, LT, LE, GT, GE, ASSIGN, BITWISE_NOT, NOT) REP8 (NODE_CASE, AND, AND_ASSIGN, OR, OR_ASSIGN, XOR, XOR_ASSIGN, LSH, LSH_ASSIGN) REP8 (NODE_CASE, RSH, RSH_ASSIGN, ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN) @@ -8412,15 +8440,12 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { error (c2m_ctx, POS (r), "pointer to atomic type as a comparison operand"); } else if (e1->const_p && e2->const_p) { e->const_p = TRUE; - e->u.i_val = (r->code == N_EQ - ? e1->u.u_val == e2->u.u_val - : r->code == N_NE - ? e1->u.u_val != e2->u.u_val - : r->code == N_LT - ? e1->u.u_val < e2->u.u_val - : r->code == N_LE ? e1->u.u_val <= e2->u.u_val - : r->code == N_GT ? e1->u.u_val > e2->u.u_val - : e1->u.u_val >= e2->u.u_val); + e->u.i_val = (r->code == N_EQ ? e1->u.u_val == e2->u.u_val + : r->code == N_NE ? e1->u.u_val != e2->u.u_val + : r->code == N_LT ? e1->u.u_val < e2->u.u_val + : r->code == N_LE ? e1->u.u_val <= e2->u.u_val + : r->code == N_GT ? e1->u.u_val > e2->u.u_val + : e1->u.u_val >= e2->u.u_val); } } else if (arithmetic_type_p (t1) && arithmetic_type_p (t2)) { if (e1->const_p && e2->const_p) { @@ -8429,35 +8454,26 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { convert_value (e2, &t); e->const_p = TRUE; if (floating_type_p (&t)) - e->u.i_val = (r->code == N_EQ - ? e1->u.d_val == e2->u.d_val - : r->code == N_NE - ? e1->u.d_val != e2->u.d_val - : r->code == N_LT - ? e1->u.d_val < e2->u.d_val - : r->code == N_LE ? e1->u.d_val <= e2->u.d_val - : r->code == N_GT ? e1->u.d_val > e2->u.d_val - : e1->u.d_val >= e2->u.d_val); + e->u.i_val = (r->code == N_EQ ? e1->u.d_val == e2->u.d_val + : r->code == N_NE ? e1->u.d_val != e2->u.d_val + : r->code == N_LT ? e1->u.d_val < e2->u.d_val + : r->code == N_LE ? e1->u.d_val <= e2->u.d_val + : r->code == N_GT ? e1->u.d_val > e2->u.d_val + : e1->u.d_val >= e2->u.d_val); else if (signed_integer_type_p (&t)) - e->u.i_val = (r->code == N_EQ - ? e1->u.i_val == e2->u.i_val - : r->code == N_NE - ? e1->u.i_val != e2->u.i_val - : r->code == N_LT - ? e1->u.i_val < e2->u.i_val - : r->code == N_LE ? e1->u.i_val <= e2->u.i_val - : r->code == N_GT ? e1->u.i_val > e2->u.i_val - : e1->u.i_val >= e2->u.i_val); + e->u.i_val = (r->code == N_EQ ? e1->u.i_val == e2->u.i_val + : r->code == N_NE ? e1->u.i_val != e2->u.i_val + : r->code == N_LT ? e1->u.i_val < e2->u.i_val + : r->code == N_LE ? e1->u.i_val <= e2->u.i_val + : r->code == N_GT ? e1->u.i_val > e2->u.i_val + : e1->u.i_val >= e2->u.i_val); else - e->u.i_val = (r->code == N_EQ - ? e1->u.u_val == e2->u.u_val - : r->code == N_NE - ? e1->u.u_val != e2->u.u_val - : r->code == N_LT - ? e1->u.u_val < e2->u.u_val - : r->code == N_LE ? e1->u.u_val <= e2->u.u_val - : r->code == N_GT ? e1->u.u_val > e2->u.u_val - : e1->u.u_val >= e2->u.u_val); + e->u.i_val = (r->code == N_EQ ? e1->u.u_val == e2->u.u_val + : r->code == N_NE ? e1->u.u_val != e2->u.u_val + : r->code == N_LT ? e1->u.u_val < e2->u.u_val + : r->code == N_LE ? e1->u.u_val <= e2->u.u_val + : r->code == N_GT ? e1->u.u_val > e2->u.u_val + : e1->u.u_val >= e2->u.u_val); } } else { error (c2m_ctx, POS (r), "invalid types of comparison operands"); @@ -8980,6 +8996,8 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if (!builtin_call_p) VARR_PUSH (node_t, call_nodes, r); arg_list = NL_NEXT (op1); if (builtin_call_p) { + if (func_block_scope != NULL && (va_arg_p || va_start_p)) + ((struct node_scope *) func_block_scope->attr)->stack_var_p = TRUE; for (arg = NL_HEAD (arg_list->u.ops); arg != NULL; arg = NL_NEXT (arg)) check (c2m_ctx, arg, r); init_type (&res_type); @@ -9258,6 +9276,8 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { /* Process parameter identifier list: */ assert (declarator->code == N_DECL); func = NL_HEAD (NL_EL (declarator->u.ops, 1)->u.ops); + /* func can be NULL or non-func in case of error */ + if (n_errors != 0 && (func == NULL || func->code != N_FUNC)) break; assert (func != NULL && func->code == N_FUNC); param_list = NL_HEAD (func->u.ops); for (p = NL_HEAD (param_list->u.ops); p != NULL; p = next_p) { @@ -9308,6 +9328,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if (p->code == N_ST_ASSERT) continue; assert (p->code == N_SPEC_DECL); param_declarator = NL_EL (p->u.ops, 1); + if (param_declarator->code == N_IGNORE) continue; assert (param_declarator->code == N_DECL); param_id = NL_HEAD (param_declarator->u.ops); assert (param_id->code == N_ID); @@ -9363,6 +9384,25 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } break; } + case N_STMTEXPR: { + node_t block = NL_HEAD (r->u.ops); + if (c2m_options->pedantic_p) { + error (c2m_ctx, POS (r), "statement expression is not a part of C11 standard"); + break; + } + check (c2m_ctx, block, r); + node_t last_stmt = NL_TAIL (NL_EL (block->u.ops, 1)->u.ops); + if (!last_stmt || last_stmt->code != N_EXPR) { + error (c2m_ctx, POS (r), "last statement in statement expression is not an expression"); + break; + } + node_t expr = NL_EL (last_stmt->u.ops, 1); + e1 = expr->attr; + t1 = e1->type; + e = create_expr (c2m_ctx, r); + *e->type = *t1; + break; + } case N_BLOCK: check_labels (c2m_ctx, NL_HEAD (r->u.ops), r); if (curr_scope != r) @@ -9720,6 +9760,7 @@ DEF_VARR (int); DEF_VARR (MIR_type_t); struct init_el { + c2m_ctx_t c2m_ctx; /* for sorting */ mir_size_t num, offset; decl_t member_decl; /* NULL for non-member initialization */ struct type *el_type; @@ -9739,6 +9780,7 @@ struct gen_ctx { HTAB (reg_var_t) * reg_var_tab; int reg_free_mark; MIR_label_t continue_label, break_label; + op_t top_gen_last_op; struct { int res_ref_p; /* flag of returning an aggregate by reference */ VARR (MIR_type_t) * ret_types; @@ -9761,6 +9803,7 @@ struct gen_ctx { #define reg_free_mark gen_ctx->reg_free_mark #define continue_label gen_ctx->continue_label #define break_label gen_ctx->break_label +#define top_gen_last_op gen_ctx->top_gen_last_op #define proto_info gen_ctx->proto_info #define init_els gen_ctx->init_els #define memset_proto gen_ctx->memset_proto @@ -9843,16 +9886,14 @@ static MIR_type_t reg_type (c2m_ctx_t c2m_ctx, MIR_reg_t reg) { MIR_type_t res; if (strcmp (n, FP_NAME) == 0 || strcmp (n, RET_ADDR_NAME) == 0) return MIR_POINTER_TYPE; - res = (n[0] == 'I' - ? MIR_T_I64 - : n[0] == 'U' - ? MIR_T_U64 - : n[0] == 'i' ? MIR_T_I32 - : n[0] == 'u' ? MIR_T_U32 - : n[0] == 'f' ? MIR_T_F - : n[0] == 'd' ? MIR_T_D - : n[0] == 'D' ? MIR_T_LD - : MIR_T_BOUND); + res = (n[0] == 'I' ? MIR_T_I64 + : n[0] == 'U' ? MIR_T_U64 + : n[0] == 'i' ? MIR_T_I32 + : n[0] == 'u' ? MIR_T_U32 + : n[0] == 'f' ? MIR_T_F + : n[0] == 'd' ? MIR_T_D + : n[0] == 'D' ? MIR_T_LD + : MIR_T_BOUND); assert (res != MIR_T_BOUND); return res; } @@ -9866,14 +9907,13 @@ static op_t get_new_temp (c2m_ctx_t c2m_ctx, MIR_type_t t) { assert (t == MIR_T_I64 || t == MIR_T_U64 || t == MIR_T_I32 || t == MIR_T_U32 || t == MIR_T_F || t == MIR_T_D || t == MIR_T_LD); sprintf (reg_name, - t == MIR_T_I64 - ? "I_%u" - : t == MIR_T_U64 - ? "U_%u" - : t == MIR_T_I32 - ? "i_%u" - : t == MIR_T_U32 ? "u_%u" - : t == MIR_T_F ? "f_%u" : t == MIR_T_D ? "d_%u" : "D_%u", + t == MIR_T_I64 ? "I_%u" + : t == MIR_T_U64 ? "U_%u" + : t == MIR_T_I32 ? "i_%u" + : t == MIR_T_U32 ? "u_%u" + : t == MIR_T_F ? "f_%u" + : t == MIR_T_D ? "d_%u" + : "D_%u", reg_free_mark++); reg = get_reg_var (c2m_ctx, t, reg_name).reg; return new_op (NULL, MIR_new_reg_op (ctx, reg)); @@ -9884,9 +9924,10 @@ static MIR_type_t get_int_mir_type (size_t size) { } static int MIR_UNUSED get_int_mir_type_size (MIR_type_t t) { - return (t == MIR_T_I8 || t == MIR_T_U8 - ? 1 - : t == MIR_T_I16 || t == MIR_T_U16 ? 2 : t == MIR_T_I32 || t == MIR_T_U32 ? 4 : 8); + return (t == MIR_T_I8 || t == MIR_T_U8 ? 1 + : t == MIR_T_I16 || t == MIR_T_U16 ? 2 + : t == MIR_T_I32 || t == MIR_T_U32 ? 4 + : 8); } static MIR_type_t get_mir_type (c2m_ctx_t c2m_ctx, struct type *type) { @@ -9905,8 +9946,9 @@ static MIR_type_t get_mir_type (c2m_ctx_t c2m_ctx, struct type *type) { } static MIR_type_t promote_mir_int_type (MIR_type_t t) { - return (t == MIR_T_I8 || t == MIR_T_I16 ? MIR_T_I32 - : t == MIR_T_U8 || t == MIR_T_U16 ? MIR_T_U32 : t); + return (t == MIR_T_I8 || t == MIR_T_I16 ? MIR_T_I32 + : t == MIR_T_U8 || t == MIR_T_U16 ? MIR_T_U32 + : t); } static MIR_type_t get_op_type (c2m_ctx_t c2m_ctx, op_t op) { @@ -9934,10 +9976,9 @@ static int push_const_val (c2m_ctx_t c2m_ctx, node_t r, op_t *res) { if (floating_type_p (e->type)) { /* MIR support only IEEE float and double */ mir_type = get_mir_type (c2m_ctx, e->type); - *res = new_op (NULL, (mir_type == MIR_T_F - ? MIR_new_float_op (ctx, e->u.d_val) - : mir_type == MIR_T_D ? MIR_new_double_op (ctx, e->u.d_val) - : MIR_new_ldouble_op (ctx, e->u.d_val))); + *res = new_op (NULL, (mir_type == MIR_T_F ? MIR_new_float_op (ctx, e->u.d_val) + : mir_type == MIR_T_D ? MIR_new_double_op (ctx, e->u.d_val) + : MIR_new_ldouble_op (ctx, e->u.d_val))); } else { assert (integer_type_p (e->type) || e->type->mode == TM_PTR); *res = new_op (NULL, (signed_integer_type_p (e->type) ? MIR_new_int_op (ctx, e->u.i_val) @@ -10043,142 +10084,137 @@ static op_t cast (c2m_ctx_t c2m_ctx, op_t op, MIR_type_t t, int new_op_p) { if (op_type == MIR_T_D) goto double_val; if (op_type == MIR_T_LD) goto ldouble_val; if (t == MIR_T_I64) { - insn_code - = (op_type == MIR_T_I32 - ? MIR_EXT32 - : op_type == MIR_T_U32 - ? MIR_UEXT32 - : op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I - : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_I32 ? MIR_EXT32 + : op_type == MIR_T_U32 ? MIR_UEXT32 + : op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); } else if (t == MIR_T_U64) { - insn_code - = (op_type == MIR_T_I32 - ? MIR_EXT32 - : op_type == MIR_T_U32 - ? MIR_UEXT32 - : op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I - : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_I32 ? MIR_EXT32 + : op_type == MIR_T_U32 ? MIR_UEXT32 + : op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); } else if (t == MIR_T_I32) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); } else if (t == MIR_T_U32) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); } else if (t == MIR_T_I16) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); insn_code2 = MIR_EXT16; } else if (t == MIR_T_U16) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); insn_code2 = MIR_UEXT16; } else if (t == MIR_T_I8) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); insn_code2 = MIR_EXT8; } else if (t == MIR_T_U8) { - insn_code - = (op_type == MIR_T_F - ? MIR_F2I - : op_type == MIR_T_D ? MIR_D2I : op_type == MIR_T_LD ? MIR_LD2I : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_F ? MIR_F2I + : op_type == MIR_T_D ? MIR_D2I + : op_type == MIR_T_LD ? MIR_LD2I + : MIR_INSN_BOUND); insn_code2 = MIR_UEXT8; } else if (t == MIR_T_F) { - insn_code - = (op_type == MIR_T_I32 ? MIR_EXT32 : op_type == MIR_T_U32 ? MIR_UEXT32 : MIR_INSN_BOUND); - insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 - ? MIR_I2F - : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2F : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_I32 ? MIR_EXT32 + : op_type == MIR_T_U32 ? MIR_UEXT32 + : MIR_INSN_BOUND); + insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 ? MIR_I2F + : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2F + : MIR_INSN_BOUND); } else if (t == MIR_T_D) { - insn_code - = (op_type == MIR_T_I32 ? MIR_EXT32 : op_type == MIR_T_U32 ? MIR_UEXT32 : MIR_INSN_BOUND); - insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 - ? MIR_I2D - : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2D : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_I32 ? MIR_EXT32 + : op_type == MIR_T_U32 ? MIR_UEXT32 + : MIR_INSN_BOUND); + insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 ? MIR_I2D + : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2D + : MIR_INSN_BOUND); } else if (t == MIR_T_LD) { - insn_code - = (op_type == MIR_T_I32 ? MIR_EXT32 : op_type == MIR_T_U32 ? MIR_UEXT32 : MIR_INSN_BOUND); - insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 - ? MIR_I2LD - : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2LD : MIR_INSN_BOUND); + insn_code = (op_type == MIR_T_I32 ? MIR_EXT32 + : op_type == MIR_T_U32 ? MIR_UEXT32 + : MIR_INSN_BOUND); + insn_code2 = (op_type == MIR_T_I64 || op_type == MIR_T_I32 ? MIR_I2LD + : op_type == MIR_T_U64 || op_type == MIR_T_U32 ? MIR_UI2LD + : MIR_INSN_BOUND); } break; case MIR_OP_INT: - insn_code - = (t == MIR_T_I8 - ? MIR_EXT8 - : t == MIR_T_U8 - ? MIR_UEXT8 - : t == MIR_T_I16 - ? MIR_EXT16 - : t == MIR_T_U16 - ? MIR_UEXT16 - : t == MIR_T_F - ? MIR_I2F - : t == MIR_T_D ? MIR_I2D : t == MIR_T_LD ? MIR_I2LD : MIR_INSN_BOUND); + insn_code = (t == MIR_T_I8 ? MIR_EXT8 + : t == MIR_T_U8 ? MIR_UEXT8 + : t == MIR_T_I16 ? MIR_EXT16 + : t == MIR_T_U16 ? MIR_UEXT16 + : t == MIR_T_F ? MIR_I2F + : t == MIR_T_D ? MIR_I2D + : t == MIR_T_LD ? MIR_I2LD + : MIR_INSN_BOUND); break; case MIR_OP_UINT: - insn_code - = (t == MIR_T_I8 - ? MIR_EXT8 - : t == MIR_T_U8 - ? MIR_UEXT8 - : t == MIR_T_I16 - ? MIR_EXT16 - : t == MIR_T_U16 - ? MIR_UEXT16 - : t == MIR_T_F - ? MIR_UI2F - : t == MIR_T_D ? MIR_UI2D : t == MIR_T_LD ? MIR_UI2LD : MIR_INSN_BOUND); + insn_code = (t == MIR_T_I8 ? MIR_EXT8 + : t == MIR_T_U8 ? MIR_UEXT8 + : t == MIR_T_I16 ? MIR_EXT16 + : t == MIR_T_U16 ? MIR_UEXT16 + : t == MIR_T_F ? MIR_UI2F + : t == MIR_T_D ? MIR_UI2D + : t == MIR_T_LD ? MIR_UI2LD + : MIR_INSN_BOUND); break; case MIR_OP_FLOAT: float_val: insn_code = (t == MIR_T_I8 || t == MIR_T_U8 || t == MIR_T_I16 || t == MIR_T_U16 || t == MIR_T_I32 || t == MIR_T_U32 || t == MIR_T_I64 || t == MIR_T_U64 ? MIR_F2I - : t == MIR_T_D ? MIR_F2D : t == MIR_T_LD ? MIR_F2LD : MIR_INSN_BOUND); - insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 - : t == MIR_T_U8 ? MIR_UEXT8 - : t == MIR_T_I16 - ? MIR_EXT16 - : t == MIR_T_U16 ? MIR_UEXT16 : MIR_INSN_BOUND); + : t == MIR_T_D ? MIR_F2D + : t == MIR_T_LD ? MIR_F2LD + : MIR_INSN_BOUND); + insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 + : t == MIR_T_U8 ? MIR_UEXT8 + : t == MIR_T_I16 ? MIR_EXT16 + : t == MIR_T_U16 ? MIR_UEXT16 + : MIR_INSN_BOUND); break; case MIR_OP_DOUBLE: double_val: insn_code = (t == MIR_T_I8 || t == MIR_T_U8 || t == MIR_T_I16 || t == MIR_T_U16 || t == MIR_T_I32 || t == MIR_T_U32 || t == MIR_T_I64 || t == MIR_T_U64 ? MIR_D2I - : t == MIR_T_F ? MIR_D2F : t == MIR_T_LD ? MIR_D2LD : MIR_INSN_BOUND); - insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 - : t == MIR_T_U8 ? MIR_UEXT8 - : t == MIR_T_I16 - ? MIR_EXT16 - : t == MIR_T_U16 ? MIR_UEXT16 : MIR_INSN_BOUND); + : t == MIR_T_F ? MIR_D2F + : t == MIR_T_LD ? MIR_D2LD + : MIR_INSN_BOUND); + insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 + : t == MIR_T_U8 ? MIR_UEXT8 + : t == MIR_T_I16 ? MIR_EXT16 + : t == MIR_T_U16 ? MIR_UEXT16 + : MIR_INSN_BOUND); break; case MIR_OP_LDOUBLE: ldouble_val: insn_code = (t == MIR_T_I8 || t == MIR_T_U8 || t == MIR_T_I16 || t == MIR_T_U16 || t == MIR_T_I32 || t == MIR_T_U32 || t == MIR_T_I64 || t == MIR_T_U64 ? MIR_LD2I - : t == MIR_T_F ? MIR_LD2F : t == MIR_T_D ? MIR_LD2D : MIR_INSN_BOUND); - insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 - : t == MIR_T_U8 ? MIR_UEXT8 - : t == MIR_T_I16 - ? MIR_EXT16 - : t == MIR_T_U16 ? MIR_UEXT16 : MIR_INSN_BOUND); + : t == MIR_T_F ? MIR_LD2F + : t == MIR_T_D ? MIR_LD2D + : MIR_INSN_BOUND); + insn_code2 = (t == MIR_T_I8 ? MIR_EXT8 + : t == MIR_T_U8 ? MIR_UEXT8 + : t == MIR_T_I16 ? MIR_EXT16 + : t == MIR_T_U16 ? MIR_UEXT16 + : MIR_INSN_BOUND); break; default: break; } @@ -10340,45 +10376,42 @@ static MIR_insn_code_t get_mir_type_insn_code (c2m_ctx_t c2m_ctx, struct type *t case N_POST_INC: case N_ADD: case N_ADD_ASSIGN: - return (t == MIR_T_F - ? MIR_FADD - : t == MIR_T_D - ? MIR_DADD - : t == MIR_T_LD ? MIR_LDADD - : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_ADD : MIR_ADDS); + return (t == MIR_T_F ? MIR_FADD + : t == MIR_T_D ? MIR_DADD + : t == MIR_T_LD ? MIR_LDADD + : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_ADD + : MIR_ADDS); case N_DEC: case N_POST_DEC: case N_SUB: case N_SUB_ASSIGN: - return (t == MIR_T_F - ? MIR_FSUB - : t == MIR_T_D - ? MIR_DSUB - : t == MIR_T_LD ? MIR_LDSUB - : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_SUB : MIR_SUBS); + return (t == MIR_T_F ? MIR_FSUB + : t == MIR_T_D ? MIR_DSUB + : t == MIR_T_LD ? MIR_LDSUB + : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_SUB + : MIR_SUBS); case N_MUL: case N_MUL_ASSIGN: - return (t == MIR_T_F - ? MIR_FMUL - : t == MIR_T_D - ? MIR_DMUL - : t == MIR_T_LD ? MIR_LDMUL - : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_MUL : MIR_MULS); + return (t == MIR_T_F ? MIR_FMUL + : t == MIR_T_D ? MIR_DMUL + : t == MIR_T_LD ? MIR_LDMUL + : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_MUL + : MIR_MULS); case N_DIV: case N_DIV_ASSIGN: - return (t == MIR_T_F - ? MIR_FDIV - : t == MIR_T_D - ? MIR_DDIV - : t == MIR_T_LD - ? MIR_LDDIV - : t == MIR_T_I64 - ? MIR_DIV - : t == MIR_T_U64 ? MIR_UDIV : t == MIR_T_I32 ? MIR_DIVS : MIR_UDIVS); + return (t == MIR_T_F ? MIR_FDIV + : t == MIR_T_D ? MIR_DDIV + : t == MIR_T_LD ? MIR_LDDIV + : t == MIR_T_I64 ? MIR_DIV + : t == MIR_T_U64 ? MIR_UDIV + : t == MIR_T_I32 ? MIR_DIVS + : MIR_UDIVS); case N_MOD: case N_MOD_ASSIGN: - return (t == MIR_T_I64 ? MIR_MOD - : t == MIR_T_U64 ? MIR_UMOD : t == MIR_T_I32 ? MIR_MODS : MIR_UMODS); + return (t == MIR_T_I64 ? MIR_MOD + : t == MIR_T_U64 ? MIR_UMOD + : t == MIR_T_I32 ? MIR_MODS + : MIR_UMODS); case N_AND: case N_AND_ASSIGN: return (t == MIR_T_I64 || t == MIR_T_U64 ? MIR_AND : MIR_ANDS); case N_OR: @@ -10389,60 +10422,54 @@ static MIR_insn_code_t get_mir_type_insn_code (c2m_ctx_t c2m_ctx, struct type *t case N_LSH_ASSIGN: return (t == MIR_T_I64 || t == MIR_T_U64 ? MIR_LSH : MIR_LSHS); case N_RSH: case N_RSH_ASSIGN: - return (t == MIR_T_I64 ? MIR_RSH - : t == MIR_T_U64 ? MIR_URSH : t == MIR_T_I32 ? MIR_RSHS : MIR_URSHS); + return (t == MIR_T_I64 ? MIR_RSH + : t == MIR_T_U64 ? MIR_URSH + : t == MIR_T_I32 ? MIR_RSHS + : MIR_URSHS); case N_EQ: - return (t == MIR_T_F - ? MIR_FEQ - : t == MIR_T_D - ? MIR_DEQ - : t == MIR_T_LD ? MIR_LDEQ : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_EQ : MIR_EQS); + return (t == MIR_T_F ? MIR_FEQ + : t == MIR_T_D ? MIR_DEQ + : t == MIR_T_LD ? MIR_LDEQ + : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_EQ + : MIR_EQS); case N_NE: - return (t == MIR_T_F - ? MIR_FNE - : t == MIR_T_D - ? MIR_DNE - : t == MIR_T_LD ? MIR_LDNE : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_NE : MIR_NES); + return (t == MIR_T_F ? MIR_FNE + : t == MIR_T_D ? MIR_DNE + : t == MIR_T_LD ? MIR_LDNE + : t == MIR_T_I64 || t == MIR_T_U64 ? MIR_NE + : MIR_NES); case N_LT: - return (t == MIR_T_F - ? MIR_FLT - : t == MIR_T_D - ? MIR_DLT - : t == MIR_T_LD - ? MIR_LDLT - : t == MIR_T_I64 - ? MIR_LT - : t == MIR_T_U64 ? MIR_ULT : t == MIR_T_I32 ? MIR_LTS : MIR_ULTS); + return (t == MIR_T_F ? MIR_FLT + : t == MIR_T_D ? MIR_DLT + : t == MIR_T_LD ? MIR_LDLT + : t == MIR_T_I64 ? MIR_LT + : t == MIR_T_U64 ? MIR_ULT + : t == MIR_T_I32 ? MIR_LTS + : MIR_ULTS); case N_LE: - return (t == MIR_T_F - ? MIR_FLE - : t == MIR_T_D - ? MIR_DLE - : t == MIR_T_LD - ? MIR_LDLE - : t == MIR_T_I64 - ? MIR_LE - : t == MIR_T_U64 ? MIR_ULE : t == MIR_T_I32 ? MIR_LES : MIR_ULES); + return (t == MIR_T_F ? MIR_FLE + : t == MIR_T_D ? MIR_DLE + : t == MIR_T_LD ? MIR_LDLE + : t == MIR_T_I64 ? MIR_LE + : t == MIR_T_U64 ? MIR_ULE + : t == MIR_T_I32 ? MIR_LES + : MIR_ULES); case N_GT: - return (t == MIR_T_F - ? MIR_FGT - : t == MIR_T_D - ? MIR_DGT - : t == MIR_T_LD - ? MIR_LDGT - : t == MIR_T_I64 - ? MIR_GT - : t == MIR_T_U64 ? MIR_UGT : t == MIR_T_I32 ? MIR_GTS : MIR_UGTS); + return (t == MIR_T_F ? MIR_FGT + : t == MIR_T_D ? MIR_DGT + : t == MIR_T_LD ? MIR_LDGT + : t == MIR_T_I64 ? MIR_GT + : t == MIR_T_U64 ? MIR_UGT + : t == MIR_T_I32 ? MIR_GTS + : MIR_UGTS); case N_GE: - return (t == MIR_T_F - ? MIR_FGE - : t == MIR_T_D - ? MIR_DGE - : t == MIR_T_LD - ? MIR_LDGE - : t == MIR_T_I64 - ? MIR_GE - : t == MIR_T_U64 ? MIR_UGE : t == MIR_T_I32 ? MIR_GES : MIR_UGES); + return (t == MIR_T_F ? MIR_FGE + : t == MIR_T_D ? MIR_DGE + : t == MIR_T_LD ? MIR_LDGE + : t == MIR_T_I64 ? MIR_GE + : t == MIR_T_U64 ? MIR_UGE + : t == MIR_T_I32 ? MIR_GES + : MIR_UGES); default: assert (FALSE); return MIR_INSN_BOUND; } } @@ -10505,7 +10532,8 @@ static MIR_label_t get_label (c2m_ctx_t c2m_ctx, node_t target) { } static void top_gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_t false_label) { - gen (c2m_ctx, r, true_label, false_label, FALSE, NULL); + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + top_gen_last_op = gen (c2m_ctx, r, true_label, false_label, FALSE, NULL); } static op_t modify_for_block_move (c2m_ctx_t c2m_ctx, op_t mem, op_t index) { @@ -10566,16 +10594,13 @@ static const char *get_reg_var_name (c2m_ctx_t c2m_ctx, MIR_type_t promoted_type char prefix[50]; sprintf (prefix, - promoted_type == MIR_T_I64 - ? "I%u_" - : promoted_type == MIR_T_U64 - ? "U%u_" - : promoted_type == MIR_T_I32 - ? "i%u_" - : promoted_type == MIR_T_U32 - ? "u%u_" - : promoted_type == MIR_T_F ? "f%u_" - : promoted_type == MIR_T_D ? "d%u_" : "D%u_", + promoted_type == MIR_T_I64 ? "I%u_" + : promoted_type == MIR_T_U64 ? "U%u_" + : promoted_type == MIR_T_I32 ? "i%u_" + : promoted_type == MIR_T_U32 ? "u%u_" + : promoted_type == MIR_T_F ? "f%u_" + : promoted_type == MIR_T_D ? "d%u_" + : "D%u_", func_scope_num); VARR_TRUNC (char, temp_string, 0); add_to_temp_string (c2m_ctx, prefix); @@ -10735,8 +10760,9 @@ static MIR_UNUSED const char *gen_get_indexed_name (c2m_ctx_t c2m_ctx, const cha } /* Can be used by target functions */ -static inline void gen_multiple_load_store (c2m_ctx_t c2m_ctx, struct type *type, MIR_op_t *var_ops, - MIR_op_t mem_op, int load_p) { +static inline void MIR_UNUSED gen_multiple_load_store (c2m_ctx_t c2m_ctx, struct type *type, + MIR_op_t *var_ops, MIR_op_t mem_op, + int load_p) { gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_op_t op, var_op; @@ -10964,6 +10990,7 @@ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type assert (initializer->code == N_STR || initializer->code == N_STR16 || initializer->code == N_STR32 || !const_only_p || cexpr->const_p || cexpr->const_addr_p || (literal != NULL && addr_p)); + init_el.c2m_ctx = c2m_ctx; init_el.num = VARR_LENGTH (init_el_t, init_els); init_el.offset = get_object_path_offset (c2m_ctx); init_el.member_decl = member_decl; @@ -10981,6 +11008,7 @@ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type && ((str = NL_EL (init->u.ops, 1))->code == N_STR || str->code == N_STR16 || str->code == N_STR32))) && type->mode == TM_ARR && init_compatible_string_p (str, type->u.arr_type->el_type)) { + init_el.c2m_ctx = c2m_ctx; init_el.num = VARR_LENGTH (init_el_t, init_els); init_el.offset = get_object_path_offset (c2m_ctx); init_el.member_decl = NULL; @@ -11024,7 +11052,7 @@ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type assert (ok_p); } else { struct type *curr_type = type; - mir_llong arr_size_val; + mir_llong arr_size_val MIR_UNUSED; int first_p = TRUE; VARR_TRUNC (init_object_t, init_object_path, mark + 1); @@ -11093,10 +11121,16 @@ static int cmp_init_el (const void *p1, const void *p2) { else if (el1->member_decl != NULL && el2->member_decl != NULL && el1->member_decl->bit_offset > el2->member_decl->bit_offset) return 1; - else if (el1->num < el2->num) + else if (el1->member_decl != NULL + && type_size (el1->c2m_ctx, el1->member_decl->decl_spec.type) == 0) + return -1; + else if (el2->member_decl != NULL + && type_size (el2->c2m_ctx, el2->member_decl->decl_spec.type) == 0) return 1; - else if (el1->num > el2->num) + else if (el1->num < el2->num) return -1; + else if (el1->num > el2->num) + return 1; else return 0; } @@ -11318,7 +11352,7 @@ static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, init_el_t init_el, next_init_el; MIR_reg_t base; MIR_type_t t; - MIR_item_t data; + MIR_item_t data = NULL; /* to remove a warning */ struct expr *e; if (var.mir_op.mode == MIR_OP_REG) { /* scalar initialization: */ @@ -11344,13 +11378,10 @@ static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, val = gen (c2m_ctx, init_el.init, NULL, NULL, t != MIR_T_UNDEF, t != MIR_T_UNDEF ? NULL : &val); if (!scalar_type_p (init_el.el_type)) { - mir_size_t s = init_el.init->code == N_STR - ? init_el.init->u.s.len - : init_el.init->code == N_STR16 - ? init_el.init->u.s.len / 2 - : init_el.init->code == N_STR32 - ? init_el.init->u.s.len / 4 - : raw_type_size (c2m_ctx, init_el.el_type); + mir_size_t s = init_el.init->code == N_STR ? init_el.init->u.s.len + : init_el.init->code == N_STR16 ? init_el.init->u.s.len / 2 + : init_el.init->code == N_STR32 ? init_el.init->u.s.len / 4 + : raw_type_size (c2m_ctx, init_el.el_type); gen_memcpy (c2m_ctx, offset + rel_offset, base, val, s); rel_offset = init_el.offset + s; } else { @@ -11605,9 +11636,9 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ ld = r->u.ld; float_val: mir_type = get_mir_type (c2m_ctx, ((struct expr *) r->attr)->type); - res = new_op (NULL, (mir_type == MIR_T_F ? MIR_new_float_op (ctx, ld) - : mir_type == MIR_T_D ? MIR_new_double_op (ctx, ld) - : MIR_new_ldouble_op (ctx, ld))); + res = new_op (NULL, (mir_type == MIR_T_F ? MIR_new_float_op (ctx, ld) + : mir_type == MIR_T_D ? MIR_new_double_op (ctx, ld) + : MIR_new_ldouble_op (ctx, ld))); break; case N_CH: ll = r->u.ch; goto int_val; case N_CH16: @@ -11701,15 +11732,17 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ gen_unary_op (c2m_ctx, r, &op1, &res); if (r->code == N_ADD) { - ic = (ic == MIR_FADD ? MIR_FMOV - : ic == MIR_DADD ? MIR_DMOV : ic == MIR_LDADD ? MIR_LDMOV : MIR_MOV); + ic = (ic == MIR_FADD ? MIR_FMOV + : ic == MIR_DADD ? MIR_DMOV + : ic == MIR_LDADD ? MIR_LDMOV + : MIR_MOV); emit2 (c2m_ctx, ic, res.mir_op, op1.mir_op); } else { - ic - = (ic == MIR_FSUB - ? MIR_FNEG - : ic == MIR_DSUB ? MIR_DNEG - : ic == MIR_LDSUB ? MIR_LDNEG : ic == MIR_SUB ? MIR_NEG : MIR_NEGS); + ic = (ic == MIR_FSUB ? MIR_FNEG + : ic == MIR_DSUB ? MIR_DNEG + : ic == MIR_LDSUB ? MIR_LDNEG + : ic == MIR_SUB ? MIR_NEG + : MIR_NEGS); emit2 (c2m_ctx, ic, res.mir_op, op1.mir_op); } break; @@ -12130,13 +12163,15 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ res.mir_op = MIR_new_mem_op (ctx, MIR_T_UNDEF, 0, res.mir_op.u.mem.base, 0, 1); t = MIR_T_I64; } else if (type->mode == TM_STRUCT || type->mode == TM_UNION) { /* passed in regs */ - res = get_new_temp (c2m_ctx, MIR_T_I64); - emit3 (c2m_ctx, MIR_ADD, res.mir_op, - MIR_new_reg_op (ctx, MIR_reg (ctx, FP_NAME, curr_func->u.func)), - MIR_new_int_op (ctx, arg_area_offset)); - if (!builtin_call_p) update_call_arg_area_offset (c2m_ctx, type, FALSE); - res.mir_op = MIR_new_mem_op (ctx, MIR_T_UNDEF, 0, res.mir_op.u.reg, 0, 1); - t = MIR_T_I64; + if (!va_arg_p) { + res = get_new_temp (c2m_ctx, MIR_T_I64); + emit3 (c2m_ctx, MIR_ADD, res.mir_op, + MIR_new_reg_op (ctx, MIR_reg (ctx, FP_NAME, curr_func->u.func)), + MIR_new_int_op (ctx, arg_area_offset)); + if (!builtin_call_p) update_call_arg_area_offset (c2m_ctx, type, FALSE); + res.mir_op = MIR_new_mem_op (ctx, MIR_T_UNDEF, 0, res.mir_op.u.reg, 0, 1); + t = MIR_T_I64; + } } else if (n > 0) { assert (n == 1); t = promote_mir_int_type (get_mir_type (c2m_ctx, type)); @@ -12430,6 +12465,11 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ finish_curr_func_reg_vars (c2m_ctx); break; } + case N_STMTEXPR: { + gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); + res = top_gen_last_op; + break; + } case N_BLOCK: emit_label (c2m_ctx, r); gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, FALSE, NULL); @@ -12839,7 +12879,7 @@ static const char *get_node_name (node_code_t code) { C (IGNORE); REP8 (C, I, L, LL, U, UL, ULL, F, D); REP7 (C, LD, CH, CH16, CH32, STR, STR16, STR32); - REP5 (C, ID, COMMA, ANDAND, OROR, EQ); + REP6 (C, ID, COMMA, ANDAND, OROR, EQ, STMTEXPR); REP8 (C, NE, LT, LE, GT, GE, ASSIGN, BITWISE_NOT, NOT); REP8 (C, AND, AND_ASSIGN, OR, OR_ASSIGN, XOR, XOR_ASSIGN, LSH, LSH_ASSIGN); REP8 (C, RSH, RSH_ASSIGN, ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN); @@ -13047,9 +13087,9 @@ static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int at case N_STR16: case N_STR32: fprintf (f, " %s\"", n->code == N_STR ? "" : n->code == N_STR16 ? "u" : "U"); - (n->code == N_STR - ? print_chars - : n->code == N_STR16 ? print_chars16 : print_chars32) (f, n->u.s.s, n->u.s.len); + (n->code == N_STR ? print_chars + : n->code == N_STR16 ? print_chars16 + : print_chars32) (f, n->u.s.s, n->u.s.len); fprintf (f, "\""); goto expr; case N_ID: @@ -13107,6 +13147,7 @@ static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int at case N_COMPOUND_LITERAL: case N_CALL: case N_GENERIC: + case N_STMTEXPR: if (attr_p && n->attr != NULL) print_expr (c2m_ctx, f, n->attr); fprintf (f, "\n"); print_ops (c2m_ctx, f, n, indent, attr_p); diff --git a/mir/c2mir/ppc64/cppc64-ABI-code.c b/mir/c2mir/ppc64/cppc64-ABI-code.c index 687f67eb..0f6762d9 100644 --- a/mir/c2mir/ppc64/cppc64-ABI-code.c +++ b/mir/c2mir/ppc64/cppc64-ABI-code.c @@ -14,7 +14,6 @@ static MIR_type_t fp_homogeneous_type (c2m_ctx_t c2m_ctx, struct type *param_typ #else static MIR_type_t fp_homogeneous_type_1 (c2m_ctx_t c2m_ctx, MIR_type_t curr_type, struct type *type, int *num) { - gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; int n; MIR_type_t t; @@ -186,7 +185,7 @@ static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t r MIR_insn_t insn; MIR_reg_t ret_addr_reg; op_t temp, var; - int i, n, size; + int n, size; if (void_type_p (ret_type)) return; if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D) @@ -251,7 +250,6 @@ static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, target_arg_info_t *arg_info, op_t arg) { gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; - MIR_var_t var; MIR_type_t type; op_t temp; int n; @@ -285,7 +283,6 @@ static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct ty decl_t param_decl, target_arg_info_t *arg_info) { gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; - MIR_var_t var; MIR_type_t type; reg_var_t reg_var; int i, n; diff --git a/mir/c2mir/ppc64/mirc_ppc64_linux.h b/mir/c2mir/ppc64/mirc_ppc64_linux.h index 7299397c..6202854a 100644 --- a/mir/c2mir/ppc64/mirc_ppc64_linux.h +++ b/mir/c2mir/ppc64/mirc_ppc64_linux.h @@ -62,6 +62,8 @@ static char ppc64_mirc[] "#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n" "#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n" "#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n" + "#define __WCHAR_MAX__ 0x7fffffff\n" + "#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)\n" "#define __SCHAR_MAX__ __INT8_MAX__\n" "#define __SHRT_MAX__ __INT16_MAX__\n" "#define __INT_MAX__ __INT32_MAX__\n" diff --git a/mir/c2mir/ppc64/mirc_ppc64_stddef.h b/mir/c2mir/ppc64/mirc_ppc64_stddef.h index ac4207de..85275b1c 100644 --- a/mir/c2mir/ppc64/mirc_ppc64_stddef.h +++ b/mir/c2mir/ppc64/mirc_ppc64_stddef.h @@ -10,7 +10,7 @@ static char stddef_str[] "typedef long ptrdiff_t;\n" "typedef unsigned long size_t;\n" "typedef long double max_align_t;\n" - "typedef unsigned int wchar_t;\n" + "typedef int wchar_t;\n" "\n" "#define NULL ((void *) 0)\n" "\n" diff --git a/mir/c2mir/ppc64/mirc_ppc64_stdint.h b/mir/c2mir/ppc64/mirc_ppc64_stdint.h index d089d6fa..ec968c34 100644 --- a/mir/c2mir/ppc64/mirc_ppc64_stdint.h +++ b/mir/c2mir/ppc64/mirc_ppc64_stdint.h @@ -108,9 +108,12 @@ static char stdint_str[] "\n" "#define SIZE_MAX (18446744073709551615UL)\n" "\n" - "/* For signed wchar_t and wint_t: */\n" - "#define WCHAR_MIN INT32_MIN\n" - "#define WCHAR_MAX INT32_MAX\n" + "#ifndef WCHAR_MAX\n" + "#define WCHAR_MAX __WCHAR_MAX__\n" + "#endif\n" + "#ifndef WCHAR_MIN\n" + "#define WCHAR_MIN __WCHAR_MIN__\n" + "#endif\n" "#define WINT_MIN WCHAR_MIN\n" "#define WINT_MAX WCHAR_MAX\n" "\n" diff --git a/mir/c2mir/riscv64/mirc_riscv64_linux.h b/mir/c2mir/riscv64/mirc_riscv64_linux.h index f421403a..81e46935 100644 --- a/mir/c2mir/riscv64/mirc_riscv64_linux.h +++ b/mir/c2mir/riscv64/mirc_riscv64_linux.h @@ -59,6 +59,8 @@ static char riscv64_mirc[] "#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n" "#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n" "#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n" + "#define __WCHAR_MAX__ 0x7fffffff\n" + "#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)\n" "#define __SCHAR_MAX__ __INT8_MAX__\n" "#define __SHRT_MAX__ __INT16_MAX__\n" "#define __INT_MAX__ __INT32_MAX__\n" diff --git a/mir/c2mir/riscv64/mirc_riscv64_stdint.h b/mir/c2mir/riscv64/mirc_riscv64_stdint.h index d089d6fa..ec968c34 100644 --- a/mir/c2mir/riscv64/mirc_riscv64_stdint.h +++ b/mir/c2mir/riscv64/mirc_riscv64_stdint.h @@ -108,9 +108,12 @@ static char stdint_str[] "\n" "#define SIZE_MAX (18446744073709551615UL)\n" "\n" - "/* For signed wchar_t and wint_t: */\n" - "#define WCHAR_MIN INT32_MIN\n" - "#define WCHAR_MAX INT32_MAX\n" + "#ifndef WCHAR_MAX\n" + "#define WCHAR_MAX __WCHAR_MAX__\n" + "#endif\n" + "#ifndef WCHAR_MIN\n" + "#define WCHAR_MIN __WCHAR_MIN__\n" + "#endif\n" "#define WINT_MIN WCHAR_MIN\n" "#define WINT_MAX WCHAR_MAX\n" "\n" diff --git a/mir/c2mir/s390x/cs390x-ABI-code.c b/mir/c2mir/s390x/cs390x-ABI-code.c index 5842f536..b10963ff 100644 --- a/mir/c2mir/s390x/cs390x-ABI-code.c +++ b/mir/c2mir/s390x/cs390x-ABI-code.c @@ -82,7 +82,6 @@ static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct ty decl_t param_decl, target_arg_info_t *arg_info) { gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; - MIR_type_t type; MIR_op_t param_op; reg_var_t reg_var; diff --git a/mir/c2mir/s390x/mirc_s390x_linux.h b/mir/c2mir/s390x/mirc_s390x_linux.h index 2ef660be..41f5a33d 100644 --- a/mir/c2mir/s390x/mirc_s390x_linux.h +++ b/mir/c2mir/s390x/mirc_s390x_linux.h @@ -56,6 +56,8 @@ static char s390x_mirc[] "#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n" "#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n" "#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n" + "#define __WCHAR_MAX__ 0x7fffffff\n" + "#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)\n" "#define __SCHAR_MAX__ __INT8_MAX__\n" "#define __SHRT_MAX__ __INT16_MAX__\n" "#define __INT_MAX__ __INT32_MAX__\n" diff --git a/mir/c2mir/s390x/mirc_s390x_stddef.h b/mir/c2mir/s390x/mirc_s390x_stddef.h index ac4207de..85275b1c 100644 --- a/mir/c2mir/s390x/mirc_s390x_stddef.h +++ b/mir/c2mir/s390x/mirc_s390x_stddef.h @@ -10,7 +10,7 @@ static char stddef_str[] "typedef long ptrdiff_t;\n" "typedef unsigned long size_t;\n" "typedef long double max_align_t;\n" - "typedef unsigned int wchar_t;\n" + "typedef int wchar_t;\n" "\n" "#define NULL ((void *) 0)\n" "\n" diff --git a/mir/c2mir/s390x/mirc_s390x_stdint.h b/mir/c2mir/s390x/mirc_s390x_stdint.h index d089d6fa..ec968c34 100644 --- a/mir/c2mir/s390x/mirc_s390x_stdint.h +++ b/mir/c2mir/s390x/mirc_s390x_stdint.h @@ -108,9 +108,12 @@ static char stdint_str[] "\n" "#define SIZE_MAX (18446744073709551615UL)\n" "\n" - "/* For signed wchar_t and wint_t: */\n" - "#define WCHAR_MIN INT32_MIN\n" - "#define WCHAR_MAX INT32_MAX\n" + "#ifndef WCHAR_MAX\n" + "#define WCHAR_MAX __WCHAR_MAX__\n" + "#endif\n" + "#ifndef WCHAR_MIN\n" + "#define WCHAR_MIN __WCHAR_MIN__\n" + "#endif\n" "#define WINT_MIN WCHAR_MIN\n" "#define WINT_MAX WCHAR_MAX\n" "\n" diff --git a/mir/c2mir/x86_64/mirc_x86_64_linux.h b/mir/c2mir/x86_64/mirc_x86_64_linux.h index 09a97048..63e05c90 100644 --- a/mir/c2mir/x86_64/mirc_x86_64_linux.h +++ b/mir/c2mir/x86_64/mirc_x86_64_linux.h @@ -50,6 +50,12 @@ static char x86_64_mirc[] "#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n" "#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n" "#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n" +#if defined(__linux__) + "#define __WCHAR_MAX__ 0x7fffffff\n" +#else + "#define __WCHAR_MAX__ 2147483647\n" +#endif + "#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)\n" "#define __SCHAR_MAX__ __INT8_MAX__\n" "#define __SHRT_MAX__ __INT16_MAX__\n" "#define __INT_MAX__ __INT32_MAX__\n" diff --git a/mir/c2mir/x86_64/mirc_x86_64_stddef.h b/mir/c2mir/x86_64/mirc_x86_64_stddef.h index b50aa577..c365f8b2 100644 --- a/mir/c2mir/x86_64/mirc_x86_64_stddef.h +++ b/mir/c2mir/x86_64/mirc_x86_64_stddef.h @@ -15,12 +15,10 @@ static char stddef_str[] "typedef unsigned long size_t;\n" #endif "typedef long double max_align_t;\n" -#if defined(__APPLE__) - "typedef int wchar_t;\n" -#elif defined(_WIN32) +#if defined(_WIN32) "typedef unsigned short wchar_t;\n" #else - "typedef unsigned int wchar_t;\n" + "typedef int wchar_t;\n" #endif "\n" #if !defined(__APPLE__) && !defined(_WIN32) diff --git a/mir/c2mir/x86_64/mirc_x86_64_stdint.h b/mir/c2mir/x86_64/mirc_x86_64_stdint.h index bb5cc54b..25e6520a 100644 --- a/mir/c2mir/x86_64/mirc_x86_64_stdint.h +++ b/mir/c2mir/x86_64/mirc_x86_64_stdint.h @@ -140,9 +140,12 @@ static char stdint_str[] "\n" "#define SIZE_MAX (18446744073709551615UL)\n" "\n" - "/* For signed wchar_t and wint_t: */\n" - "#define WCHAR_MIN INT32_MIN\n" - "#define WCHAR_MAX INT32_MAX\n" + "#ifndef WCHAR_MAX\n" + "#define WCHAR_MAX __WCHAR_MAX__\n" + "#endif\n" + "#ifndef WCHAR_MIN\n" + "#define WCHAR_MIN __WCHAR_MIN__\n" + "#endif\n" "#define WINT_MIN WCHAR_MIN\n" "#define WINT_MAX WCHAR_MAX\n" "\n" diff --git a/mir/mir-aarch64.c b/mir/mir-aarch64.c index 222707f0..95d1dfea 100644 --- a/mir/mir-aarch64.c +++ b/mir/mir-aarch64.c @@ -18,7 +18,7 @@ /* Any small BLK type (less or equal to two quadwords) args are passed in *fully* regs or on stack (w/o address), otherwise it is put - somehwere on stack and its address passed instead. First RBLK arg + somewhere on stack and its address passed instead. First RBLK arg is passed in r8. Other RBLK independently of size is always passed by address as an usual argument. */ @@ -66,7 +66,6 @@ struct aarch64_va_list { void *va_arg_builtin (void *p, uint64_t t) { struct aarch64_va_list *va = p; MIR_type_t type = t; - int fp_p = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD; #if defined(__APPLE__) void *a = va->arg_area; @@ -79,6 +78,7 @@ void *va_arg_builtin (void *p, uint64_t t) { if (type == MIR_T_F || type == MIR_T_I32) a = (char *) a + 4; /* 2nd word of doubleword */ #endif #else + int fp_p = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD; void *a; if (fp_p && va->__vr_offs < 0) { @@ -318,7 +318,6 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s MIR_type_t type; uint32_t n_xregs = 0, n_vregs = 0, sp_offset = 0, blk_offset = 0, pat, offset_imm, scale; uint32_t sp = 31, addr_reg, qwords; - uint32_t *addr; const uint32_t temp_reg = 10; /* x10 */ VARR (uint8_t) * code; void *res; @@ -460,15 +459,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s /* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item, va_list va, MIR_val_t *results) */ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handler) { - static const uint32_t temp_reg = 10; /* x10 */ - static const uint32_t save_x19_pat = 0xf81f0ff3; /* str x19, [sp,-16]! */ - static const uint32_t add_x2_sp = 0x910003e2; /* add x2, sp, X*/ - static const uint32_t set_gr_offs = 0x128007e9; /* mov w9, #-64 # gr_offs */ - static const uint32_t set_x8_gr_offs = 0x128008e9; /* mov w9, #-72 # gr_offs */ - static const uint32_t arg_mov_start_pat[] = { - 0x910003e9, /* mov x9,sp */ - 0xd10003ff, /* sub sp, sp, # non-varg */ - }; + static const uint32_t save_x19_pat = 0xf81f0ff3; /* str x19, [sp,-16]! */ static const uint32_t prepare_pat[] = { #if !defined(__APPLE__) 0xd10083ff, /* sub sp, sp, 32 # allocate va_list */ @@ -509,17 +500,22 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl uint32_t pat, imm, n_xregs, n_vregs, offset, offset_imm; MIR_func_t func = func_item->u.func; uint32_t nres = func->nres; - int x8_res_p = func->nargs != 0 && VARR_GET (MIR_var_t, func->vars, 0).type == MIR_T_RBLK; MIR_type_t *results = func->res_types; VARR (uint8_t) * code; void *res; - uint32_t base_reg_mask = ~(uint32_t) (0x3f << 5); VARR_CREATE (uint8_t, code, 128); #if defined(__APPLE__) int stack_arg_sp_offset, sp_offset, scale; uint32_t qwords, sp = 31; + uint32_t base_reg_mask = ~(uint32_t) (0x3f << 5); + static const uint32_t temp_reg = 10; /* x10 */ MIR_type_t type; + static const uint32_t add_x2_sp = 0x910003e2; /* add x2, sp, X*/ + static const uint32_t arg_mov_start_pat[] = { + 0x910003e9, /* mov x9,sp */ + 0xd10003ff, /* sub sp, sp, # non-varg */ + }; assert (__SIZEOF_LONG_DOUBLE__ == 8); push_insns (code, arg_mov_start_pat, sizeof (arg_mov_start_pat)); @@ -605,6 +601,9 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl ((uint32_t *) VARR_ADDR (uint8_t, code))[1] |= sp_offset << 10; push_insns (code, &save_x19_pat, sizeof (save_x19_pat)); #else + static const uint32_t set_gr_offs = 0x128007e9; /* mov w9, #-64 # gr_offs */ + static const uint32_t set_x8_gr_offs = 0x128008e9; /* mov w9, #-72 # gr_offs */ + int x8_res_p = func->nargs != 0 && VARR_GET (MIR_var_t, func->vars, 0).type == MIR_T_RBLK; push_insns (code, &save_x19_pat, sizeof (save_x19_pat)); push_insns (code, save_insns, sizeof (save_insns)); if (x8_res_p) diff --git a/mir/mir-gen-aarch64.c b/mir/mir-gen-aarch64.c index a70059a3..f34419de 100644 --- a/mir/mir-gen-aarch64.c +++ b/mir/mir-gen-aarch64.c @@ -196,7 +196,6 @@ static MIR_op_t get_new_hard_reg_mem_op (gen_ctx_t gen_ctx, MIR_type_t type, MIR static MIR_op_t new_hard_reg_mem_op (gen_ctx_t gen_ctx, MIR_insn_t anchor, MIR_type_t type, MIR_disp_t disp, MIR_reg_t base) { - MIR_context_t ctx = gen_ctx->ctx; MIR_insn_t insn1, insn2; MIR_op_t op = get_new_hard_reg_mem_op (gen_ctx, type, disp, base, &insn1, &insn2); if (insn1 != NULL) gen_add_insn_before (gen_ctx, anchor, insn1); @@ -431,10 +430,9 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { if (type == MIR_T_LD && __SIZEOF_LONG_DOUBLE__ == 16 && mem_size % 16 != 0) mem_size = (mem_size + 15) / 16 * 16; mem_type = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD ? type : MIR_T_I64; - new_insn_code = (type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : type == MIR_T_LD ? MIR_LDMOV - : MIR_MOV); + new_insn_code + = (type == MIR_T_F ? MIR_FMOV + : type == MIR_T_D ? MIR_DMOV : type == MIR_T_LD ? MIR_LDMOV : MIR_MOV); mem_op = get_new_hard_reg_mem_op (gen_ctx, mem_type, mem_size, SP_HARD_REG, &insn1, &insn2); if (type != MIR_T_RBLK) { new_insn = MIR_new_insn (ctx, new_insn_code, mem_op, arg_op); @@ -468,11 +466,9 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { type = proto->res_types[i]; float_p = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD; if (float_p && n_vregs < 8) { - new_insn = MIR_new_insn (ctx, - type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV, - ret_reg_op, _MIR_new_hard_reg_op (ctx, V0_HARD_REG + n_vregs)); + new_insn + = MIR_new_insn (ctx, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV, + ret_reg_op, _MIR_new_hard_reg_op (ctx, V0_HARD_REG + n_vregs)); n_vregs++; } else if (!float_p && n_iregs < 8) { new_insn = MIR_new_insn (ctx, MIR_MOV, ret_reg_op, @@ -861,10 +857,9 @@ static void target_machinize (gen_ctx_t gen_ctx) { } mem_type = type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD ? type : MIR_T_I64; if (type == MIR_T_LD) mem_size = (mem_size + 15) / 16 * 16; - new_insn_code = (type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : type == MIR_T_LD ? MIR_LDMOV - : MIR_MOV); + new_insn_code + = (type == MIR_T_F ? MIR_FMOV + : type == MIR_T_D ? MIR_DMOV : type == MIR_T_LD ? MIR_LDMOV : MIR_MOV); mem_op = new_hard_reg_mem_op (gen_ctx, anchor, mem_type, mem_size, R8_HARD_REG); gen_mov (gen_ctx, anchor, new_insn_code, MIR_new_reg_op (ctx, i + 1), mem_op); mem_size += type == MIR_T_LD ? 16 : 8; @@ -881,12 +876,13 @@ static void target_machinize (gen_ctx_t gen_ctx) { if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE || code == MIR_LDBGT || code == MIR_LDBLE) { temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func)); - code = (code == MIR_LDBEQ ? MIR_LDEQ - : code == MIR_LDBNE ? MIR_LDNE - : code == MIR_LDBLT ? MIR_LDLT - : code == MIR_LDBGE ? MIR_LDGE - : code == MIR_LDBGT ? MIR_LDGT - : MIR_LDLE); + code = (code == MIR_LDBEQ + ? MIR_LDEQ + : code == MIR_LDBNE + ? MIR_LDNE + : code == MIR_LDBLT + ? MIR_LDLT + : code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE); new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]); gen_add_insn_before (gen_ctx, insn, new_insn); next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op); @@ -1012,9 +1008,8 @@ static void target_machinize (gen_ctx_t gen_ctx) { assert (insn->ops[i].mode == MIR_OP_REG); res_type = func->res_types[i]; if ((res_type == MIR_T_F || res_type == MIR_T_D || res_type == MIR_T_LD) && n_vregs < 8) { - new_insn_code = res_type == MIR_T_F ? MIR_FMOV - : res_type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV; + new_insn_code + = res_type == MIR_T_F ? MIR_FMOV : res_type == MIR_T_D ? MIR_DMOV : MIR_LDMOV; ret_reg = V0_HARD_REG + n_vregs++; } else if (n_iregs < 8) { new_insn_code = MIR_MOV; @@ -1031,6 +1026,7 @@ static void target_machinize (gen_ctx_t gen_ctx) { } } +#if !defined(__APPLE__) static void isave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t base, MIR_reg_t hard_reg) { gen_mov (gen_ctx, anchor, MIR_MOV, new_hard_reg_mem_op (gen_ctx, anchor, MIR_T_I64, disp, base), @@ -1042,6 +1038,7 @@ static void fsave (gen_ctx_t gen_ctx, MIR_insn_t anchor, int disp, MIR_reg_t bas gen_mov (gen_ctx, anchor, MIR_LDMOV, new_hard_reg_mem_op (gen_ctx, anchor, MIR_T_LD, disp, base), _MIR_new_hard_reg_op (gen_ctx->ctx, hard_reg)); } +#endif static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_regs, size_t stack_slots_num) { @@ -1049,7 +1046,6 @@ static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_reg MIR_func_t func; MIR_insn_t anchor, new_insn; MIR_op_t sp_reg_op, fp_reg_op, treg_op, treg_op2; - int64_t start; int save_prev_stack_p; size_t i, offset, frame_size, frame_size_after_saved_regs, saved_iregs_num, saved_fregs_num; @@ -1094,10 +1090,10 @@ static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_reg frame_size += 16; } frame_size += 16; /* lr/fp */ + treg_op2 = _MIR_new_hard_reg_op (ctx, R10_HARD_REG); if (frame_size < (1 << 12)) { new_insn = MIR_new_insn (ctx, MIR_SUB, sp_reg_op, sp_reg_op, MIR_new_int_op (ctx, frame_size)); } else { - treg_op2 = _MIR_new_hard_reg_op (ctx, R10_HARD_REG); new_insn = MIR_new_insn (ctx, MIR_MOV, treg_op2, MIR_new_int_op (ctx, frame_size)); gen_add_insn_before (gen_ctx, anchor, new_insn); /* t = frame_size */ new_insn = MIR_new_insn (ctx, MIR_SUB, sp_reg_op, sp_reg_op, treg_op2); @@ -1117,6 +1113,7 @@ static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_reg #if !defined(__APPLE__) if (func->vararg_p) { // ??? saving only regs corresponding to ... MIR_reg_t base = SP_HARD_REG; + int64_t start; start = (int64_t) frame_size - reg_save_area_size; if ((start + 184) >= (1 << 12)) { @@ -1198,16 +1195,17 @@ static void target_make_prolog_epilog (gen_ctx_t gen_ctx, bitmap_t used_hard_reg /* Restore lr, sp, fp */ gen_mov (gen_ctx, anchor, MIR_MOV, _MIR_new_hard_reg_op (ctx, LINK_HARD_REG), _MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 8, FP_HARD_REG, MIR_NON_HARD_REG, 1)); + gen_mov (gen_ctx, anchor, MIR_MOV, treg_op2, fp_reg_op); /* r10 = fp */ + gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op, + _MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, FP_HARD_REG, MIR_NON_HARD_REG, 1)); if (frame_size < (1 << 12)) { - new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, MIR_new_int_op (ctx, frame_size)); + new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, treg_op2, MIR_new_int_op (ctx, frame_size)); } else { new_insn = MIR_new_insn (ctx, MIR_MOV, treg_op, MIR_new_int_op (ctx, frame_size)); - gen_add_insn_before (gen_ctx, anchor, new_insn); /* t = frame_size */ - new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, fp_reg_op, treg_op); + gen_add_insn_before (gen_ctx, anchor, new_insn); /* t(r9) = frame_size */ + new_insn = MIR_new_insn (ctx, MIR_ADD, sp_reg_op, treg_op2, treg_op); } - gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = fp + (frame_size|t) */ - gen_mov (gen_ctx, anchor, MIR_MOV, fp_reg_op, - _MIR_new_hard_reg_mem_op (ctx, MIR_T_I64, 0, FP_HARD_REG, MIR_NON_HARD_REG, 1)); + gen_add_insn_before (gen_ctx, anchor, new_insn); /* sp = r10 + (frame_size|t) */ } struct pattern { @@ -1249,8 +1247,8 @@ struct pattern { Mf - memory of float Md - memory of double Mld - memory of long double - I -- immediate as 3th op for arithemtic insn (12-bit unsigned with possible 12-bit LSL) - Iu -- immediate for arithemtic insn roundup to 16 + I -- immediate as 3th op for arithmetic insn (12-bit unsigned with possible 12-bit LSL) + Iu -- immediate for arithmetic insn roundup to 16 SR -- any immediate for right 64-bit shift (0-63) Sr -- any immediate for right 32-bit shift (0-31) SL -- any immediate for left 64-bit shift (0-63) @@ -1856,13 +1854,13 @@ static int arithm_roundup_const (uint64_t v, int *imm) { } /* Return immr for right 64-bit or 32-bit (if SHORT_P) shift by V. If the - shift can not be be represented, return FALSE. */ + shift can not be represented, return FALSE. */ static int rshift_const (int64_t v, int short_p) { return v < 0 || v > 63 || (short_p && v > 31) ? -1 : v; } /* Return immr and imms for left 64-bit or 32-bit (if SHORT_P) shift - by V. If the shift can not be be represented, return FALSE. */ + by V. If the shift can not be represented, return FALSE. */ static int lshift_const_p (int64_t v, int short_p, int *immr, int *imms) { if (short_p) { if (v < 0 || v > 31) return FALSE; @@ -2068,10 +2066,9 @@ static void patterns_finish (gen_ctx_t gen_ctx) { } static int hex_value (int ch) { - return ('0' <= ch && ch <= '9' ? ch - '0' - : 'A' <= ch && ch <= 'F' ? ch - 'A' + 10 - : 'a' <= ch && ch <= 'f' ? ch - 'a' + 10 - : -1); + return ('0' <= ch && ch <= '9' + ? ch - '0' + : 'A' <= ch && ch <= 'F' ? ch - 'A' + 10 : 'a' <= ch && ch <= 'f' ? ch - 'a' + 10 : -1); } static uint64_t read_hex (const char **ptr) { @@ -2364,8 +2361,10 @@ static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacemen opcode |= imm12_shift << 22; opcode_mask = check_and_set_mask (opcode_mask, 0x3 << 22); } - if (label_ref_num >= 0) VARR_ADDR (label_ref_t, label_refs) - [label_ref_num].label_val_disp = VARR_LENGTH (uint8_t, result_code); + if (label_ref_num >= 0) + VARR_ADDR (label_ref_t, label_refs) + [label_ref_num].label_val_disp + = VARR_LENGTH (uint8_t, result_code); if (switch_table_addr_p) switch_table_adr_insn_start = VARR_LENGTH (uint8_t, result_code); put_uint64 (gen_ctx, opcode, 4); /* output the machine insn */ diff --git a/mir/mir-gen-ppc64.c b/mir/mir-gen-ppc64.c index 69fd7472..049d67f9 100644 --- a/mir/mir-gen-ppc64.c +++ b/mir/mir-gen-ppc64.c @@ -88,7 +88,7 @@ static inline int target_call_used_hard_reg_p (MIR_reg_t hard_reg, MIR_type_t ty SP,R31->+-- Back chain (SP + 0) (SP + 0) Alloca area (after that new 48 or 32 bytes header should be created with new values) -Originaly SP(r1) and FP (r31) are the same but r1 can be changed by alloca */ +Originally SP(r1) and FP (r31) are the same but r1 can be changed by alloca */ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define PPC64_STACK_HEADER_SIZE 32 @@ -289,9 +289,7 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn); arg_reg_op = _MIR_new_hard_reg_op (ctx, F1_HARD_REG + n_fregs); gen_mov (gen_ctx, call_insn, - type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV, // ??? + type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV, // ??? arg_reg_op, arg_op); call_insn->ops[i] = arg_reg_op; if (vararg_p) { // ??? dead insns @@ -346,10 +344,9 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { call_insn->ops[i] = arg_reg_op; } else { /* put arguments on the stack */ if (ext_insn != NULL) gen_add_insn_before (gen_ctx, call_insn, ext_insn); - new_insn_code = (type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : type == MIR_T_LD ? MIR_LDMOV - : MIR_MOV); + new_insn_code + = (type == MIR_T_F ? MIR_FMOV + : type == MIR_T_D ? MIR_DMOV : type == MIR_T_LD ? MIR_LDMOV : MIR_MOV); mem_op = _MIR_new_hard_reg_mem_op (ctx, mem_type, mem_size + PPC64_STACK_HEADER_SIZE, SP_HARD_REG, MIR_NON_HARD_REG, 1); if (type != MIR_T_RBLK) { @@ -660,19 +657,13 @@ static void target_machinize (gen_ctx_t gen_ctx) { 1)); } arg_reg_op = _MIR_new_hard_reg_op (ctx, F1_HARD_REG + fp_arg_num); - gen_mov (gen_ctx, anchor, - type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV, + gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV, arg_var_op, arg_reg_op); /* (f|d|ld|)mov arg, arg_hard_reg */ fp_arg_num += type == MIR_T_LD ? 2 : 1; } else if (type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) { /* (f|d|ld|)mov arg, arg_memory */ set_prev_sp_op (gen_ctx, anchor, &prev_sp_op); - gen_mov (gen_ctx, anchor, - type == MIR_T_F ? MIR_FMOV - : type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV, + gen_mov (gen_ctx, anchor, type == MIR_T_F ? MIR_FMOV : type == MIR_T_D ? MIR_DMOV : MIR_LDMOV, arg_var_op, _MIR_new_hard_reg_mem_op (ctx, type, disp, R12_HARD_REG, MIR_NON_HARD_REG, 1)); } else if (MIR_blk_type_p (type)) { @@ -717,12 +708,13 @@ static void target_machinize (gen_ctx_t gen_ctx) { if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE || code == MIR_LDBGT || code == MIR_LDBLE) { /* split to cmp and branch */ temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func)); - code = (code == MIR_LDBEQ ? MIR_LDEQ - : code == MIR_LDBNE ? MIR_LDNE - : code == MIR_LDBLT ? MIR_LDLT - : code == MIR_LDBGE ? MIR_LDGE - : code == MIR_LDBGT ? MIR_LDGT - : MIR_LDLE); + code = (code == MIR_LDBEQ + ? MIR_LDEQ + : code == MIR_LDBNE + ? MIR_LDNE + : code == MIR_LDBLT + ? MIR_LDLT + : code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE); new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]); gen_add_insn_before (gen_ctx, insn, new_insn); next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op); @@ -815,9 +807,8 @@ static void target_machinize (gen_ctx_t gen_ctx) { res_type = func->res_types[i]; if (((res_type == MIR_T_F || res_type == MIR_T_D) && n_fregs < 4) || (res_type == MIR_T_LD && n_fregs < 3)) { - new_insn_code = res_type == MIR_T_F ? MIR_FMOV - : res_type == MIR_T_D ? MIR_DMOV - : MIR_LDMOV; + new_insn_code + = res_type == MIR_T_F ? MIR_FMOV : res_type == MIR_T_D ? MIR_DMOV : MIR_LDMOV; ret_reg = F1_HARD_REG + n_fregs++; } else if (n_gpregs < 8) { new_insn_code = MIR_MOV; @@ -964,7 +955,7 @@ struct pattern { I - 16 bit signed immediate shift left by 16 u - 16 bit unsigned immediate U - 16 bit unsigned immediate shift left by 16 - x - 64 bit unsigned immediate whose hight 32-bit part is described by pattern 0*1* + x - 64 bit unsigned immediate whose high 32-bit part is described by pattern 0*1* z - 32-bit unsigned immediate zs - 32-bit unsigned immediate with zero 0-th bit Z - any integer immediate @@ -1178,10 +1169,10 @@ static const struct pattern patterns[] = { #define CMPWI(i) "o11 bf7 L0 ra1 " #i #define FCMPU "o63 O0 bf7 ra1 rb2" #define CRNOT(s, f) "o19 O33 ht" #s " ha" #f " hb" #f ";" -#define CROR(t,a,b) "o19 O449 ht" #t " ha" #a " hb" #b ";" -#define CRORC(t,a,b) "o19 O417 ht" #t " ha" #a " hb" #b ";" -#define CRNOR(t,a,b) "o19 O33 ht" #t " ha" #a " hb" #b ";" -#define CRANDC(t,a,b) "o19 O129 ht" #t " ha" #a " hb" #b ";" +#define CROR(t, a, b) "o19 O449 ht" #t " ha" #a " hb" #b ";" +#define CRORC(t, a, b) "o19 O417 ht" #t " ha" #a " hb" #b ";" +#define CRNOR(t, a, b) "o19 O33 ht" #t " ha" #a " hb" #b ";" +#define CRANDC(t, a, b) "o19 O129 ht" #t " ha" #a " hb" #b ";" // all ld insn are changed to builtins /* cmpd 7,ra,rb; mfcr rt; rlwinm rt,rt,31,31,31;*/ {MIR_EQ, "r r r", CMPD "; " EQEND}, @@ -1304,75 +1295,97 @@ static const struct pattern patterns[] = { #define BRC(o, i) "o16 BO" #o " BI" #i " l" #define BRCL(o, i) "o16 BO" #o " BI" #i " l8; o18 L" -#define BRLOG(CODE, CMP, BI, COND, NEG_COND) \ - {CODE, "l r", CMP (i0) "; " BRC (COND, BI)}, /* cmp 7,ra1,0;bcond 7,l; */ \ - {CODE, "L r", CMP (i0) "; " BRCL (NEG_COND, BI)} /* cmp 7,ra1,0;bneg_cond 7,o8;b L;l8:*/ - - BRLOG (MIR_BT, CMPDI, 30, 4, 12), BRLOG (MIR_BTS, CMPWI, 30, 4, 12), - BRLOG (MIR_BF, CMPDI, 30, 12, 4), BRLOG (MIR_BFS, CMPWI, 30, 12, 4), - -#define BRCMP(CODE, CMP, CMPI, BI, COND, NEG_COND) \ - {CODE, "l r r", CMP "; " BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ - {CODE, "l r i", CMPI "; " BRC (COND, BI)}, /* cmpi 7,ra1,i;bcond 7,l;:*/ \ - {CODE, "L r r", CMP "; " BRCL (NEG_COND, BI)}, /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ \ - {CODE, "L r i", CMPI "; " BRCL (NEG_COND, BI)} /* cmp 7,ra1,i;bneg_cond 7,o8;b L;l8:*/ - -#define BRFCMP(CODE, BI, COND, COND_NAND, NEG_COND, NEG_COND_NAND) \ - {CODE, "l r r", FCMPU "; " COND_NAND BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ - {CODE, "L r r", FCMPU "; " NEG_COND_NAND BRCL (NEG_COND, BI)} /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ - -#define LT_OR CROR(28,28,31) -#define GT_OR CROR(29,29,31) -#define EQ_OR CROR(30,30,31) - -#define LT_ANDC CRANDC(28,28,31) -#define GT_ANDC CRANDC(29,29,31) -#define EQ_ANDC CRANDC(30,30,31) +#define BRLOG(CODE, CMP, BI, COND, NEG_COND) \ + {CODE, "l r", CMP (i0) "; " BRC (COND, BI)}, /* cmp 7,ra1,0;bcond 7,l; */ \ + { \ + CODE, "L r", CMP (i0) "; " BRCL (NEG_COND, BI) \ + } /* cmp 7,ra1,0;bneg_cond 7,o8;b L;l8:*/ + + BRLOG (MIR_BT, CMPDI, 30, 4, 12), + BRLOG (MIR_BTS, CMPWI, 30, 4, 12), + BRLOG (MIR_BF, CMPDI, 30, 12, 4), + BRLOG (MIR_BFS, CMPWI, 30, 12, 4), + +#define BRCMP(CODE, CMP, CMPI, BI, COND, NEG_COND) \ + {CODE, "l r r", CMP "; " BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ + {CODE, "l r i", CMPI "; " BRC (COND, BI)}, /* cmpi 7,ra1,i;bcond 7,l;:*/ \ + {CODE, "L r r", CMP "; " BRCL (NEG_COND, BI)}, /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ \ + { \ + CODE, "L r i", CMPI "; " BRCL (NEG_COND, BI) \ + } /* cmp 7,ra1,i;bneg_cond 7,o8;b L;l8:*/ + +#define BRFCMP(CODE, BI, COND, COND_NAND, NEG_COND, NEG_COND_NAND) \ + {CODE, "l r r", FCMPU "; " COND_NAND BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ + { \ + CODE, "L r r", FCMPU "; " NEG_COND_NAND BRCL (NEG_COND, BI) \ + } /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ + +#define LT_OR CROR (28, 28, 31) +#define GT_OR CROR (29, 29, 31) +#define EQ_OR CROR (30, 30, 31) + +#define LT_ANDC CRANDC (28, 28, 31) +#define GT_ANDC CRANDC (29, 29, 31) +#define EQ_ANDC CRANDC (30, 30, 31) // all ld insn are changed to builtins and bt/bts - BRCMP (MIR_BEQ, CMPD, CMPDI (i), 30, 12, 4), BRCMP (MIR_BEQS, CMPW, CMPWI (i), 30, 12, 4), - BRFCMP (MIR_FBEQ, 30, 12, EQ_ANDC, 4, EQ_OR), BRFCMP (MIR_DBEQ, 30, 12, EQ_ANDC, 4, EQ_OR), - - BRCMP (MIR_BNE, CMPD, CMPDI (i), 30, 4, 12), BRCMP (MIR_BNES, CMPW, CMPWI (i), 30, 4, 12), - BRFCMP (MIR_FBNE, 30, 4, EQ_ANDC, 12, EQ_ANDC), BRFCMP (MIR_DBNE, 30, 4, EQ_ANDC, 12, EQ_ANDC), - -#define BRUCMP(CODE, CMP, CMPI, BI, COND, NEG_COND) \ - {CODE, "l r r", CMP "; " BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ - {CODE, "l r u", CMPI "; " BRC (COND, BI)}, /* cmpi 7,ra1,u;bcond 7,l;:*/ \ - {CODE, "L r r", CMP "; " BRCL (NEG_COND, BI)}, /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ \ - {CODE, "L r u", CMPI "; " BRCL (NEG_COND, BI)} /* cmp 7,ra1,u;bneg_cond 7,o8;b L;l8:*/ + BRCMP (MIR_BEQ, CMPD, CMPDI (i), 30, 12, 4), + BRCMP (MIR_BEQS, CMPW, CMPWI (i), 30, 12, 4), + BRFCMP (MIR_FBEQ, 30, 12, EQ_ANDC, 4, EQ_OR), + BRFCMP (MIR_DBEQ, 30, 12, EQ_ANDC, 4, EQ_OR), + + BRCMP (MIR_BNE, CMPD, CMPDI (i), 30, 4, 12), + BRCMP (MIR_BNES, CMPW, CMPWI (i), 30, 4, 12), + BRFCMP (MIR_FBNE, 30, 4, EQ_ANDC, 12, EQ_ANDC), + BRFCMP (MIR_DBNE, 30, 4, EQ_ANDC, 12, EQ_ANDC), + +#define BRUCMP(CODE, CMP, CMPI, BI, COND, NEG_COND) \ + {CODE, "l r r", CMP "; " BRC (COND, BI)}, /* cmp 7,ra1,rb2;bcond 7,l; */ \ + {CODE, "l r u", CMPI "; " BRC (COND, BI)}, /* cmpi 7,ra1,u;bcond 7,l;:*/ \ + {CODE, "L r r", CMP "; " BRCL (NEG_COND, BI)}, /* cmp 7,ra1,rb2;bneg_cond 7,o8;b L;l8:*/ \ + { \ + CODE, "L r u", CMPI "; " BRCL (NEG_COND, BI) \ + } /* cmp 7,ra1,u;bneg_cond 7,o8;b L;l8:*/ /* LT: */ - BRCMP (MIR_BLT, CMPD, CMPDI (i), 28, 12, 4), BRCMP (MIR_BLTS, CMPW, CMPWI (i), 28, 12, 4), - BRFCMP (MIR_FBLT, 28, 12, LT_ANDC, 4, LT_OR), BRFCMP (MIR_DBLT, 28, 12, LT_ANDC, 4, LT_OR), - BRUCMP (MIR_UBLT, CMPLD, CMPLDI, 28, 12, 4), BRUCMP (MIR_UBLTS, CMPLW, CMPLWI, 28, 12, 4), - + BRCMP (MIR_BLT, CMPD, CMPDI (i), 28, 12, 4), + BRCMP (MIR_BLTS, CMPW, CMPWI (i), 28, 12, 4), + BRFCMP (MIR_FBLT, 28, 12, LT_ANDC, 4, LT_OR), + BRFCMP (MIR_DBLT, 28, 12, LT_ANDC, 4, LT_OR), + BRUCMP (MIR_UBLT, CMPLD, CMPLDI, 28, 12, 4), + BRUCMP (MIR_UBLTS, CMPLW, CMPLWI, 28, 12, 4), + /* GE: */ BRCMP (MIR_BGE, CMPD, CMPDI (i), 28, 4, 12), - BRCMP (MIR_BGES, CMPW, CMPWI (i), 28, 4, 12), BRFCMP (MIR_FBGE, 28, 4, LT_OR, 12, LT_ANDC), - BRFCMP (MIR_DBGE, 28, 4, LT_OR, 12, LT_ANDC), BRUCMP (MIR_UBGE, CMPLD, CMPLDI, 28, 4, 12), + BRCMP (MIR_BGES, CMPW, CMPWI (i), 28, 4, 12), + BRFCMP (MIR_FBGE, 28, 4, LT_OR, 12, LT_ANDC), + BRFCMP (MIR_DBGE, 28, 4, LT_OR, 12, LT_ANDC), + BRUCMP (MIR_UBGE, CMPLD, CMPLDI, 28, 4, 12), BRUCMP (MIR_UBGES, CMPLW, CMPLWI, 28, 4, 12), /* GT: */ BRCMP (MIR_BGT, CMPD, CMPDI (i), 29, 12, 4), - BRCMP (MIR_BGTS, CMPW, CMPWI (i), 29, 12, 4), BRFCMP (MIR_FBGT, 29, 12, GT_ANDC, 4, GT_OR), - BRFCMP (MIR_DBGT, 29, 12, GT_ANDC, 4, GT_OR), BRUCMP (MIR_UBGT, CMPLD, CMPLDI, 29, 12, 4), + BRCMP (MIR_BGTS, CMPW, CMPWI (i), 29, 12, 4), + BRFCMP (MIR_FBGT, 29, 12, GT_ANDC, 4, GT_OR), + BRFCMP (MIR_DBGT, 29, 12, GT_ANDC, 4, GT_OR), + BRUCMP (MIR_UBGT, CMPLD, CMPLDI, 29, 12, 4), BRUCMP (MIR_UBGTS, CMPLW, CMPLWI, 29, 12, 4), /* LE: */ BRCMP (MIR_BLE, CMPD, CMPDI (i), 29, 4, 12), BRCMP (MIR_BLES, CMPW, CMPWI (i), 29, 4, 12), - BRFCMP (MIR_FBLE, 29, 4, GT_OR, 12, GT_ANDC), BRFCMP (MIR_DBLE, 29, 4, GT_OR, 12, GT_ANDC), + BRFCMP (MIR_FBLE, 29, 4, GT_OR, 12, GT_ANDC), + BRFCMP (MIR_DBLE, 29, 4, GT_OR, 12, GT_ANDC), BRUCMP (MIR_UBLE, CMPLD, CMPLDI, 29, 4, 12), BRUCMP (MIR_UBLES, CMPLW, CMPLWI, 29, 4, 12), - + #define NEG "o31 O104 rt0 ra1" #define FNEG "o63 O40 rt0 rb1" - {MIR_NEG, "r r", NEG}, /* neg Rt,Ra */ - {MIR_NEGS, "r r", NEG}, /* neg Rt,Ra */ - {MIR_FNEG, "r r", FNEG}, /* fneg rt,rb */ - {MIR_DNEG, "r r", FNEG}, /* fneg rt,rb */ + {MIR_NEG, "r r", NEG}, /* neg Rt,Ra */ + {MIR_NEGS, "r r", NEG}, /* neg Rt,Ra */ + {MIR_FNEG, "r r", FNEG}, /* fneg rt,rb */ + {MIR_DNEG, "r r", FNEG}, /* fneg rt,rb */ // ldneg is a builtin #define SHR(s) "o31 O" #s " ra0 rs1 rb2" @@ -2321,8 +2334,10 @@ static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacemen binsn |= lb << (32 - 11); binsn_mask = check_and_set_mask (binsn_mask, 1 << (32 - 11)); } - if (label_ref_num >= 0) VARR_ADDR (label_ref_t, label_refs) - [label_ref_num].label_val_disp = VARR_LENGTH (uint8_t, result_code); + if (label_ref_num >= 0) + VARR_ADDR (label_ref_t, label_refs) + [label_ref_num].label_val_disp + = VARR_LENGTH (uint8_t, result_code); if (switch_table_addr_p) switch_table_addr_insn_start = VARR_LENGTH (uint8_t, result_code); put_uint32 (gen_ctx, binsn); /* output the machine insn */ diff --git a/mir/mir-gen-riscv64.c b/mir/mir-gen-riscv64.c index d5b16c91..8e386674 100644 --- a/mir/mir-gen-riscv64.c +++ b/mir/mir-gen-riscv64.c @@ -1327,10 +1327,10 @@ struct pattern { mcd[s] - double memory with compressed based register (or stack register) and 6-bit unsigned displacement scaled by 8 - i -- 2nd or 3rd immediate op for arithemtic insn (12-bit signed) + i -- 2nd or 3rd immediate op for arithmetic insn (12-bit signed) j -- as i but -j should be also i (it means excluding minimal 12-bit signed) and only 3rd op ju -- as j but but rounded to 16 first and only 2nd op - iu -- 32-bit signed immediate for arithemtic insn with zero 12 bits as 2nd op + iu -- 32-bit signed immediate for arithmetic insn with zero 12 bits as 2nd op ia -- any 32-bit signed immediate as 2nd op I -- any 64-bit immediate s -- immediate shift (5 bits) as 3th op @@ -1338,10 +1338,10 @@ struct pattern { Sp -- nonzero immediate shift (6 bits) as 3th op l -- label as the 1st or 2nd op which can be present by signed 13-bit pc offset - k -- 2nd or 3rd immediate op for arithemtic insn (6-bit signed) - kp -- nonzero 2nd or 3rd immediate op for arithemtic insn (6-bit signed) - ks -- nonzero 2nd or 3rd immediate op for arithemtic insn (9-bit signed) multiple of 16 - ku -- 18-bit signed immediate for arithemtic insn with zero low 12-bits as 2nd op + k -- 2nd or 3rd immediate op for arithmetic insn (6-bit signed) + kp -- nonzero 2nd or 3rd immediate op for arithmetic insn (6-bit signed) + ks -- nonzero 2nd or 3rd immediate op for arithmetic insn (9-bit signed) multiple of 16 + ku -- 18-bit signed immediate for arithmetic insn with zero low 12-bits as 2nd op kw -- nonzero scaled by 4 8-bit unsigned immediate jus -- imm rounded to 16 first and considered as ks @@ -1589,7 +1589,6 @@ static const struct pattern patterns[] = { {MIR_ULTS, "r r i", "O13 F3 f0 rd0 rs1 i"}, /* sltiu rd,rs1,i */ // ??? le r,imm -> lt r,imm+1 - /* !(op2 < op1) /* sgt rd,rs1,rs2;xori rd,rs1,1 */ {MIR_LE, "r r r", "O33 F2 f0 rd0 rs2 rS1; O13 F4 f0 rd0 rs0 i1"}, /* sgti rd,rs1,i;xori rd,rs1,1 */ @@ -1880,7 +1879,6 @@ static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_in char ch, start_ch; MIR_op_t op, original; MIR_op_mode_t mode; - MIR_reg_t hr; for (nop = 0, p = pat->pattern; *p != 0; p++, nop++) { while (*p == ' ' || *p == '\t') p++; @@ -2196,7 +2194,6 @@ static uint32_t check_and_set_mask (uint32_t opcode_mask, uint32_t mask) { static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacement) { MIR_context_t ctx = gen_ctx->ctx; - size_t offset; const char *p, *insn_str; label_ref_t lr; const_ref_t cr; @@ -2208,11 +2205,12 @@ static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacemen insn->ops[1].u.u = (insn->ops[1].u.u + 15) & -16; for (insn_str = replacement;; insn_str = p + 1) { char ch, ch2, start_ch, d; - uint32_t insn32 = 0, insn_mask = 0, el_mask; + uint32_t insn32 = 0, insn_mask = 0, el_mask = 0; int n, opcode = -1, funct3 = -1, funct7 = -1, rd = -1, rs1 = -1, rs2 = -1; int opcodec = -1, funct3c = -1, funct4c = -1, funct6c = -1, funct2c = -1, funct2bc = -1; int rs2m = -1, rdc = -1, rs2c = -1, uimm8c = -1; - int shamt = -1, shamtc = -1, imm12, imm20, imm6c, st_disp, unsign_disp4 = -1, unsign_disp8 = -1; + int shamt = -1, shamtc = -1, imm12, imm20, imm6c = 0, st_disp = 0; + int unsign_disp4 = -1, unsign_disp8 = -1; int unsign_sp_disp4 = -1, unsign_sp_disp8 = -1; int unsign_sp_store_disp4 = -1, unsign_sp_store_disp8 = -1; int imm12_p = FALSE, imm20_p = FALSE, imm6c_p = FALSE, st_disp_p = FALSE; diff --git a/mir/mir-gen-s390x.c b/mir/mir-gen-s390x.c index d25559c4..0fb5efdf 100644 --- a/mir/mir-gen-s390x.c +++ b/mir/mir-gen-s390x.c @@ -85,7 +85,7 @@ SP,R11->+-- Back chain (optional) (SP + 0) Alloca area (after that new 160 bytes header should be created with new values) SP alignment is always 8. -Originaly SP(r15) and FP (r11) are the same but r15 can be changed by alloca */ +Originally SP(r15) and FP (r11) are the same but r15 can be changed by alloca */ #define S390X_STACK_HEADER_SIZE 160 #define S390X_GP_REG_RSAVE_AREA_START 16 @@ -754,12 +754,13 @@ static void target_machinize (gen_ctx_t gen_ctx) { if (code == MIR_LDBEQ || code == MIR_LDBNE || code == MIR_LDBLT || code == MIR_LDBGE || code == MIR_LDBGT || code == MIR_LDBLE) { /* split to cmp and branch */ temp_op = MIR_new_reg_op (ctx, gen_new_temp_reg (gen_ctx, MIR_T_I64, func)); - code = (code == MIR_LDBEQ ? MIR_LDEQ - : code == MIR_LDBNE ? MIR_LDNE - : code == MIR_LDBLT ? MIR_LDLT - : code == MIR_LDBGE ? MIR_LDGE - : code == MIR_LDBGT ? MIR_LDGT - : MIR_LDLE); + code = (code == MIR_LDBEQ + ? MIR_LDEQ + : code == MIR_LDBNE + ? MIR_LDNE + : code == MIR_LDBLT + ? MIR_LDLT + : code == MIR_LDBGE ? MIR_LDGE : code == MIR_LDBGT ? MIR_LDGT : MIR_LDLE); new_insn = MIR_new_insn (ctx, code, temp_op, insn->ops[1], insn->ops[2]); gen_add_insn_before (gen_ctx, insn, new_insn); next_insn = MIR_new_insn (ctx, MIR_BT, insn->ops[0], temp_op); @@ -1298,12 +1299,12 @@ static const struct pattern patterns[] = { {MIR_NES, "r 0 m2", "57 r0 m; 11* r0 R0; 88 r0 R0 Sd31"}, {MIR_NES, "r 0 M2", "e3:57 r0 m; 11* r0 R0; 88 r0 R0 Sd31"}, - /* (cer r1,r2 | ce r1, mf); lghi r0,1; jne L; lghi r0,0: */ - {MIR_FNE, "r r r", "b309 r1 R2" CMPEND (6)}, - {MIR_FNE, "r r mf", "ed:09 r1 m" CMPEND (6)}, - /* (cdbr r1,r2 | cdb r1, mf); lghi r0,1; jne L; lghi r0,0: */ - {MIR_DNE, "r r r", "b319 r1 R2" CMPEND (6)}, - {MIR_DNE, "r r md", "ed:19 r1 m" CMPEND (6)}, + /* (cer r1,r2 | ce r1, mf); lghi r0,1; j L; lghi r0,0: */ + {MIR_FNE, "r r r", "b309 r1 R2" CMPEND (7)}, + {MIR_FNE, "r r mf", "ed:09 r1 m" CMPEND (7)}, + /* (cdbr r1,r2 | cdb r1, mf); lghi r0,1; j L; lghi r0,0: */ + {MIR_DNE, "r r r", "b319 r1 R2" CMPEND (7)}, + {MIR_DNE, "r r md", "ed:19 r1 m" CMPEND (7)}, #define CMP(LC, SC, ULC, USC, FC, DC, m) \ {LC, "r r r", "b920 r1 R2" CMPEND (m)}, /* cgr r1,r2;lghi r0,1;jm L;lghi r0,0 */ \ @@ -1338,22 +1339,24 @@ static const struct pattern patterns[] = { {MIR_BTS, "L r", "12* r1 R1" BRCL (6)}, /* ltr r0,r0; bcril m8,l */ {MIR_BFS, "L r", "12* r1 R1" BRCL (8)}, /* ltr r1,r1; bcril m6,l */ -#define BCMP(LC, SC, FC, DC, m) \ +#define BCMP(LC, SC, FC, DC, m, fm) \ {LC, "L r r", "b920 r1 R2" BRCL (m)}, /* cgr r1,r2; bcril m,l */ \ {LC, "L r M3", "e3:20 r1 m" BRCL (m)}, /* cg r1,m; bcril m,l */ \ {LC, "L r Ms2", "e3:30 r1 m" BRCL (m)}, /* cgf r1,m; bcril m,l */ \ {SC, "L r r", "19* r1 R2" BRCL (m)}, /* cr r1,r2; bcril m,l */ \ {SC, "L r m2", "59 r1 m" BRCL (m)}, /* c r1,m; bcril m,l */ \ {SC, "L r M2", "e3:59 r1 m" BRCL (m)}, /* cy r1,m; bcril m,l */ \ - {FC, "L r r", "b309 r1 R2" BRCL (m)}, /* cer r1,r2; bcril L */ \ - {FC, "L r mf", "ed:09 r1 m" BRCL (m)}, /* ce r1, mf; bcril L */ \ - {DC, "L r r", "b319 r1 R2" BRCL (m)}, /* cdbr r1,r2; bcril L */ \ - {DC, "L r md", "ed:19 r1 m" BRCL (m)}, /* cdb r1, md; bcril L: */ - - BCMP (MIR_BEQ, MIR_BEQS, MIR_FBEQ, MIR_DBEQ, 8) BCMP (MIR_BNE, MIR_BNES, MIR_FBNE, MIR_DBNE, 6) - BCMP (MIR_BLT, MIR_BLTS, MIR_FBLT, MIR_DBLT, 4) BCMP (MIR_BGT, MIR_BGTS, MIR_FBGT, MIR_DBGT, 2) - BCMP (MIR_BLE, MIR_BLES, MIR_FBLE, MIR_DBLE, 12) - BCMP (MIR_BGE, MIR_BGES, MIR_FBGE, MIR_DBGE, 10) + {FC, "L r r", "b309 r1 R2" BRCL (fm)}, /* cer r1,r2; bcril L */ \ + {FC, "L r mf", "ed:09 r1 m" BRCL (fm)}, /* ce r1, mf; bcril L */ \ + {DC, "L r r", "b319 r1 R2" BRCL (fm)}, /* cdbr r1,r2; bcril L */ \ + {DC, "L r md", "ed:19 r1 m" BRCL (fm)}, /* cdb r1, md; bcril L: */ + + BCMP (MIR_BEQ, MIR_BEQS, MIR_FBEQ, MIR_DBEQ, 8, 8) + BCMP (MIR_BNE, MIR_BNES, MIR_FBNE, MIR_DBNE, 6, 7) /* only fp ne has unordered mask bit */ + BCMP (MIR_BLT, MIR_BLTS, MIR_FBLT, MIR_DBLT, 4, 4) + BCMP (MIR_BGT, MIR_BGTS, MIR_FBGT, MIR_DBGT, 2, 2) + BCMP (MIR_BLE, MIR_BLES, MIR_FBLE, MIR_DBLE, 12, 12) + BCMP (MIR_BGE, MIR_BGES, MIR_FBGE, MIR_DBGE, 10, 10) #define BCMPU(LC, SC, m) \ {LC, "L r r", "b921 r1 R2" BRCL (m)}, /* clgr r1,r2; bcril m,l */ \ @@ -2129,15 +2132,21 @@ static void out_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, const char *replacemen set_insn_field (&binsn, label_off, 16, 16); check_and_set_mask (&binsn_mask, 0xffff, 16, 16); } - if (const_ref_num >= 0) VARR_ADDR (const_ref_t, const_refs) - [const_ref_num].insn_pc = VARR_LENGTH (uint8_t, result_code); - if (label_ref_num >= 0) VARR_ADDR (label_ref_t, label_refs) - [label_ref_num].label_val_disp = VARR_LENGTH (uint8_t, result_code); + if (const_ref_num >= 0) + VARR_ADDR (const_ref_t, const_refs) + [const_ref_num].insn_pc + = VARR_LENGTH (uint8_t, result_code); + if (label_ref_num >= 0) + VARR_ADDR (label_ref_t, label_refs) + [label_ref_num].label_val_disp + = VARR_LENGTH (uint8_t, result_code); if (switch_table_addr_p) switch_table_addr_insn_start = VARR_LENGTH (uint8_t, result_code); VARR_PUSH_ARR (uint8_t, result_code, (uint8_t *) &binsn, len); /* output the machine insn */ - if (const_ref_num >= 0) VARR_ADDR (const_ref_t, const_refs) - [const_ref_num].next_insn_pc = VARR_LENGTH (uint8_t, result_code); + if (const_ref_num >= 0) + VARR_ADDR (const_ref_t, const_refs) + [const_ref_num].next_insn_pc + = VARR_LENGTH (uint8_t, result_code); if (*p == 0) break; } diff --git a/mir/mir-gen-x86_64.c b/mir/mir-gen-x86_64.c index 18ffd8c0..f863e3b5 100644 --- a/mir/mir-gen-x86_64.c +++ b/mir/mir-gen-x86_64.c @@ -1069,9 +1069,37 @@ static void target_machinize (gen_ctx_t gen_ctx) { new_insn = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], areg_op); gen_add_insn_after (gen_ctx, insn, new_insn); insn->ops[0] = areg_op; + /* Following conditional branches are changed to correctly process unordered numbers: */ + switch (code) { + case MIR_FLT: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_FGT; + break; + case MIR_FLE: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_FGE; + break; + case MIR_DLT: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_DGT; + break; + case MIR_DLE: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_DGE; + break; + default: break; /* do nothing */ + } break; } - /* Following conditional branches are changed to correctly process unordered numbers: */ + /* Following conditional branches are changed to correctly process unordered numbers: */ + case MIR_LDLT: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_LDGT; + break; + case MIR_LDLE: + SWAP (insn->ops[1], insn->ops[2], temp_op); + insn->code = MIR_LDGE; + break; case MIR_FBLT: SWAP (insn->ops[1], insn->ops[2], temp_op); insn->code = MIR_FBGT; @@ -1307,7 +1335,7 @@ struct pattern { const char *replacement; }; -// make imm always second operand (symplify for cmp and commutative op) +// make imm always second operand (simplify for cmp and commutative op) // make result of cmp op always a register and memory only the 2nd operand if first is reg, // but not for FP (NAN) (simplify) // for FP cmp first operand should be always reg (machinize) @@ -1659,11 +1687,11 @@ static void target_get_early_clobbered_hard_regs (MIR_insn_t insn, MIR_reg_t *hr // constraint: esp can not be index static int int8_p (int64_t v) { return INT8_MIN <= v && v <= INT8_MAX; } -static int uint8_p (int64_t v) { return 0 <= v && v <= UINT8_MAX; } +static int MIR_UNUSED uint8_p (int64_t v) { return 0 <= v && v <= UINT8_MAX; } static int int16_p (int64_t v) { return INT16_MIN <= v && v <= INT16_MAX; } static int MIR_UNUSED uint16_p (int64_t v) { return 0 <= v && v <= UINT16_MAX; } static int int32_p (int64_t v) { return INT32_MIN <= v && v <= INT32_MAX; } -static int uint32_p (int64_t v) { return 0 <= v && v <= UINT32_MAX; } +static int MIR_UNUSED uint32_p (int64_t v) { return 0 <= v && v <= UINT32_MAX; } static int dec_value (int ch) { return '0' <= ch && ch <= '9' ? ch - '0' : -1; } diff --git a/mir/mir-gen.c b/mir/mir-gen.c index 9d46c915..a0501694 100644 --- a/mir/mir-gen.c +++ b/mir/mir-gen.c @@ -52,7 +52,7 @@ reg - MIR (pseudo-)register (their numbers are in MIR_OP_REG and MIR_OP_MEM) hard reg - MIR hard register (their numbers are in MIR_OP_HARD_REG and MIR_OP_HARD_REG_MEM) breg (based reg) - function pseudo registers whose numbers start with zero - var - pseudo and hard register (var numbers for psedo-registers + var - pseudo and hard register (var numbers for pseudo-registers are based reg numbers + MAX_HARD_REG + 1) loc - hard register and stack locations (stack slot numbers start with MAX_HARD_REG + 1). @@ -65,11 +65,7 @@ #include -#ifdef NDEBUG -static inline int gen_assert (int cond) { return 0 && cond; } -#else #define gen_assert(cond) assert (cond) -#endif typedef struct gen_ctx *gen_ctx_t; @@ -102,11 +98,11 @@ static void setup_call_hard_reg_args (gen_ctx_t gen_ctx, MIR_insn_t call_insn, M #endif #if MIR_NO_GEN_DEBUG -#define DEBUG(code) +#define DEBUG(level, code) #else -#define DEBUG(code) \ - { \ - if (debug_file != NULL) code; \ +#define DEBUG(level, code) \ + { \ + if (debug_file != NULL && debug_level >= level) code; \ } #endif @@ -151,6 +147,7 @@ struct gen_ctx { MIR_item_t curr_func_item; #if !MIR_NO_GEN_DEBUG FILE *debug_file; + int debug_level; #endif bitmap_t insn_to_consider, temp_bitmap, temp_bitmap2; bitmap_t call_used_hard_regs[MIR_T_BOUND], func_used_hard_regs; @@ -176,6 +173,7 @@ struct gen_ctx { #define optimize_level gen_ctx->optimize_level #define curr_func_item gen_ctx->curr_func_item #define debug_file gen_ctx->debug_file +#define debug_level gen_ctx->debug_level #define insn_to_consider gen_ctx->insn_to_consider #define temp_bitmap gen_ctx->temp_bitmap #define temp_bitmap2 gen_ctx->temp_bitmap2 @@ -409,7 +407,7 @@ DEF_DLIST (src_mv_t, src_link); struct reg_info { long freq; - /* The followd members are defined and used only in RA */ + /* The following members are defined and used only in RA */ long thread_freq; /* thread accumulated freq, defined for first thread breg */ /* first/next breg of the same thread, MIR_MAX_REG_NUM is end mark */ MIR_reg_t thread_first, thread_next; @@ -662,7 +660,8 @@ static void gen_move_insn_before (gen_ctx_t gen_ctx, MIR_insn_t before, MIR_insn } } -static void setup_call_hard_reg_args (gen_ctx_t gen_ctx, MIR_insn_t call_insn, MIR_reg_t hard_reg) { +static void MIR_UNUSED setup_call_hard_reg_args (gen_ctx_t gen_ctx, MIR_insn_t call_insn, + MIR_reg_t hard_reg) { insn_data_t insn_data; gen_assert (MIR_call_code_p (call_insn->code) && hard_reg <= MAX_HARD_REG); @@ -1232,7 +1231,7 @@ static void rename_op_reg (gen_ctx_t gen_ctx, MIR_op_t *op_ref, MIR_reg_t reg, M } } if (!change_p) return; /* definition was already changed from another use */ - DEBUG ({ + DEBUG (2, { MIR_func_t func = curr_func_item->u.func; fprintf (debug_file, " Change %s to %s in insn %-5lu", MIR_reg_name (ctx, reg, func), @@ -1271,6 +1270,7 @@ static void build_func_cfg (gen_ctx_t gen_ctx) { curr_cfg->curr_bb_insn_index = 0; curr_cfg->max_reg = 0; curr_cfg->min_reg = 0; + curr_cfg->non_conflicting_moves = 0; curr_cfg->root_loop_node = NULL; curr_bb_index = 0; for (i = 0; i < VARR_LENGTH (MIR_var_t, curr_func_item->u.func->vars); i++) { @@ -1479,7 +1479,7 @@ static void finish_data_flow (gen_ctx_t gen_ctx) { All phi insns always use the same reg to guarantee conventional SSA. It also means that some regs have more one definition but ssa edges represent the correct SSA. The only optimization in the pipeline which would benefit from full renaming is copy propagation (full - SSA copy propgation would not keep conventional SSA). + SSA copy propagation would not keep conventional SSA). */ typedef struct ssa_edge *ssa_edge_t; @@ -1673,7 +1673,7 @@ static void minimize_ssa (gen_ctx_t gen_ctx, size_t insns_num) { } VARR_TRUNC (bb_insn_t, phis, saved_bound); } while (change_p); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "Minimizing SSA phis: from %ld to %ld phis (non-phi insns %ld)\n", (long) VARR_LENGTH (bb_insn_t, deleted_phis) + (long) VARR_LENGTH (bb_insn_t, phis), (long) VARR_LENGTH (bb_insn_t, phis), (long) insns_num); @@ -1808,7 +1808,7 @@ static int push_to_rename (gen_ctx_t gen_ctx, ssa_edge_t ssa_edge) { if (ssa_edge->flag) return FALSE; VARR_PUSH (ssa_edge_t, ssa_edges_to_process, ssa_edge); ssa_edge->flag = TRUE; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Adding ssa edge: def %lu:%d -> use %lu:%d:\n ", (unsigned long) ssa_edge->def->index, ssa_edge->def_op_num, (unsigned long) ssa_edge->use->index, ssa_edge->use_op_num); @@ -1853,7 +1853,7 @@ static void rename_bb_insn (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { if (!out_p || !var_is_reg_p (var)) continue; ssa_edge = insn->ops[op_num].data; if (ssa_edge != NULL && ssa_edge->flag) continue; /* already processed */ - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Start def insn %-5lu", (long unsigned) bb_insn->index); print_bb_insn (gen_ctx, bb_insn, FALSE); }); @@ -2053,6 +2053,7 @@ static void copy_prop (gen_ctx_t gen_ctx) { size_t passed_mem_num; MIR_reg_t var, reg, new_reg; insn_var_iterator_t iter; + long deleted_insns_num = 0; bitmap_clear (temp_bitmap); for (bb_t bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) @@ -2077,7 +2078,7 @@ static void copy_prop (gen_ctx_t gen_ctx) { if (se->prev_use != NULL || se->next_use != NULL || !move_p (def_insn) || bitmap_bit_p (temp_bitmap, def_insn->ops[1].u.reg)) break; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Removing copy insn %-5lu", (unsigned long) def->index); MIR_output_insn (gen_ctx->ctx, debug_file, def_insn, curr_func_item->u.func, TRUE); }); @@ -2086,6 +2087,7 @@ static void copy_prop (gen_ctx_t gen_ctx) { remove_ssa_edge (gen_ctx, se); insn->ops[op_num].data = def_insn->ops[1].data; gen_delete_insn (gen_ctx, def_insn); + deleted_insns_num++; se = insn->ops[op_num].data; se->use = bb_insn; se->use_op_num = op_num; @@ -2099,19 +2101,20 @@ static void copy_prop (gen_ctx_t gen_ctx) { w2 = get_ext_params (def_insn->code, &sign2_p); if (w2 != 0 && sign_p == sign2_p && w2 <= w && !bitmap_bit_p (temp_bitmap, def_insn->ops[1].u.reg)) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Change code of insn %lu: before", (unsigned long) bb_insn->index); MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, FALSE); }); insn->code = MIR_MOV; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " after"); MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); } } } + DEBUG (1, { fprintf (debug_file, "%5ld deleted copy insns\n", deleted_insns_num); }); } /* New Page */ @@ -2221,7 +2224,7 @@ static int find_expr (gen_ctx_t gen_ctx, MIR_insn_t insn, expr_t *e) { } static void insert_expr (gen_ctx_t gen_ctx, expr_t e) { - expr_t e2; + expr_t MIR_UNUSED e2; gen_assert (!find_expr (gen_ctx, e->insn, &e2)); HTAB_DO (expr_t, expr_tab, e, HTAB_INSERT, e); @@ -2294,6 +2297,7 @@ static void gvn_modify (gen_ctx_t gen_ctx) { bb_t bb; bb_insn_t bb_insn, new_bb_insn, next_bb_insn, expr_bb_insn; MIR_reg_t temp_reg; + long gvn_insns_num = 0; for (size_t i = 0; i < VARR_LENGTH (bb_t, worklist); i++) { bb = VARR_GET (bb_t, worklist, i); @@ -2310,13 +2314,13 @@ static void gvn_modify (gen_ctx_t gen_ctx) { if (!gvn_insn_p (insn)) continue; if (!find_expr (gen_ctx, insn, &e)) { e = add_expr (gen_ctx, insn); - DEBUG ({ print_expr (gen_ctx, e, "Adding"); }); + DEBUG (2, { print_expr (gen_ctx, e, "Adding"); }); } if (move_p (insn)) bb_insn->gvn_val = ((ssa_edge_t) insn->ops[1].data)->def->gvn_val; else bb_insn->gvn_val = e->num; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "Val=%lu for insn %lu:", (unsigned long) bb_insn->gvn_val, (unsigned long) bb_insn->index); MIR_output_insn (ctx, debug_file, bb_insn->insn, curr_func_item->u.func, TRUE); @@ -2326,7 +2330,9 @@ static void gvn_modify (gen_ctx_t gen_ctx) { continue; if (phi_use_p (e->insn)) continue; /* keep conventional SSA */ expr_bb_insn = e->insn->data; - if (!bitmap_bit_p (bb->dom_in, expr_bb_insn->bb->index)) continue; + if (bb->index != expr_bb_insn->bb->index + && !bitmap_bit_p (bb->dom_in, expr_bb_insn->bb->index)) + continue; add_def_p = e->temp_reg == 0; temp_reg = get_expr_temp_reg (gen_ctx, e); op = MIR_new_reg_op (ctx, temp_reg); @@ -2348,7 +2354,7 @@ static void gvn_modify (gen_ctx_t gen_ctx) { change_ssa_edge_list_def (list, new_bb_insn, 0, e->insn->ops[0].u.reg, temp_reg); if (!find_expr (gen_ctx, new_insn, &new_e)) new_e = add_expr (gen_ctx, new_insn); new_bb_insn->gvn_val = e->num; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " adding insn "); MIR_output_insn (ctx, debug_file, new_insn, curr_func_item->u.func, FALSE); fprintf (debug_file, " after def insn "); @@ -2366,7 +2372,8 @@ static void gvn_modify (gen_ctx_t gen_ctx) { change_ssa_edge_list_def (list, new_bb_insn, 0, 0, 0); if (!find_expr (gen_ctx, new_insn, &new_e)) new_e = add_expr (gen_ctx, new_insn); new_bb_insn->gvn_val = e->num; - DEBUG ({ + gvn_insns_num++; + DEBUG (2, { fprintf (debug_file, " adding insn "); MIR_output_insn (ctx, debug_file, new_insn, curr_func_item->u.func, FALSE); fprintf (debug_file, " after use insn "); @@ -2374,6 +2381,7 @@ static void gvn_modify (gen_ctx_t gen_ctx) { }); } } + DEBUG (1, { fprintf (debug_file, "%5ld found GVN redundant insns\n", gvn_insns_num); }); } static void gvn (gen_ctx_t gen_ctx) { @@ -2961,7 +2969,7 @@ static void ccp_push_used_insns (gen_ctx_t gen_ctx, ssa_edge_t first_ssa_edge) { if (bb_insn->flag || !bitmap_bit_p (bb_visited, bb_insn->bb->index)) continue; /* already in ccp_insns or bb is not processed yet */ VARR_PUSH (bb_insn_t, ccp_insns, bb_insn); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " pushing bb%lu insn: ", (unsigned long) bb_insn->bb->index); MIR_output_insn (ctx, debug_file, bb_insn->insn, curr_func_item->u.func, FALSE); }); @@ -2971,7 +2979,7 @@ static void ccp_push_used_insns (gen_ctx_t gen_ctx, ssa_edge_t first_ssa_edge) { static void ccp_process_active_edge (gen_ctx_t gen_ctx, edge_t e) { if (e->skipped_p && !e->dst->flag) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Make edge bb%lu->bb%lu active\n", (unsigned long) e->src->index, (unsigned long) e->dst->index); }); @@ -2986,7 +2994,7 @@ static void ccp_make_insn_update (gen_ctx_t gen_ctx, MIR_insn_t insn) { ccp_val_t ccp_val; if (!ccp_insn_update (gen_ctx, insn)) { - DEBUG ({ + DEBUG (2, { if (MIR_call_code_p (insn->code)) { fprintf (debug_file, " -- keep all results varying"); } else if (get_ccp_res_op (gen_ctx, insn, 0, &op) && var_insn_op_p (insn, 0)) { @@ -3010,7 +3018,7 @@ static void ccp_make_insn_update (gen_ctx_t gen_ctx, MIR_insn_t insn) { ccp_push_used_insns (gen_ctx, op.data); } gen_assert (ccp_val != NULL); - DEBUG ({ + DEBUG (2, { if (MIR_call_code_p (insn->code)) { fprintf (debug_file, " -- make all results varying\n"); } else if (ccp_val->val_kind == CCP_VARYING) { @@ -3032,7 +3040,7 @@ static void ccp_process_insn (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { bb_t bb = bb_insn->bb; MIR_insn_t insn = bb_insn->insn; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " processing bb%lu insn: ", (unsigned long) bb_insn->bb->index); MIR_output_insn (gen_ctx->ctx, debug_file, bb_insn->insn, curr_func_item->u.func, FALSE); }); @@ -3040,7 +3048,7 @@ static void ccp_process_insn (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { ccp_make_insn_update (gen_ctx, insn); // ??? should we process SWITCH as cond branch return; } - DEBUG ({ fprintf (debug_file, "\n"); }); + DEBUG (2, { fprintf (debug_file, "\n"); }); if ((ccp_res = ccp_branch_update (gen_ctx, insn, &res)) == CCP_CONST) { /* Remember about an edge to exit bb. First edge is always for fall through and the 2nd edge is for jump bb. */ @@ -3058,12 +3066,12 @@ static void ccp_process_bb (gen_ctx_t gen_ctx, bb_t bb) { bb_insn_t bb_insn; edge_t e; - DEBUG ({ fprintf (debug_file, " processing bb%lu\n", (unsigned long) bb->index); }); + DEBUG (2, { fprintf (debug_file, " processing bb%lu\n", (unsigned long) bb->index); }); for (bb_insn = DLIST_HEAD (bb_insn_t, bb->bb_insns); bb_insn != NULL; bb_insn = DLIST_NEXT (bb_insn_t, bb_insn)) { if ((insn = bb_insn->insn)->code == MIR_LABEL) continue; if (insn->code != MIR_PHI) break; - DEBUG ({ + DEBUG (2, { gen_assert (insn->ops[0].mode == MIR_OP_REG); fprintf (debug_file, " processing phi of reg%lu(%s) in bb%lu:", (long unsigned) insn->ops[0].u.reg, @@ -3127,6 +3135,7 @@ static int ccp_modify (gen_ctx_t gen_ctx) { MIR_insn_t insn, prev_insn, first_insn; ssa_edge_t se, next_se; int res, change_p = FALSE; + long deleted_insns_num = 0, deleted_branches_num = 0; #ifndef NDEBUG for (bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) @@ -3137,7 +3146,7 @@ static int ccp_modify (gen_ctx_t gen_ctx) { next_bb = DLIST_NEXT (bb_t, bb); if (!bb->flag) { change_p = TRUE; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " deleting unreachable bb%lu and its edges\n", (unsigned long) bb->index); }); @@ -3147,6 +3156,7 @@ static int ccp_modify (gen_ctx_t gen_ctx) { insn = bb_insn->insn; ccp_remove_insn_ssa_edges (gen_ctx, insn); gen_delete_insn (gen_ctx, insn); + deleted_insns_num++; } delete_bb (gen_ctx, bb); continue; @@ -3160,7 +3170,7 @@ static int ccp_modify (gen_ctx_t gen_ctx) { && bb_insn->insn->ops[1].mode != MIR_OP_UINT))) { gen_assert (!MIR_call_code_p (bb_insn->insn->code)); change_p = TRUE; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing insn "); MIR_output_insn (gen_ctx->ctx, debug_file, bb_insn->insn, curr_func_item->u.func, FALSE); }); @@ -3185,7 +3195,7 @@ static int ccp_modify (gen_ctx_t gen_ctx) { MIR_remove_insn (ctx, curr_func_item, bb_insn->insn); insn->data = bb_insn; bb_insn->insn = insn; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " on insn "); MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); @@ -3196,30 +3206,35 @@ static int ccp_modify (gen_ctx_t gen_ctx) { first_insn = DLIST_HEAD (bb_insn_t, bb->bb_insns)->insn; if (first_insn->code == MIR_LABEL && (prev_insn = DLIST_PREV (MIR_insn_t, first_insn)) != NULL && prev_insn->code == MIR_JMP && prev_insn->ops[0].u.label == first_insn) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " removing useless jump insn "); MIR_output_insn (ctx, debug_file, prev_insn, curr_func_item->u.func, TRUE); fprintf (debug_file, "\n"); }); ccp_remove_insn_ssa_edges (gen_ctx, prev_insn); gen_delete_insn (gen_ctx, prev_insn); + deleted_branches_num++; } if (!MIR_branch_code_p (insn->code) || insn->code == MIR_JMP || insn->code == MIR_SWITCH || ccp_branch_update (gen_ctx, insn, &res) != CCP_CONST) continue; change_p = TRUE; if (!res) { - DEBUG ({ + edge_t e; + + DEBUG (2, { fprintf (debug_file, " removing branch insn "); MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, TRUE); fprintf (debug_file, "\n"); }); ccp_remove_insn_ssa_edges (gen_ctx, insn); gen_delete_insn (gen_ctx, insn); - delete_edge (DLIST_EL (out_edge_t, bb->out_edges, 1)); + if ((e = DLIST_EL (out_edge_t, bb->out_edges, 1)) != NULL) + delete_edge (e); /* e can be arleady deleted by previous removing an unreachable BB */ + deleted_branches_num++; } else { insn = MIR_new_insn (ctx, MIR_JMP, insn->ops[0]); /* label is always 0-th op */ - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing branch insn "); MIR_output_insn (ctx, debug_file, bb_insn->insn, curr_func_item->u.func, FALSE); fprintf (debug_file, " onto jump insn "); @@ -3234,11 +3249,15 @@ static int ccp_modify (gen_ctx_t gen_ctx) { delete_edge (DLIST_EL (out_edge_t, bb->out_edges, 0)); } } + DEBUG (1, { + fprintf (debug_file, "%5ld deleted CCP insns + %ld deleted branches\n", deleted_insns_num, + deleted_branches_num); + }); return change_p; } static int ccp (gen_ctx_t gen_ctx) { /* conditional constant propagation */ - DEBUG ({ fprintf (debug_file, " CCP analysis:\n"); }); + DEBUG (2, { fprintf (debug_file, " CCP analysis:\n"); }); curr_ccp_run++; bb_visited = temp_bitmap; initiate_ccp_info (gen_ctx); @@ -3257,7 +3276,7 @@ static int ccp (gen_ctx_t gen_ctx) { /* conditional constant propagation */ ccp_process_insn (gen_ctx, bb_insn); } } - DEBUG ({ fprintf (debug_file, " CCP modification:\n"); }); + DEBUG (2, { fprintf (debug_file, " CCP modification:\n"); }); return ccp_modify (gen_ctx); } @@ -3406,7 +3425,7 @@ static MIR_insn_t initiate_bb_live_info (gen_ctx_t gen_ctx, MIR_insn_t bb_tail_i if (insn->ops[1].mode == MIR_OP_REG) DLIST_APPEND (src_mv_t, breg_infos[reg2breg (gen_ctx, insn->ops[1].u.reg)].src_moves, mv); (*mvs_num)++; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " move with freq %10lu:", (unsigned long) mv->freq); MIR_output_insn (gen_ctx->ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); @@ -3630,7 +3649,7 @@ static void shrink_live_ranges (gen_ctx_t gen_ctx) { } n++; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "Compressing live ranges: from %d to %ld - %ld%%\n", curr_point, n, curr_point == 0 ? 100 : 100 * n / curr_point); }); @@ -3651,7 +3670,7 @@ static void shrink_live_ranges (gen_ctx_t gen_ctx) { free (lr); } } - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "Ranges after the compression:\n"); print_live_ranges (gen_ctx); }); @@ -3670,8 +3689,9 @@ static void build_live_ranges (gen_ctx_t gen_ctx) { gen_assert (VARR_LENGTH (live_range_t, var_live_ranges) == 0); for (i = 0; i < nvars; i++) VARR_PUSH (live_range_t, var_live_ranges, NULL); for (bb_t bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) { - DEBUG ( - { fprintf (debug_file, " ------BB%u end: point=%d\n", (unsigned) bb->index, curr_point); }); + DEBUG (2, { + fprintf (debug_file, " ------BB%u end: point=%d\n", (unsigned) bb->index, curr_point); + }); bitmap_clear (live_vars); if (bb->live_out != NULL) FOREACH_BITMAP_BIT (bi, bb->live_out, nel) { make_var_live (gen_ctx, nel, curr_point); @@ -3679,7 +3699,7 @@ static void build_live_ranges (gen_ctx_t gen_ctx) { for (bb_insn_t bb_insn = DLIST_TAIL (bb_insn_t, bb->bb_insns); bb_insn != NULL; bb_insn = DLIST_PREV (bb_insn_t, bb_insn)) { insn = bb_insn->insn; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " p%-5d", curr_point); print_bb_insn (gen_ctx, bb_insn, TRUE); }); @@ -3723,7 +3743,7 @@ static void build_live_ranges (gen_ctx_t gen_ctx) { FOREACH_BITMAP_BIT (bi, bb->live_in, nel) { make_var_dead (gen_ctx, nel, curr_point); } if (!bitmap_empty_p (bb->live_in)) curr_point++; } - DEBUG ({ print_live_ranges (gen_ctx); }); + DEBUG (2, { print_live_ranges (gen_ctx); }); shrink_live_ranges (gen_ctx); } @@ -3894,7 +3914,7 @@ static void fast_assign (gen_ctx_t gen_ctx) { } } } - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Assigning to %s:var=%3u, breg=%3u -- %lu\n", MIR_reg_name (gen_ctx->ctx, reg, curr_func_item->u.func), reg2var (gen_ctx, reg), breg, (unsigned long) best_loc); @@ -3974,7 +3994,7 @@ static void setup_loc_profits (gen_ctx_t gen_ctx, MIR_reg_t breg) { reg_info_t *info = &curr_breg_infos[breg]; for (mv = DLIST_HEAD (dst_mv_t, info->dst_moves); mv != NULL; mv = DLIST_NEXT (dst_mv_t, mv)) - setup_loc_profit_from_op (gen_ctx, mv->bb_insn->insn->ops[1], mv->freq); + setup_loc_profit_from_op (gen_ctx, mv->bb_insn->insn->ops[0], mv->freq); for (mv = DLIST_HEAD (src_mv_t, info->src_moves); mv != NULL; mv = DLIST_NEXT (src_mv_t, mv)) setup_loc_profit_from_op (gen_ctx, mv->bb_insn->insn->ops[1], mv->freq); } @@ -4107,7 +4127,7 @@ static void quality_assign (gen_ctx_t gen_ctx) { func_stack_slots_num = VARR_LENGTH (size_t, loc_profits) - MAX_HARD_REG - 1; } } - DEBUG ({ + DEBUG (2, { MIR_reg_t thread_breg = curr_breg_infos[breg].thread_first; fprintf (debug_file, @@ -4134,7 +4154,7 @@ static void assign (gen_ctx_t gen_ctx) { fast_assign (gen_ctx); else quality_assign (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++Disposition after assignment:"); for (i = 0; i < nregs; i++) { if (i % 8 == 0) fprintf (debug_file, "\n"); @@ -4248,7 +4268,7 @@ static void rewrite (gen_ctx_t gen_ctx) { for (i = 0; i < nops; i++) { op = &insn->ops[i]; data_mode = MIR_insn_op_mode (ctx, insn, i, &out_p); - DEBUG ({ + DEBUG (2, { if (out_p) out_op = *op; /* we don't care about multiple call outputs here */ else @@ -4294,7 +4314,7 @@ static void rewrite (gen_ctx_t gen_ctx) { if (move_code_p (insn->code)) { movs_num++; if (MIR_op_eq_p (ctx, insn->ops[0], insn->ops[1])) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "Deleting noop move "); MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, FALSE); fprintf (debug_file, " which was "); @@ -4302,20 +4322,22 @@ static void rewrite (gen_ctx_t gen_ctx) { insn->ops[1] = in_op; MIR_output_insn (ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); - deleted_movs_num++; gen_delete_insn (gen_ctx, insn); + deleted_movs_num++; } } } - DEBUG ({ + DEBUG (1, { fprintf (debug_file, - "Deleting moves: %lu deleted noop moves out of %lu non-conflicting moves " + "%5lu deleted RA noop moves out of %lu non-conflicting moves " "(%.1f%%), " - "out of %lu all moves (%.1f), out of %lu all insns (%.1f)\n", + "out of %lu all moves (%.1f%%), out of %lu all insns (%.1f%%)\n", (unsigned long) deleted_movs_num, (unsigned long) curr_cfg->non_conflicting_moves, - deleted_movs_num * 100.0 / curr_cfg->non_conflicting_moves, (unsigned long) movs_num, - deleted_movs_num * 100.0 / movs_num, (unsigned long) insns_num, - deleted_movs_num * 100.0 / insns_num); + curr_cfg->non_conflicting_moves == 0 + ? 100.0 + : deleted_movs_num * 100.0 / curr_cfg->non_conflicting_moves, + (unsigned long) movs_num, deleted_movs_num * 100.0 / movs_num, + (unsigned long) insns_num, deleted_movs_num * 100.0 / insns_num); }); } @@ -4385,6 +4407,7 @@ struct selection_ctx { static MIR_insn_code_t commutative_insn_code (MIR_insn_code_t insn_code) { switch (insn_code) { + /* we can not change fp comparison and branches because NaNs */ case MIR_ADD: case MIR_ADDS: case MIR_FADD: @@ -4453,30 +4476,6 @@ static MIR_insn_code_t commutative_insn_code (MIR_insn_code_t insn_code) { case MIR_BGES: return MIR_BLES; case MIR_UBGE: return MIR_UBLE; case MIR_UBGES: return MIR_UBLES; - case MIR_FLT: return MIR_FGT; - case MIR_DLT: return MIR_DGT; - case MIR_LDLT: return MIR_LDGT; - case MIR_FLE: return MIR_FGE; - case MIR_DLE: return MIR_DGE; - case MIR_LDLE: return MIR_LDGE; - case MIR_FGT: return MIR_FLT; - case MIR_DGT: return MIR_DLT; - case MIR_LDGT: return MIR_LDLT; - case MIR_FGE: return MIR_FLE; - case MIR_DGE: return MIR_DLE; - case MIR_LDGE: return MIR_LDLE; - case MIR_FBLT: return MIR_FBGT; - case MIR_DBLT: return MIR_DBGT; - case MIR_LDBLT: return MIR_LDBGT; - case MIR_FBLE: return MIR_FBGE; - case MIR_DBLE: return MIR_DBGE; - case MIR_LDBLE: return MIR_LDBGE; - case MIR_FBGT: return MIR_FBLT; - case MIR_DBGT: return MIR_DBLT; - case MIR_LDBGT: return MIR_LDBLT; - case MIR_FBGE: return MIR_FBLE; - case MIR_DBGE: return MIR_DBLE; - case MIR_LDBGE: return MIR_LDBLE; default: return MIR_INSN_BOUND; } } @@ -4527,14 +4526,13 @@ static void combine_process_op (gen_ctx_t gen_ctx, const MIR_op_t *op_ref, bb_in } } -static void combine_delete_insn (gen_ctx_t gen_ctx, MIR_insn_t def_insn, bb_insn_t bb_insn) { +static int combine_delete_insn (gen_ctx_t gen_ctx, MIR_insn_t def_insn, bb_insn_t bb_insn) { MIR_reg_t hr; gen_assert (def_insn->ops[0].mode == MIR_OP_HARD_REG); hr = def_insn->ops[0].u.hard_reg; - if (hreg_ref_ages_addr[hr] != curr_bb_hreg_ref_age || hreg_refs_addr[hr].del_p) return; - DEBUG ({ - // deleted_insns_num++; + if (hreg_ref_ages_addr[hr] != curr_bb_hreg_ref_age || hreg_refs_addr[hr].del_p) return FALSE; + DEBUG (2, { fprintf (debug_file, " deleting now dead insn "); print_bb_insn (gen_ctx, def_insn->data, TRUE); }); @@ -4546,6 +4544,7 @@ static void combine_delete_insn (gen_ctx_t gen_ctx, MIR_insn_t def_insn, bb_insn e.g. "hr1 = hr0; hr0 = ...; hr0 = ... (deleted); ...= ...hr1..." */ gen_delete_insn (gen_ctx, def_insn); hreg_refs_addr[hr].del_p = TRUE; /* to exclude repetitive deletion */ + return TRUE; } static int64_t power2 (int64_t p) { @@ -4579,7 +4578,7 @@ static MIR_insn_t get_uptodate_def_insn (gen_ctx_t gen_ctx, int hr) { return def_insn; } -static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t *bb_insn_ref) { +static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t *bb_insn_ref, long *deleted_insns_num) { MIR_context_t ctx = gen_ctx->ctx; bb_insn_t bb_insn = *bb_insn_ref; MIR_insn_t insn = bb_insn->insn, def_insn; @@ -4621,21 +4620,21 @@ static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t *bb_insn_ref) { def_insn->ops[0] = saved_op; if (!success_p) return FALSE; gen_move_insn_before (gen_ctx, insn, def_insn); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " moving insn "); print_bb_insn (gen_ctx, def_insn->data, FALSE); fprintf (debug_file, " before insn "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); def_insn->ops[0] = insn->ops[0]; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing it to "); print_bb_insn (gen_ctx, def_insn->data, TRUE); - // deleted_insns_num++; fprintf (debug_file, " deleting insn "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); gen_delete_insn (gen_ctx, insn); + (*deleted_insns_num)++; *bb_insn_ref = def_insn->data; return TRUE; } @@ -4748,8 +4747,8 @@ static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t *bb_insn_ref) { } if (success_p) { gen_assert (def_insn != NULL); - combine_delete_insn (gen_ctx, def_insn, bb_insn); - DEBUG ({ + if (combine_delete_insn (gen_ctx, def_insn, bb_insn)) (*deleted_insns_num)++; + DEBUG (2, { fprintf (debug_file, " changing to "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); @@ -4805,7 +4804,8 @@ static MIR_insn_code_t get_combined_br_code (int true_p, MIR_insn_code_t cmp_cod } } -static MIR_insn_t combine_branch_and_cmp (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { +static MIR_insn_t combine_branch_and_cmp (gen_ctx_t gen_ctx, bb_insn_t bb_insn, + long *deleted_insns_num) { MIR_context_t ctx = gen_ctx->ctx; MIR_insn_t def_insn, new_insn, insn = bb_insn->insn; MIR_insn_code_t code = insn->code; @@ -4831,18 +4831,17 @@ static MIR_insn_t combine_branch_and_cmp (gen_ctx_t gen_ctx, bb_insn_t bb_insn) MIR_remove_insn (ctx, curr_func_item, insn); new_insn->data = bb_insn; bb_insn->insn = new_insn; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing to "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); - combine_delete_insn (gen_ctx, def_insn, bb_insn); + if (combine_delete_insn (gen_ctx, def_insn, bb_insn)) (*deleted_insns_num)++; return new_insn; } } -static MIR_insn_t combine_exts (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { - MIR_context_t ctx = gen_ctx->ctx; - MIR_insn_t def_insn, new_insn, insn = bb_insn->insn; +static MIR_insn_t combine_exts (gen_ctx_t gen_ctx, bb_insn_t bb_insn, long *deleted_insns_num) { + MIR_insn_t def_insn, insn = bb_insn->insn; MIR_insn_code_t code = insn->code; MIR_op_t op, saved_op; int size, size2, sign_p = FALSE, sign2_p = FALSE, ok_p; @@ -4879,40 +4878,41 @@ static MIR_insn_t combine_exts (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { insn->ops[1] = saved_op; return NULL; } - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing to "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); - combine_delete_insn (gen_ctx, def_insn, bb_insn); + if (combine_delete_insn (gen_ctx, def_insn, bb_insn)) (*deleted_insns_num)++; return insn; } else if (sign_p == sign2_p && size < size2) { saved_op = def_insn->ops[0]; def_insn->ops[0] = insn->ops[0]; - ok_p = target_insn_ok_p (gen_ctx, insn); + ok_p = target_insn_ok_p (gen_ctx, def_insn); def_insn->ops[0] = saved_op; if (!ok_p) return NULL; gen_move_insn_before (gen_ctx, insn, def_insn); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " moving insn "); print_bb_insn (gen_ctx, def_insn->data, FALSE); fprintf (debug_file, " before insn "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); def_insn->ops[0] = insn->ops[0]; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing it to "); print_bb_insn (gen_ctx, def_insn->data, TRUE); - // deleted_insns_num++; fprintf (debug_file, " deleting insn "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); gen_delete_insn (gen_ctx, insn); + (*deleted_insns_num)++; return def_insn; } return NULL; } -static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { +static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_insn, + long *deleted_insns_num) { MIR_context_t ctx = gen_ctx->ctx; MIR_insn_t def_insn = NULL, new_insns[6], insn = bb_insn->insn; MIR_insn_code_t new_code, code = insn->code; @@ -4940,17 +4940,18 @@ static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_in new_insns[0] = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], insn->ops[1]); gen_add_insn_before (gen_ctx, insn, new_insns[0]); move_bb_insn_dead_vars (new_insns[0]->data, bb_insn); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing to "); print_bb_insn (gen_ctx, new_insns[0]->data, TRUE); }); gen_delete_insn (gen_ctx, insn); if (def_insn != NULL) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " deleting now dead insn "); print_bb_insn (gen_ctx, def_insn->data, TRUE); }); gen_delete_insn (gen_ctx, def_insn); + (*deleted_insns_num)++; } return new_insns[0]; } else if (code == MIR_MUL || code == MIR_MULS || code == MIR_UDIV || code == MIR_UDIVS) { @@ -4960,7 +4961,7 @@ static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_in if ((ok_p = target_insn_ok_p (gen_ctx, new_insns[0]))) { insn->code = new_insns[0]->code; insn->ops[2] = new_insns[0]->ops[2]; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing to "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); @@ -4995,7 +4996,7 @@ static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_in } else { move_bb_insn_dead_vars (new_insns[3]->data, bb_insn); add_bb_insn_dead_var (gen_ctx, new_insns[5]->data, TEMP_INT_HARD_REG2); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " changing to "); for (n = 0; n < 6; n++) { if (n != 0) fprintf (debug_file, " "); @@ -5003,12 +5004,14 @@ static MIR_insn_t combine_mul_div_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_in } }); gen_delete_insn (gen_ctx, insn); + *deleted_insns_num -= 5; if (def_insn != NULL) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " deleting now dead insn "); print_bb_insn (gen_ctx, def_insn->data, TRUE); }); gen_delete_insn (gen_ctx, def_insn); + (*deleted_insns_num)++; } return new_insns[0]; } @@ -5036,15 +5039,13 @@ static void combine (gen_ctx_t gen_ctx) { MIR_op_t temp_op, *op_ref; MIR_reg_t early_clobbered_hard_reg1, early_clobbered_hard_reg2; int out_p, change_p, block_change_p; -#if !MIR_NO_GEN_DEBUG - size_t insns_num = 0, deleted_insns_num = 0; -#endif + long insns_num = 0, deleted_insns_num = 0; hreg_refs_addr = VARR_ADDR (hreg_ref_t, hreg_refs); hreg_ref_ages_addr = VARR_ADDR (size_t, hreg_ref_ages); for (bb_t bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) { do { - DEBUG ({ fprintf (debug_file, "Processing bb%lu\n", (unsigned long) bb->index); }); + DEBUG (2, { fprintf (debug_file, "Processing bb%lu\n", (unsigned long) bb->index); }); block_change_p = FALSE; curr_bb_hreg_ref_age++; last_mem_ref_insn_num = 0; /* means undef */ @@ -5052,8 +5053,8 @@ static void combine (gen_ctx_t gen_ctx) { bb_insn = DLIST_NEXT (bb_insn_t, bb_insn), curr_insn_num++) { insn = bb_insn->insn; nops = MIR_insn_nops (ctx, insn); - DEBUG ({ - if (insn->code != MIR_LABEL) insns_num++; + if (insn->code != MIR_LABEL) insns_num++; + DEBUG (2, { fprintf (debug_file, " Processing "); print_bb_insn (gen_ctx, bb_insn, TRUE); }); @@ -5075,15 +5076,17 @@ static void combine (gen_ctx_t gen_ctx) { last_mem_ref_insn_num = curr_insn_num; /* Change memory */ } else if (code == MIR_RET) { /* ret is transformed in machinize and should be not modified after that */ - } else if ((new_insn = combine_branch_and_cmp (gen_ctx, bb_insn)) != NULL - || (new_insn = combine_exts (gen_ctx, bb_insn)) != NULL - || (new_insn = combine_mul_div_substitute (gen_ctx, bb_insn)) != NULL) { + } else if ((new_insn = combine_branch_and_cmp (gen_ctx, bb_insn, &deleted_insns_num)) + != NULL + || (new_insn = combine_exts (gen_ctx, bb_insn, &deleted_insns_num)) != NULL + || (new_insn = combine_mul_div_substitute (gen_ctx, bb_insn, &deleted_insns_num)) + != NULL) { bb_insn = new_insn->data; insn = new_insn; nops = MIR_insn_nops (ctx, insn); block_change_p = TRUE; } else { - if ((change_p = combine_substitute (gen_ctx, &bb_insn))) { + if ((change_p = combine_substitute (gen_ctx, &bb_insn, &deleted_insns_num))) { insn = bb_insn->insn; nops = MIR_insn_nops (ctx, insn); } else if (!change_p @@ -5092,7 +5095,7 @@ static void combine (gen_ctx_t gen_ctx) { temp_op = insn->ops[1]; insn->ops[1] = insn->ops[2]; insn->ops[2] = temp_op; - if (combine_substitute (gen_ctx, &bb_insn)) { + if (combine_substitute (gen_ctx, &bb_insn, &deleted_insns_num)) { insn = bb_insn->insn; nops = MIR_insn_nops (ctx, insn); change_p = TRUE; @@ -5129,9 +5132,9 @@ static void combine (gen_ctx_t gen_ctx) { } } while (block_change_p); } - DEBUG ({ - fprintf (debug_file, " %lu deleted out of %lu (%.1f%%)\n", (long unsigned) deleted_insns_num, - (long unsigned) insns_num, 100.0 * deleted_insns_num / insns_num); + DEBUG (1, { + fprintf (debug_file, "%5ld deleted combine insns out of %ld (%.1f%%)\n", deleted_insns_num, + insns_num, 100.0 * deleted_insns_num / insns_num); }); } @@ -5177,8 +5180,9 @@ static void dead_code_elimination (gen_ctx_t gen_ctx) { int op_num, out_p, reg_def_p, dead_p, mem_p; bitmap_t live; insn_var_iterator_t insn_var_iter; + long dead_insns_num = 0; - DEBUG ({ fprintf (debug_file, "+++++++++++++Dead code elimination:\n"); }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++Dead code elimination:\n"); }); live = bitmap_create2 (DEFAULT_INIT_BITMAP_BITS_NUM); for (bb_t bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) { bitmap_copy (live, bb->live_out); @@ -5199,11 +5203,12 @@ static void dead_code_elimination (gen_ctx_t gen_ctx) { && !(insn->ops[0].mode == MIR_OP_HARD_REG && (insn->ops[0].u.hard_reg == FP_HARD_REG || insn->ops[0].u.hard_reg == SP_HARD_REG))) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Removing dead insn %-5lu", (unsigned long) bb_insn->index); MIR_output_insn (gen_ctx->ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); gen_delete_insn (gen_ctx, insn); + dead_insns_num++; continue; } if (MIR_call_code_p (insn->code)) @@ -5221,13 +5226,14 @@ static void dead_code_elimination (gen_ctx_t gen_ctx) { } } bitmap_destroy (live); + DEBUG (1, { fprintf (debug_file, "%5ld removed dead insns\n", dead_insns_num); }); } #undef live_out /* New Page */ -/* SSA dead code elimnination */ +/* SSA dead code elimination */ static int dead_insn_p (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { MIR_insn_t insn = bb_insn->insn; @@ -5260,8 +5266,9 @@ static void ssa_dead_code_elimination (gen_ctx_t gen_ctx) { MIR_reg_t var; insn_var_iterator_t iter; ssa_edge_t ssa_edge; + long dead_insns_num = 0; - DEBUG ({ fprintf (debug_file, "+++++++++++++Dead code elimination:\n"); }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++Dead code elimination:\n"); }); gen_assert (def_use_repr_p); VARR_TRUNC (bb_insn_t, dead_bb_insns, 0); for (bb_t bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = DLIST_NEXT (bb_t, bb)) @@ -5271,7 +5278,7 @@ static void ssa_dead_code_elimination (gen_ctx_t gen_ctx) { while (VARR_LENGTH (bb_insn_t, dead_bb_insns) != 0) { bb_insn = VARR_POP (bb_insn_t, dead_bb_insns); insn = bb_insn->insn; - DEBUG ({ + DEBUG (2, { fprintf (debug_file, " Removing dead insn %-5lu", (unsigned long) bb_insn->index); MIR_output_insn (gen_ctx->ctx, debug_file, insn, curr_func_item->u.func, TRUE); }); @@ -5283,7 +5290,9 @@ static void ssa_dead_code_elimination (gen_ctx_t gen_ctx) { if (dead_insn_p (gen_ctx, def)) VARR_PUSH (bb_insn_t, dead_bb_insns, def); } gen_delete_insn (gen_ctx, insn); + dead_insns_num++; } + DEBUG (1, { fprintf (debug_file, "%5ld removed SSA dead insns\n", dead_insns_num); }); } /* New Page */ @@ -5321,13 +5330,16 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { if (func_item->u.func->machine_code != NULL) { gen_assert (func_item->u.func->call_addr != NULL); _MIR_redirect_thunk (ctx, func_item->addr, func_item->u.func->call_addr); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++The code for %s has been already generated\n", MIR_item_name (ctx, func_item)); }); return func_item->addr; } - DEBUG ({ + DEBUG (0, { + fprintf (debug_file, "Code generation of function %s:\n", MIR_item_name (ctx, func_item)); + }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR before generator:\n"); MIR_output_item (ctx, debug_file, func_item); }); @@ -5335,13 +5347,13 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { _MIR_duplicate_func_insns (ctx, func_item); curr_cfg = func_item->data = gen_malloc (gen_ctx, sizeof (struct func_cfg)); build_func_cfg (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after building CFG:\n"); print_CFG (gen_ctx, TRUE, FALSE, TRUE, FALSE, NULL); }); if (optimize_level >= 2) { build_ssa (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after building SSA:\n"); print_varr_insns (gen_ctx, "undef init", undef_insns); print_varr_insns (gen_ctx, "arg init", arg_bb_insns); @@ -5351,9 +5363,9 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { } #ifndef NO_COPY_PROP if (optimize_level >= 2) { - DEBUG ({ fprintf (debug_file, "+++++++++++++Copy Propagation:\n"); }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++Copy Propagation:\n"); }); copy_prop (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after Copy Propagation:\n"); print_CFG (gen_ctx, TRUE, FALSE, TRUE, TRUE, NULL); }); @@ -5361,9 +5373,9 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { #endif /* #ifndef NO_COPY_PROP */ #ifndef NO_GVN if (optimize_level >= 2) { - DEBUG ({ fprintf (debug_file, "+++++++++++++GVN:\n"); }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++GVN:\n"); }); gvn (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after GVN:\n"); print_CFG (gen_ctx, TRUE, FALSE, TRUE, TRUE, NULL); }); @@ -5373,7 +5385,7 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { #ifndef NO_GVN if (optimize_level >= 2) { ssa_dead_code_elimination (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after dead code elimination after GVN:\n"); print_CFG (gen_ctx, TRUE, TRUE, TRUE, TRUE, NULL); }); @@ -5381,14 +5393,14 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { #endif /* #ifndef NO_GVN */ #ifndef NO_CCP if (optimize_level >= 2) { - DEBUG ({ fprintf (debug_file, "+++++++++++++CCP:\n"); }); + DEBUG (2, { fprintf (debug_file, "+++++++++++++CCP:\n"); }); if (ccp (gen_ctx)) { - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after CCP:\n"); print_CFG (gen_ctx, TRUE, FALSE, TRUE, TRUE, NULL); }); ssa_dead_code_elimination (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after dead code elimination after CCP:\n"); print_CFG (gen_ctx, TRUE, TRUE, TRUE, TRUE, NULL); }); @@ -5398,13 +5410,13 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { if (optimize_level >= 2) undo_build_ssa (gen_ctx); make_io_dup_op_insns (gen_ctx); target_machinize (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after machinize:\n"); print_CFG (gen_ctx, FALSE, FALSE, TRUE, TRUE, NULL); }); if (optimize_level != 0) build_loop_tree (gen_ctx); calculate_func_cfg_live_info (gen_ctx, optimize_level != 0); - DEBUG ({ + DEBUG (2, { add_bb_insn_dead_vars (gen_ctx); fprintf (debug_file, "+++++++++++++MIR after building live_info:\n"); print_loop_tree (gen_ctx, TRUE); @@ -5413,7 +5425,7 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { if (optimize_level != 0) build_live_ranges (gen_ctx); assign (gen_ctx); rewrite (gen_ctx); /* After rewrite the BB live info is still valid */ - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after rewrite:\n"); print_CFG (gen_ctx, FALSE, FALSE, TRUE, FALSE, NULL); }); @@ -5421,24 +5433,24 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { if (optimize_level >= 1) { calculate_func_cfg_live_info (gen_ctx, FALSE); add_bb_insn_dead_vars (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR before combine:\n"); print_CFG (gen_ctx, FALSE, FALSE, TRUE, FALSE, NULL); }); combine (gen_ctx); /* After combine the BB live info is still valid */ - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after combine:\n"); print_CFG (gen_ctx, FALSE, FALSE, TRUE, FALSE, NULL); }); dead_code_elimination (gen_ctx); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after dead code elimination after combine:\n"); print_CFG (gen_ctx, TRUE, TRUE, TRUE, FALSE, output_bb_live_info); }); } #endif /* #ifndef NO_COMBINE */ target_make_prolog_epilog (gen_ctx, func_used_hard_regs, func_stack_slots_num); - DEBUG ({ + DEBUG (2, { fprintf (debug_file, "+++++++++++++MIR after forming prolog/epilog:\n"); print_CFG (gen_ctx, FALSE, FALSE, TRUE, FALSE, NULL); }); @@ -5448,7 +5460,7 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { #if MIR_GEN_CALL_TRACE func_item->u.func->call_addr = _MIR_get_wrapper (ctx, func_item, print_and_execute_wrapper); #endif - DEBUG ({ + DEBUG (2, { _MIR_dump_code (NULL, gen_ctx->gen_num, machine_code, code_len); fprintf (debug_file, "code size = %lu:\n", (unsigned long) code_len); }); @@ -5456,9 +5468,9 @@ void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { destroy_func_live_ranges (gen_ctx); if (optimize_level != 0) destroy_loop_tree (gen_ctx, curr_cfg->root_loop_node); destroy_func_cfg (gen_ctx); - DEBUG ({ + DEBUG (0, { fprintf (debug_file, - "Generation of code for %s: %lu MIR insns (addr=%llx, len=%lu) -- time %.2f ms\n", + " Code generation for %s: %lu MIR insns (addr=%llx, len=%lu) -- time %.2f ms\n", MIR_item_name (ctx, func_item), (long unsigned) DLIST_LENGTH (MIR_insn_t, func_item->u.func->insns), (unsigned long long) machine_code, (unsigned long) code_len, @@ -5495,6 +5507,24 @@ void MIR_gen_set_debug_file (MIR_context_t ctx, int gen_num, FILE *f) { #endif } +void MIR_gen_set_debug_level (MIR_context_t ctx, int gen_num, int level) { +#if !MIR_NO_GEN_DEBUG + struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); + gen_ctx_t gen_ctx; + + if (all_gen_ctx == NULL) { + fprintf (stderr, "Calling MIR_gen_set_debug_level before MIR_gen_init -- good bye\n"); + exit (1); + } +#if !MIR_PARALLEL_GEN + gen_num = 0; +#endif + gen_assert (gen_num >= 0 && gen_num < all_gen_ctx->gens_num); + gen_ctx = &all_gen_ctx->gen_ctx[gen_num]; + debug_level = level; +#endif +} + void MIR_gen_set_optimize_level (MIR_context_t ctx, int gen_num, unsigned int level) { struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); gen_ctx_t gen_ctx; @@ -5614,6 +5644,7 @@ void MIR_gen_init (MIR_context_t ctx, int gens_num) { gen_ctx->selection_ctx = NULL; #if !MIR_NO_GEN_DEBUG debug_file = NULL; + debug_level = 100; #endif VARR_CREATE (bb_insn_t, dead_bb_insns, 16); VARR_CREATE (loop_node_t, loop_nodes, 32); @@ -5660,6 +5691,7 @@ void MIR_gen_finish (MIR_context_t ctx) { (*MIR_get_error_func (all_gen_ctx->ctx)) (MIR_parallel_error, "can not destroy generator mutex or signals"); } + VARR_DESTROY (MIR_item_t, funcs_to_generate); #endif for (int i = 0; i < all_gen_ctx->gens_num; i++) { gen_ctx = &all_gen_ctx->gen_ctx[i]; diff --git a/mir/mir-gen.h b/mir/mir-gen.h index 50381f86..77b251d1 100644 --- a/mir/mir-gen.h +++ b/mir/mir-gen.h @@ -12,8 +12,13 @@ #define MIR_NO_GEN_DEBUG 0 #endif +#ifdef __cplusplus +extern "C" { +#endif + extern void MIR_gen_init (MIR_context_t ctx, int gens_num); extern void MIR_gen_set_debug_file (MIR_context_t ctx, int gen_num, FILE *f); +extern void MIR_gen_set_debug_level (MIR_context_t ctx, int gen_num, int debug_level); extern void MIR_gen_set_optimize_level (MIR_context_t ctx, int gen_num, unsigned int level); extern void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item); extern void MIR_set_gen_interface (MIR_context_t ctx, MIR_item_t func_item); @@ -21,4 +26,8 @@ extern void MIR_set_parallel_gen_interface (MIR_context_t ctx, MIR_item_t func_i extern void MIR_set_lazy_gen_interface (MIR_context_t ctx, MIR_item_t func_item); extern void MIR_gen_finish (MIR_context_t ctx); +#ifdef __cplusplus +} +#endif + #endif /* #ifndef MIR_GEN_H */ diff --git a/mir/mir-hash.h b/mir/mir-hash.h index 49c1dc9f..aebd5cc2 100644 --- a/mir/mir-hash.h +++ b/mir/mir-hash.h @@ -3,7 +3,7 @@ Copyright (C) 2018-2021 Vladimir Makarov . */ -/* Simple high-quality multiplicative hash passing demerphq-smhsher, +/* Simple high-quality multiplicative hash passing demerphq-smhasher, faster than spooky, city, or xxhash for strings less 100 bytes. Hash for the same key can be different on different architectures. To get machine-independent hash, use mir_hash_strict which is about diff --git a/mir/mir-htab.h b/mir/mir-htab.h index 32cd5146..62587228 100644 --- a/mir/mir-htab.h +++ b/mir/mir-htab.h @@ -7,6 +7,10 @@ #include "mir-varr.h" +#ifdef __cplusplus +extern "C" { +#endif + #define FALSE 0 #define TRUE 1 @@ -242,4 +246,8 @@ DEF_VARR (htab_ind_t) #define HTAB_COLLISIONS(T, V) (HTAB_OP (T, collisions) (V)) #define HTAB_FOREACH_ELEM(T, V, F, A) (HTAB_OP (T, foreach_elem) (V, F, A)) +#ifdef __cplusplus +} +#endif + #endif /* #ifndef MIR_HTAB_H */ diff --git a/mir/mir-ppc64.c b/mir/mir-ppc64.c index 3883e746..6f74a904 100644 --- a/mir/mir-ppc64.c +++ b/mir/mir-ppc64.c @@ -96,26 +96,26 @@ static void ppc64_gen_st (VARR (uint8_t) * insn_varr, unsigned from, unsigned ba static void ppc64_gen_stdu (VARR (uint8_t) * insn_varr, int disp) { assert ((disp & 0x3) == 0); - push_insn (insn_varr, 0xf8210001 | disp & 0xfffc); /* stdu 1, disp (1) */ + push_insn (insn_varr, 0xf8210001 | (disp & 0xfffc)); /* stdu 1, disp (1) */ } static void ppc64_gen_address (VARR (uint8_t) * insn_varr, unsigned int reg, void *p) { uint64_t a = (uint64_t) p; if ((a >> 32) == 0) { if (((a >> 31) & 1) == 0) { /* lis r,0,Z2 */ - push_insn (insn_varr, (15 << 26) | (reg << 21) | (0 << 16) | (a >> 16) & 0xffff); + push_insn (insn_varr, (15 << 26) | (reg << 21) | (0 << 16) | ((a >> 16) & 0xffff)); } else { /* xor r,r,r; oris r,r,Z2 */ push_insn (insn_varr, (31 << 26) | (316 << 1) | (reg << 21) | (reg << 16) | (reg << 11)); - push_insn (insn_varr, (25 << 26) | (reg << 21) | (reg << 16) | (a >> 16) & 0xffff); + push_insn (insn_varr, (25 << 26) | (reg << 21) | (reg << 16) | ((a >> 16) & 0xffff)); } } else { /* lis r,0,Z0; ori r,r,Z1; rldicr r,r,32,31; oris r,r,Z2; ori r,r,Z3: */ push_insn (insn_varr, (15 << 26) | (reg << 21) | (0 << 16) | (a >> 48)); - push_insn (insn_varr, (24 << 26) | (reg << 21) | (reg << 16) | (a >> 32) & 0xffff); + push_insn (insn_varr, (24 << 26) | (reg << 21) | (reg << 16) | ((a >> 32) & 0xffff)); push_insn (insn_varr, (30 << 26) | (reg << 21) | (reg << 16) | 0x07c6); - push_insn (insn_varr, (25 << 26) | (reg << 21) | (reg << 16) | (a >> 16) & 0xffff); + push_insn (insn_varr, (25 << 26) | (reg << 21) | (reg << 16) | ((a >> 16) & 0xffff)); } - push_insn (insn_varr, (24 << 26) | (reg << 21) | (reg << 16) | a & 0xffff); + push_insn (insn_varr, (24 << 26) | (reg << 21) | (reg << 16) | (a & 0xffff)); } static void ppc64_gen_jump (VARR (uint8_t) * insn_varr, unsigned int reg, int call_p) { @@ -227,7 +227,6 @@ struct ppc64_va_list { void *va_arg_builtin (void *p, uint64_t t) { struct ppc64_va_list *va = p; MIR_type_t type = t; - int fp_p = type == MIR_T_F || type == MIR_T_D; void *a = va->arg_area; if (type == MIR_T_LD) { diff --git a/mir/mir-reduce.h b/mir/mir-reduce.h index 0d38f194..df07da46 100644 --- a/mir/mir-reduce.h +++ b/mir/mir-reduce.h @@ -197,7 +197,7 @@ static inline uint32_t _reduce_dict_find_longest (struct reduce_data *data, uint uint32_t *dict_pos) { uint32_t len, best_len, len_bound; uint64_t hash; - uint32_t off, ref_size, best_ref_size; + uint32_t off, ref_size, best_ref_size = 0; uint32_t curr, next; const uint8_t *s1, *s2; struct _reduce_el *el, *best_el = NULL; diff --git a/mir/mir-riscv64.c b/mir/mir-riscv64.c index dee7bb59..e3b08f50 100644 --- a/mir/mir-riscv64.c +++ b/mir/mir-riscv64.c @@ -34,7 +34,7 @@ static const int fa0_num = 10; BLK: int regs and/or on stack (w/o address) BLK1: int regs (even-odd for 9-16 bytes) and/or on stack (w/o address) - Otherwise any BLK is put somehwere on the stack and its address passed instead. + Otherwise any BLK is put somewhere on the stack and its address passed instead. All RBLK independently of size is always passed by address as an usual argument. */ void *_MIR_get_bstart_builtin (MIR_context_t ctx) { @@ -264,26 +264,22 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s 0x00058493, /* addi s1,a1,0 */ }; #endif - static const uint32_t ld_word_pat = 0x0003b003; /* ld zero,0(t2) */ - static const uint32_t ld_word_temp_pat = 0x0003b303; /* ld t1,0(t2) */ - static const uint32_t flw_word_pat = 0x0003a007; /* flw f0,0(t2) */ - static const uint32_t fld_word_pat = 0x0003b007; /* fld f0,0(t2) */ - static const uint32_t flw_word_temp_pat = 0x0003a087; /* flw ft1,0(t2) */ - static const uint32_t fld_word_temp_pat = 0x0003b087; /* fld ft1,0(t2) */ - static const uint32_t ld_temp_pat = 0x0004b303; /* ld t1,0(s1) */ - static const uint32_t st_temp_pat = 0x00613023; /* sd t1,0(sp) */ - static const uint32_t st_arg_pat = 0x0004b023; /* sd x0,0(s1) */ - static const uint32_t fsw_arg_pat = 0x0004a027; /* fsw f0,0(s1) */ - static const uint32_t fsd_arg_pat = 0x0004b027; /* fsd f0,0(s1) */ - static const uint32_t flw_temp_pat = 0x0004a087; /* flw ft1,0(s1) */ - static const uint32_t fld_temp_pat = 0x0004b087; /* fld ft1,0(s1) */ - static const uint32_t fsw_temp_pat = 0x00112027; /* fsw ft1,0(sp) */ - static const uint32_t fsd_temp_pat = 0x00113027; /* fsd ft1,0(sp) */ - static const uint32_t fmvs_arg_pat = 0xe0000053; /* fmv.x.w x0,f0 */ - static const uint32_t fmvd_arg_pat = 0xe2000053; /* fmv.x.d x0,f0 */ - static const uint32_t fmvs_temp_pat = 0xe0008353; /* fmv.x.w t1,ft1 */ - static const uint32_t fmvd_temp_pat = 0xe2008353; /* fmv.x.d t1,ft1 */ - static const uint32_t mv_t1_pat = 0x00030013; /* addi zero,t1,0 */ + static const uint32_t ld_word_pat = 0x0003b003; /* ld zero,0(t2) */ + static const uint32_t ld_word_temp_pat = 0x0003b303; /* ld t1,0(t2) */ + static const uint32_t ld_temp_pat = 0x0004b303; /* ld t1,0(s1) */ + static const uint32_t st_temp_pat = 0x00613023; /* sd t1,0(sp) */ + static const uint32_t st_arg_pat = 0x0004b023; /* sd x0,0(s1) */ + static const uint32_t fsw_arg_pat = 0x0004a027; /* fsw f0,0(s1) */ + static const uint32_t fsd_arg_pat = 0x0004b027; /* fsd f0,0(s1) */ + static const uint32_t flw_temp_pat = 0x0004a087; /* flw ft1,0(s1) */ + static const uint32_t fld_temp_pat = 0x0004b087; /* fld ft1,0(s1) */ + static const uint32_t fsw_temp_pat = 0x00112027; /* fsw ft1,0(sp) */ + static const uint32_t fsd_temp_pat = 0x00113027; /* fsd ft1,0(sp) */ + static const uint32_t fmvs_arg_pat = 0xe0000053; /* fmv.x.w x0,f0 */ + static const uint32_t fmvd_arg_pat = 0xe2000053; /* fmv.x.d x0,f0 */ + static const uint32_t fmvs_temp_pat = 0xe0008353; /* fmv.x.w t1,ft1 */ + static const uint32_t fmvd_temp_pat = 0xe2008353; /* fmv.x.d t1,ft1 */ + static const uint32_t mv_t1_pat = 0x00030013; /* addi zero,t1,0 */ static const uint32_t long_sp_add_pat[] = { 0x00000337, /* lui t1,0 */ 0x00030313, /* addi t1,t1,0 */ @@ -723,15 +719,6 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl return res; } -#if __riscv_compressed -static uint16_t save_fp = 0xe022; /* c.sdsp s0,0(sp) */ -static uint16_t restore_fp = 0x6402 /* c.ldsp s0,0(sp) */; -#else -static uint32_t save_fp = 0x00813023; /* sd s0,0(sp) */ -static uint32_t restore_fp = 0x00013403; /* ld s0,0(sp) */ -; -#endif - /* save a0-a7,fa0-fa7: */ #if __riscv_compressed static const uint16_t save_insns[] = { diff --git a/mir/mir-s390x.c b/mir/mir-s390x.c index b5596a4f..7c5f547d 100644 --- a/mir/mir-s390x.c +++ b/mir/mir-s390x.c @@ -174,7 +174,7 @@ void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) { assert (offset % 2 == 0); offset /= 2; if (-(1l << 31) < offset && offset < (1l << 31)) { /* brcl m15,offset: */ - uint64_t brcl = ((0xc0l << 40) | (15l << 36) | (4l << 32) | offset & 0xffffffff) << 16; + uint64_t brcl = ((0xc0l << 40) | (15l << 36) | (4l << 32) | (offset & 0xffffffff)) << 16; push_insns (code, (uint8_t *) &brcl, 6); } else { /* 6b:lalr r1,8+padding; 6b:lg r1,0(r1); 2b:bcr m15,r1;padding; 64-bit address: */ size_t rem = (VARR_LENGTH (uint8_t, code) + 14) % 8; @@ -262,7 +262,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s if (nres > 0 && res_types[0] == MIR_T_LD) n_gpregs++; /* ld address */ for (uint32_t i = 0; i < nargs; i++) { /* calculate param area size: */ type = arg_descs[i].type; - if (MIR_blk_type_p (type)) frame_size += (arg_descs[i].size + 7) / 8; /* blk value space */ + if (MIR_blk_type_p (type)) frame_size += (arg_descs[i].size + 7) / 8 * 8; /* blk value space */ if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) { n_fpregs++; } else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 5) { /* RBLK too */ @@ -350,6 +350,10 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s s390x_gen_ld (code, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ s390x_gen_jump (code, 14, FALSE); /* bcr m15,r14 */ res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); +#if 0 + if (getenv ("MIR_code_dump") != NULL) + _MIR_dump_code ("ffi:", 0, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); +#endif VARR_DESTROY (uint8_t, code); return res; } @@ -361,7 +365,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s call handler with args; move results to return regs; restore r7,r14,r15; return */ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handler) { MIR_func_t func = func_item->u.func; - uint32_t nres = func->nres, nargs = func->nargs; + uint32_t nres = func->nres; MIR_type_t type, *res_types = func->res_types; int disp, frame_size, local_var_size, n_gpregs, n_fpregs, va_list_disp, results_disp; VARR (uint8_t) * code; @@ -423,6 +427,10 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl s390x_gen_ld (code, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ s390x_gen_jump (code, 14, FALSE); /* bcr m15,r14 */ res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); +#if 0 + if (getenv ("MIR_code_dump") != NULL) + _MIR_dump_code (func->name, 0, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); +#endif VARR_DESTROY (uint8_t, code); return res; } diff --git a/mir/mir-varr.h b/mir/mir-varr.h index ea3a8a2e..0402d818 100644 --- a/mir/mir-varr.h +++ b/mir/mir-varr.h @@ -9,6 +9,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #if !defined(VARR_ENABLE_CHECKING) && !defined(NDEBUG) #define VARR_ENABLE_CHECKING #endif @@ -169,4 +173,8 @@ static inline void MIR_VARR_NO_RETURN mir_varr_error (const char *message) { #define VARR_FOREACH_ELEM(T, V, I, EL) \ for ((I) = 0; (I) >= VARR_LENGTH (T, V) ? 0 : (EL = VARR_GET (T, V, I), 1); (I)++) +#ifdef __cplusplus +} +#endif + #endif /* #ifndef MIR_VARR_H */ diff --git a/mir/mir.c b/mir/mir.c index fe37fc1d..aab33b5b 100644 --- a/mir/mir.c +++ b/mir/mir.c @@ -521,6 +521,15 @@ const char *MIR_item_name (MIR_context_t ctx, MIR_item_t item) { } } +MIR_func_t MIR_get_item_func (MIR_context_t ctx, MIR_item_t item) { + mir_assert (item != NULL); + if (item->item_type == MIR_func_item) { + return item->u.func; + } else { + return NULL; + } +} + #if !MIR_NO_IO static void io_init (MIR_context_t ctx); static void io_finish (MIR_context_t ctx); @@ -587,7 +596,9 @@ static void parallel_error (MIR_context_t ctx, const char *err_message) { MIR_get_error_func (ctx) (MIR_parallel_error, err_message); } -MIR_context_t MIR_init (void) { +double _MIR_get_api_version (void) { return MIR_API_VERSION; } + +MIR_context_t _MIR_init (void) { MIR_context_t ctx; mir_assert (MIR_OP_BOUND < OUT_FLAG); @@ -1183,6 +1194,7 @@ static MIR_item_t new_func_arr (MIR_context_t ctx, const char *name, size_t nres MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of func %s", name); } func->name = get_ctx_str (ctx, name); + func->func_item = func_item; func->nres = nres; func->res_types = (MIR_type_t *) ((char *) func + sizeof (struct MIR_func)); for (size_t i = 0; i < nres; i++) func->res_types[i] = canon_type (res_types[i]); @@ -2172,7 +2184,9 @@ int MIR_op_eq_p (MIR_context_t ctx, MIR_op_t op1, MIR_op_t op2) { case MIR_OP_DOUBLE: return op1.u.d == op2.u.d; case MIR_OP_LDOUBLE: return op1.u.ld == op2.u.ld; case MIR_OP_REF: - return strcmp (MIR_item_name (ctx, op1.u.ref), MIR_item_name (ctx, op2.u.ref)) == 0; + if (op1.u.ref->item_type == MIR_export_item || op1.u.ref->item_type == MIR_import_item) + return strcmp (MIR_item_name (ctx, op1.u.ref), MIR_item_name (ctx, op2.u.ref)) == 0; + return op1.u.ref == op2.u.ref; case MIR_OP_STR: return op1.u.str.len == op2.u.str.len && memcmp (op1.u.str.s, op2.u.str.s, op1.u.str.len) == 0; case MIR_OP_MEM: @@ -2218,7 +2232,10 @@ htab_hash_t MIR_op_hash_step (MIR_context_t ctx, htab_hash_t h, MIR_op_t op) { u.ld = op.u.ld; return mir_hash_step (mir_hash_step (h, u.u[0]), u.u[1]); } - case MIR_OP_REF: return mir_hash_step (h, (uint64_t) MIR_item_name (ctx, op.u.ref)); + case MIR_OP_REF: + if (op.u.ref->item_type == MIR_export_item || op.u.ref->item_type == MIR_import_item) + return mir_hash_step (h, (uint64_t) MIR_item_name (ctx, op.u.ref)); + return mir_hash_step (h, (uint64_t) op.u.ref); case MIR_OP_STR: return mir_hash_step (h, (uint64_t) op.u.str.s); case MIR_OP_MEM: h = mir_hash_step (h, (uint64_t) op.u.mem.type); @@ -2314,6 +2331,7 @@ void _MIR_duplicate_func_insns (MIR_context_t ctx, MIR_item_t func_item) { mir_assert (func_item != NULL && func_item->item_type == MIR_func_item); func = func_item->u.func; mir_assert (DLIST_HEAD (MIR_insn_t, func->original_insns) == NULL); + func->original_vars_num = VARR_LENGTH (MIR_var_t, func->vars); func->original_insns = func->insns; DLIST_INIT (MIR_insn_t, func->insns); VARR_CREATE (MIR_insn_t, labels, 0); @@ -2335,6 +2353,20 @@ void _MIR_restore_func_insns (MIR_context_t ctx, MIR_item_t func_item) { mir_assert (func_item != NULL && func_item->item_type == MIR_func_item); func = func_item->u.func; + while (VARR_LENGTH (MIR_var_t, func->vars) > func->original_vars_num) { + reg_desc_t *rd; + int res_p = TRUE; + size_t rdn, tab_rdn; + MIR_var_t var = VARR_POP (MIR_var_t, func->vars); + func_regs_t func_regs = func->internal; + + rd = find_rd_by_name (ctx, var.name, func); + mir_assert (rd != NULL); + rdn = rd - VARR_ADDR (reg_desc_t, func_regs->reg_descs); + res_p &= HTAB_DO (size_t, func_regs->name2rdn_tab, rdn, HTAB_DELETE, tab_rdn); + res_p &= HTAB_DO (size_t, func_regs->reg2rdn_tab, rdn, HTAB_DELETE, tab_rdn); + mir_assert (res_p); + } while ((insn = DLIST_HEAD (MIR_insn_t, func->insns)) != NULL) MIR_remove_insn (ctx, func_item, insn); func->insns = func->original_insns; @@ -2440,7 +2472,7 @@ static void out_str (FILE *f, MIR_str_t str) { else if (str.s[i] == '\f') fprintf (f, "\\f"); else - fprintf (f, "\\%03o", str.s[i]); + fprintf (f, "\\%03o", (unsigned char) str.s[i]); fprintf (f, "\""); } @@ -2484,7 +2516,10 @@ void MIR_output_op (MIR_context_t ctx, FILE *f, MIR_op_t op, MIR_func_t func) { } break; } - case MIR_OP_REF: fprintf (f, "%s", MIR_item_name (ctx, op.u.ref)); break; + case MIR_OP_REF: + if (op.u.ref->module != func->func_item->module) fprintf (f, "%s.", op.u.ref->module->name); + fprintf (f, "%s", MIR_item_name (ctx, op.u.ref)); + break; case MIR_OP_STR: out_str (f, op.u.str); break; case MIR_OP_LABEL: output_label (ctx, f, func, op.u.label); break; default: mir_assert (FALSE); @@ -2771,7 +2806,7 @@ void MIR_simplify_op (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t insn, if (nop == 0) return; /* do nothing: it is a prototype */ if (nop == 1 && op->mode == MIR_OP_REF && (op->u.ref->item_type == MIR_import_item || op->u.ref->item_type == MIR_func_item)) - return; /* do nothing: it is an immediate oeprand */ + return; /* do nothing: it is an immediate operand */ } if (code == MIR_VA_ARG && nop == 2) return; /* do nothing: this operand is used as a type */ switch (op->mode) { @@ -3584,8 +3619,6 @@ static int mem_protect (void *addr, size_t len, int prot) { #if !defined(__APPLE__) || !defined(__aarch64__) return mprotect (addr, len, prot); #else - int res; - if (!pthread_jit_write_protect_supported_np ()) { fprintf (stderr, "unsupported pthread_jit_write_protect_np -- good bye!\n"); exit (1); @@ -3595,13 +3628,13 @@ static int mem_protect (void *addr, size_t len, int prot) { pthread_jit_write_protect_np (TRUE); sys_icache_invalidate (addr, len); } else if (0) { - if ((res = mprotect (addr, len, prot)) != 0) { + if (mprotect (addr, len, prot) != 0) { perror ("mem_protect"); fprintf (stderr, "good bye!\n"); exit (1); } } - return res; + return 0; #endif } @@ -3812,6 +3845,19 @@ static void code_finish (MIR_context_t ctx) { /* New Page */ +#if !MIR_NO_IO || !MIR_NO_SCAN +static void process_reserved_name (const char *s, const char *prefix, uint32_t *max_num) { + char *end; + uint32_t num; + size_t len = strlen (prefix); + + if (strncmp (s, prefix, len) != 0) return; + num = strtoul (s + len, &end, 10); + if (*end != '\0') return; + if (*max_num < num) *max_num = num; +} +#endif + #if !MIR_NO_IO /* Input/output of binary MIR. Major goal of binary MIR is fast @@ -4438,17 +4484,6 @@ static MIR_str_t to_str (MIR_context_t ctx, uint64_t str_num) { return VARR_GET (MIR_str_t, bin_strings, str_num); } -static void process_reserved_name (const char *s, const char *prefix, uint32_t *max_num) { - char *end; - uint32_t num; - size_t len = strlen (prefix); - - if (strncmp (s, prefix, len) != 0) return; - num = strtoul (s + len, &end, 10); - if (*end != '\0') return; - if (*max_num < num) *max_num = num; -} - static MIR_reg_t to_reg (MIR_context_t ctx, uint64_t reg_str_num, MIR_item_t func) { const char *s = to_str (ctx, reg_str_num).s; @@ -5483,7 +5518,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { const char *name; MIR_module_t module = NULL; MIR_item_t item, func = NULL; - MIR_insn_code_t insn_code; + MIR_insn_code_t insn_code = MIR_INSN_BOUND; /* for removing uninitialized warning */ MIR_insn_t insn; MIR_type_t type, data_type = MIR_T_BOUND; MIR_op_t op, *op_addr; @@ -5501,7 +5536,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { t.code = TC_NL; for (;;) { if (setjmp (error_jmp_buf)) { - while (t.code != TC_NL && t.code != EOF) + while (t.code != TC_NL && t.code != TC_EOFILE) scan_token (ctx, &t, get_string_char, unget_string_char); if (t.code == TC_EOFILE) break; } @@ -5515,6 +5550,8 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { scan_token (ctx, &t, get_string_char, unget_string_char); if (t.code != TC_COL) break; VARR_PUSH (label_name_t, label_names, name); + if (module != NULL) + process_reserved_name (name, TEMP_ITEM_NAME_PREFIX, &module->last_temp_item_num); scan_token (ctx, &t, get_string_char, unget_string_char); if (t.code == TC_NL) scan_token (ctx, &t, get_string_char, unget_string_char); /* label_names without insn */ @@ -5649,7 +5686,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { scan_error (ctx, local_p ? "wrong var" : "wrong arg"); } else { op.u.mem.base = t.u.i; - if (t.u.i <= 0 || t.u.i >= (1ll << sizeof (MIR_reg_t) * 8)) + if (t.u.i < 0 || t.u.i >= (1ll << sizeof (MIR_reg_t) * 8)) scan_error (ctx, "invalid block arg size"); scan_token (ctx, &t, get_string_char, unget_string_char); if (t.code != TC_LEFT_PAR) scan_error (ctx, "wrong block arg"); @@ -5899,8 +5936,12 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { if (func != NULL) MIR_append_insn (ctx, func, insn); } } - if (func != NULL) scan_error (ctx, "absent endfunc"); - if (module != NULL) scan_error (ctx, "absent endmodule"); + if (func != NULL) { + if (!setjmp (error_jmp_buf)) scan_error (ctx, "absent endfunc"); + } + if (module != NULL) { + if (!setjmp (error_jmp_buf)) scan_error (ctx, "absent endmodule"); + } if (VARR_LENGTH (char, error_msg_buf) != 0) MIR_get_error_func (ctx) (MIR_syntax_error, VARR_ADDR (char, error_msg_buf)); } diff --git a/mir/mir.h b/mir/mir.h index c02a744a..f9cac07d 100644 --- a/mir/mir.h +++ b/mir/mir.h @@ -6,6 +6,10 @@ #define MIR_H +#ifdef __cplusplus +extern "C" { +#endif + #if defined(_WIN32) && !defined(_WIN64) #error "MIR does not work on 32-bit Windows" #endif @@ -17,6 +21,8 @@ #include "mir-varr.h" #include "mir-htab.h" +#define MIR_API_VERSION 0.1 + #ifdef NDEBUG static inline int mir_assert (int cond) { return 0 && cond; } #else @@ -106,11 +112,11 @@ typedef pthread_attr_t mir_thread_attr_t; #define INSN_EL(i) MIR_##i /* The most MIR insns have destination operand and one or two source - operands. The destination can be ony a register or memory. + operands. The destination can be only a register or memory. There are additional constraints on insn operands: - o A register in porgram can contain only one type values: integer, + o A register in program can contain only one type values: integer, float, double, or long double. o Operand types should be what the insn expects */ typedef enum { @@ -139,7 +145,7 @@ typedef enum { REP7 (INSN_EL, LE, LES, ULE, ULES, FLE, DLE, LDLE), /* Less or equal */ REP7 (INSN_EL, GT, GTS, UGT, UGTS, FGT, DGT, LDGT), /* Greater then */ REP7 (INSN_EL, GE, GES, UGE, UGES, FGE, DGE, LDGE), /* Greater or equal */ - /* Uncoditional (1 operand) and conditional (2 operands) branch + /* Unconditional (1 operand) and conditional (2 operands) branch insns. The first operand is a label. */ REP5 (INSN_EL, JMP, BT, BTS, BF, BFS), /* Compare and branch (3 operand) insns. The first operand is the @@ -156,7 +162,7 @@ typedef enum { REP2 (INSN_EL, CALL, INLINE), /* 1st operand is an index, subsequent ops are labels to which goto according the index (1st label has index zero). The insn - behaviour is undefined if there is no label for the index. */ + behavior is undefined if there is no label for the index. */ INSN_EL (SWITCH), /* 1 operand insn: */ INSN_EL (RET), @@ -312,6 +318,8 @@ DEF_VARR (MIR_var_t); /* Function definition */ typedef struct MIR_func { const char *name; + MIR_item_t func_item; + size_t original_vars_num; DLIST (MIR_insn_t) insns, original_insns; uint32_t nres, nargs, last_temp_num, n_inlines; MIR_type_t *res_types; @@ -452,8 +460,20 @@ static inline int MIR_branch_code_p (MIR_insn_code_t code) { return (code == MIR_JMP || MIR_int_branch_code_p (code) || MIR_FP_branch_code_p (code)); } +extern double _MIR_get_api_version (void); +extern MIR_context_t _MIR_init (void); + /* Use only the following API to create MIR code. */ -extern MIR_context_t MIR_init (void); +static inline MIR_context_t MIR_init (void) { + if (MIR_API_VERSION != _MIR_get_api_version ()) { + fprintf (stderr, + "mir.h header has version %g different from used mir code version %g -- good bye!\n", + MIR_API_VERSION, _MIR_get_api_version ()); + exit (1); + } + return _MIR_init (); +} + extern void MIR_finish (MIR_context_t ctx); extern MIR_module_t MIR_new_module (MIR_context_t ctx, const char *name); @@ -488,6 +508,7 @@ extern MIR_item_t MIR_new_vararg_func_arr (MIR_context_t ctx, const char *name, extern MIR_item_t MIR_new_vararg_func (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, size_t nargs, ...); extern const char *MIR_item_name (MIR_context_t ctx, MIR_item_t item); +extern MIR_func_t MIR_get_item_func(MIR_context_t ctx, MIR_item_t item); extern MIR_reg_t MIR_new_func_reg (MIR_context_t ctx, MIR_func_t func, MIR_type_t type, const char *name); extern void MIR_finish_func (MIR_context_t ctx); @@ -589,6 +610,8 @@ extern void MIR_interp_arr_varg (MIR_context_t ctx, MIR_item_t func_item, MIR_va extern void MIR_set_interp_interface (MIR_context_t ctx, MIR_item_t func_item); /* Private: */ +extern double _MIR_get_api_version (void); +extern MIR_context_t _MIR_init (void); extern const char *_MIR_uniq_string (MIR_context_t ctx, const char *str); extern int _MIR_reserved_ref_name_p (MIR_context_t ctx, const char *name); extern int _MIR_reserved_name_p (MIR_context_t ctx, const char *name); @@ -661,4 +684,8 @@ extern void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void * extern void _MIR_dump_code (const char *name, int index, uint8_t *code, size_t code_len); +#ifdef __cplusplus +} +#endif + #endif /* #ifndef MIR_H */