From e6890743f04dc19ec19260d9d4b21c1efc2a0dc2 Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Mon, 28 Dec 2020 19:28:38 +0000 Subject: [PATCH] issue #169 Update MIR --- mir/c2mir/aarch64/caarch64.h | 5 + mir/c2mir/c2mir.c | 471 +++++++++++++++++++++------- mir/c2mir/ppc64/cppc64.h | 5 + mir/c2mir/s390x/cs390x.h | 5 + mir/c2mir/x86_64/cx86_64-ABI-code.c | 10 +- mir/c2mir/x86_64/cx86_64.h | 9 +- mir/mir-aarch64.c | 4 +- mir/mir-gen-aarch64.c | 2 +- mir/mir-gen-x86_64.c | 24 +- mir/mir-interp.c | 69 ++-- mir/mir-ppc64.c | 4 +- mir/mir-s390x.c | 2 +- mir/mir-x86_64.c | 144 +++++---- mir/mir.c | 94 +++--- mir/mir.h | 6 +- 15 files changed, 607 insertions(+), 247 deletions(-) diff --git a/mir/c2mir/aarch64/caarch64.h b/mir/c2mir/aarch64/caarch64.h index 0ca92b7..2f6b0c8 100644 --- a/mir/c2mir/aarch64/caarch64.h +++ b/mir/c2mir/aarch64/caarch64.h @@ -28,12 +28,17 @@ typedef uint16_t mir_ushort; typedef uint32_t mir_uint; typedef uint64_t mir_ulong; typedef uint64_t mir_ullong; +typedef uint32_t mir_wchar; +typedef uint16_t mir_char16; +typedef uint32_t mir_char32; #define MIR_UCHAR_MAX UINT8_MAX #define MIR_USHORT_MAX UINT16_MAX #define MIR_UINT_MAX UINT32_MAX #define MIR_ULONG_MAX UINT64_MAX #define MIR_ULLONG_MAX UINT64_MAX +#define MIR_WCHAR_MIN 0 +#define MIR_WCHAR_MAX UINT32_MAX typedef mir_schar mir_char; #define MIR_CHAR_MIN MIR_SCHAR_MIN diff --git a/mir/c2mir/c2mir.c b/mir/c2mir/c2mir.c index e021a14..9e12bc2 100644 --- a/mir/c2mir/c2mir.c +++ b/mir/c2mir/c2mir.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "time.h" #include "c2mir.h" @@ -452,7 +453,8 @@ void c2mir_finish (MIR_context_t ctx) { '}'. The input is parse tokens and the output is the following AST nodes (the AST root is transl_unit): -expr : N_I | N_L | N_LL | N_U | N_UL | N_ULL | N_F | N_D | N_LD | N_CH | N_STR | N_ID +expr : N_I | N_L | N_LL | N_U | N_UL | N_ULL | N_F | N_D | N_LD + | N_CH | N_CH16 | N_CH32 | N_STR | N_STR16 | N_STR32 | N_ID | N_ADD (expr) | N_SUB (expr) | N_ADD (expr, expr) | N_SUB (expr, expr) | N_MUL (expr, expr) | N_DIV (expr, expr) | N_MOD (expr, expr) | N_LSH (expr, expr) | N_RSH (expr, expr) @@ -479,7 +481,7 @@ stmt: compound_stmt | N_IF(N_LIST:(label)*, expr, stmt, stmt?) | N_RETURN(N_LIST:(label)*, expr?) | N_EXPR(N_LIST:(label)*, expr) compound_stmt: N_BLOCK(N_LIST:(label)*, N_LIST:(declaration | stmt)*) declaration: N_SPEC_DECL(N_SHARE(declaration_specs), declarator?, initializer?) | st_assert -st_assert: N_ST_ASSERT(const_expr, N_STR) +st_assert: N_ST_ASSERT(const_expr, N_STR | N_STR16 | N_STR32) declaration_specs: N_LIST:(align_spec|sc_spec|type_qual|func_spec|type_spec)* align_spec: N_ALIGNAS(type_name|const_expr) sc_spec: N_TYPEDEF|N_EXTERN|N_STATIC|N_AUTO|N_REGISTER|N_THREAD_LOCAL @@ -549,7 +551,8 @@ 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, STR, ID, COMMA, ANDAND, OROR), + REP8 (NODE_EL, D, LD, CH, CH16, CH32, STR, STR16, STR32), + REP4 (NODE_EL, ID, COMMA, ANDAND, OROR), 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), @@ -580,7 +583,7 @@ struct node { mir_char ch; mir_long l; mir_llong ll; - mir_ulong ul; + mir_ulong ul; /* includes CH16 and CH32 */ mir_ullong ull; mir_float f; mir_double d; @@ -693,67 +696,66 @@ static node_t new_pos_node4 (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p, node_t } static node_t new_ch_node (c2m_ctx_t c2m_ctx, int ch, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_CH, p); - n->u.ch = ch; return n; } +static node_t new_ch16_node (c2m_ctx_t c2m_ctx, mir_ulong ch, pos_t p) { + node_t n = new_pos_node (c2m_ctx, N_CH16, p); + n->u.ul = ch; + return n; +} +static node_t new_ch32_node (c2m_ctx_t c2m_ctx, mir_ulong ch, pos_t p) { + node_t n = new_pos_node (c2m_ctx, N_CH32, p); + n->u.ul = ch; + return n; +} static node_t new_i_node (c2m_ctx_t c2m_ctx, long l, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_I, p); - n->u.l = l; return n; } static node_t new_l_node (c2m_ctx_t c2m_ctx, long l, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_L, p); - n->u.l = l; return n; } static node_t new_ll_node (c2m_ctx_t c2m_ctx, long long ll, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_LL, p); - n->u.ll = ll; return n; } static node_t new_u_node (c2m_ctx_t c2m_ctx, unsigned long ul, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_U, p); - n->u.ul = ul; return n; } static node_t new_ul_node (c2m_ctx_t c2m_ctx, unsigned long ul, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_UL, p); - n->u.ul = ul; return n; } static node_t new_ull_node (c2m_ctx_t c2m_ctx, unsigned long long ull, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_ULL, p); - n->u.ull = ull; return n; } static node_t new_f_node (c2m_ctx_t c2m_ctx, float f, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_F, p); - n->u.f = f; return n; } static node_t new_d_node (c2m_ctx_t c2m_ctx, double d, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_D, p); - n->u.d = d; return n; } static node_t new_ld_node (c2m_ctx_t c2m_ctx, long double ld, pos_t p) { node_t n = new_pos_node (c2m_ctx, N_LD, p); - n->u.ld = ld; return n; } static node_t new_str_node (c2m_ctx_t c2m_ctx, node_code_t nc, str_t s, pos_t p) { node_t n = new_pos_node (c2m_ctx, nc, p); - n->u.s = s; return n; } @@ -1036,30 +1038,87 @@ static void remove_string_stream (c2m_ctx_t c2m_ctx) { cs = VARR_LAST (stream_t, streams); } -static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp) { - int i, str_len, curr_c; +#define MAX_UTF8 0x1FFFFF + +/* We use UTF-32 for 32-bit wchars and UTF-16 for 16-bit wchar (LE/BE + depending on endianess of the target), UTF-8 for anything else. */ +static void push_str_char (c2m_ctx_t c2m_ctx, VARR (char) * temp, uint64_t ch, int type) { + int i, len = 0; + + switch (type) { + case ' ': + if (ch <= 0xFF) { + VARR_PUSH (char, temp, ch); + return; + } + /* Fall through */ + case '8': + if (ch <= 0x7F) { + VARR_PUSH (char, temp, ch); + } else if (ch <= 0x7FF) { + VARR_PUSH (char, temp, 0xC0 | (ch >> 6)); + VARR_PUSH (char, temp, 0x80 | (ch & 0x3F)); + } else if (ch <= 0xFFFF) { + VARR_PUSH (char, temp, 0xE0 | (ch >> 12)); + VARR_PUSH (char, temp, 0x80 | ((ch >> 6) & 0x3F)); + VARR_PUSH (char, temp, 0x80 | (ch & 0x3F)); + } else { + assert (ch <= MAX_UTF8); + VARR_PUSH (char, temp, 0xF0 | (ch >> 18)); + VARR_PUSH (char, temp, 0x80 | ((ch >> 12) & 0x3F)); + VARR_PUSH (char, temp, 0x80 | ((ch >> 6) & 0x3F)); + VARR_PUSH (char, temp, 0x80 | (ch & 0x3F)); + } + return; + case 'L': + if (sizeof (mir_wchar) == 4) goto U; + /* Fall through */ + case 'u': len = 2; break; + case 'U': + U: + len = 4; + break; + default: assert (FALSE); + } +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + for (i = 0; i < len; i++) VARR_PUSH (char, temp, (ch >> i * 8) & 0xff); +#else + for (i = len - 1; i >= 0; i--) VARR_PUSH (char, temp, (ch >> i * 8) & 0xff); +#endif +} + +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); + int start = type == ' ' ? 0 : type == '8' ? 2 : 1; + int string_p = t->repr[start] == '"'; const char *str; assert (t->code == T_STR || t->code == T_CH); str = t->repr; VARR_TRUNC (char, temp, 0); str_len = strlen (str); - assert (str_len >= 2 && (str[0] == '"' || str[0] == '\'') && str[0] == str[str_len - 1]); - for (i = 1; i < str_len - 1; i++) { - curr_c = str[i]; + assert (str_len >= start + 2 && (str[start] == '"' || str[start] == '\'') + && str[start] == str[str_len - 1]); + for (i = start + 1; i < str_len - 1; i++) { + if (!string_p && last_c >= 0) error (c2m_ctx, t->pos, "multibyte character"); + last_c = curr_c = str[i]; if (curr_c != '\\') { - VARR_PUSH (char, temp, curr_c); + push_str_char (c2m_ctx, temp, curr_c, type); continue; } - curr_c = str[++i]; + last_c = curr_c = str[++i]; switch (curr_c) { - case 'a': curr_c = '\a'; break; - case 'b': curr_c = '\b'; break; - case 'n': curr_c = '\n'; break; - case 'f': curr_c = '\f'; break; - case 'r': curr_c = '\r'; break; - case 't': curr_c = '\t'; break; - case 'v': curr_c = '\v'; break; + case 'a': last_c = curr_c = '\a'; break; + case 'b': last_c = curr_c = '\b'; break; + case 'n': last_c = curr_c = '\n'; break; + case 'f': last_c = curr_c = '\f'; break; + case 'r': last_c = curr_c = '\r'; break; + case 't': last_c = curr_c = '\t'; break; + case 'v': last_c = curr_c = '\v'; break; case '\\': case '\'': case '\?': @@ -1067,7 +1126,7 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp) { case 'e': (c2m_options->pedantic_p ? error : warning) (c2m_ctx, t->pos, "non-standard escape sequence \\e"); - curr_c = '\033'; + last_c = curr_c = '\033'; break; case '0': case '1': @@ -1077,7 +1136,7 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp) { case '5': case '6': case '7': { - unsigned long v = curr_c - '0'; + uint64_t v = curr_c - '0'; curr_c = str[++i]; if (!isdigit (curr_c) || curr_c == '8' || curr_c == '9') { @@ -1090,42 +1149,77 @@ static void set_string_val (c2m_ctx_t c2m_ctx, token_t t, VARR (char) * temp) { else v = v * 8 + curr_c - '0'; } - curr_c = v; + last_c = curr_c = v; break; } case 'x': case 'X': { int first_p = TRUE; - unsigned long v = 0; + uint64_t v = 0; for (i++;; i++) { curr_c = str[i]; if (!isxdigit (curr_c)) break; first_p = FALSE; - v *= 16; - v += (isdigit (curr_c) ? curr_c - '0' - : islower (curr_c) ? curr_c - 'a' + 10 : curr_c - 'A' + 10); + if (v <= UINT32_MAX) { + v *= 16; + v += (isdigit (curr_c) ? curr_c - '0' + : islower (curr_c) ? curr_c - 'a' + 10 : curr_c - 'A' + 10); + } } - if (first_p) + if (first_p) { error (c2m_ctx, t->pos, "wrong hexadecimal char %c", curr_c); - else if (v > MIR_UCHAR_MAX) + } else if (v > max_char) { (c2m_options->pedantic_p ? error : warning) (c2m_ctx, t->pos, "too big hexadecimal char 0x%x", v); - curr_c = v; + curr_c = max_char; + } + last_c = curr_c = v; i--; break; } + case 'u': + case 'U': { + int n, start_c = curr_c, digits_num = curr_c == 'u' ? 4 : 8; + int64_t v = 0; + + for (i++, n = 0; n < digits_num; i++, n++) { + 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); + } + last_c = curr_c = v; + if (n < digits_num) { + error (c2m_ctx, t->pos, "unfinished \\%c", start_c); + } else if (v > max_char && (!string_p || (type != ' ' && type != '8') || v > MAX_UTF8)) { + (c2m_options->pedantic_p ? error : warning) (c2m_ctx, t->pos, + "too big universal char 0x%lx in \\%c", + (unsigned long) v, start_c); + last_c = curr_c = max_char; + } else if ((0xD800 <= v && v <= 0xDFFF) + || (v < 0xA0 && v != 0x24 && v != 0x40 && v != 0x60)) { + error (c2m_ctx, t->pos, "usage of reserved value 0x%lx in \\%c", (unsigned long) v, + start_c); + curr_c = -1; + } + if (n < digits_num) i--; + break; + } default: error (c2m_ctx, t->pos, "wrong escape char 0x%x", curr_c); curr_c = -1; } - if (t->repr[0] == '\'' || curr_c >= 0) VARR_PUSH (char, temp, curr_c); + if (!string_p || curr_c >= 0) push_str_char (c2m_ctx, temp, curr_c, type); } - VARR_PUSH (char, temp, '\0'); - if (t->repr[0] == '"') + push_str_char (c2m_ctx, temp, '\0', type); + if (string_p) t->node->u.s = uniq_str (c2m_ctx, VARR_ADDR (char, temp), VARR_LENGTH (char, temp)); - else if (VARR_LENGTH (char, temp) == 1) + else if (last_c < 0) error (c2m_ctx, t->pos, "empty char constant"); + else if (type == 'U' || type == 'u' || type == 'L') + t->node->u.ul = last_c; else - t->node->u.ch = VARR_GET (char, temp, 0); + t->node->u.ch = last_c; } static token_t new_id_token (c2m_ctx_t c2m_ctx, pos_t pos, const char *id_str) { @@ -1138,7 +1232,7 @@ static token_t new_id_token (c2m_ctx_t c2m_ctx, pos_t pos, const char *id_str) { } static token_t get_next_pptoken_1 (c2m_ctx_t c2m_ctx, int header_p) { - int start_c, curr_c, nl_p, comment_char; + int start_c, curr_c, nl_p, comment_char, wide_type; pos_t pos; if (cs->fname != NULL && VARR_LENGTH (token_t, buffered_tokens) != 0) @@ -1495,7 +1589,9 @@ static token_t get_next_pptoken_1 (c2m_ctx_t c2m_ctx, int header_p) { N_IGNORE); } case '\'': - case '\"': { /* ??? unicode and wchar */ + case '\"': + wide_type = ' '; + literal : { token_t t; int stop = curr_c; @@ -1518,15 +1614,45 @@ static token_t get_next_pptoken_1 (c2m_ctx_t c2m_ctx, int header_p) { VARR_PUSH (char, symbol_text, stop); } VARR_PUSH (char, symbol_text, '\0'); - t = (stop == '\"' ? new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_STR, - new_str_node (c2m_ctx, N_STR, empty_str, pos)) - : new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_CH, - new_ch_node (c2m_ctx, ' ', pos))); - set_string_val (c2m_ctx, t, symbol_text); + if (wide_type == 'U' || (sizeof (mir_wchar) == 4 && wide_type == 'L')) { + t = (stop == '\"' ? new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_STR, + new_str_node (c2m_ctx, N_STR32, empty_str, pos)) + : new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_CH, + new_ch32_node (c2m_ctx, ' ', pos))); + } else if (wide_type == 'u' || wide_type == 'L') { + t = (stop == '\"' ? new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_STR, + new_str_node (c2m_ctx, N_STR16, empty_str, pos)) + : new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_CH, + new_ch16_node (c2m_ctx, ' ', pos))); + } else { + t = (stop == '\"' ? new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_STR, + new_str_node (c2m_ctx, N_STR, empty_str, pos)) + : new_node_token (c2m_ctx, pos, VARR_ADDR (char, symbol_text), T_CH, + new_ch_node (c2m_ctx, ' ', pos))); + } + set_string_val (c2m_ctx, t, symbol_text, wide_type); return t; } default: if (isalpha (curr_c) || curr_c == '_') { + if (curr_c == 'L' || curr_c == 'u' || curr_c == 'U') { + wide_type = curr_c; + if ((curr_c = cs_get (c2m_ctx)) == '\"' || curr_c == '\'') { + VARR_PUSH (char, symbol_text, wide_type); + goto literal; + } else if (wide_type == 'u' && curr_c == '8') { + wide_type = '8'; + if ((curr_c = cs_get (c2m_ctx)) == '\"') { + VARR_PUSH (char, symbol_text, 'u'); + VARR_PUSH (char, symbol_text, '8'); + goto literal; + } + cs_unget (c2m_ctx, curr_c); + curr_c = '8'; + } + cs_unget (c2m_ctx, curr_c); + curr_c = wide_type; + } pos = cs->pos; do { VARR_PUSH (char, symbol_text, curr_c); @@ -1624,7 +1750,7 @@ static token_t token_stringify (c2m_ctx_t c2m_ctx, token_t t, VARR (token_t) * t VARR_PUSH (char, temp_string, '"'); VARR_PUSH (char, temp_string, '\0'); t->repr = uniq_cstr (c2m_ctx, VARR_ADDR (char, temp_string)).s; - set_string_val (c2m_ctx, t, temp_string); + set_string_val (c2m_ctx, t, temp_string, ' '); return t; } @@ -2316,7 +2442,6 @@ static pos_t check_line_directive_args (c2m_ctx_t c2m_ctx, VARR (token_t) * buff } static void check_pragma (c2m_ctx_t c2m_ctx, token_t t, VARR (token_t) * tokens) { - pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; token_t *tokens_arr = VARR_ADDR (token_t, tokens); size_t i, tokens_len = VARR_LENGTH (token_t, tokens); @@ -2325,6 +2450,7 @@ static void check_pragma (c2m_ctx_t c2m_ctx, token_t t, VARR (token_t) * tokens) #ifdef _WIN32 if (i + 1 == tokens_len && tokens_arr[i]->code == T_ID && strcmp (tokens_arr[i]->repr, "once") == 0) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; VARR_PUSH (char_ptr_t, once_include_files, cs->fname); return; } @@ -2828,7 +2954,7 @@ static void process_directive (c2m_ctx_t c2m_ctx) { error (c2m_ctx, t1->pos, "garbage at the end of #%s", t1->repr); skip_nl (c2m_ctx, NULL, NULL); } - if (VARR_LENGTH (ifstate_t, ifs) < cs->ifs_length_at_stream_start) + if (VARR_LENGTH (ifstate_t, ifs) <= cs->ifs_length_at_stream_start) error (c2m_ctx, t1->pos, "unmatched #%s", t1->repr); else if (strcmp (t1->repr, "endif") == 0) { pop_ifstate (c2m_ctx); @@ -3241,6 +3367,8 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { else res.u.i_val = tree->u.ch; break; + case N_CH16: + case N_CH32: res.u.u_val = tree->u.ul; break; case N_I: case N_L: res.uns_p = FALSE; @@ -3428,7 +3556,7 @@ static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { VARR_PUSH (char, temp_string, '\0'); t = new_node_token (c2m_ctx, t->pos, VARR_ADDR (char, temp_string), T_STR, new_str_node (c2m_ctx, N_STR, empty_str, t->pos)); - set_string_val (c2m_ctx, t, temp_string); + set_string_val (c2m_ctx, t, temp_string, ' '); out_token (c2m_ctx, t); } else if (strcmp (t->repr, "__LINE__") == 0) { char str[50]; @@ -3541,17 +3669,48 @@ static void pre_out (c2m_ctx_t c2m_ctx, token_t t) { if (t->code == T_STR && VARR_LENGTH (token_t, recorded_tokens) != 0 && VARR_LAST (token_t, recorded_tokens)->code == T_STR) { /* concat strings */ token_t last_t = VARR_POP (token_t, recorded_tokens); + int type = ' ', last_t_quot_off = 0, t_quot_off = 0, err_p = FALSE; + const char *s; VARR_TRUNC (char, temp_string, 0); - for (const char *s = last_t->repr; *s != 0; s++) VARR_PUSH (char, temp_string, *s); - assert (VARR_LAST (char, temp_string) == '"' && t->repr[0] == '"'); + if (last_t->repr[0] == 'u' && last_t->repr[1] == '8') { + err_p = t->repr[0] != '\"' && (t->repr[0] != 'u' || t->repr[1] != '8'); + last_t_quot_off = 2; + } else if (last_t->repr[0] == 'L' || last_t->repr[0] == 'u' || last_t->repr[0] == 'U') { + err_p = t->repr[0] != '\"' && (t->repr[0] != last_t->repr[0] || t->repr[1] == '8'); + last_t_quot_off = 1; + } + if (t->repr[0] == 'u' && t->repr[1] == '8') { + err_p = last_t->repr[0] != '\"' && (last_t->repr[0] != 'u' || last_t->repr[1] != '8'); + t_quot_off = 2; + } else if (t->repr[0] == 'L' || t->repr[0] == 'u' || t->repr[0] == 'U') { + err_p = last_t->repr[0] != '\"' && (t->repr[0] != last_t->repr[0] || last_t->repr[1] == '8'); + t_quot_off = 1; + } + if (err_p) error (c2m_ctx, t->pos, "concatenation of different type string literals"); + if (sizeof (mir_wchar) == 4 && (last_t->repr[0] == 'L' || t->repr[0] == 'L')) { + type = 'L'; + } else if (last_t->repr[0] == 'U' || t->repr[0] == 'U') { + type = 'U'; + } else if (last_t->repr[0] == 'L' || t->repr[0] == 'L') { + type = 'L'; + } else if ((last_t->repr[0] == 'u' && last_t->repr[1] == '8') + || (t->repr[0] == 'u' && t->repr[1] == '8')) { + VARR_PUSH (char, temp_string, 'u'); + type = '8'; + } else if ((last_t->repr[0] == 'u' || t->repr[0] == 'u')) { + type = 'u'; + } + if (type != ' ') VARR_PUSH (char, temp_string, type); + for (s = last_t->repr + last_t_quot_off; *s != 0; s++) VARR_PUSH (char, temp_string, *s); + assert (VARR_LAST (char, temp_string) == '"'); VARR_POP (char, temp_string); - for (const char *s = &t->repr[1]; *s != 0; s++) VARR_PUSH (char, temp_string, *s); + for (s = t->repr + t_quot_off + 1; *s != 0; s++) VARR_PUSH (char, temp_string, *s); t = last_t; assert (VARR_LAST (char, temp_string) == '"'); VARR_PUSH (char, temp_string, '\0'); t->repr = uniq_cstr (c2m_ctx, VARR_ADDR (char, temp_string)).s; - set_string_val (c2m_ctx, t, temp_string); + set_string_val (c2m_ctx, t, temp_string, type); } VARR_PUSH (token_t, recorded_tokens, t); } @@ -6393,7 +6552,6 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec } else { mir_llong curr_val = -1, min_val = 0; mir_ullong max_val = 0; - enum basic_type basic_type; struct enum_type *enum_type; int neg_p = FALSE; @@ -7001,6 +7159,22 @@ static int update_init_object_path (c2m_ctx_t c2m_ctx, size_t mark, struct type } } +static enum basic_type get_uint_basic_type (size_t size) { + if (sizeof (mir_uint) == size) return TP_UINT; + if (sizeof (mir_ulong) == size) return TP_ULONG; + if (sizeof (mir_ullong) == size) return TP_ULLONG; + if (sizeof (mir_ushort) == size) return TP_USHORT; + return TP_UCHAR; +} + +static int init_compatible_string_p (node_t n, struct type *el_type) { + return ((n->code == N_STR && char_type_p (el_type)) + || (n->code == N_STR16 && el_type->mode == TM_BASIC + && el_type->u.basic_type == get_uint_basic_type (2)) + || (n->code == N_STR32 && el_type->mode == TM_BASIC + && el_type->u.basic_type == get_uint_basic_type (4))); +} + static int update_path_and_do (c2m_ctx_t c2m_ctx, void (*action) (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type **type_ptr, node_t initializer, @@ -7021,7 +7195,7 @@ static int update_path_and_do (c2m_ctx_t c2m_ctx, if (init_object.container_type->mode == TM_ARR) { el_type = init_object.container_type->u.arr_type->el_type; action (c2m_ctx, NULL, - (value->code == N_STR && char_type_p (el_type) + (init_compatible_string_p (value, el_type) ? &init_object.container_type : &init_object.container_type->u.arr_type->el_type), value, const_only_p, FALSE); @@ -7058,6 +7232,8 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll } switch (r->code) { case N_STR: + case N_STR16: + case N_STR32: *base = r; *offset = 0; *deref = 0; @@ -7196,6 +7372,8 @@ static node_t get_compound_literal (node_t n, int *addr_p) { case N_DEREF: addr--; break; case N_CAST: break; // ??? case N_STR: + case N_STR16: + case N_STR32: case N_COMPOUND_LITERAL: if (addr < 0) return NULL; *addr_p = addr > 0; @@ -7222,16 +7400,18 @@ static void check_initializer (c2m_ctx_t c2m_ctx, decl_t member_decl, struct typ int addr_p = FALSE; /* to remove an uninitialized warning */ literal = get_compound_literal (initializer, &addr_p); - if (literal != NULL && !addr_p && initializer->code != N_STR) { + if (literal != NULL && !addr_p && initializer->code != N_STR && initializer->code != N_STR16 + && initializer->code != N_STR32) { cexpr = initializer->attr; check_assignment_types (c2m_ctx, type, NULL, cexpr, initializer); initializer = NL_EL (literal->u.ops, 1); } check_one_value: if (initializer->code != N_LIST - && !(initializer->code == N_STR && type->mode == TM_ARR - && char_type_p (type->u.arr_type->el_type))) { - if ((cexpr = initializer->attr)->const_p || initializer->code == N_STR || !const_only_p) { + && !(type->mode == TM_ARR + && init_compatible_string_p (initializer, type->u.arr_type->el_type))) { + if ((cexpr = initializer->attr)->const_p || initializer->code == N_STR + || initializer->code == N_STR16 || initializer->code == N_STR32 || !const_only_p) { check_assignment_types (c2m_ctx, type, NULL, cexpr, initializer); } else { setup_const_addr_p (c2m_ctx, initializer); @@ -7245,12 +7425,14 @@ check_one_value: return; } init = NL_HEAD (initializer->u.ops); - if (((str = initializer)->code == N_STR /* string or string in parentheses */ + if (((str = initializer)->code == N_STR || str->code == N_STR16 + || str->code == N_STR32 /* string or string in parentheses */ || (init != NULL && init->code == N_INIT && NL_EL (initializer->u.ops, 1) == NULL && (des_list = NL_HEAD (init->u.ops))->code == N_LIST && NL_HEAD (des_list->u.ops) == NULL && NL_EL (init->u.ops, 1) != NULL - && (str = NL_EL (init->u.ops, 1))->code == N_STR)) - && type->mode == TM_ARR && char_type_p (type->u.arr_type->el_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)) { len = str->u.s.len; if (incomplete_type_p (c2m_ctx, type)) { assert (len < MIR_INT_MAX); @@ -7809,14 +7991,15 @@ static void classify_node (node_t n, int *expr_attr_p, int *stmt_p) { *expr_attr_p = *stmt_p = FALSE; switch (n->code) { REP8 (NODE_CASE, I, L, LL, U, UL, ULL, F, D) - REP8 (NODE_CASE, LD, CH, STR, ID, COMMA, ANDAND, OROR, EQ) + REP7 (NODE_CASE, LD, CH, CH16, CH32, STR, STR16, STR32) + REP5 (NODE_CASE, ID, COMMA, ANDAND, OROR, EQ) 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) REP8 (NODE_CASE, DIV, DIV_ASSIGN, MOD, MOD_ASSIGN, IND, FIELD, ADDR, DEREF) REP8 (NODE_CASE, DEREF_FIELD, COND, INC, DEC, POST_INC, POST_DEC, ALIGNOF, SIZEOF) - REP6 (NODE_CASE, EXPR_SIZEOF, CAST, COMPOUND_LITERAL, CALL, GENERIC, GENERIC_ASSOC) - *expr_attr_p = TRUE; + REP6 (NODE_CASE, EXPR_SIZEOF, CAST, COMPOUND_LITERAL, CALL, GENERIC, GENERIC_ASSOC) *expr_attr_p + = TRUE; break; REP8 (NODE_CASE, IF, SWITCH, WHILE, DO, FOR, GOTO, CONTINUE, BREAK) REP4 (NODE_CASE, RETURN, EXPR, BLOCK, SPEC_DECL) /* SPEC DECL may have an initializer */ @@ -7994,8 +8177,17 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { else e->u.u_val = r->u.ch; break; - case N_STR: { + case N_CH16: + case N_CH32: + e = create_basic_type_expr (c2m_ctx, r, get_uint_basic_type (r->code == N_CH16 ? 2 : 4)); + e->const_p = TRUE; + e->u.u_val = r->u.ul; + break; + case N_STR: + case N_STR16: + case N_STR32: { struct arr_type *arr_type; + int size = r->code == N_STR ? 1 : r->code == N_STR16 ? 2 : 4; e = create_expr (c2m_ctx, r); e->lvalue_node = r; @@ -8007,7 +8199,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { arr_type->el_type = create_type (c2m_ctx, NULL); arr_type->el_type->pos_node = r; arr_type->el_type->mode = TM_BASIC; - arr_type->el_type->u.basic_type = TP_CHAR; + arr_type->el_type->u.basic_type = size == 1 ? TP_CHAR : get_uint_basic_type (size); arr_type->size = new_i_node (c2m_ctx, r->u.s.len, POS (r)); check (c2m_ctx, arr_type->size, NULL); break; @@ -8367,7 +8559,8 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } else if (e1->lvalue_node->code == N_COMPOUND_LITERAL) { t2 = t1; } else { - assert (e1->lvalue_node->code == N_STR); + assert (e1->lvalue_node->code == N_STR || e1->lvalue_node->code == N_STR16 + || e1->lvalue_node->code == N_STR32); t2 = t1; } e->type->mode = TM_PTR; @@ -8842,7 +9035,9 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { else ok_p = e1->u.u_val != 0; if (!ok_p) { - assert (NL_NEXT (op1) != NULL && NL_NEXT (op1)->code == N_STR); + assert (NL_NEXT (op1) != NULL + && (NL_NEXT (op1)->code == N_STR || NL_NEXT (op1)->code == N_STR16 + || NL_NEXT (op1)->code == N_STR32)); error (c2m_ctx, POS (r), "static assertion failed: \"%s\"", NL_NEXT (op1)->u.s.s); // ??? } @@ -10350,6 +10545,10 @@ static void MIR_UNUSED simple_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_t } } +static MIR_type_t MIR_UNUSED simple_target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) { + return MIR_T_BLK; +} + static void MIR_UNUSED simple_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, void *arg_info, VARR (MIR_var_t) * arg_vars) { @@ -10520,6 +10719,10 @@ static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t v simple_add_ret_ops (c2m_ctx, ret_type, val); } +/* Return BLK type should be used for VA_BLOCK_ARG for accessing aggregate type ARG_TYPE. */ +static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) { + return simple_target_get_blk_type (c2m_ctx, arg_type); +} /* Add one or more vars to arg_vars which pass arg NAME of ARG_TYPE. */ static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) { @@ -10615,16 +10818,18 @@ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type init_object_t init_object; literal = get_compound_literal (initializer, &addr_p); - if (literal != NULL && !addr_p && initializer->code != N_STR) + if (literal != NULL && !addr_p && initializer->code != N_STR && initializer->code != N_STR16 + && initializer->code != N_STR32) initializer = NL_EL (literal->u.ops, 1); check_one_value: if (initializer->code != N_LIST && !(initializer->code == N_STR && type->mode == TM_ARR - && char_type_p (type->u.arr_type->el_type))) { + && init_compatible_string_p (initializer, type->u.arr_type->el_type))) { cexpr = initializer->attr; /* static or thread local object initialization should be const expr or addr: */ - assert (initializer->code == N_STR || !const_only_p || cexpr->const_p || cexpr->const_addr_p - || (literal != NULL && addr_p)); + 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.num = VARR_LENGTH (init_el_t, init_els); init_el.offset = get_object_path_offset (c2m_ctx); init_el.member_decl = member_decl; @@ -10634,12 +10839,14 @@ check_one_value: return; } init = NL_HEAD (initializer->u.ops); - if (((str = initializer)->code == N_STR /* string or string in parentheses */ + if (((str = initializer)->code == N_STR || str->code == N_STR16 + || str->code == N_STR32 /* string or string in parentheses */ || (init != NULL && init->code == N_INIT && NL_EL (initializer->u.ops, 1) == NULL && (des_list = NL_HEAD (init->u.ops))->code == N_LIST && NL_HEAD (des_list->u.ops) == NULL && NL_EL (init->u.ops, 1) != NULL - && (str = NL_EL (init->u.ops, 1))->code == N_STR)) - && type->mode == TM_ARR && char_type_p (type->u.arr_type->el_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.num = VARR_LENGTH (init_el_t, init_els); init_el.offset = get_object_path_offset (c2m_ctx); init_el.member_decl = NULL; @@ -10912,6 +11119,39 @@ static void add_bit_field (c2m_ctx_t c2m_ctx, uint64_t *u, uint64_t v, decl_t me *u |= v; } +static MIR_item_t get_mir_str_op_data (c2m_ctx_t c2m_ctx, MIR_str_t str) { + MIR_context_t ctx = c2m_ctx->ctx; + MIR_item_t data; + char buff[50]; + MIR_module_t module = DLIST_TAIL (MIR_module_t, *MIR_get_module_list (ctx)); + + _MIR_get_temp_item_name (ctx, module, buff, sizeof (buff)); + data = MIR_new_string_data (ctx, buff, str); + move_item_to_module_start (module, data); + return data; +} + +static MIR_item_t get_string_data (c2m_ctx_t c2m_ctx, node_t n) { + MIR_context_t ctx = c2m_ctx->ctx; + MIR_item_t data; + char buff[50]; + MIR_module_t module = DLIST_TAIL (MIR_module_t, *MIR_get_module_list (ctx)); + + _MIR_get_temp_item_name (ctx, module, buff, sizeof (buff)); + if (n->code == N_STR) { + data = MIR_new_string_data (ctx, buff, (MIR_str_t){n->u.s.len, n->u.s.s}); + } else { + assert (n->code == N_STR16 || n->code == N_STR32); + if (n->code == N_STR16) { + data = MIR_new_data (ctx, buff, MIR_T_U16, n->u.s.len / 2, n->u.s.s); + } else { + data = MIR_new_data (ctx, buff, MIR_T_U32, n->u.s.len / 4, n->u.s.s); + } + } + move_item_to_module_start (module, data); + return data; +} + static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, const char *global_name, mir_size_t size, int local_p) { gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; @@ -10923,9 +11163,7 @@ static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, MIR_reg_t base; MIR_type_t t; MIR_item_t data; - MIR_module_t module; struct expr *e; - char buff[50]; if (var.mir_op.mode == MIR_OP_REG) { /* scalar initialization: */ assert (local_p && offset == 0 && VARR_LENGTH (init_el_t, init_els) - init_start == 1); @@ -10950,9 +11188,13 @@ 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 - : 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 { @@ -10999,13 +11241,10 @@ static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, data = MIR_new_data (ctx, global_name, MIR_T_P, 1, &s); data_size = _MIR_type_size (ctx, MIR_T_P); } else { - if (def->code != N_STR) { + if (def->code != N_STR && def->code != N_STR16 && def->code != N_STR32) { data = ((decl_t) def->attr)->item; } else { - module = DLIST_TAIL (MIR_module_t, *MIR_get_module_list (ctx)); - _MIR_get_temp_item_name (ctx, module, buff, sizeof (buff)); - data = MIR_new_string_data (ctx, buff, (MIR_str_t){def->u.s.len, def->u.s.s}); - move_item_to_module_start (module, data); + data = get_string_data (c2m_ctx, def); } data = MIR_new_ref_data (ctx, global_name, data, e->u.i_val); data_size = _MIR_type_size (ctx, t); @@ -11068,10 +11307,7 @@ static void gen_initializer (c2m_ctx_t c2m_ctx, size_t init_start, op_t var, if (data_size > str_len) MIR_new_bss (ctx, NULL, data_size - str_len); } } else { - module = DLIST_TAIL (MIR_module_t, *MIR_get_module_list (ctx)); - _MIR_get_temp_item_name (ctx, module, buff, sizeof (buff)); - data = MIR_new_string_data (ctx, buff, val.mir_op.u.str); - move_item_to_module_start (module, data); + data = get_mir_str_op_data (c2m_ctx, val.mir_op.u.str); data = MIR_new_ref_data (ctx, global_name, data, 0); data_size = _MIR_type_size (ctx, t); } @@ -11201,6 +11437,10 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ : MIR_new_ldouble_op (ctx, ld))); break; case N_CH: ll = r->u.ch; goto int_val; + case N_CH16: + case N_CH32: ll = r->u.ul; goto int_val; + case N_STR16: + case N_STR32: res = new_op (NULL, MIR_new_ref_op (ctx, get_string_data (c2m_ctx, r))); break; case N_STR: res = new_op (NULL, @@ -12400,7 +12640,8 @@ static const char *get_node_name (node_code_t code) { switch (code) { C (IGNORE); REP8 (C, I, L, LL, U, UL, ULL, F, D); - REP8 (C, LD, CH, STR, ID, COMMA, ANDAND, OROR, EQ); + REP7 (C, LD, CH, CH16, CH32, STR, STR16, STR32); + REP5 (C, ID, COMMA, ANDAND, OROR, EQ); 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); @@ -12420,19 +12661,31 @@ static const char *get_node_name (node_code_t code) { #undef REP_SEP } -static void print_char (FILE *f, int ch) { +static void print_char (FILE *f, mir_ulong ch) { assert (ch >= 0); - if (ch == '"' || ch == '\"' || ch == '\\') fprintf (f, "\\"); - if (isprint (ch)) - fprintf (f, "%c", ch); - else - fprintf (f, "\\%o", ch); + if (ch >= 0x100) { + fprintf (f, ch <= 0xFFFF ? "\\u%04x" : "\\U%08x", (unsigned int) ch); + } else { + if (ch == '"' || ch == '\"' || ch == '\\') fprintf (f, "\\"); + if (isprint (ch)) + fprintf (f, "%c", (unsigned int) ch); + else + fprintf (f, "\\%o", (unsigned int) ch); + } } static void print_chars (FILE *f, const char *str, size_t len) { for (size_t i = 0; i < len; i++) print_char (f, str[i]); } +static void print_chars16 (FILE *f, const char *str, size_t len) { + for (size_t i = 0; i < len; i += 2) print_char (f, ((mir_char16 *) str)[i]); +} + +static void print_chars32 (FILE *f, const char *str, size_t len) { + for (size_t i = 0; i < len; i += 4) print_char (f, ((mir_char32 *) str)[i]); +} + static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int attr_p); void debug_node (c2m_ctx_t c2m_ctx, node_t n) { print_node (c2m_ctx, stderr, n, 0, TRUE); } @@ -12581,13 +12834,19 @@ static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int at case N_D: fprintf (f, " %.*g", DBL_MANT_DIG, (double) n->u.d); goto expr; case N_LD: fprintf (f, " %.*Lg", LDBL_MANT_DIG, (long double) n->u.ld); goto expr; case N_CH: - fprintf (f, " '"); + case N_CH16: + case N_CH32: + fprintf (f, " %s'", n->code == N_CH ? "" : n->code == N_CH16 ? "u" : "U"); print_char (f, n->u.ch); fprintf (f, "'"); goto expr; case N_STR: - fprintf (f, " \""); - print_chars (f, n->u.s.s, n->u.s.len); + 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); fprintf (f, "\""); goto expr; case N_ID: diff --git a/mir/c2mir/ppc64/cppc64.h b/mir/c2mir/ppc64/cppc64.h index 0ca92b7..2f6b0c8 100644 --- a/mir/c2mir/ppc64/cppc64.h +++ b/mir/c2mir/ppc64/cppc64.h @@ -28,12 +28,17 @@ typedef uint16_t mir_ushort; typedef uint32_t mir_uint; typedef uint64_t mir_ulong; typedef uint64_t mir_ullong; +typedef uint32_t mir_wchar; +typedef uint16_t mir_char16; +typedef uint32_t mir_char32; #define MIR_UCHAR_MAX UINT8_MAX #define MIR_USHORT_MAX UINT16_MAX #define MIR_UINT_MAX UINT32_MAX #define MIR_ULONG_MAX UINT64_MAX #define MIR_ULLONG_MAX UINT64_MAX +#define MIR_WCHAR_MIN 0 +#define MIR_WCHAR_MAX UINT32_MAX typedef mir_schar mir_char; #define MIR_CHAR_MIN MIR_SCHAR_MIN diff --git a/mir/c2mir/s390x/cs390x.h b/mir/c2mir/s390x/cs390x.h index 0ca92b7..2f6b0c8 100644 --- a/mir/c2mir/s390x/cs390x.h +++ b/mir/c2mir/s390x/cs390x.h @@ -28,12 +28,17 @@ typedef uint16_t mir_ushort; typedef uint32_t mir_uint; typedef uint64_t mir_ulong; typedef uint64_t mir_ullong; +typedef uint32_t mir_wchar; +typedef uint16_t mir_char16; +typedef uint32_t mir_char32; #define MIR_UCHAR_MAX UINT8_MAX #define MIR_USHORT_MAX UINT16_MAX #define MIR_UINT_MAX UINT32_MAX #define MIR_ULONG_MAX UINT64_MAX #define MIR_ULLONG_MAX UINT64_MAX +#define MIR_WCHAR_MIN 0 +#define MIR_WCHAR_MAX UINT32_MAX typedef mir_schar mir_char; #define MIR_CHAR_MIN MIR_SCHAR_MIN diff --git a/mir/c2mir/x86_64/cx86_64-ABI-code.c b/mir/c2mir/x86_64/cx86_64-ABI-code.c index 4e3288f..42c880f 100644 --- a/mir/c2mir/x86_64/cx86_64-ABI-code.c +++ b/mir/c2mir/x86_64/cx86_64-ABI-code.c @@ -322,7 +322,7 @@ static MIR_type_t get_blk_type (int n_qwords, MIR_type_t *qword_types) { assert (n_qwords <= 2); if (n_qwords == 0) return MIR_T_BLK; for (n = 0; n < n_qwords; n++) { /* start from the last qword */ - switch (qword_types[n]) { + switch ((int) qword_types[n]) { case MIR_T_I8: case MIR_T_I16: case MIR_T_I32: @@ -334,10 +334,10 @@ static MIR_type_t get_blk_type (int n_qwords, MIR_type_t *qword_types) { default: assert (FALSE); } } - if (n_iregs == n_qwords) return MIR_T_BLK2; - if (n_fregs == n_qwords) return MIR_T_BLK3; - if (qword_types[0] == MIR_T_F || qword_types[0] == MIR_T_D) return MIR_T_BLK5; - return MIR_T_BLK4; + if (n_iregs == n_qwords) return MIR_T_BLK + 1; + if (n_fregs == n_qwords) return MIR_T_BLK + 2; + if (qword_types[0] == MIR_T_F || qword_types[0] == MIR_T_D) return MIR_T_BLK + 4; + return MIR_T_BLK + 3; } static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) { diff --git a/mir/c2mir/x86_64/cx86_64.h b/mir/c2mir/x86_64/cx86_64.h index b87e9b3..256af11 100644 --- a/mir/c2mir/x86_64/cx86_64.h +++ b/mir/c2mir/x86_64/cx86_64.h @@ -35,21 +35,28 @@ typedef int64_t mir_llong; typedef uint8_t mir_uchar; typedef uint16_t mir_ushort; typedef uint32_t mir_uint; +typedef uint64_t mir_ullong; #ifdef _WIN32 typedef uint32_t mir_ulong; +typedef uint16_t mir_wchar; #else typedef uint64_t mir_ulong; +typedef uint32_t mir_wchar; #endif -typedef uint64_t mir_ullong; +typedef uint16_t mir_char16; +typedef uint32_t mir_char32; #define MIR_UCHAR_MAX UINT8_MAX #define MIR_USHORT_MAX UINT16_MAX #define MIR_UINT_MAX UINT32_MAX #ifdef _WIN32 #define MIR_ULONG_MAX UINT32_MAX +#define MIR_WCHAR_MAX UINT16_MAX #else #define MIR_ULONG_MAX UINT64_MAX +#define MIR_WCHAR_MAX UINT32_MAX #endif +#define MIR_WCHAR_MIN 0 #define MIR_ULLONG_MAX UINT64_MAX typedef mir_schar mir_char; diff --git a/mir/mir-aarch64.c b/mir/mir-aarch64.c index fed2200..a4d1b5b 100644 --- a/mir/mir-aarch64.c +++ b/mir/mir-aarch64.c @@ -4,7 +4,7 @@ #define VA_LIST_IS_ARRAY_P 0 -/* Small BLK..BLK5 (less or equal to two quadwords) args are passed in +/* 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 is passed in r8. Other RBLK independently of size is always passed @@ -279,7 +279,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s VARR_CREATE (uint8_t, code, 128); mir_assert (sizeof (long double) == 16); - for (size_t i = 0; i < nargs; i++) { /* caclulate offset for blk params */ + for (size_t i = 0; i < nargs; i++) { /* calculate offset for blk params */ type = arg_descs[i].type; if ((MIR_T_I8 <= type && type <= MIR_T_U64) || type == MIR_T_P || MIR_all_blk_type_p (type)) { if (MIR_blk_type_p (type) && (qwords = (arg_descs[i].size + 7) / 8) <= 2) { diff --git a/mir/mir-gen-aarch64.c b/mir/mir-gen-aarch64.c index ac39e10..637dc7d 100644 --- a/mir/mir-gen-aarch64.c +++ b/mir/mir-gen-aarch64.c @@ -256,7 +256,7 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { call_insn->ops[1] = temp_op; gen_add_insn_before (gen_ctx, call_insn, new_insn); } - for (size_t i = start; i < nops; i++) { /* caclulate offset for blk params */ + for (size_t i = start; i < nops; i++) { /* calculate offset for blk params */ if (i - start < nargs) { type = arg_vars[i - start].type; } else if (call_insn->ops[i].mode == MIR_OP_MEM) { diff --git a/mir/mir-gen-x86_64.c b/mir/mir-gen-x86_64.c index d4717d4..d00dc09 100644 --- a/mir/mir-gen-x86_64.c +++ b/mir/mir-gen-x86_64.c @@ -282,12 +282,12 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { gen_assert (prev_call_insn != NULL); /* call_insn should not be 1st after simplification */ } #ifndef _WIN32 - if ((type == MIR_T_BLK2 && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG + if ((type == MIR_T_BLK + 1 && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG && (size <= 8 || get_int_arg_reg (int_arg_num + 1) != MIR_NON_HARD_REG)) - || (type == MIR_T_BLK3 && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG + || (type == MIR_T_BLK + 2 && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG && (size <= 8 || get_fp_arg_reg (fp_arg_num + 1) != MIR_NON_HARD_REG))) { /* all is passed in gprs or fprs */ - MIR_type_t mov_type = type == MIR_T_BLK2 ? MIR_T_I64 : MIR_T_D; + MIR_type_t mov_type = type == MIR_T_BLK + 1 ? MIR_T_I64 : MIR_T_D; MIR_insn_code_t mov_code; MIR_reg_t reg2, reg1 = get_arg_reg (mov_type, &int_arg_num, &fp_arg_num, &mov_code); @@ -305,12 +305,12 @@ static void machinize_call (gen_ctx_t gen_ctx, MIR_insn_t call_insn) { setup_call_hard_reg_args (gen_ctx, call_insn, reg2); } continue; - } else if ((type == MIR_T_BLK4 || type == MIR_T_BLK5) + } else if ((type == MIR_T_BLK + 3 || type == MIR_T_BLK + 4) && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG) { /* gpr and then fpr or fpr and then gpr */ - MIR_type_t mov_type1 = type == MIR_T_BLK4 ? MIR_T_I64 : MIR_T_D; - MIR_type_t mov_type2 = type == MIR_T_BLK4 ? MIR_T_D : MIR_T_I64; + MIR_type_t mov_type1 = type == MIR_T_BLK + 3 ? MIR_T_I64 : MIR_T_D; + MIR_type_t mov_type2 = type == MIR_T_BLK + 3 ? MIR_T_D : MIR_T_I64; MIR_insn_code_t mov_code1, mov_code2; MIR_reg_t reg1 = get_arg_reg (mov_type1, &int_arg_num, &fp_arg_num, &mov_code1); MIR_reg_t reg2 = get_arg_reg (mov_type2, &int_arg_num, &fp_arg_num, &mov_code2); @@ -717,12 +717,12 @@ static void target_machinize (gen_ctx_t gen_ctx) { type = VARR_GET (MIR_var_t, func->vars, i).type; blk_size = MIR_blk_type_p (type) ? (VARR_GET (MIR_var_t, func->vars, i).size + 7) / 8 * 8 : 0; #ifndef _WIN32 - if ((type == MIR_T_BLK2 && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG + if ((type == MIR_T_BLK + 1 && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG && (blk_size <= 8 || get_int_arg_reg (int_arg_num + 1) != MIR_NON_HARD_REG)) - || (type == MIR_T_BLK3 && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG + || (type == MIR_T_BLK + 2 && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG && (blk_size <= 8 || get_fp_arg_reg (fp_arg_num + 1) != MIR_NON_HARD_REG))) { /* all is passed in gprs or fprs */ - MIR_type_t mov_type = type == MIR_T_BLK2 ? MIR_T_I64 : MIR_T_D; + MIR_type_t mov_type = type == MIR_T_BLK + 1 ? MIR_T_I64 : MIR_T_D; MIR_insn_code_t mov_code1, mov_code2; MIR_reg_t reg2, reg1 = get_arg_reg (mov_type, &int_arg_num, &fp_arg_num, &mov_code1); @@ -740,12 +740,12 @@ static void target_machinize (gen_ctx_t gen_ctx) { MIR_new_int_op (ctx, blk_size)); prepend_insn (gen_ctx, new_insn); continue; - } else if ((type == MIR_T_BLK4 || type == MIR_T_BLK5) + } else if ((type == MIR_T_BLK + 3 || type == MIR_T_BLK + 4) && get_int_arg_reg (int_arg_num) != MIR_NON_HARD_REG && get_fp_arg_reg (fp_arg_num) != MIR_NON_HARD_REG) { /* gpr and then fpr or fpr and then gpr */ - MIR_type_t mov_type1 = type == MIR_T_BLK4 ? MIR_T_I64 : MIR_T_D; - MIR_type_t mov_type2 = type == MIR_T_BLK4 ? MIR_T_D : MIR_T_I64; + MIR_type_t mov_type1 = type == MIR_T_BLK + 3 ? MIR_T_I64 : MIR_T_D; + MIR_type_t mov_type2 = type == MIR_T_BLK + 3 ? MIR_T_D : MIR_T_I64; MIR_insn_code_t mov_code1, mov_code2; MIR_reg_t reg1 = get_arg_reg (mov_type1, &int_arg_num, &fp_arg_num, &mov_code1); MIR_reg_t reg2 = get_arg_reg (mov_type2, &int_arg_num, &fp_arg_num, &mov_code2); diff --git a/mir/mir-interp.c b/mir/mir-interp.c index a693425..6700313 100644 --- a/mir/mir-interp.c +++ b/mir/mir-interp.c @@ -401,11 +401,11 @@ static void generate_icode (MIR_context_t ctx, MIR_item_t func_item) { mir_assert (ops[i].mode == MIR_OP_REF && ops[i].u.ref->item_type == MIR_proto_item); v.a = ops[i].u.ref; } else if (i == 1 && imm_call_p) { - mir_assert (ops[i].u.ref->item_type == MIR_import_item - || ops[i].u.ref->item_type == MIR_export_item - || ops[i].u.ref->item_type == MIR_forward_item - || ops[i].u.ref->item_type == MIR_func_item); - v.a = ops[i].u.ref->addr; + MIR_item_t item = ops[i].u.ref; + + mir_assert (item->item_type == MIR_import_item || item->item_type == MIR_export_item + || item->item_type == MIR_forward_item || item->item_type == MIR_func_item); + v.a = item->addr; } else if (code == MIR_VA_ARG && i == 2) { /* type */ mir_assert (ops[i].mode == MIR_OP_MEM); v.i = ops[i].u.mem.type; @@ -830,10 +830,12 @@ static void finish_insn_trace (MIR_context_t ctx, MIR_full_insn_code_t code, cod bp[ops[0].i].u, bp[ops[0].i].u); break; case MIR_OP_FLOAT: fprintf (stderr, "\t# res = %.*ef", FLT_DECIMAL_DIG, bp[ops[0].i].f); break; - case MIR_OP_DOUBLE: fprintf (stderr, "\t# res = %.*e", DBL_DECIMAL_DIG, bp[ops[0].i].d); break; case MIR_OP_LDOUBLE: +#ifndef _WIN32 fprintf (stderr, "\t# res = %.*Le", LDBL_DECIMAL_DIG, bp[ops[0].i].ld); break; +#endif + case MIR_OP_DOUBLE: fprintf (stderr, "\t# res = %.*e", DBL_DECIMAL_DIG, bp[ops[0].i].d); break; default: assert (op_mode == MIR_OP_UNDEF); } fprintf (stderr, "\n"); @@ -1261,8 +1263,37 @@ static void OPTIMIZE eval (MIR_context_t ctx, func_desc_t func_desc, MIR_val_t * SCASE (MIR_DBGE, 3, BDCMP (>=)); SCASE (MIR_LDBGE, 3, BLDCMP (>=)); - SCASE (MIR_CALL, 0, pc = call_insn_execute (ctx, pc, bp, ops, FALSE)); - SCASE (IC_IMM_CALL, 0, pc = call_insn_execute (ctx, pc, bp, ops, TRUE)); + CASE (MIR_CALL, 0) { + int (*func_addr) (void *buf) = *get_aop (bp, ops + 4); + + if (func_addr != setjmp_addr) { + pc = call_insn_execute (ctx, pc, bp, ops, FALSE); + } else { + int64_t nops = get_i (ops); /* #args w/o nop, insn, and ff interface address */ + MIR_item_t proto_item = get_a (ops + 3); + size_t start = proto_item->u.proto->nres + 5; + + bp[get_i (ops + 5)].i = (*func_addr) (*get_aop (bp, ops + start)); + pc += nops + 3; /* nops itself, the call insn, add ff interface address */ + } + END_INSN; + } + CASE (IC_IMM_CALL, 0) { + int (*func_addr) (void *buf) = get_a (ops + 4); + + if (func_addr != setjmp_addr) { + pc = call_insn_execute (ctx, pc, bp, ops, TRUE); + } else { + int64_t nops = get_i (ops); /* #args w/o nop, insn, and ff interface address */ + MIR_item_t proto_item = get_a (ops + 3); + size_t start = proto_item->u.proto->nres + 5; + + bp[get_i (ops + 5)].i = (*func_addr) (*get_aop (bp, ops + start)); + pc += nops + 3; /* nops itself, the call insn, add ff interface address */ + } + END_INSN; + } + SCASE (MIR_INLINE, 0, mir_assert (FALSE)); CASE (MIR_SWITCH, 0) { @@ -1497,14 +1528,11 @@ static void call (MIR_context_t ctx, MIR_val_t *bp, MIR_op_t *insn_arg_ops, code case MIR_T_F: call_res_args[i + nres].f = arg_vals[i].f; break; case MIR_T_D: call_res_args[i + nres].d = arg_vals[i].d; break; case MIR_T_LD: call_res_args[i + nres].ld = arg_vals[i].ld; break; - case MIR_T_P: - case MIR_T_BLK: - case MIR_T_BLK2: - case MIR_T_BLK3: - case MIR_T_BLK4: - case MIR_T_BLK5: - case MIR_T_RBLK: call_res_args[i + nres].u = (uint64_t) arg_vals[i].a; break; - default: mir_assert (FALSE); + case MIR_T_P: call_res_args[i + nres].u = (uint64_t) arg_vals[i].a; break; + default: + mir_assert (MIR_all_blk_type_p (type)); + call_res_args[i + nres].u = (uint64_t) arg_vals[i].a; + break; } } ((void (*) (void *, void *)) ff_interface_addr) (addr, call_res_args); /* call */ @@ -1679,12 +1707,7 @@ static void interp (MIR_context_t ctx, MIR_item_t func_item, va_list va, MIR_val case MIR_T_LD: arg_vals[i].ld = va_arg (va, long double); break; case MIR_T_P: case MIR_T_RBLK: arg_vals[i].a = va_arg (va, void *); break; - case MIR_T_BLK: - case MIR_T_BLK2: - case MIR_T_BLK3: - case MIR_T_BLK4: - case MIR_T_BLK5: { - arg_vals[i].a = alloca (arg_vars[i].size); + default: mir_assert (MIR_blk_type_p (type)); arg_vals[i].a = alloca (arg_vars[i].size); #if defined(__PPC64__) || defined(__aarch64__) || defined(_WIN32) va_block_arg_builtin (arg_vals[i].a, &va, arg_vars[i].size, type - MIR_T_BLK); #else @@ -1692,8 +1715,6 @@ static void interp (MIR_context_t ctx, MIR_item_t func_item, va_list va, MIR_val #endif break; } - default: mir_assert (FALSE); - } } #if VA_LIST_IS_ARRAY_P interp_arr_varg (ctx, func_item, results, nargs, arg_vals, va); diff --git a/mir/mir-ppc64.c b/mir/mir-ppc64.c index 2be8296..d06bcda 100644 --- a/mir/mir-ppc64.c +++ b/mir/mir-ppc64.c @@ -2,8 +2,8 @@ Copyright (C) 2018-2020 Vladimir Makarov . */ -/* BLK..BLK5 is passed in int regs, and if the regs are not enough, the rest is passed on the stack. - RBLK is always passed by address. */ +/* All BLK type values is passed in int regs, and if the regs are not enough, the rest is passed on + the stack. RBLK is always passed by address. */ #define VA_LIST_IS_ARRAY_P 1 /* one element which is a pointer to args */ diff --git a/mir/mir-s390x.c b/mir/mir-s390x.c index f946509..c45e849 100644 --- a/mir/mir-s390x.c +++ b/mir/mir-s390x.c @@ -4,7 +4,7 @@ /* Long doubles (-mlong-double=128) are always passed by its address (for args and results) */ -/* BLK..BLK5 and RBLK args are always passed by address. */ +/* All BLK type values and RBLK args are always passed by address. */ #if 0 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #error "s390x works only in BE mode" diff --git a/mir/mir-x86_64.c b/mir/mir-x86_64.c index a8441d8..8904868 100644 --- a/mir/mir-x86_64.c +++ b/mir/mir-x86_64.c @@ -3,11 +3,11 @@ */ /* RBLK args are always passed by address. - BLK first is copied on the caller stack and passed implicitly. - BLK2 is passed in general regs - BLK3 is passed in fp regs - BLK4 is passed in gpr and then fpr - BLK5 is passed in fpr and then gpr + BLK0 first is copied on the caller stack and passed implicitly. + BLK1 is passed in general regs + BLK2 is passed in fp regs + BLK3 is passed in gpr and then fpr + BLK4 is passed in fpr and then gpr If there are no enough regs, they work as BLK. Windows: small BLKs (<= 8 bytes) are passed by value; all other BLKs is always passed by pointer as regular int arg. */ @@ -145,6 +145,7 @@ void va_start_interp_builtin (MIR_context_t ctx, void *p, void *a) { assert (sizeof (struct x86_64_va_list) == sizeof (va_list)); *va = (struct x86_64_va_list *) vap; } + #endif void va_end_interp_builtin (MIR_context_t ctx, void *p) {} @@ -292,6 +293,7 @@ static void gen_movxmm2 (VARR (uint8_t) * insn_varr, uint32_t offset, uint32_t r addr[4] |= reg << 3; } +#ifdef _WIN32 static void gen_add (VARR (uint8_t) * insn_varr, uint32_t sp_offset, int reg) { static const uint8_t lea_pat[] = { 0x48, 0x8d, 0x84, 0x24, 0, 0, 0, 0, /* lea (%sp),reg */ @@ -301,6 +303,7 @@ static void gen_add (VARR (uint8_t) * insn_varr, uint32_t sp_offset, int reg) { addr[2] |= (reg & 7) << 3; if (reg > 7) addr[0] |= 4; } +#endif static void gen_st (VARR (uint8_t) * insn_varr, uint32_t sp_offset, int b64_p) { static const uint8_t st_pat[] = { @@ -348,7 +351,7 @@ static void gen_st80 (VARR (uint8_t) * insn_varr, uint32_t src_offset) { goto L if rax > 0) ... rax=8; call *r11; sp+=offset r10=mem[rbx,]; res_reg=mem[r10]; ... - pop rbx; push r12; ret. */ + pop rbx; pop r12; ret. */ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, size_t nargs, _MIR_arg_desc_t *arg_descs, int vararg_p) { static const uint8_t prolog[] = { @@ -359,21 +362,29 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s 0x49, 0x89, 0xfb, /* mov $rdi, $r11 -- fun addr */ 0x48, 0x89, 0xf3, /* mov $rsi, $rbx -- result/arg addresses */ #else - 0x41, 0x54, /* pushq %r12 */ - 0x53, /* pushq %rbx */ - 0x48, 0x81, 0xec, 0, 0, 0, 0, /* subq , %rsp */ - 0x49, 0x89, 0xcb, /* mov $rcx, $r11 -- fun addr */ - 0x48, 0x89, 0xd3, /* mov $rdx, $rbx -- result/arg addresses */ + /* 0x0: */ 0x41, 0x54, /* pushq %r12 */ + /* 0x2: */ 0x53, /* pushq %rbx */ + /* 0x3: */ 0x55, /* push %rbp */ + /* 0x4: */ 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */ + /* 0x7: */ 0x48, 0x81, 0xec, 0, 0, 0, 0, /* subq , %rsp */ + /* 0xe: */ 0x49, 0x89, 0xcb, /* mov $rcx, $r11 -- fun addr */ + /* 0x11: */ 0x48, 0x89, 0xd3, /* mov $rdx, $rbx -- result/arg addresses */ #endif }; static const uint8_t call_end[] = { #ifndef _WIN32 0x48, 0xc7, 0xc0, 0x08, 0, 0, 0, /* mov $8, rax -- to save xmm varargs */ #endif - 0x41, 0xff, 0xd3, /* callq *%r11 */ + 0x41, 0xff, 0xd3, /* callq *%r11 */ +#ifndef _WIN32 0x48, 0x81, 0xc4, 0, 0, 0, 0, /* addq , %rsp */ +#endif }; static const uint8_t epilog[] = { +#ifdef _WIN32 /* Strict form of windows epilogue for unwinding: */ + 0x48, 0x8d, 0x65, 0x0, /* lea 0x0(%rbp),%rsp */ + 0x5d, /* pop %rbp */ +#endif 0x5b, /* pop %rbx */ 0x41, 0x5c, /* pop %r12 */ 0xc3, /* ret */ @@ -423,7 +434,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s } else if (MIR_blk_type_p (type)) { qwords = (arg_descs[i].size + 7) / 8; #ifndef _WIN32 - if (type == MIR_T_BLK2 && n_iregs + qwords <= max_iregs) { + if (type == MIR_T_BLK + 1 && n_iregs + qwords <= max_iregs) { assert (qwords <= 2); gen_mov (code, (i + nres) * sizeof (long double), 12, TRUE); /* r12 = block addr */ gen_mov2 (code, 0, iregs[n_iregs], TRUE); /* arg_reg = mem[r12] */ @@ -431,14 +442,14 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s n_iregs += qwords; n_xregs += qwords; continue; - } else if (type == MIR_T_BLK3 && n_xregs + qwords <= max_xregs) { + } else if (type == MIR_T_BLK + 2 && n_xregs + qwords <= max_xregs) { assert (qwords <= 2); gen_mov (code, (i + nres) * sizeof (long double), 12, TRUE); /* r12 = block addr */ gen_movxmm2 (code, 0, n_xregs, TRUE); /* xmm = mem[r12] */ if (qwords == 2) gen_movxmm2 (code, 8, n_xregs + 1, TRUE); /* xmm = mem[r12 + 8] */ n_xregs += qwords; continue; - } else if (type == MIR_T_BLK4 && n_iregs < max_iregs && n_xregs < max_xregs) { + } else if (type == MIR_T_BLK + 3 && n_iregs < max_iregs && n_xregs < max_xregs) { assert (qwords == 2); gen_mov (code, (i + nres) * sizeof (long double), 12, TRUE); /* r12 = block addr */ gen_mov2 (code, 0, iregs[n_iregs], TRUE); /* arg_reg = mem[r12] */ @@ -447,7 +458,7 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s gen_movxmm2 (code, 8, n_xregs, TRUE); /* xmm = mem[r12 + 8] */ n_xregs++; continue; - } else if (type == MIR_T_BLK5 && n_iregs < max_iregs && n_xregs < max_xregs) { + } else if (type == MIR_T_BLK + 4 && n_iregs < max_iregs && n_xregs < max_xregs) { assert (qwords == 2); gen_mov (code, (i + nres) * sizeof (long double), 12, TRUE); /* r12 = block addr */ gen_movxmm2 (code, 0, n_xregs, TRUE); /* xmm = mem[r12] */ @@ -492,12 +503,19 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s if (blk_offset > sp_offset) sp_offset = blk_offset; #endif sp_offset = (sp_offset + 15) / 16 * 16; - sp_offset += 8; +#ifndef _WIN32 + sp_offset += 8; /* align */ +#endif addr = VARR_ADDR (uint8_t, code); +#ifndef _WIN32 memcpy (addr + 6, &sp_offset, sizeof (uint32_t)); +#else + memcpy (addr + 10, &sp_offset, sizeof (uint32_t)); +#endif addr = push_insns (code, call_end, sizeof (call_end)); +#ifndef _WIN32 memcpy (addr + sizeof (call_end) - 4, &sp_offset, sizeof (uint32_t)); -#ifdef _WIN32 +#else if (nres > 1) MIR_get_error_func (ctx) (MIR_call_op_error, "Windows x86-64 doesn't support multiple return values"); @@ -550,27 +568,34 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl static const uint32_t hndl_offset = 0x4c; static const uint32_t prep_stack_size = 208; #else - /* 0: */ 0x4c, 0x8d, 0x44, 0x24, 0x08, /* lea 8(%rsp),%r8 */ - /* 5: */ 0x53, /* push %rbx */ - /* 6: */ 0x48, 0x81, 0xec, 0, 0, 0, 0, /* sub ,%rsp */ - /* d: */ 0x48, 0x89, 0xe3, /* mov %rsp,%rbx */ - /* 10: */ 0x49, 0x89, 0xe1, /* mov %rsp,%r9 */ - /* 13: */ 0x48, 0x83, 0xec, 0x20, /* sub 32,%rsp */ - /* 17: */ 0x48, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rcx */ - /* 21: */ 0x48, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rdx*/ - /* 2b: */ 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rax */ - /* 35: */ 0xff, 0xd0, /* callq *%rax */ + /* 0: */ 0x53, /* push %rbx */ + /* 1: */ 0x55, /* push %rbp */ + /* 2: */ 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */ + /* 5: */ 0x4c, 0x8d, 0x44, 0x24, 0x18, /* lea 24(%rsp),%r8 */ + /* a: */ 0x48, 0x81, 0xec, 0, 0, 0, 0, /* sub ,%rsp */ + /* 11: */ 0x48, 0x89, 0xe3, /* mov %rsp,%rbx */ + /* 14: */ 0x49, 0x89, 0xe1, /* mov %rsp,%r9 */ + /* 17: */ 0x48, 0x83, 0xec, 0x20, /* sub 32,%rsp */ + /* 1b: */ 0x48, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rcx */ + /* 25: */ 0x48, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rdx*/ + /* 2f: */ 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%rax */ + /* 39: */ 0xff, 0xd0, /* callq *%rax */ }; - static const uint32_t nres_offset = 0x09; - static const uint32_t ctx_offset = 0x19; - static const uint32_t func_offset = 0x23; - static const uint32_t hndl_offset = 0x2d; + static const uint32_t nres_offset = 0x0d; + static const uint32_t ctx_offset = 0x1d; + static const uint32_t func_offset = 0x27; + static const uint32_t hndl_offset = 0x31; static const uint32_t prep_stack_size = 32; #endif static const uint8_t shim_end[] = { +#ifndef _WIN32 /* 0: */ 0x48, 0x81, 0xc4, 0, 0, 0, 0, /*add prep_stack_size+n,%rsp*/ - /* 7: */ 0x5b, /*pop %rbx*/ - /* 8: */ 0xc3, /*retq */ +#else /* Strict form of windows epilogue for unwinding: */ + /* 0 */ 0x48, 0x8d, 0x65, 0x0, /* lea 0x0(%rbp),%rsp */ + /* 4: */ 0x5d, /* pop %rbp */ +#endif + 0x5b, /*pop %rbx*/ + 0xc3, /*retq */ }; static const uint8_t ld_pat[] = {0x48, 0x8b, 0x83, 0, 0, 0, 0}; /* mov (%rbx), %reg */ static const uint8_t movss_pat[] @@ -593,6 +618,9 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl push_insns (code, save_pat, sizeof (save_pat)); addr = push_insns (code, prepare_pat, sizeof (prepare_pat)); imm = nres * 16; +#ifdef _WIN32 + imm += 8; /*align */ +#endif memcpy (addr + nres_offset, &imm, sizeof (uint32_t)); memcpy (addr + ctx_offset, &ctx, sizeof (void *)); memcpy (addr + func_offset, &func_item, sizeof (void *)); @@ -632,8 +660,10 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl offset += 16; } addr = push_insns (code, shim_end, sizeof (shim_end)); +#ifndef _WIN32 imm = prep_stack_size + nres * 16; memcpy (addr + 3, &imm, sizeof (uint32_t)); +#endif res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); VARR_DESTROY (uint8_t, code); return res; @@ -649,25 +679,33 @@ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_ad #endif 0x41, 0xff, 0xe2, /*jmpq *%r10 */ }; - static const uint8_t call_pat[] = { + static const uint8_t call_pat[] = #ifndef _WIN32 - 0x48, 0xbe, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs called_func,%rsi */ - 0x48, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs ctx,%rdi */ - 0x49, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs ,%r10 */ - 0x41, 0xff, 0xd2, /*callq *%r10 */ - 0x49, 0x89, 0xc2, /*mov %rax,%r10 */ + { + 0x48, 0xbe, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs called_func,%rsi */ + 0x48, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ctx,%rdi */ + 0x49, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%r10 */ + 0x41, 0xff, 0xd2, /* callq *%r10 */ + 0x49, 0x89, 0xc2, /* mov %rax,%r10 */ + }; + size_t call_func_offset = 2, ctx_offset = 12, hook_offset = 22; #else - 0x48, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs called_func,%rdx */ - 0x48, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs ctx,%rcx */ - 0x49, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /*movabs ,%r10*/ - 0x50, /*push %rax */ - 0x48, 0x83, 0xec, 0x20, /*sub 32,%rsp */ - 0x41, 0xff, 0xd2, /*callq *%r10 */ - 0x49, 0x89, 0xc2, /*mov %rax,%r10 */ - 0x48, 0x83, 0xc4, 0x20, /*add 32,%rsp */ - 0x58, /*pop %rax */ + { + 0x55, /* push %rbp */ + 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */ + 0x48, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs called_func,%rdx */ + 0x48, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ctx,%rcx */ + 0x49, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs ,%r10*/ + 0x50, /* push %rax */ + 0x48, 0x83, 0xec, 0x28, /* sub 40,%rsp */ + 0x41, 0xff, 0xd2, /* callq *%r10 */ + 0x49, 0x89, 0xc2, /* mov %rax,%r10 */ + 0x48, 0x83, 0xc4, 0x28, /* add 40,%rsp */ + 0x58, /* pop %rax */ + 0x5d, /* pop %rbp */ + }; + size_t call_func_offset = 6, ctx_offset = 16, hook_offset = 26; #endif - }; uint8_t *addr; VARR (uint8_t) * code; void *res; @@ -678,9 +716,9 @@ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_ad #endif push_insns (code, save_pat, sizeof (save_pat)); addr = push_insns (code, call_pat, sizeof (call_pat)); - memcpy (addr + 2, &called_func, sizeof (void *)); - memcpy (addr + 12, &ctx, sizeof (void *)); - memcpy (addr + 22, &hook_address, sizeof (void *)); + memcpy (addr + call_func_offset, &called_func, sizeof (void *)); + memcpy (addr + ctx_offset, &ctx, sizeof (void *)); + memcpy (addr + hook_offset, &hook_address, sizeof (void *)); push_insns (code, restore_pat, sizeof (restore_pat)); push_insns (code, wrap_end, sizeof (wrap_end)); res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); diff --git a/mir/mir.c b/mir/mir.c index 9aff9b3..85ed68a 100644 --- a/mir/mir.c +++ b/mir/mir.c @@ -51,6 +51,7 @@ struct MIR_context { struct io_ctx *io_ctx; struct scan_ctx *scan_ctx; struct interp_ctx *interp_ctx; + void *setjmp_addr; /* used in interpreter to call setjmp directly not from a shim and FFI */ }; #define ctx_mutex ctx->ctx_mutex @@ -66,6 +67,7 @@ struct MIR_context { #define curr_label_num ctx->curr_label_num #define all_modules ctx->all_modules #define modules_to_link ctx->modules_to_link +#define setjmp_addr ctx->setjmp_addr static void util_error (MIR_context_t ctx, const char *message); #define MIR_VARR_ERROR util_error @@ -763,7 +765,10 @@ MIR_module_t MIR_new_module (MIR_context_t ctx, const char *name) { DLIST (MIR_module_t) * MIR_get_module_list (MIR_context_t ctx) { return &all_modules; } -static const char *type_str (MIR_type_t tp) { +static const char *type_str (MIR_context_t ctx, MIR_type_t tp) { + int n; + char str[100]; + switch (tp) { case MIR_T_I8: return "i8"; case MIR_T_U8: return "u8"; @@ -777,19 +782,19 @@ static const char *type_str (MIR_type_t tp) { case MIR_T_D: return "d"; case MIR_T_LD: return "ld"; case MIR_T_P: return "p"; - case MIR_T_BLK: return "blk"; - case MIR_T_BLK2: return "blk2"; - case MIR_T_BLK3: return "blk3"; - case MIR_T_BLK4: return "blk4"; - case MIR_T_BLK5: return "blk5"; case MIR_T_RBLK: return "rblk"; case MIR_T_UNDEF: return "undef"; - default: return ""; + default: + if (MIR_blk_type_p (tp) && (n = tp - MIR_T_BLK) >= 0 && n < MIR_BLK_NUM) { + sprintf (str, "blk%d", n); + return get_ctx_str (ctx, str); + } + return ""; } } const char *MIR_type_str (MIR_context_t ctx, MIR_type_t tp) { - const char *str = type_str (tp); + const char *str = type_str (ctx, tp); if (strcmp (str, "") == 0) MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_type_str: wrong type"); @@ -1264,7 +1269,7 @@ MIR_reg_t MIR_new_func_reg (MIR_context_t ctx, MIR_func_t func, MIR_type_t type, if (type != MIR_T_I64 && type != MIR_T_F && type != MIR_T_D && type != MIR_T_LD) MIR_get_error_func (ctx) (MIR_reg_type_error, "wrong type for register %s: got '%s'", name, - type_str (type)); + type_str (ctx, type)); mir_assert (func != NULL); res = create_func_reg (ctx, func, name, VARR_LENGTH (MIR_var_t, func->vars) + 1, type, FALSE, &stored_name); @@ -1576,8 +1581,8 @@ void MIR_load_module (MIR_context_t ctx, MIR_module_t m) { } else if (item->item_type == MIR_func_item) { if (item->addr == NULL) { item->addr = _MIR_get_thunk (ctx); -#ifdef MIR_DEBUG - fprintf (stderr, "%016lx: %s\n", (size_t) item->addr, item->u.func->name); +#if defined(MIR_DEBUG) + fprintf (stderr, "%016llx: %s\n", (unsigned long long) item->addr, item->u.func->name); #endif } _MIR_redirect_thunk (ctx, item->addr, undefined_interface); @@ -1592,7 +1597,12 @@ void MIR_load_module (MIR_context_t ctx, MIR_module_t m) { VARR_PUSH (MIR_module_t, modules_to_link, m); } +#define SETJMP_NAME "setjmp" +#define SETJMP_NAME2 "_setjmp" + void MIR_load_external (MIR_context_t ctx, const char *name, void *addr) { + if (strcmp (name, SETJMP_NAME) == 0 || (SETJMP_NAME2 != NULL && strcmp (name, SETJMP_NAME2) == 0)) + setjmp_addr = addr; setup_global (ctx, name, addr, NULL); } @@ -1998,7 +2008,7 @@ MIR_reg_t _MIR_new_temp_reg (MIR_context_t ctx, MIR_type_t type, MIR_func_t func if (type != MIR_T_I64 && type != MIR_T_F && type != MIR_T_D && type != MIR_T_LD) MIR_get_error_func (ctx) (MIR_reg_type_error, "wrong type %s for temporary register", - type_str (type)); + type_str (ctx, type)); mir_assert (func != NULL); for (;;) { func->last_temp_num++; @@ -2398,7 +2408,9 @@ void MIR_change_module_ctx (MIR_context_t old_ctx, MIR_module_t m, MIR_context_t } } -static void output_type (FILE *f, MIR_type_t tp) { fprintf (f, "%s", MIR_type_str (NULL, tp)); } +static void output_type (MIR_context_t ctx, FILE *f, MIR_type_t tp) { + fprintf (f, "%s", MIR_type_str (ctx, tp)); +} static void output_disp (FILE *f, MIR_disp_t disp) { fprintf (f, "%" PRId64, (int64_t) disp); } @@ -2451,7 +2463,7 @@ void MIR_output_op (MIR_context_t ctx, FILE *f, MIR_op_t op, MIR_func_t func) { case MIR_OP_HARD_REG_MEM: { MIR_reg_t no_reg = op.mode == MIR_OP_MEM ? 0 : MIR_NON_HARD_REG; - output_type (f, op.u.mem.type); + output_type (ctx, f, op.u.mem.type); fprintf (f, ":"); if (op.u.mem.disp != 0 || (op.u.mem.base == no_reg && op.u.mem.index == no_reg)) output_disp (f, op.u.mem.disp); @@ -2510,23 +2522,23 @@ void MIR_output_insn (MIR_context_t ctx, FILE *f, MIR_insn_t insn, MIR_func_t fu if (newline_p) fprintf (f, "\n"); } -static void output_func_proto (FILE *f, size_t nres, MIR_type_t *types, size_t nargs, - VARR (MIR_var_t) * args, int vararg_p) { +static void output_func_proto (MIR_context_t ctx, FILE *f, size_t nres, MIR_type_t *types, + size_t nargs, VARR (MIR_var_t) * args, int vararg_p) { size_t i; MIR_var_t var; for (i = 0; i < nres; i++) { if (i != 0) fprintf (f, ", "); - fprintf (f, "%s", MIR_type_str (NULL, types[i])); + fprintf (f, "%s", MIR_type_str (ctx, types[i])); } for (i = 0; i < nargs; i++) { var = VARR_GET (MIR_var_t, args, i); if (i != 0 || nres != 0) fprintf (f, ", "); mir_assert (var.name != NULL); if (!MIR_all_blk_type_p (var.type)) - fprintf (f, "%s:%s", MIR_type_str (NULL, var.type), var.name); + fprintf (f, "%s:%s", MIR_type_str (ctx, var.type), var.name); else - fprintf (f, "%s:%lu(%s)", MIR_type_str (NULL, var.type), (unsigned long) var.size, var.name); + fprintf (f, "%s:%lu(%s)", MIR_type_str (ctx, var.type), (unsigned long) var.size, var.name); } if (vararg_p) fprintf (f, nargs == 0 && nres == 0 ? "..." : ", ..."); fprintf (f, "\n"); @@ -2575,7 +2587,7 @@ void MIR_output_item (MIR_context_t ctx, FILE *f, MIR_item_t item) { if (item->item_type == MIR_data_item) { data = item->u.data; if (data->name != NULL) fprintf (f, "%s:", data->name); - fprintf (f, "\t%s\t", MIR_type_str (NULL, data->el_type)); + fprintf (f, "\t%s\t", MIR_type_str (ctx, data->el_type)); for (size_t i = 0; i < data->nel; i++) { switch (data->el_type) { case MIR_T_I8: fprintf (f, "%" PRId8, ((int8_t *) data->u.els)[i]); break; @@ -2607,13 +2619,13 @@ void MIR_output_item (MIR_context_t ctx, FILE *f, MIR_item_t item) { if (item->item_type == MIR_proto_item) { proto = item->u.proto; fprintf (f, "%s:\tproto\t", proto->name); - output_func_proto (f, proto->nres, proto->res_types, VARR_LENGTH (MIR_var_t, proto->args), + output_func_proto (ctx, f, proto->nres, proto->res_types, VARR_LENGTH (MIR_var_t, proto->args), proto->args, proto->vararg_p); return; } func = item->u.func; fprintf (f, "%s:\tfunc\t", func->name); - output_func_proto (f, func->nres, func->res_types, func->nargs, func->vars, func->vararg_p); + output_func_proto (ctx, f, func->nres, func->res_types, func->nargs, func->vars, func->vararg_p); nlocals = VARR_LENGTH (MIR_var_t, func->vars) - func->nargs; for (i = 0; i < nlocals; i++) { var = VARR_GET (MIR_var_t, func->vars, i + func->nargs); @@ -2621,7 +2633,7 @@ void MIR_output_item (MIR_context_t ctx, FILE *f, MIR_item_t item) { if (i != 0) fprintf (f, "\n"); fprintf (f, "\tlocal\t"); } - fprintf (f, i % 8 == 0 ? "%s:%s" : ", %s:%s", MIR_type_str (NULL, var.type), var.name); + fprintf (f, i % 8 == 0 ? "%s:%s" : ", %s:%s", MIR_type_str (ctx, var.type), var.name); } fprintf (f, "\n# %u arg%s, %u local%s\n", func->nargs, func->nargs == 1 ? "" : "s", (unsigned) nlocals, nlocals == 1 ? "" : "s"); @@ -3790,8 +3802,9 @@ typedef enum { REP3 (TAG_EL, MEM_DISP_INDEX, MEM_BASE_INDEX, MEM_DISP_BASE_INDEX), /* MIR types. The same order as MIR types: */ REP8 (TAG_EL, TI8, TU8, TI16, TU16, TI32, TU32, TI64, TU64), - REP8 (TAG_EL, TF, TD, TP, TV, TBLOCK, TBLOCK2, TBLOCK3, TBLOCK4), - REP3 (TAG_EL, TBLOCK5, TRBLOCK, EOI), + REP5 (TAG_EL, TF, TD, TP, TV, TBLOCK), + TAG_EL (TRBLOCK) = TAG_EL (TBLOCK) + MIR_BLK_NUM, + TAG_EL (EOI), TAG_EL (EOFILE), /* end of insn with variable number operands (e.g. a call) or end of file */ /* unsigned integer 0..127 is kept in one byte. The most significant bit of the byte is 1: */ U0_MASK = 0x7f, @@ -4515,11 +4528,15 @@ static bin_tag_t read_token (MIR_context_t ctx, token_attr_t *attr) { REP3 (TAG_CASE, MEM_DISP_BASE_INDEX, EOI, EOFILE) break; REP8 (TAG_CASE, TI8, TU8, TI16, TU16, TI32, TU32, TI64, TU64) - REP8 (TAG_CASE, TF, TD, TP, TV, TBLOCK, TBLOCK2, TBLOCK3, TBLOCK4) - REP2 (TAG_CASE, TBLOCK5, TRBLOCK) + REP5 (TAG_CASE, TF, TD, TP, TV, TRBLOCK) attr->t = (MIR_type_t) (c - TAG_TI8) + MIR_T_I8; break; - default: MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong tag %d", c); + default: + if (TAG_TBLOCK <= c && c < TAG_TBLOCK + MIR_BLK_NUM) { + attr->t = (MIR_type_t) (c - TAG_TBLOCK) + MIR_T_BLK; + break; + } + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong tag %d", c); } return c; } @@ -4841,7 +4858,7 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) default: MIR_get_error_func (ctx) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + type_str (ctx, type)); } break; case TAG_I1: @@ -4872,28 +4889,28 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) default: MIR_get_error_func (ctx) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + type_str (ctx, type)); } break; case TAG_F: if (type != MIR_T_F) MIR_get_error_func (ctx) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + type_str (ctx, type)); push_data (ctx, (uint8_t *) &attr.f, sizeof (float)); break; case TAG_D: if (type != MIR_T_D) MIR_get_error_func (ctx) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + type_str (ctx, type)); push_data (ctx, (uint8_t *) &attr.d, sizeof (double)); break; case TAG_LD: if (type != MIR_T_LD) MIR_get_error_func (ctx) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + type_str (ctx, type)); push_data (ctx, (uint8_t *) &attr.ld, sizeof (long double)); break; /* ??? ptr */ @@ -4965,6 +4982,7 @@ void MIR_read (MIR_context_t ctx, FILE *f) { } static void io_init (MIR_context_t ctx) { + mir_assert (TAG_EOFILE < 127); /* see bin_tag_t */ if ((ctx->io_ctx = malloc (sizeof (struct io_ctx))) == NULL) MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); VARR_CREATE (MIR_var_t, proto_vars, 0); @@ -5401,11 +5419,11 @@ static MIR_type_t str2type (const char *type_name) { if (strcmp (type_name, "u16") == 0) return MIR_T_U16; if (strcmp (type_name, "i8") == 0) return MIR_T_I8; if (strcmp (type_name, "u8") == 0) return MIR_T_U8; - if (strcmp (type_name, "blk") == 0) return MIR_T_BLK; - if (strcmp (type_name, "blk2") == 0) return MIR_T_BLK2; - if (strcmp (type_name, "blk3") == 0) return MIR_T_BLK3; - if (strcmp (type_name, "blk4") == 0) return MIR_T_BLK4; - if (strcmp (type_name, "blk5") == 0) return MIR_T_BLK5; + if (strncmp (type_name, "blk", 3) == 0) { + int i, n = 0; + for (i = 3; isdigit (type_name[i]) && n < MIR_BLK_NUM; i++) n = n * 10 + (type_name[i] - '0'); + if (type_name[i] == 0 && n < MIR_BLK_NUM) return MIR_T_BLK + n; + } if (strcmp (type_name, "rblk") == 0) return MIR_T_RBLK; return MIR_T_BOUND; } diff --git a/mir/mir.h b/mir/mir.h index 80a983b..204c0bc 100644 --- a/mir/mir.h +++ b/mir/mir.h @@ -176,11 +176,13 @@ typedef enum { #define TYPE_EL(t) MIR_T_##t +#define MIR_BLK_NUM 5 /* Data types: */ typedef enum { REP8 (TYPE_EL, I8, U8, I16, U16, I32, U32, I64, U64), /* Integer types of different size: */ REP3 (TYPE_EL, F, D, LD), /* Float or (long) double type */ - REP7 (TYPE_EL, P, BLK, BLK2, BLK3, BLK4, BLK5, RBLK), /* Pointer, (return) memory block */ + REP2 (TYPE_EL, P, BLK), /* Pointer, memory blocks */ + TYPE_EL (RBLK) = TYPE_EL (BLK) + MIR_BLK_NUM, /* return block */ REP2 (TYPE_EL, UNDEF, BOUND), } MIR_type_t; @@ -190,7 +192,7 @@ static inline int MIR_int_type_p (MIR_type_t t) { static inline int MIR_fp_type_p (MIR_type_t t) { return MIR_T_F <= t && t <= MIR_T_LD; } -static inline int MIR_blk_type_p (MIR_type_t t) { return MIR_T_BLK <= t && t <= MIR_T_BLK5; } +static inline int MIR_blk_type_p (MIR_type_t t) { return MIR_T_BLK <= t && t < MIR_T_RBLK; } static inline int MIR_all_blk_type_p (MIR_type_t t) { return MIR_T_BLK <= t && t <= MIR_T_RBLK; } #if UINTPTR_MAX == 0xffffffff