diff --git a/mir/c2mir/aarch64/caarch64-ABI-code.c b/mir/c2mir/aarch64/caarch64-ABI-code.c index dfab8bb..76c35a2 100644 --- a/mir/c2mir/aarch64/caarch64-ABI-code.c +++ b/mir/c2mir/aarch64/caarch64-ABI-code.c @@ -36,6 +36,7 @@ static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, target_arg_info_t *arg_info, size_t call_arg_area_offset) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; int size; @@ -52,6 +53,7 @@ static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res, MIR_insn_t call, size_t call_ops_start) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; int size; if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) @@ -63,6 +65,7 @@ static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_t } static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; int i, size; if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) { diff --git a/mir/c2mir/c2mir.c b/mir/c2mir/c2mir.c index bd631eb..aec4c5f 100644 --- a/mir/c2mir/c2mir.c +++ b/mir/c2mir/c2mir.c @@ -86,10 +86,15 @@ DEF_VARR (void_ptr_t); typedef struct { const char *s; - size_t len, key, flags; + size_t len; } str_t; -DEF_HTAB (str_t); +typedef struct { + str_t str; + size_t key, flags; +} tab_str_t; + +DEF_HTAB (tab_str_t); typedef struct token *token_t; DEF_VARR (token_t); @@ -122,10 +127,12 @@ struct init_object { typedef struct init_object init_object_t; DEF_VARR (init_object_t); -struct pre_ctx; -struct parse_ctx; -struct check_ctx; -struct gen_ctx; +typedef struct pre_ctx *pre_ctx_t; +typedef struct parse_ctx *parse_ctx_t; +typedef struct check_ctx *check_ctx_t; +typedef struct gen_ctx *gen_ctx_t; + +DEF_VARR (pos_t); struct c2m_ctx { MIR_context_t ctx; @@ -138,10 +145,10 @@ struct c2m_ctx { VARR (void_ptr_t) * reg_memory; VARR (stream_t) * streams; /* stack of streams */ stream_t cs, eof_s; /* current stream and stream corresponding the last EOF */ - HTAB (str_t) * str_tab; - HTAB (str_t) * str_key_tab; + HTAB (tab_str_t) * str_tab; + HTAB (tab_str_t) * str_key_tab; str_t empty_str; - unsigned long curr_uid; + unsigned curr_uid; int (*c_getc) (void *); /* c2mir interface get function */ void *c_getc_data; unsigned n_errors, n_warnings; @@ -149,6 +156,7 @@ struct c2m_ctx { VARR (token_t) * recorded_tokens, *buffered_tokens; node_t top_scope; HTAB (symbol_t) * symbol_tab; + VARR (pos_t) * node_positions; VARR (node_t) * call_nodes; VARR (node_t) * containing_anon_members; VARR (init_object_t) * init_object_path; @@ -185,6 +193,7 @@ typedef struct c2m_ctx *c2m_ctx_t; #define buffered_tokens c2m_ctx->buffered_tokens #define top_scope c2m_ctx->top_scope #define symbol_tab c2m_ctx->symbol_tab +#define node_positions c2m_ctx->node_positions #define call_nodes c2m_ctx->call_nodes #define containing_anon_members c2m_ctx->containing_anon_members #define init_object_path c2m_ctx->init_object_path @@ -354,59 +363,61 @@ static int char_is_signed_p (void) { return MIR_CHAR_MAX == MIR_SCHAR_MAX; } enum str_flag { FLAG_EXT = 1, FLAG_C89, FLAG_EXT89 }; -static int str_eq (str_t str1, str_t str2, void *arg) { - return str1.len == str2.len && memcmp (str1.s, str2.s, str1.len) == 0; +static int str_eq (tab_str_t str1, tab_str_t str2, void *arg) { + return str1.str.len == str2.str.len && memcmp (str1.str.s, str2.str.s, str1.str.len) == 0; +} +static htab_hash_t str_hash (tab_str_t str, void *arg) { + return mir_hash (str.str.s, str.str.len, 0x42); } -static htab_hash_t str_hash (str_t str, void *arg) { return mir_hash (str.s, str.len, 0x42); } -static int str_key_eq (str_t str1, str_t str2, void *arg) { return str1.key == str2.key; } -static htab_hash_t str_key_hash (str_t str, void *arg) { return mir_hash64 (str.key, 0x24); } +static int str_key_eq (tab_str_t str1, tab_str_t str2, void *arg) { return str1.key == str2.key; } +static htab_hash_t str_key_hash (tab_str_t str, void *arg) { return mir_hash64 (str.key, 0x24); } static str_t uniq_cstr (c2m_ctx_t c2m_ctx, const char *str); static void str_init (c2m_ctx_t c2m_ctx) { - HTAB_CREATE (str_t, str_tab, 1000, str_hash, str_eq, NULL); - HTAB_CREATE (str_t, str_key_tab, 200, str_key_hash, str_key_eq, NULL); + HTAB_CREATE (tab_str_t, str_tab, 1000, str_hash, str_eq, NULL); + HTAB_CREATE (tab_str_t, str_key_tab, 200, str_key_hash, str_key_eq, NULL); empty_str = uniq_cstr (c2m_ctx, ""); } -static int str_exists_p (c2m_ctx_t c2m_ctx, const char *s, size_t len, str_t *tab_str) { - str_t el, str; +static int str_exists_p (c2m_ctx_t c2m_ctx, const char *s, size_t len, tab_str_t *tab_str) { + tab_str_t el, str; - str.s = s; - str.len = len; - if (!HTAB_DO (str_t, str_tab, str, HTAB_FIND, el)) return FALSE; + str.str.s = s; + str.str.len = len; + if (!HTAB_DO (tab_str_t, str_tab, str, HTAB_FIND, el)) return FALSE; *tab_str = el; return TRUE; } -static str_t str_add (c2m_ctx_t c2m_ctx, const char *s, size_t len, size_t key, size_t flags, - int key_p) { +static tab_str_t str_add (c2m_ctx_t c2m_ctx, const char *s, size_t len, size_t key, size_t flags, + int key_p) { char *heap_s; - str_t el, str; + tab_str_t el, str; if (str_exists_p (c2m_ctx, s, len, &el)) return el; heap_s = reg_malloc (c2m_ctx, len); memcpy (heap_s, s, len); - str.s = heap_s; - str.len = len; + str.str.s = heap_s; + str.str.len = len; str.key = key; str.flags = flags; - HTAB_DO (str_t, str_tab, str, HTAB_INSERT, el); - if (key_p) HTAB_DO (str_t, str_key_tab, str, HTAB_INSERT, el); + HTAB_DO (tab_str_t, str_tab, str, HTAB_INSERT, el); + if (key_p) HTAB_DO (tab_str_t, str_key_tab, str, HTAB_INSERT, el); return str; } static const char *str_find_by_key (c2m_ctx_t c2m_ctx, size_t key) { - str_t el, str; + tab_str_t el, str; str.key = key; - if (!HTAB_DO (str_t, str_key_tab, str, HTAB_FIND, el)) return NULL; - return el.s; + if (!HTAB_DO (tab_str_t, str_key_tab, str, HTAB_FIND, el)) return NULL; + return el.str.s; } static void str_finish (c2m_ctx_t c2m_ctx) { - HTAB_DESTROY (str_t, str_tab); - HTAB_DESTROY (str_t, str_key_tab); + HTAB_DESTROY (tab_str_t, str_tab); + HTAB_DESTROY (tab_str_t, str_key_tab); } static void *c2mir_calloc (c2m_ctx_t c2m_ctx, size_t size) { @@ -564,10 +575,9 @@ DEF_DLIST_TYPE (node_t); struct node { node_code_t code; - unsigned long uid; - pos_t pos; + unsigned uid; + void *attr; /* used a scope for parser and as an attribute after */ DLIST_LINK (node_t) op_link; - DLIST (node_t) ops; union { str_t s; mir_char ch; @@ -578,11 +588,21 @@ struct node { mir_float f; mir_double d; mir_ldouble ld; - node_t scope; + DLIST (node_t) ops; } u; - void *attr; }; +static pos_t get_node_pos (c2m_ctx_t c2m_ctx, node_t n) { + return VARR_GET (pos_t, node_positions, n->uid); +} + +#define POS(n) get_node_pos (c2m_ctx, n) + +static void set_node_pos (c2m_ctx_t c2m_ctx, node_t n, pos_t pos) { + while (n->uid >= VARR_LENGTH (pos_t, node_positions)) VARR_PUSH (pos_t, node_positions, no_pos); + VARR_SET (pos_t, node_positions, n->uid, pos); +} + DEF_DLIST_CODE (node_t, op_link); struct token { @@ -594,30 +614,30 @@ struct token { const char *repr; }; -static node_t add_pos (node_t n, pos_t p) { - if (n->pos.lno < 0) n->pos = p; +static node_t add_pos (c2m_ctx_t c2m_ctx, node_t n, pos_t p) { + if (POS (n).lno < 0) set_node_pos (c2m_ctx, n, p); return n; } -static node_t op_append (node_t n, node_t op) { - NL_APPEND (n->ops, op); - return add_pos (n, op->pos); +static node_t op_append (c2m_ctx_t c2m_ctx, node_t n, node_t op) { + NL_APPEND (n->u.ops, op); + return add_pos (c2m_ctx, n, POS (op)); } -static node_t op_prepend (node_t n, node_t op) { - NL_PREPEND (n->ops, op); - return add_pos (n, op->pos); +static node_t op_prepend (c2m_ctx_t c2m_ctx, node_t n, node_t op) { + NL_PREPEND (n->u.ops, op); + return add_pos (c2m_ctx, n, POS (op)); } -static void op_flat_append (node_t n, node_t op) { +static void op_flat_append (c2m_ctx_t c2m_ctx, node_t n, node_t op) { if (op->code != N_LIST) { - op_append (n, op); + op_append (c2m_ctx, n, op); return; } - for (node_t next_el, el = NL_HEAD (op->ops); el != NULL; el = next_el) { + for (node_t next_el, el = NL_HEAD (op->u.ops); el != NULL; el = next_el) { next_el = NL_NEXT (el); - NL_REMOVE (op->ops, el); - op_append (n, el); + NL_REMOVE (op->u.ops, el); + op_append (c2m_ctx, n, el); } } @@ -626,53 +646,53 @@ static node_t new_node (c2m_ctx_t c2m_ctx, node_code_t nc) { n->code = nc; n->uid = curr_uid++; - DLIST_INIT (node_t, n->ops); + DLIST_INIT (node_t, n->u.ops); n->attr = NULL; - n->pos = no_pos; + set_node_pos (c2m_ctx, n, no_pos); return n; } static node_t copy_node_with_pos (c2m_ctx_t c2m_ctx, node_t n, pos_t pos) { node_t r = new_node (c2m_ctx, n->code); - r->pos = pos; + set_node_pos (c2m_ctx, r, pos); r->u = n->u; return r; } static node_t copy_node (c2m_ctx_t c2m_ctx, node_t n) { - return copy_node_with_pos (c2m_ctx, n, n->pos); + return copy_node_with_pos (c2m_ctx, n, POS (n)); } static node_t new_pos_node (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p) { - return add_pos (new_node (c2m_ctx, nc), p); + return add_pos (c2m_ctx, new_node (c2m_ctx, nc), p); } static node_t new_node1 (c2m_ctx_t c2m_ctx, node_code_t nc, node_t op1) { - return op_append (new_node (c2m_ctx, nc), op1); + return op_append (c2m_ctx, new_node (c2m_ctx, nc), op1); } static node_t new_pos_node1 (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p, node_t op1) { - return add_pos (new_node1 (c2m_ctx, nc, op1), p); + return add_pos (c2m_ctx, new_node1 (c2m_ctx, nc, op1), p); } static node_t new_node2 (c2m_ctx_t c2m_ctx, node_code_t nc, node_t op1, node_t op2) { - return op_append (new_node1 (c2m_ctx, nc, op1), op2); + return op_append (c2m_ctx, new_node1 (c2m_ctx, nc, op1), op2); } static node_t new_pos_node2 (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p, node_t op1, node_t op2) { - return add_pos (new_node2 (c2m_ctx, nc, op1, op2), p); + return add_pos (c2m_ctx, new_node2 (c2m_ctx, nc, op1, op2), p); } static node_t new_node3 (c2m_ctx_t c2m_ctx, node_code_t nc, node_t op1, node_t op2, node_t op3) { - return op_append (new_node2 (c2m_ctx, nc, op1, op2), op3); + return op_append (c2m_ctx, new_node2 (c2m_ctx, nc, op1, op2), op3); } static node_t new_pos_node3 (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p, node_t op1, node_t op2, node_t op3) { - return add_pos (new_node3 (c2m_ctx, nc, op1, op2, op3), p); + return add_pos (c2m_ctx, new_node3 (c2m_ctx, nc, op1, op2, op3), p); } static node_t new_node4 (c2m_ctx_t c2m_ctx, node_code_t nc, node_t op1, node_t op2, node_t op3, node_t op4) { - return op_append (new_node3 (c2m_ctx, nc, op1, op2, op3), op4); + return op_append (c2m_ctx, new_node3 (c2m_ctx, nc, op1, op2, op3), op4); } static node_t new_pos_node4 (c2m_ctx_t c2m_ctx, node_code_t nc, pos_t p, node_t op1, node_t op2, node_t op3, node_t op4) { - return add_pos (new_node4 (c2m_ctx, nc, op1, op2, op3, op4), p); + return add_pos (c2m_ctx, new_node4 (c2m_ctx, nc, op1, op2, op3, op4), p); } 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); @@ -742,16 +762,16 @@ static node_t new_str_node (c2m_ctx_t c2m_ctx, node_code_t nc, str_t s, pos_t p) } static node_t get_op (node_t n, int nop) { - n = NL_HEAD (n->ops); + n = NL_HEAD (n->u.ops); for (; nop > 0; nop--) n = NL_NEXT (n); return n; } static str_t uniq_cstr (c2m_ctx_t c2m_ctx, const char *str) { - return str_add (c2m_ctx, str, strlen (str) + 1, T_STR, 0, FALSE); + return str_add (c2m_ctx, str, strlen (str) + 1, T_STR, 0, FALSE).str; } static str_t uniq_str (c2m_ctx_t c2m_ctx, const char *str, size_t len) { - return str_add (c2m_ctx, str, len, T_STR, 0, FALSE); + return str_add (c2m_ctx, str, len, T_STR, 0, FALSE).str; } static token_t new_token (c2m_ctx_t c2m_ctx, pos_t pos, const char *repr, int token_code, @@ -842,12 +862,14 @@ static void warning (c2m_ctx_t c2m_ctx, pos_t pos, const char *format, ...) { if ((f = c2m_options->message_file) == NULL) return; n_warnings++; - va_start (args, format); - print_pos (f, pos, TRUE); - fprintf (f, "warning -- "); - vfprintf (f, format, args); - va_end (args); - fprintf (f, "\n"); + if (!c2m_options->ignore_warnings_p) { + va_start (args, format); + print_pos (f, pos, TRUE); + fprintf (f, "warning -- "); + vfprintf (f, format, args); + va_end (args); + fprintf (f, "\n"); + } } #define TAB_STOP 8 @@ -1639,7 +1661,7 @@ static token_t pptoken2token (c2m_ctx_t c2m_ctx, token_t t, int id2kw_p) { && t->code != T_RDBLNO); if (t->code == T_NO_MACRO_IDENT) t->code = T_ID; if (t->code == T_ID && id2kw_p) { - str_t str = str_add (c2m_ctx, t->repr, strlen (t->repr) + 1, T_STR, 0, FALSE); + tab_str_t str = str_add (c2m_ctx, t->repr, strlen (t->repr) + 1, T_STR, 0, FALSE); if (str.key != T_STR) { t->code = str.key; @@ -1792,24 +1814,24 @@ struct pre_ctx { void (*pre_out_token_func) (c2m_ctx_t c2m_ctx, token_t); }; -#define temp_tokens c2m_ctx->pre_ctx->temp_tokens -#define macro_tab c2m_ctx->pre_ctx->macro_tab -#define macros c2m_ctx->pre_ctx->macros -#define ifs c2m_ctx->pre_ctx->ifs -#define no_out_p c2m_ctx->pre_ctx->no_out_p -#define skip_if_part_p c2m_ctx->pre_ctx->skip_if_part_p -#define if_id c2m_ctx->pre_ctx->if_id -#define date_str c2m_ctx->pre_ctx->date_str -#define time_str c2m_ctx->pre_ctx->time_str -#define date_str_repr c2m_ctx->pre_ctx->date_str_repr -#define time_str_repr c2m_ctx->pre_ctx->time_str_repr -#define output_buffer c2m_ctx->pre_ctx->output_buffer -#define macro_call_stack c2m_ctx->pre_ctx->macro_call_stack -#define pre_expr c2m_ctx->pre_ctx->pre_expr -#define pre_last_token c2m_ctx->pre_ctx->pre_last_token -#define actual_pre_pos c2m_ctx->pre_ctx->actual_pre_pos -#define pptokens_num c2m_ctx->pre_ctx->pptokens_num -#define pre_out_token_func c2m_ctx->pre_ctx->pre_out_token_func +#define temp_tokens pre_ctx->temp_tokens +#define macro_tab pre_ctx->macro_tab +#define macros pre_ctx->macros +#define ifs pre_ctx->ifs +#define no_out_p pre_ctx->no_out_p +#define skip_if_part_p pre_ctx->skip_if_part_p +#define if_id pre_ctx->if_id +#define date_str pre_ctx->date_str +#define time_str pre_ctx->time_str +#define date_str_repr pre_ctx->date_str_repr +#define time_str_repr pre_ctx->time_str_repr +#define output_buffer pre_ctx->output_buffer +#define macro_call_stack pre_ctx->macro_call_stack +#define pre_expr pre_ctx->pre_expr +#define pre_last_token pre_ctx->pre_last_token +#define actual_pre_pos pre_ctx->actual_pre_pos +#define pptokens_num pre_ctx->pptokens_num +#define pre_out_token_func pre_ctx->pre_out_token_func /* It is a token based prerpocessor. It is input preprocessor tokens and output is (parser) tokens */ @@ -1842,6 +1864,7 @@ static void new_std_macro (c2m_ctx_t c2m_ctx, const char *id_str) { } static void init_macros (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; VARR (token_t) * params; VARR_CREATE (macro_t, macros, 2048); @@ -1859,6 +1882,7 @@ static void init_macros (c2m_ctx_t c2m_ctx) { static macro_t new_macro (c2m_ctx_t c2m_ctx, token_t id, VARR (token_t) * params, VARR (token_t) * replacement) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; macro_t tab_m, m = malloc (sizeof (struct macro)); m->id = id; @@ -1872,6 +1896,7 @@ static macro_t new_macro (c2m_ctx_t c2m_ctx, token_t id, VARR (token_t) * params } static void finish_macros (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; if (macros != NULL) { while (VARR_LENGTH (macro_t, macros) != 0) { macro_t m = VARR_POP (macro_t, macros); @@ -1918,13 +1943,17 @@ static ifstate_t new_ifstate (int skip_p, int true_p, int else_p, pos_t if_pos) return ifstate; } -static void pop_ifstate (c2m_ctx_t c2m_ctx) { free (VARR_POP (ifstate_t, ifs)); } +static void pop_ifstate (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + free (VARR_POP (ifstate_t, ifs)); +} static void pre_init (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx; time_t t, time_loc; struct tm *tm, tm_loc; - c2m_ctx->pre_ctx = c2mir_calloc (c2m_ctx, sizeof (struct pre_ctx)); + c2m_ctx->pre_ctx = pre_ctx = c2mir_calloc (c2m_ctx, sizeof (struct pre_ctx)); no_out_p = skip_if_part_p = FALSE; t = time (&time_loc); #ifdef _MSC_VER @@ -1951,7 +1980,9 @@ static void pre_init (c2m_ctx_t c2m_ctx) { } static void pre_finish (c2m_ctx_t c2m_ctx) { - if (c2m_ctx == NULL || c2m_ctx->pre_ctx == NULL) return; + pre_ctx_t pre_ctx; + + if (c2m_ctx == NULL || (pre_ctx = c2m_ctx->pre_ctx) == NULL) return; if (temp_tokens != NULL) VARR_DESTROY (token_t, temp_tokens); if (output_buffer != NULL) VARR_DESTROY (token_t, output_buffer); finish_macros (c2m_ctx); @@ -1968,6 +1999,7 @@ static void pre_finish (c2m_ctx_t c2m_ctx) { } static void add_include_stream (c2m_ctx_t c2m_ctx, const char *fname, pos_t err_pos) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; FILE *f; assert (fname != NULL); @@ -2033,6 +2065,7 @@ static int replacement_eq_p (VARR (token_t) * r1, VARR (token_t) * r2) { } static void define (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; VARR (token_t) * repl, *params; token_t id, t; const char *name; @@ -2295,6 +2328,7 @@ static void check_pragma (c2m_ctx_t c2m_ctx, token_t t, VARR (token_t) * tokens) } static void pop_macro_call (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; macro_call_t mc; mc = VARR_POP (macro_call_t, macro_call_stack); @@ -2572,6 +2606,7 @@ static void prepare_pragma_string (const char *repr, VARR (char) * to) { } static int process_pragma (c2m_ctx_t c2m_ctx, token_t t) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; token_t t1, t2; if (strcmp (t->repr, "_Pragma") != 0) return FALSE; @@ -2616,12 +2651,16 @@ static int process_pragma (c2m_ctx_t c2m_ctx, token_t t) { } static void flush_buffer (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + for (size_t i = 0; i < VARR_LENGTH (token_t, output_buffer); i++) pre_out_token_func (c2m_ctx, VARR_GET (token_t, output_buffer, i)); VARR_TRUNC (token_t, output_buffer, 0); } static void out_token (c2m_ctx_t c2m_ctx, token_t t) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + if (no_out_p || VARR_LENGTH (macro_call_t, macro_call_stack) != 0) { VARR_PUSH (token_t, output_buffer, t); return; @@ -2704,6 +2743,7 @@ static const char *get_header_name (c2m_ctx_t c2m_ctx, VARR (token_t) * buffer, } static void process_directive (c2m_ctx_t c2m_ctx) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; token_t t, t1; int true_p; VARR (token_t) * temp_buffer; @@ -2886,6 +2926,7 @@ ret: } static int pre_match (c2m_ctx_t c2m_ctx, int c, pos_t *pos, node_code_t *node_code, node_t *node) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; token_t t; if (VARR_LENGTH (token_t, pre_expr) == 0) return FALSE; @@ -2914,7 +2955,7 @@ static node_t pre_primary_expr (c2m_ctx_t c2m_ctx) { if (!pre_match (c2m_ctx, ',', NULL, NULL, NULL)) return NULL; } } - return new_pos_node (c2m_ctx, N_IGNORE, n->pos); /* error only during evaluation */ + return new_pos_node (c2m_ctx, N_IGNORE, POS (n)); /* error only during evaluation */ } if (pre_match (c2m_ctx, '(', NULL, NULL, NULL)) { if ((r = pre_cond_expr (c2m_ctx)) == NULL) return NULL; @@ -2947,7 +2988,7 @@ static node_t pre_left_op (c2m_ctx_t c2m_ctx, int token, int token2, || (token2 >= 0 && pre_match (c2m_ctx, token2, &pos, &code, NULL))) { n = new_pos_node1 (c2m_ctx, code, pos, r); if ((r = f (c2m_ctx)) == NULL) return r; - op_append (n, r); + op_append (c2m_ctx, n, r); r = n; } return r; @@ -2992,14 +3033,15 @@ static node_t pre_cond_expr (c2m_ctx_t c2m_ctx) { if (!pre_match (c2m_ctx, '?', &pos, NULL, NULL)) return r; n = new_pos_node1 (c2m_ctx, N_COND, pos, r); if ((r = pre_cond_expr (c2m_ctx)) == NULL) return r; - op_append (n, r); + op_append (c2m_ctx, n, r); if (!pre_match (c2m_ctx, ':', NULL, NULL, NULL)) return NULL; if ((r = pre_cond_expr (c2m_ctx)) == NULL) return r; - op_append (n, r); + op_append (c2m_ctx, n, r); return n; } static node_t parse_pre_expr (c2m_ctx_t c2m_ctx, VARR (token_t) * expr) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; node_t r; token_t t; @@ -3012,6 +3054,7 @@ static node_t parse_pre_expr (c2m_ctx_t c2m_ctx, VARR (token_t) * expr) { } static void replace_defined (c2m_ctx_t c2m_ctx, VARR (token_t) * expr_buffer) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; int i, j, k, len; token_t t, id; const char *res; @@ -3054,6 +3097,7 @@ static void replace_defined (c2m_ctx_t c2m_ctx, VARR (token_t) * expr_buffer) { static struct val eval (c2m_ctx_t c2m_ctx, node_t tree); static struct val eval_expr (c2m_ctx_t c2m_ctx, VARR (token_t) * expr_buffer, token_t if_token) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; int i, j; token_t t, ppt; VARR (token_t) * temp_buffer; @@ -3111,8 +3155,8 @@ static struct val eval_expr (c2m_ctx_t c2m_ctx, VARR (token_t) * expr_buffer, to } static int eval_binop_operands (c2m_ctx_t c2m_ctx, node_t tree, struct val *v1, struct val *v2) { - *v1 = eval (c2m_ctx, NL_HEAD (tree->ops)); - *v2 = eval (c2m_ctx, NL_EL (tree->ops, 1)); + *v1 = eval (c2m_ctx, NL_HEAD (tree->u.ops)); + *v2 = eval (c2m_ctx, NL_EL (tree->u.ops, 1)); if (v1->uns_p && !v2->uns_p) { v2->uns_p = TRUE; v2->u.u_val = v2->u.i_val; @@ -3127,14 +3171,14 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { int cond; struct val res, v1, v2; -#define UNOP(op) \ - do { \ - v1 = eval (c2m_ctx, NL_HEAD (tree->ops)); \ - res = v1; \ - if (res.uns_p) \ - res.u.u_val = op res.u.u_val; \ - else \ - res.u.i_val = op res.u.i_val; \ +#define UNOP(op) \ + do { \ + v1 = eval (c2m_ctx, NL_HEAD (tree->u.ops)); \ + res = v1; \ + if (res.uns_p) \ + res.u.u_val = op res.u.u_val; \ + else \ + res.u.i_val = op res.u.i_val; \ } while (0) #define BINOP(op) \ @@ -3148,7 +3192,7 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { switch (tree->code) { case N_IGNORE: - error (c2m_ctx, tree->pos, "wrong preprocessor expression"); + error (c2m_ctx, POS (tree), "wrong preprocessor expression"); res.uns_p = FALSE; res.u.i_val = 0; break; @@ -3186,14 +3230,14 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { case N_GT: BINOP (>); break; case N_GE: BINOP (>=); break; case N_ADD: - if (NL_EL (tree->ops, 1) == NULL) { + if (NL_EL (tree->u.ops, 1) == NULL) { UNOP (+); } else { BINOP (+); } break; case N_SUB: - if (NL_EL (tree->ops, 1) == NULL) { + if (NL_EL (tree->u.ops, 1) == NULL) { UNOP (-); } else { BINOP (-); @@ -3220,25 +3264,25 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { : 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, tree->pos, "division (%s) by zero in preporocessor", + error (c2m_ctx, POS (tree), "division (%s) by zero in preporocessor", tree->code == N_DIV ? "/" : "%"); break; } case N_ANDAND: case N_OROR: - v1 = eval (c2m_ctx, NL_HEAD (tree->ops)); + v1 = eval (c2m_ctx, NL_HEAD (tree->u.ops)); cond = v1.uns_p ? v1.u.u_val != 0 : v1.u.i_val != 0; if (tree->code == N_ANDAND ? cond : !cond) { - v2 = eval (c2m_ctx, NL_EL (tree->ops, 1)); + v2 = eval (c2m_ctx, NL_EL (tree->u.ops, 1)); cond = v2.uns_p ? v2.u.u_val != 0 : v2.u.i_val != 0; } res.uns_p = FALSE; res.u.i_val = cond; break; case N_COND: - v1 = eval (c2m_ctx, NL_HEAD (tree->ops)); + v1 = eval (c2m_ctx, NL_HEAD (tree->u.ops)); cond = v1.uns_p ? v1.u.u_val != 0 : v1.u.i_val != 0; - res = eval (c2m_ctx, NL_EL (tree->ops, cond ? 1 : 2)); + res = eval (c2m_ctx, NL_EL (tree->u.ops, cond ? 1 : 2)); break; default: res.uns_p = FALSE; @@ -3249,6 +3293,7 @@ static struct val eval (c2m_ctx_t c2m_ctx, node_t tree) { } static macro_call_t try_param_macro_call (c2m_ctx_t c2m_ctx, macro_t m, token_t macro_id) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; macro_call_t mc; token_t t1 = get_next_pptoken (c2m_ctx), t2 = NULL; @@ -3273,6 +3318,7 @@ static macro_call_t try_param_macro_call (c2m_ctx_t c2m_ctx, macro_t m, token_t } static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; token_t t; struct macro macro_struct; macro_t m; @@ -3342,7 +3388,7 @@ static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { } else if (strcmp (t->repr, "__FILE__") == 0) { stringify (t->pos.fname, temp_string); VARR_PUSH (char, temp_string, '\0'); - t = new_node_token (c2m_ctx, t->pos, uniq_cstr (c2m_ctx, VARR_ADDR (char, temp_string)).s, + 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); out_token (c2m_ctx, t); @@ -3350,7 +3396,7 @@ static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { char str[50]; sprintf (str, "%d", t->pos.lno); - out_token (c2m_ctx, new_node_token (c2m_ctx, t->pos, uniq_cstr (c2m_ctx, str).s, T_NUMBER, + out_token (c2m_ctx, new_node_token (c2m_ctx, t->pos, str, T_NUMBER, new_i_node (c2m_ctx, t->pos.lno, t->pos))); } else if (strcmp (t->repr, "__DATE__") == 0) { t = new_node_token (c2m_ctx, t->pos, date_str_repr, T_STR, @@ -3382,7 +3428,7 @@ static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { m->ignore_p = TRUE; unget_next_pptoken (c2m_ctx, new_node_token (c2m_ctx, t->pos, - uniq_cstr (c2m_ctx, res ? "1" : "0").s, T_NUMBER, + res ? "1" : "0", T_NUMBER, new_i_node (c2m_ctx, res, t->pos))); } } else { @@ -3412,6 +3458,7 @@ static void processing (c2m_ctx_t c2m_ctx, int ignore_directive_p) { } static void pre_text_out (c2m_ctx_t c2m_ctx, token_t t) { /* NULL means end of output */ + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; int i; FILE *f = c2m_options->prepro_output_file; @@ -3445,6 +3492,8 @@ static void pre_text_out (c2m_ctx_t c2m_ctx, token_t t) { /* NULL means end of o } static void pre_out (c2m_ctx_t c2m_ctx, token_t t) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + if (t == NULL) { t = new_token (c2m_ctx, pre_last_token == NULL ? no_pos : pre_last_token->pos, "", T_EOFILE, N_IGNORE); @@ -3472,11 +3521,15 @@ static void pre_out (c2m_ctx_t c2m_ctx, token_t t) { } static void common_pre_out (c2m_ctx_t c2m_ctx, token_t t) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + pptokens_num++; (c2m_options->prepro_only_p ? pre_text_out : pre_out) (c2m_ctx, t); } static void pre (c2m_ctx_t c2m_ctx, const char *start_source_name) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; + pre_last_token = NULL; actual_pre_pos.fname = NULL; actual_pre_pos.lno = 0; @@ -3515,28 +3568,34 @@ struct parse_ctx { HTAB (tpname_t) * tpname_tab; }; -#define record_level c2m_ctx->parse_ctx->record_level -#define next_token_index c2m_ctx->parse_ctx->next_token_index -#define next_token_index c2m_ctx->parse_ctx->next_token_index -#define curr_token c2m_ctx->parse_ctx->curr_token -#define curr_scope c2m_ctx->parse_ctx->curr_scope -#define tpname_tab c2m_ctx->parse_ctx->tpname_tab +#define record_level parse_ctx->record_level +#define next_token_index parse_ctx->next_token_index +#define next_token_index parse_ctx->next_token_index +#define curr_token parse_ctx->curr_token +#define curr_scope parse_ctx->curr_scope +#define tpname_tab parse_ctx->tpname_tab static struct node err_struct; static const node_t err_node = &err_struct; static void read_token (c2m_ctx_t c2m_ctx) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + curr_token = VARR_GET (token_t, recorded_tokens, next_token_index); next_token_index++; } static size_t record_start (c2m_ctx_t c2m_ctx) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + assert (next_token_index > 0 && record_level >= 0); record_level++; return next_token_index - 1; } static void record_stop (c2m_ctx_t c2m_ctx, size_t mark, int restore_p) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + assert (record_level > 0); record_level--; if (!restore_p) return; @@ -3545,6 +3604,8 @@ static void record_stop (c2m_ctx_t c2m_ctx, size_t mark, int restore_p) { } static void syntax_error (c2m_ctx_t c2m_ctx, const char *expected_name) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + FILE *f; if ((f = c2m_options->message_file) == NULL) return; @@ -3575,10 +3636,13 @@ static htab_hash_t tpname_hash (tpname_t tpname, void *arg) { } static void tpname_init (c2m_ctx_t c2m_ctx) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + HTAB_CREATE (tpname_t, tpname_tab, 1000, tpname_hash, tpname_eq, NULL); } static int tpname_find (c2m_ctx_t c2m_ctx, node_t id, node_t scope, tpname_t *res) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; int found_p; tpname_t el, tpname; @@ -3590,6 +3654,7 @@ static int tpname_find (c2m_ctx_t c2m_ctx, node_t id, node_t scope, tpname_t *re } static tpname_t tpname_add (c2m_ctx_t c2m_ctx, node_t id, node_t scope) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; tpname_t el, tpname; tpname.id = id; @@ -3600,6 +3665,8 @@ static tpname_t tpname_add (c2m_ctx_t c2m_ctx, node_t id, node_t scope) { } static void tpname_finish (c2m_ctx_t c2m_ctx) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + if (tpname_tab != NULL) HTAB_DESTROY (tpname_t, tpname_tab); } @@ -3654,6 +3721,8 @@ typedef node_t (*nonterm_arg_func_t) (c2m_ctx_t c2m_ctx, int, node_t); #define C(c) (curr_token->code == c) static int match (c2m_ctx_t c2m_ctx, int c, pos_t *pos, node_code_t *node_code, node_t *node) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + if (curr_token->code != c) return FALSE; if (pos != NULL) *pos = curr_token->pos; if (node_code != NULL) *node_code = curr_token->node_code; @@ -3693,6 +3762,7 @@ D (assign_expr); D (initializer_list); D (par_type_name) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; PT ('('); @@ -3702,6 +3772,7 @@ D (par_type_name) { } D (primary_expr) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r, n, op, gn, list; pos_t pos; @@ -3722,12 +3793,12 @@ D (primary_expr) { } else { P (type_name); op = r; - pos = op->pos; + pos = POS (op); } PT (':'); P (assign_expr); gn = new_pos_node2 (c2m_ctx, N_GENERIC_ASSOC, pos, op, r); - op_append (list, gn); + op_append (c2m_ctx, list, gn); if (!M (',')) break; } PT (')'); @@ -3737,6 +3808,7 @@ D (primary_expr) { } DA (post_expr_part) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r, n, op, list; node_code_t code; pos_t pos; @@ -3764,7 +3836,7 @@ DA (post_expr_part) { if (!C (')')) { for (;;) { P (assign_expr); - op_append (list, r); + op_append (c2m_ctx, list, r); if (!M (',')) break; } } @@ -3772,7 +3844,7 @@ DA (post_expr_part) { PT (')'); } n = new_pos_node1 (c2m_ctx, code, pos, op); - if (r != NULL) op_append (n, r); + if (r != NULL) op_append (c2m_ctx, n, r); r = n; } return r; @@ -3840,7 +3912,7 @@ static node_t left_op (c2m_ctx_t c2m_ctx, int no_err_p, int token, int token2, n while (MC (token, pos, code) || (token2 >= 0 && MC (token2, pos, code))) { n = new_pos_node1 (c2m_ctx, code, pos, r); P (f); - op_append (n, r); + op_append (c2m_ctx, n, r); r = n; } return r; @@ -3856,7 +3928,7 @@ static node_t right_op (c2m_ctx_t c2m_ctx, int no_err_p, int token, int token2, if (MC (token, pos, code) || (token2 >= 0 && MC (token2, pos, code))) { n = new_pos_node1 (c2m_ctx, code, pos, r); P (right); - op_append (n, r); + op_append (c2m_ctx, n, r); r = n; } return r; @@ -3881,10 +3953,10 @@ D (cond_expr) { if (!MP ('?', pos)) return r; n = new_pos_node1 (c2m_ctx, N_COND, pos, r); P (expr); - op_append (n, r); + op_append (c2m_ctx, n, r); if (!M (':')) return err_node; P (cond_expr); - op_append (n, r); + op_append (c2m_ctx, n, r); return n; } @@ -3917,6 +3989,7 @@ D (initializer); D (st_assert); D (asm_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; PTN (T_ID); @@ -3948,6 +4021,7 @@ static node_t try_attr_spec (c2m_ctx_t c2m_ctx, pos_t pos) { } D (declaration) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; int typedef_p; node_t op, list, decl, spec, r; pos_t pos, last_pos; @@ -3962,22 +4036,23 @@ D (declaration) { try_attr_spec (c2m_ctx, curr_token->pos); PA (declaration_specs, curr_scope == top_scope ? (node_t) 1 : NULL); spec = r; - last_pos = spec->pos; + last_pos = POS (spec); list = new_node (c2m_ctx, N_LIST); if (C (';')) { - op_append (list, new_node3 (c2m_ctx, N_SPEC_DECL, spec, new_node (c2m_ctx, N_IGNORE), - new_node (c2m_ctx, N_IGNORE))); + op_append (c2m_ctx, list, + new_node3 (c2m_ctx, N_SPEC_DECL, spec, new_node (c2m_ctx, N_IGNORE), + new_node (c2m_ctx, N_IGNORE))); } else { /* init-declarator-list */ - for (op = NL_HEAD (spec->ops); op != NULL; op = NL_NEXT (op)) + for (op = NL_HEAD (spec->u.ops); op != NULL; op = NL_NEXT (op)) if (op->code == N_TYPEDEF) break; typedef_p = op != NULL; for (;;) { /* init-declarator */ P (declarator); decl = r; - last_pos = decl->pos; + last_pos = POS (decl); assert (decl->code == N_DECL); if (typedef_p) { - op = NL_HEAD (decl->ops); + op = NL_HEAD (decl->u.ops); tpname_add (c2m_ctx, op, curr_scope); } try_attr_spec (c2m_ctx, last_pos); @@ -3986,8 +4061,9 @@ D (declaration) { } else { r = new_node (c2m_ctx, N_IGNORE); } - op_append (list, new_pos_node3 (c2m_ctx, N_SPEC_DECL, decl->pos, - new_node1 (c2m_ctx, N_SHARE, spec), decl, r)); + op_append (c2m_ctx, list, + new_pos_node3 (c2m_ctx, N_SPEC_DECL, POS (decl), + new_node1 (c2m_ctx, N_SHARE, spec), decl, r)); if (!M (',')) break; } } @@ -3998,6 +4074,8 @@ D (declaration) { } D (attr) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + if (C (')') || C (',')) /* empty */ return NULL; if (FIRST_KW <= curr_token->code && curr_token->code <= LAST_KW) @@ -4019,6 +4097,7 @@ D (attr) { } D (attr_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; PTN (T_ID); @@ -4036,6 +4115,7 @@ D (attr_spec) { } DA (declaration_specs) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, r, prev_type_spec = NULL; int first_p; pos_t pos = curr_token->pos, spec_pos; @@ -4057,17 +4137,18 @@ DA (declaration_specs) { continue; } else break; - op_append (list, r); + op_append (c2m_ctx, list, r); } if (prev_type_spec == NULL && arg != NULL) { if (c2m_options->pedantic_p) warning (c2m_ctx, pos, "type defaults to int"); r = new_pos_node (c2m_ctx, N_INT, pos); - op_append (list, r); + op_append (c2m_ctx, list, r); } return list; } D (sc_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; pos_t pos; @@ -4091,6 +4172,7 @@ D (sc_spec) { } DA (type_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t op1, op2, op3, op4, r; int struct_p, id_p = FALSE; pos_t pos; @@ -4161,7 +4243,7 @@ DA (type_spec) { P (const_expr); op4 = r; } - op_append (op2, new_node2 (c2m_ctx, N_ENUM_CONST, op3, op4)); + op_append (c2m_ctx, op2, new_node2 (c2m_ctx, N_ENUM_CONST, op3, op4)); if (!M (',')) break; if (C ('}')) break; } @@ -4181,18 +4263,19 @@ DA (type_spec) { } D (struct_declaration_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r, res, el, next_el; res = new_node (c2m_ctx, N_LIST); for (;;) { P (struct_declaration); if (r->code != N_LIST) { - op_append (res, r); + op_append (c2m_ctx, res, r); } else { - for (el = NL_HEAD (r->ops); el != NULL; el = next_el) { + for (el = NL_HEAD (r->u.ops); el != NULL; el = next_el) { next_el = NL_NEXT (el); - NL_REMOVE (r->ops, el); - op_append (res, el); + NL_REMOVE (r->u.ops, el); + op_append (c2m_ctx, res, el); } } if (C ('}')) break; @@ -4201,6 +4284,7 @@ D (struct_declaration_list) { } D (struct_declaration) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, spec, op, r; if (C (T_STATIC_ASSERT)) { @@ -4210,9 +4294,9 @@ D (struct_declaration) { spec = r; list = new_node (c2m_ctx, N_LIST); if (M (';')) { - op = new_pos_node3 (c2m_ctx, N_MEMBER, spec->pos, new_node1 (c2m_ctx, N_SHARE, spec), + op = new_pos_node3 (c2m_ctx, N_MEMBER, POS (spec), new_node1 (c2m_ctx, N_SHARE, spec), new_node (c2m_ctx, N_IGNORE), new_node (c2m_ctx, N_IGNORE)); - op_append (list, op); + op_append (c2m_ctx, list, op); } else { /* struct-declarator-list */ for (;;) { /* struct-declarator */ if (!C (':')) { @@ -4226,8 +4310,8 @@ D (struct_declaration) { } else { r = new_node (c2m_ctx, N_IGNORE); } - op = new_pos_node3 (c2m_ctx, N_MEMBER, op->pos, new_node1 (c2m_ctx, N_SHARE, spec), op, r); - op_append (list, op); + op = new_pos_node3 (c2m_ctx, N_MEMBER, POS (op), new_node1 (c2m_ctx, N_SHARE, spec), op, r); + op_append (c2m_ctx, list, op); if (!M (',')) break; } PT (';'); @@ -4238,6 +4322,7 @@ D (struct_declaration) { } D (spec_qual_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, op, r, arg = NULL; int first_p; @@ -4253,12 +4338,13 @@ D (spec_qual_list) { } else { break; } - op_append (list, op); + op_append (c2m_ctx, list, op); } return list; } D (type_qual) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; pos_t pos; @@ -4278,6 +4364,7 @@ D (type_qual) { } D (func_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; pos_t pos; @@ -4293,6 +4380,7 @@ D (func_spec) { } D (align_spec) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; pos_t pos; @@ -4308,6 +4396,7 @@ D (align_spec) { } D (declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, p = NULL, r, el, next_el; if (C ('*')) { @@ -4316,18 +4405,19 @@ D (declarator) { } P (direct_declarator); if (p != NULL) { - list = NL_NEXT (NL_HEAD (r->ops)); + list = NL_NEXT (NL_HEAD (r->u.ops)); assert (list->code == N_LIST); - for (el = NL_HEAD (p->ops); el != NULL; el = next_el) { + for (el = NL_HEAD (p->u.ops); el != NULL; el = next_el) { next_el = NL_NEXT (el); - NL_REMOVE (p->ops, el); - op_append (list, el); + NL_REMOVE (p->u.ops, el); + op_append (c2m_ctx, list, el); } } return r; } D (direct_declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, tql, ae, res, r; pos_t pos, static_pos; @@ -4340,7 +4430,7 @@ D (direct_declarator) { } else { return err_node; } - list = NL_NEXT (NL_HEAD (res->ops)); + list = NL_NEXT (NL_HEAD (res->u.ops)); assert (list->code == N_LIST); for (;;) { if (MP ('(', pos)) { @@ -4349,7 +4439,7 @@ D (direct_declarator) { P (id_list); } PT (')'); - op_append (list, new_pos_node1 (c2m_ctx, N_FUNC, pos, r)); + op_append (c2m_ctx, list, new_pos_node1 (c2m_ctx, N_FUNC, pos, r)); } else if (M ('[')) { int static_p = FALSE; @@ -4377,10 +4467,11 @@ D (direct_declarator) { ae = new_node (c2m_ctx, N_IGNORE); } PT (']'); - op_append (list, new_node3 (c2m_ctx, N_ARR, - static_p ? new_pos_node (c2m_ctx, N_STATIC, static_pos) - : new_node (c2m_ctx, N_IGNORE), - tql, ae)); + op_append (c2m_ctx, list, + new_node3 (c2m_ctx, N_ARR, + static_p ? new_pos_node (c2m_ctx, N_STATIC, static_pos) + : new_node (c2m_ctx, N_IGNORE), + tql, ae)); } else break; } @@ -4388,6 +4479,7 @@ D (direct_declarator) { } D (pointer) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t op, r; pos_t pos; @@ -4403,23 +4495,25 @@ D (pointer) { } else { r = new_node (c2m_ctx, N_LIST); } - op_append (r, op); + op_append (c2m_ctx, r, op); return r; } D (type_qual_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, r; list = new_node (c2m_ctx, N_LIST); for (;;) { P (type_qual); - op_append (list, r); + op_append (c2m_ctx, list, r); if (!C (T_CONST) && !C (T_RESTRICT) && !C (T_VOLATILE) && !C (T_ATOMIC)) break; } return list; } D (param_type_abstract_declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r = err_node; P (abstract_declarator); @@ -4428,6 +4522,7 @@ D (param_type_abstract_declarator) { } D (param_type_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, op1, op2, r = err_node; int comma_p; pos_t pos; @@ -4447,9 +4542,9 @@ D (param_type_list) { r = new_node2 (c2m_ctx, N_TYPE, op1, op2); } else { P (declarator); - r = new_pos_node3 (c2m_ctx, N_SPEC_DECL, op2->pos, op1, r, new_node (c2m_ctx, N_IGNORE)); + r = new_pos_node3 (c2m_ctx, N_SPEC_DECL, POS (op2), op1, r, new_node (c2m_ctx, N_IGNORE)); } - op_append (list, r); + op_append (c2m_ctx, list, r); comma_p = FALSE; if (!M (',')) break; comma_p = TRUE; @@ -4457,49 +4552,52 @@ D (param_type_list) { } if (comma_p) { PTP (T_DOTS, pos); - op_append (list, new_pos_node (c2m_ctx, N_DOTS, pos)); + op_append (c2m_ctx, list, new_pos_node (c2m_ctx, N_DOTS, pos)); } return list; } D (id_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, r; list = new_node (c2m_ctx, N_LIST); if (C (')')) return list; for (;;) { PTN (T_ID); - op_append (list, r); + op_append (c2m_ctx, list, r); if (!M (',')) break; } return list; } D (abstract_declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, p = NULL, r, el, next_el; if (C ('*')) { P (pointer); p = r; if ((r = TRY (direct_abstract_declarator)) == err_node) - r = new_pos_node2 (c2m_ctx, N_DECL, p->pos, new_node (c2m_ctx, N_IGNORE), + r = new_pos_node2 (c2m_ctx, N_DECL, POS (p), new_node (c2m_ctx, N_IGNORE), new_node (c2m_ctx, N_LIST)); } else { P (direct_abstract_declarator); } if (p != NULL) { - list = NL_NEXT (NL_HEAD (r->ops)); + list = NL_NEXT (NL_HEAD (r->u.ops)); assert (list->code == N_LIST); - for (el = NL_HEAD (p->ops); el != NULL; el = next_el) { + for (el = NL_HEAD (p->u.ops); el != NULL; el = next_el) { next_el = NL_NEXT (el); - NL_REMOVE (p->ops, el); - op_append (list, el); + NL_REMOVE (p->u.ops, el); + op_append (c2m_ctx, list, el); } } return r; } D (par_abstract_declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; PT ('('); @@ -4509,6 +4607,7 @@ D (par_abstract_declarator) { } D (direct_abstract_declarator) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t res, list, tql, ae, r; pos_t pos, pos2 = no_pos; @@ -4517,13 +4616,13 @@ D (direct_abstract_declarator) { } else { res = new_node2 (c2m_ctx, N_DECL, new_node (c2m_ctx, N_IGNORE), new_node (c2m_ctx, N_LIST)); } - list = NL_NEXT (NL_HEAD (res->ops)); + list = NL_NEXT (NL_HEAD (res->u.ops)); assert (list->code == N_LIST); for (;;) { if (MP ('(', pos)) { P (param_type_list); PT (')'); - op_append (list, new_pos_node1 (c2m_ctx, N_FUNC, pos, r)); + op_append (c2m_ctx, list, new_pos_node1 (c2m_ctx, N_FUNC, pos, r)); } else { PTP ('[', pos); if (MP ('*', pos2)) { @@ -4556,19 +4655,20 @@ D (direct_abstract_declarator) { tql, ae); } PT (']'); - op_append (list, r); + op_append (c2m_ctx, list, r); } if (!C ('(') && !C ('[')) break; } - add_pos (res, list->pos); + add_pos (c2m_ctx, res, POS (list)); return res; } D (typedef_name) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t scope, r; PTN (T_ID); - for (scope = curr_scope;; scope = scope->u.scope) { + for (scope = curr_scope;; scope = scope->attr) { if (tpname_find (c2m_ctx, r, scope, NULL)) return r; if (scope == NULL) break; } @@ -4576,6 +4676,7 @@ D (typedef_name) { } D (initializer) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r; if (!M ('{')) { @@ -4590,6 +4691,7 @@ D (initializer) { } D (initializer_list) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, list2, r; int first_p; @@ -4610,13 +4712,13 @@ D (initializer_list) { r = new_node1 (c2m_ctx, N_FIELD_ID, r); } else break; - op_append (list2, r); + op_append (c2m_ctx, list2, r); } if (!first_p) { PT ('='); } P (initializer); - op_append (list, new_node2 (c2m_ctx, N_INIT, list2, r)); + op_append (c2m_ctx, list, new_node2 (c2m_ctx, N_INIT, list2, r)); if (!M (',')) break; if (C ('}')) break; } @@ -4624,6 +4726,7 @@ D (initializer_list) { } D (type_name) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t op, r; P (spec_qual_list); @@ -4631,13 +4734,14 @@ D (type_name) { if (!C (')') && !C (':')) { P (abstract_declarator); } else { - r = new_pos_node2 (c2m_ctx, N_DECL, op->pos, new_node (c2m_ctx, N_IGNORE), + r = new_pos_node2 (c2m_ctx, N_DECL, POS (op), new_node (c2m_ctx, N_IGNORE), new_node (c2m_ctx, N_LIST)); } return new_node2 (c2m_ctx, N_TYPE, op, r); } D (st_assert) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t op1, r; pos_t pos; @@ -4657,6 +4761,7 @@ D (st_assert) { D (compound_stmt); D (label) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t r, n; pos_t pos; @@ -4665,7 +4770,7 @@ D (label) { n = new_pos_node1 (c2m_ctx, N_CASE, pos, r); if (M (T_DOTS)) { P (expr); - op_append (n, r); + op_append (c2m_ctx, n, r); } r = n; } else if (MP (T_DEFAULT, pos)) { @@ -4679,19 +4784,20 @@ D (label) { } D (stmt) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t l, n, op1, op2, op3, r; pos_t pos; l = new_node (c2m_ctx, N_LIST); while ((op1 = TRY (label)) != err_node) { - op_append (l, op1); + op_append (c2m_ctx, l, op1); } if (C ('{')) { P (compound_stmt); - if (NL_HEAD (l->ops) != NULL) { /* replace empty label list */ - assert (NL_HEAD (r->ops)->code == N_LIST && NL_HEAD (NL_HEAD (r->ops)->ops) == NULL); - NL_REMOVE (r->ops, NL_HEAD (r->ops)); - NL_PREPEND (r->ops, l); + if (NL_HEAD (l->u.ops) != NULL) { /* replace empty label list */ + assert (NL_HEAD (r->u.ops)->code == N_LIST && NL_HEAD (NL_HEAD (r->u.ops)->u.ops) == NULL); + NL_REMOVE (r->u.ops, NL_HEAD (r->u.ops)); + NL_PREPEND (r->u.ops, l); } } else if (MP (T_IF, pos)) { /* selection-statement */ PT ('('); @@ -4732,13 +4838,13 @@ D (stmt) { } else if (MP (T_FOR, pos)) { /* iteration-statement */ PT ('('); n = new_pos_node (c2m_ctx, N_FOR, pos); - n->u.scope = curr_scope; + n->attr = curr_scope; curr_scope = n; if ((r = TRY (declaration)) != err_node) { op1 = r; - curr_scope = n->u.scope; + curr_scope = n->attr; } else { - curr_scope = n->u.scope; + curr_scope = n->attr; if (!M (';')) { P (expr); op1 = r; @@ -4762,11 +4868,11 @@ D (stmt) { } PT (')'); P (stmt); - op_append (n, l); - op_append (n, op1); - op_append (n, op2); - op_append (n, op3); - op_append (n, r); + op_append (c2m_ctx, n, l); + op_append (c2m_ctx, n, op1); + op_append (c2m_ctx, n, op2); + op_append (c2m_ctx, n, op3); + op_append (c2m_ctx, n, r); r = n; } else if (MP (T_GOTO, pos)) { /* jump-statement */ PTN (T_ID); @@ -4793,12 +4899,14 @@ D (stmt) { P (expr); } PT (';'); - r = new_pos_node2 (c2m_ctx, N_EXPR, r->pos, l, r); + r = new_pos_node2 (c2m_ctx, N_EXPR, POS (r), l, r); } return r; } static void error_recovery (c2m_ctx_t c2m_ctx, int par_lev, const char *expected) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + syntax_error (c2m_ctx, expected); if (c2m_options->debug_p) fprintf (stderr, "error recovery: skipping"); for (;;) { @@ -4818,25 +4926,26 @@ static void error_recovery (c2m_ctx_t c2m_ctx, int par_lev, const char *expected } D (compound_stmt) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t n, list, r; pos_t pos; PTE ('{', pos, err0); list = new_node (c2m_ctx, N_LIST); n = new_pos_node2 (c2m_ctx, N_BLOCK, pos, new_node (c2m_ctx, N_LIST), list); - n->u.scope = curr_scope; + n->attr = curr_scope; curr_scope = n; while (!C ('}') && !C (T_EOFILE)) { /* block-item-list, block_item */ if ((r = TRY (declaration)) != err_node) { } else { PE (stmt, err1); } - op_flat_append (list, r); + op_flat_append (c2m_ctx, list, r); continue; err1: error_recovery (c2m_ctx, 1, ""); } - curr_scope = n->u.scope; + curr_scope = n->attr; if (!C (T_EOFILE)) PT ('}'); return n; err0: @@ -4845,6 +4954,7 @@ err0: } D (transl_unit) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; node_t list, ds, d, dl, r; // curr_token->code = ';'; /* for error recovery */ @@ -4858,20 +4968,20 @@ D (transl_unit) { PE (declarator, err); d = r; dl = new_node (c2m_ctx, N_LIST); - d->u.scope = curr_scope; + d->attr = curr_scope; curr_scope = d; while (!C ('{')) { /* declaration-list */ PE (declaration, decl_err); - op_flat_append (dl, r); + op_flat_append (c2m_ctx, dl, r); } P (compound_stmt); - r = new_pos_node4 (c2m_ctx, N_FUNC_DEF, d->pos, ds, d, dl, r); - curr_scope = d->u.scope; + r = new_pos_node4 (c2m_ctx, N_FUNC_DEF, POS (d), ds, d, dl, r); + curr_scope = d->attr; } - op_flat_append (list, r); + op_flat_append (c2m_ctx, list, r); continue; decl_err: - curr_scope = d->u.scope; + curr_scope = d->attr; err: error_recovery (c2m_ctx, 0, ""); } @@ -4888,7 +4998,10 @@ static void kw_add (c2m_ctx_t c2m_ctx, const char *name, token_code_t tc, size_t } static void parse_init (c2m_ctx_t c2m_ctx) { - c2m_ctx->parse_ctx = c2mir_calloc (c2m_ctx, sizeof (struct parse_ctx)); + parse_ctx_t parse_ctx; + + c2m_ctx->parse_ctx = parse_ctx = c2mir_calloc (c2m_ctx, sizeof (struct parse_ctx)); + curr_scope = NULL; error_func = fatal_error; record_level = 0; curr_uid = 0; @@ -4965,6 +5078,8 @@ static void add_standard_includes (c2m_ctx_t c2m_ctx) { } static node_t parse (c2m_ctx_t c2m_ctx) { + parse_ctx_t parse_ctx = c2m_ctx->parse_ctx; + next_token_index = 0; return transl_unit (c2m_ctx, FALSE); } @@ -5020,7 +5135,10 @@ DEF_VARR (decl_t); typedef struct case_attr *case_t; DEF_HTAB (case_t); +#undef curr_scope + struct check_ctx { + node_t curr_scope; VARR (node_t) * gotos; node_t func_block_scope; unsigned curr_func_scope_num; @@ -5035,21 +5153,21 @@ struct check_ctx { VARR (node_t) * context_stack; }; -#define gotos c2m_ctx->check_ctx->gotos -#define func_block_scope c2m_ctx->check_ctx->func_block_scope -#define curr_func_scope_num c2m_ctx->check_ctx->curr_func_scope_num -#define in_params_p c2m_ctx->check_ctx->in_params_p -#define curr_unnamed_anon_struct_union_member \ - c2m_ctx->check_ctx->curr_unnamed_anon_struct_union_member -#define curr_switch c2m_ctx->check_ctx->curr_switch -#define func_decls_for_allocation c2m_ctx->check_ctx->func_decls_for_allocation -#define n_i1_node c2m_ctx->check_ctx->n_i1_node -#define case_tab c2m_ctx->check_ctx->case_tab -#define curr_func_def c2m_ctx->check_ctx->curr_func_def -#define curr_loop c2m_ctx->check_ctx->curr_loop -#define curr_loop_switch c2m_ctx->check_ctx->curr_loop_switch -#define curr_call_arg_area_offset c2m_ctx->check_ctx->curr_call_arg_area_offset -#define context_stack c2m_ctx->check_ctx->context_stack +#define curr_scope check_ctx->curr_scope +#define gotos check_ctx->gotos +#define func_block_scope check_ctx->func_block_scope +#define curr_func_scope_num check_ctx->curr_func_scope_num +#define in_params_p check_ctx->in_params_p +#define curr_unnamed_anon_struct_union_member check_ctx->curr_unnamed_anon_struct_union_member +#define curr_switch check_ctx->curr_switch +#define func_decls_for_allocation check_ctx->func_decls_for_allocation +#define n_i1_node check_ctx->n_i1_node +#define case_tab check_ctx->case_tab +#define curr_func_def check_ctx->curr_func_def +#define curr_loop check_ctx->curr_loop +#define curr_loop_switch check_ctx->curr_loop_switch +#define curr_call_arg_area_offset check_ctx->curr_call_arg_area_offset +#define context_stack check_ctx->context_stack static int supported_alignment_p (mir_llong align) { return TRUE; } // ??? @@ -5336,7 +5454,7 @@ static struct decl_spec *get_param_decl_spec (node_t param) { node_t MIR_UNUSED declarator; if (param->code == N_TYPE) return param->attr; - declarator = NL_EL (param->ops, 1); + declarator = NL_EL (param->u.ops, 1); assert (param->code == N_SPEC_DECL && declarator != NULL && declarator->code == N_DECL); return &((decl_t) param->attr)->decl_spec; } @@ -5366,9 +5484,9 @@ static int type_eq_p (struct type *type1, struct type *type2) { struct decl_spec *ds1, *ds2; if (ft1->dots_p != ft2->dots_p || !type_eq_p (ft1->ret_type, ft2->ret_type) - || NL_LENGTH (ft1->param_list->ops) != NL_LENGTH (ft2->param_list->ops)) + || NL_LENGTH (ft1->param_list->u.ops) != NL_LENGTH (ft2->param_list->u.ops)) return FALSE; - for (node_t p1 = NL_HEAD (ft1->param_list->ops), p2 = NL_HEAD (ft2->param_list->ops); + for (node_t p1 = NL_HEAD (ft1->param_list->u.ops), p2 = NL_HEAD (ft2->param_list->u.ops); p1 != NULL; p1 = NL_NEXT (p1), p2 = NL_NEXT (p2)) { ds1 = get_param_decl_spec (p1); ds2 = get_param_decl_spec (p2); @@ -5409,8 +5527,8 @@ static int compatible_types_p (struct type *type1, struct type *type2, int ignor } else if (type1->mode == TM_FUNC) { struct func_type *ft1 = type1->u.func_type, *ft2 = type2->u.func_type; - if (NL_HEAD (ft1->param_list->ops) != NULL && NL_HEAD (ft2->param_list->ops) != NULL - && NL_LENGTH (ft1->param_list->ops) != NL_LENGTH (ft2->param_list->ops)) + if (NL_HEAD (ft1->param_list->u.ops) != NULL && NL_HEAD (ft2->param_list->u.ops) != NULL + && NL_LENGTH (ft1->param_list->u.ops) != NL_LENGTH (ft2->param_list->u.ops)) return FALSE; // ??? check parameter types } else { @@ -5518,11 +5636,11 @@ static void aux_set_type_align (c2m_ctx_t c2m_ctx, struct type *type) { align = -1; } else { align = 1; - for (node_t member = NL_HEAD (NL_EL (type->u.tag_type->ops, 1)->ops); member != NULL; + for (node_t member = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); member != NULL; member = NL_NEXT (member)) if (member->code == N_MEMBER) { decl_t decl = member->attr; - node_t width = NL_EL (member->ops, 2); + node_t width = NL_EL (member->u.ops, 2); struct expr *expr; if (type->mode == TM_UNION && width->code != N_IGNORE && (expr = width->attr)->const_p @@ -5604,7 +5722,8 @@ static void update_members_offset (struct type *type, mir_size_t offset) { assert ((type->mode == TM_STRUCT || type->mode == TM_UNION) && type->unnamed_anon_struct_union_member_type_p); assert (offset != MIR_SIZE_MAX || type->raw_size == MIR_SIZE_MAX); - for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->ops, 1)->ops); el != NULL; el = NL_NEXT (el)) + for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL; + el = NL_NEXT (el)) if (el->code == N_MEMBER) { decl_t decl = el->attr; @@ -5644,13 +5763,13 @@ static void set_type_layout (c2m_ctx_t c2m_ctx, struct type *type) { if (incomplete_type_p (c2m_ctx, type)) { overall_size = MIR_SIZE_MAX; } else { - for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->ops, 1)->ops); el != NULL; + for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL; el = NL_NEXT (el)) if (el->code == N_MEMBER) { decl_t decl = el->attr; int member_align; mir_size_t member_size; - node_t width = NL_EL (el->ops, 2); + node_t width = NL_EL (el->u.ops, 2); struct expr *expr; int anon_process_p = (!type->unnamed_anon_struct_union_member_type_p && decl->decl_spec.type->unnamed_anon_struct_union_member_type_p @@ -5708,6 +5827,8 @@ static int void_ptr_p (struct type *type) { } static int incomplete_type_p (c2m_ctx_t c2m_ctx, struct type *type) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + switch (type->mode) { case TM_BASIC: return type->u.basic_type == TP_VOID; case TM_ENUM: @@ -5715,7 +5836,7 @@ static int incomplete_type_p (c2m_ctx_t c2m_ctx, struct type *type) { case TM_UNION: { node_t scope, n = type->u.tag_type; - if (NL_EL (n->ops, 1)->code == N_IGNORE) return TRUE; + if (NL_EL (n->u.ops, 1)->code == N_IGNORE) return TRUE; for (scope = curr_scope; scope != NULL && scope != top_scope && scope != n; scope = ((struct node_scope *) scope->attr)->scope) ; @@ -5848,6 +5969,7 @@ static int non_reg_decl_spec_p (struct decl_spec *ds) { } static void create_node_scope (c2m_ctx_t c2m_ctx, node_t node) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; struct node_scope *ns = reg_malloc (c2m_ctx, sizeof (struct node_scope)); assert (node != curr_scope); @@ -5860,26 +5982,28 @@ static void create_node_scope (c2m_ctx_t c2m_ctx, node_t node) { } static void finish_scope (c2m_ctx_t c2m_ctx) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + curr_scope = ((struct node_scope *) curr_scope->attr)->scope; } static void set_type_qual (c2m_ctx_t c2m_ctx, node_t r, struct type_qual *tq, enum type_mode tmode) { - for (node_t n = NL_HEAD (r->ops); n != NULL; n = NL_NEXT (n)) switch (n->code) { + for (node_t n = NL_HEAD (r->u.ops); n != NULL; n = NL_NEXT (n)) switch (n->code) { /* Type qualifiers: */ case N_CONST: tq->const_p = TRUE; break; case N_RESTRICT: tq->restrict_p = TRUE; if (tmode != TM_PTR && tmode != TM_UNDEF) - error (c2m_ctx, n->pos, "restrict requires a pointer"); + error (c2m_ctx, POS (n), "restrict requires a pointer"); break; case N_VOLATILE: tq->volatile_p = TRUE; break; case N_ATOMIC: tq->atomic_p = TRUE; if (tmode == TM_ARR) - error (c2m_ctx, n->pos, "_Atomic qualifying array"); + error (c2m_ctx, POS (n), "_Atomic qualifying array"); else if (tmode == TM_FUNC) - error (c2m_ctx, n->pos, "_Atomic qualifying function"); + error (c2m_ctx, POS (n), "_Atomic qualifying function"); break; default: break; /* Ignore */ } @@ -5888,11 +6012,11 @@ static void set_type_qual (c2m_ctx_t c2m_ctx, node_t r, struct type_qual *tq, static void check_type_duplication (c2m_ctx_t c2m_ctx, struct type *type, node_t n, const char *name, int size, int sign) { if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) - error (c2m_ctx, n->pos, "%s with another type", name); + error (c2m_ctx, POS (n), "%s with another type", name); else if (type->mode != TM_BASIC && size != 0) - error (c2m_ctx, n->pos, "size with non-numeric type"); + error (c2m_ctx, POS (n), "size with non-numeric type"); else if (type->mode != TM_BASIC && sign != 0) - error (c2m_ctx, n->pos, "sign attribute with non-integer type"); + error (c2m_ctx, POS (n), "sign attribute with non-integer type"); } static node_t find_def (c2m_ctx_t c2m_ctx, enum symbol_mode mode, node_t id, node_t scope, @@ -5911,6 +6035,7 @@ static node_t find_def (c2m_ctx_t c2m_ctx, enum symbol_mode mode, node_t id, nod } static node_t process_tag (c2m_ctx_t c2m_ctx, node_t r, node_t id, node_t decl_list) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; symbol_t sym; int found_p; node_t scope, tab_decl_list; @@ -5929,14 +6054,14 @@ static node_t process_tag (c2m_ctx_t c2m_ctx, node_t r, node_t id, node_t decl_l if (!found_p) { symbol_insert (c2m_ctx, S_TAG, id, scope, r, NULL); } else if (sym.def_node->code != r->code) { - error (c2m_ctx, id->pos, "kind of tag %s is unmatched with previous declaration", id->u.s.s); - } else if ((tab_decl_list = NL_EL (sym.def_node->ops, 1))->code != N_IGNORE + error (c2m_ctx, POS (id), "kind of tag %s is unmatched with previous declaration", id->u.s.s); + } else if ((tab_decl_list = NL_EL (sym.def_node->u.ops, 1))->code != N_IGNORE && decl_list->code != N_IGNORE) { - error (c2m_ctx, id->pos, "tag %s redeclaration", id->u.s.s); + error (c2m_ctx, POS (id), "tag %s redeclaration", id->u.s.s); } else { if (decl_list->code != N_IGNORE) { /* swap decl lists */ DLIST (node_t) temp; - SWAP (r->ops, sym.def_node->ops, temp); + SWAP (r->u.ops, sym.def_node->u.ops, temp); } r = sym.def_node; } @@ -5954,7 +6079,7 @@ static void def_symbol (c2m_ctx_t c2m_ctx, enum symbol_mode mode, node_t id, nod || scope->code == N_UNION || scope->code == N_FUNC || scope->code == N_FOR); decl_spec = ((decl_t) def_node->attr)->decl_spec; if (decl_spec.thread_local_p && !decl_spec.static_p && !decl_spec.extern_p) - error (c2m_ctx, id->pos, "auto %s is declared as thread local", id->u.s.s); + error (c2m_ctx, POS (id), "auto %s is declared as thread local", id->u.s.s); if (!symbol_find (c2m_ctx, mode, id, scope, &sym)) { symbol_insert (c2m_ctx, mode, id, scope, def_node, NULL); return; @@ -5967,16 +6092,16 @@ static void def_symbol (c2m_ctx_t c2m_ctx, enum symbol_mode mode, node_t id, nod /* a hack to use our definition instead of macosx for non-GNU compiler */ if (strcmp (id->u.s.s, "__darwin_va_list") != 0) #endif - error (c2m_ctx, id->pos, "repeated declaration %s", id->u.s.s); + error (c2m_ctx, POS (id), "repeated declaration %s", id->u.s.s); } else if (!compatible_types_p (decl_spec.type, tab_decl_spec.type, FALSE)) { - error (c2m_ctx, id->pos, "incompatible types of %s declarations", id->u.s.s); + error (c2m_ctx, POS (id), "incompatible types of %s declarations", id->u.s.s); } if (tab_decl_spec.thread_local_p != decl_spec.thread_local_p) { - error (c2m_ctx, id->pos, "thread local and non-thread local declarations of %s", id->u.s.s); + error (c2m_ctx, POS (id), "thread local and non-thread local declarations of %s", id->u.s.s); } if ((decl_spec.linkage == N_EXTERN && linkage == N_STATIC) || (decl_spec.linkage == N_STATIC && linkage == N_EXTERN)) - warning (c2m_ctx, id->pos, "%s defined with external and internal linkage", id->u.s.s); + warning (c2m_ctx, POS (id), "%s defined with external and internal linkage", id->u.s.s); VARR_PUSH (node_t, sym.defs, def_node); if (!incomplete_type_p (c2m_ctx, decl_spec.type) && incomplete_type_p (c2m_ctx, tab_decl_spec.type)) @@ -5993,6 +6118,7 @@ static void make_type_complete (c2m_ctx_t c2m_ctx, struct type *type) { static void check (c2m_ctx_t c2m_ctx, node_t node, node_t context); static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t decl) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; int n_sc = 0, sign = 0, size = 0, func_p = FALSE; struct decl_spec *res; struct type *type; @@ -6001,10 +6127,10 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec if (decl->code == N_FUNC_DEF) { func_p = TRUE; } else if (decl->code == N_SPEC_DECL) { - node_t declarator = NL_EL (decl->ops, 1); - node_t list = NL_EL (declarator->ops, 1); + node_t declarator = NL_EL (decl->u.ops, 1); + node_t list = NL_EL (declarator->u.ops, 1); - func_p = list != NULL && NL_HEAD (list->ops) != NULL && NL_HEAD (list->ops)->code == N_FUNC; + func_p = list != NULL && NL_HEAD (list->u.ops) != NULL && NL_HEAD (list->u.ops)->code == N_FUNC; } r->attr = res = reg_malloc (c2m_ctx, sizeof (struct decl_spec)); res->typedef_p = res->extern_p = res->static_p = FALSE; @@ -6017,28 +6143,28 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec type->pos_node = r; type->mode = TM_BASIC; type->u.basic_type = TP_UNDEF; - for (node_t n = NL_HEAD (r->ops); n != NULL; n = NL_NEXT (n)) + for (node_t n = NL_HEAD (r->u.ops); n != NULL; n = NL_NEXT (n)) if (n->code == N_SIGNED || n->code == N_UNSIGNED) { if (sign != 0) - error (c2m_ctx, n->pos, "more than one sign qualifier"); + error (c2m_ctx, POS (n), "more than one sign qualifier"); else sign = n->code == N_SIGNED ? 1 : -1; } else if (n->code == N_SHORT) { if (size != 0) - error (c2m_ctx, n->pos, "more than one type"); + error (c2m_ctx, POS (n), "more than one type"); else size = 1; } else if (n->code == N_LONG) { if (size == 2) size = 3; else if (size == 3) - error (c2m_ctx, n->pos, "more than two long"); + error (c2m_ctx, POS (n), "more than two long"); else if (size == 1) - error (c2m_ctx, n->pos, "short with long"); + error (c2m_ctx, POS (n), "short with long"); else size = 2; } - for (node_t n = NL_HEAD (r->ops); n != NULL; n = NL_NEXT (n)) switch (n->code) { + for (node_t n = NL_HEAD (r->u.ops); n != NULL; n = NL_NEXT (n)) switch (n->code) { /* Type qualifiers are already processed. */ case N_CONST: case N_RESTRICT: @@ -6048,13 +6174,13 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec /* Func specifiers: */ case N_INLINE: if (!func_p) - error (c2m_ctx, n->pos, "non-function declaration with inline"); + error (c2m_ctx, POS (n), "non-function declaration with inline"); else res->inline_p = TRUE; break; case N_NO_RETURN: if (!func_p) - error (c2m_ctx, n->pos, "non-function declaration with _Noreturn"); + error (c2m_ctx, POS (n), "non-function declaration with _Noreturn"); else res->no_return_p = TRUE; break; @@ -6063,7 +6189,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_AUTO: case N_REGISTER: if (n_sc != 0) - error (c2m_ctx, n->pos, "more than one storage specifier"); + error (c2m_ctx, POS (n), "more than one storage specifier"); else if (n->code == N_TYPEDEF) res->typedef_p = TRUE; else if (n->code == N_AUTO) @@ -6075,7 +6201,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_EXTERN: case N_STATIC: if (n_sc != 0 && (n_sc != 1 || !res->thread_local_p)) - error (c2m_ctx, n->pos, "more than one storage specifier"); + error (c2m_ctx, POS (n), "more than one storage specifier"); else if (n->code == N_EXTERN) res->extern_p = TRUE; else @@ -6084,7 +6210,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec break; case N_THREAD_LOCAL: if (n_sc != 0 && (n_sc != 1 || (!res->extern_p && !res->static_p))) - error (c2m_ctx, n->pos, "more than one storage specifier"); + error (c2m_ctx, POS (n), "more than one storage specifier"); else res->thread_local_p = TRUE; n_sc++; @@ -6092,11 +6218,11 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_VOID: set_type_pos_node (type, n); if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) - error (c2m_ctx, n->pos, "void with another type"); + error (c2m_ctx, POS (n), "void with another type"); else if (sign != 0) - error (c2m_ctx, n->pos, "void with sign qualifier"); + error (c2m_ctx, POS (n), "void with sign qualifier"); else if (size != 0) - error (c2m_ctx, n->pos, "void with short or long"); + error (c2m_ctx, POS (n), "void with short or long"); else type->u.basic_type = TP_VOID; break; @@ -6108,10 +6234,10 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_INT: set_type_pos_node (type, n); if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) { - error (c2m_ctx, n->pos, "char or int with another type"); + error (c2m_ctx, POS (n), "char or int with another type"); } else if (n->code == N_CHAR) { if (size != 0) - error (c2m_ctx, n->pos, "char with short or long"); + error (c2m_ctx, POS (n), "char with short or long"); else type->u.basic_type = sign == 0 ? TP_CHAR : sign < 0 ? TP_UCHAR : TP_SCHAR; } else if (size == 0) @@ -6126,36 +6252,36 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_BOOL: set_type_pos_node (type, n); if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) - error (c2m_ctx, n->pos, "_Bool with another type"); + error (c2m_ctx, POS (n), "_Bool with another type"); else if (sign != 0) - error (c2m_ctx, n->pos, "_Bool with sign qualifier"); + error (c2m_ctx, POS (n), "_Bool with sign qualifier"); else if (size != 0) - error (c2m_ctx, n->pos, "_Bool with short or long"); + error (c2m_ctx, POS (n), "_Bool with short or long"); type->u.basic_type = TP_BOOL; break; case N_FLOAT: set_type_pos_node (type, n); if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) - error (c2m_ctx, n->pos, "float with another type"); + error (c2m_ctx, POS (n), "float with another type"); else if (sign != 0) - error (c2m_ctx, n->pos, "float with sign qualifier"); + error (c2m_ctx, POS (n), "float with sign qualifier"); else if (size != 0) - error (c2m_ctx, n->pos, "float with short or long"); + error (c2m_ctx, POS (n), "float with short or long"); else type->u.basic_type = TP_FLOAT; break; case N_DOUBLE: set_type_pos_node (type, n); if (type->mode != TM_BASIC || type->u.basic_type != TP_UNDEF) - error (c2m_ctx, n->pos, "double with another type"); + error (c2m_ctx, POS (n), "double with another type"); else if (sign != 0) - error (c2m_ctx, n->pos, "double with sign qualifier"); + error (c2m_ctx, POS (n), "double with sign qualifier"); else if (size == 0) type->u.basic_type = TP_DOUBLE; else if (size == 2) type->u.basic_type = TP_LDOUBLE; else - error (c2m_ctx, n->pos, "double with short"); + error (c2m_ctx, POS (n), "double with short"); break; case N_ID: { node_t def = find_def (c2m_ctx, S_REGULAR, n, curr_scope, NULL); @@ -6163,7 +6289,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec set_type_pos_node (type, n); if (def == NULL) { - error (c2m_ctx, n->pos, "unknown type %s", n->u.s.s); + error (c2m_ctx, POS (n), "unknown type %s", n->u.s.s); init_type (type); type->mode = TM_BASIC; type->u.basic_type = TP_INT; @@ -6179,7 +6305,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec case N_STRUCT: case N_UNION: { int new_scope_p; - node_t res, id = NL_HEAD (n->ops); + node_t res, id = NL_HEAD (n->u.ops); node_t decl_list = NL_NEXT (id); node_t saved_unnamed_anon_struct_union_member = curr_unnamed_anon_struct_union_member; @@ -6190,7 +6316,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec type->mode = n->code == N_STRUCT ? TM_STRUCT : TM_UNION; type->u.tag_type = res; new_scope_p = (id->code != N_IGNORE || decl->code != N_MEMBER - || NL_EL (decl->ops, 1)->code != N_IGNORE); + || NL_EL (decl->u.ops, 1)->code != N_IGNORE); type->unnamed_anon_struct_union_member_type_p = !new_scope_p; curr_unnamed_anon_struct_union_member = new_scope_p ? NULL : decl; if (decl_list->code != N_IGNORE) { @@ -6203,7 +6329,7 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec break; } case N_ENUM: { - node_t res, id = NL_HEAD (n->ops); + node_t res, id = NL_HEAD (n->u.ops); node_t enum_list = NL_NEXT (id); set_type_pos_node (type, n); @@ -6213,21 +6339,21 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec type->u.tag_type = res; if (enum_list->code == N_IGNORE) { if (incomplete_type_p (c2m_ctx, type)) - error (c2m_ctx, n->pos, "enum storage size is unknown"); + error (c2m_ctx, POS (n), "enum storage size is unknown"); } else { mir_int curr_val = 0; - for (node_t en = NL_HEAD (enum_list->ops); en != NULL; en = NL_NEXT (en)) { // ??? id + for (node_t en = NL_HEAD (enum_list->u.ops); en != NULL; en = NL_NEXT (en)) { // ??? id node_t id, const_expr; symbol_t sym; struct enum_value *enum_value; assert (en->code == N_ENUM_CONST); - id = NL_HEAD (en->ops); + id = NL_HEAD (en->u.ops); const_expr = NL_NEXT (id); check (c2m_ctx, const_expr, n); if (symbol_find (c2m_ctx, S_REGULAR, id, curr_scope, &sym)) { - error (c2m_ctx, id->pos, "enum constant %s redeclaration", id->u.s.s); + error (c2m_ctx, POS (id), "enum constant %s redeclaration", id->u.s.s); } else { symbol_insert (c2m_ctx, S_REGULAR, id, curr_scope, en, n); } @@ -6235,12 +6361,12 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec struct expr *cexpr = const_expr->attr; if (!cexpr->const_p) - error (c2m_ctx, const_expr->pos, "non-constant value in enum const expression"); + error (c2m_ctx, POS (const_expr), "non-constant value in enum const expression"); else if (!integer_type_p (cexpr->type)) - error (c2m_ctx, const_expr->pos, "enum const expression is not of an integer type"); + error (c2m_ctx, POS (const_expr), "enum const expression is not of an integer type"); else if ((signed_integer_type_p (cexpr->type) && cexpr->u.i_val > MIR_INT_MAX) || (!signed_integer_type_p (cexpr->type) && cexpr->u.u_val > MIR_INT_MAX)) - error (c2m_ctx, const_expr->pos, "enum const expression is not represented by int"); + error (c2m_ctx, POS (const_expr), "enum const expression is not represented by int"); else curr_val = cexpr->u.i_val; } @@ -6256,14 +6382,14 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec int align = -1; if (decl->code == N_FUNC_DEF) { - error (c2m_ctx, n->pos, "_Alignas for function"); - } else if (decl->code == N_MEMBER && (el = NL_EL (decl->ops, 3)) != NULL + error (c2m_ctx, POS (n), "_Alignas for function"); + } else if (decl->code == N_MEMBER && (el = NL_EL (decl->u.ops, 3)) != NULL && el->code != N_IGNORE) { - error (c2m_ctx, n->pos, "_Alignas for a bit-field"); + error (c2m_ctx, POS (n), "_Alignas for a bit-field"); } else if (decl->code == N_SPEC_DECL && in_params_p) { - error (c2m_ctx, n->pos, "_Alignas for a function parameter"); + error (c2m_ctx, POS (n), "_Alignas for a function parameter"); } else { - node_t op = NL_HEAD (n->ops); + node_t op = NL_HEAD (n->u.ops); check (c2m_ctx, op, n); if (op->code == N_TYPE) { @@ -6274,14 +6400,14 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec struct expr *cexpr = op->attr; if (!cexpr->const_p) { - error (c2m_ctx, op->pos, "non-constant value in _Alignas"); + error (c2m_ctx, POS (op), "non-constant value in _Alignas"); } else if (!integer_type_p (cexpr->type)) { - error (c2m_ctx, op->pos, "constant value in _Alignas is not of an integer type"); + error (c2m_ctx, POS (op), "constant value in _Alignas is not of an integer type"); } else if (!signed_integer_type_p (cexpr->type) || !supported_alignment_p (cexpr->u.i_val)) { - error (c2m_ctx, op->pos, "constant value in _Alignas specifies unspported alignment"); + error (c2m_ctx, POS (op), "constant value in _Alignas specifies unspported alignment"); } else if (invalid_alignment (cexpr->u.i_val)) { - error (c2m_ctx, op->pos, "unsupported alignmnent"); + error (c2m_ctx, POS (op), "unsupported alignmnent"); } else { align = cexpr->u.i_val; } @@ -6297,8 +6423,8 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec } if (type->mode == TM_BASIC && type->u.basic_type == TP_UNDEF) { if (size == 0 && sign == 0) { - (c2m_options->pedantic_p ? error (c2m_ctx, r->pos, "no any type specifier") - : warning (c2m_ctx, r->pos, "type defaults to int")); + (c2m_options->pedantic_p ? error (c2m_ctx, POS (r), "no any type specifier") + : warning (c2m_ctx, POS (r), "type defaults to int")); type->u.basic_type = TP_INT; } else if (size == 0) { type->u.basic_type = sign >= 0 ? TP_INT : TP_UINT; @@ -6313,9 +6439,9 @@ static struct decl_spec check_decl_spec (c2m_ctx_t c2m_ctx, node_t r, node_t dec set_type_qual (c2m_ctx, r, &type->type_qual, type->mode); if (res->align_node) { if (res->typedef_p) - error (c2m_ctx, res->align_node->pos, "_Alignas in typedef"); + error (c2m_ctx, POS (res->align_node), "_Alignas in typedef"); else if (res->register_p) - error (c2m_ctx, res->align_node->pos, "_Alignas with register"); + error (c2m_ctx, POS (res->align_node), "_Alignas with register"); } return *res; } @@ -6373,17 +6499,18 @@ static void adjust_param_type (c2m_ctx_t c2m_ctx, struct type **type_ptr) { } static struct type *check_declarator (c2m_ctx_t c2m_ctx, node_t r, int func_def_p) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; struct type *type, *res = NULL; - node_t list = NL_EL (r->ops, 1); + node_t list = NL_EL (r->u.ops, 1); assert (r->code == N_DECL); - if (NL_HEAD (list->ops) == NULL) return NULL; - for (node_t n = NL_HEAD (list->ops); n != NULL; n = NL_NEXT (n)) { + if (NL_HEAD (list->u.ops) == NULL) return NULL; + for (node_t n = NL_HEAD (list->u.ops); n != NULL; n = NL_NEXT (n)) { type = create_type (c2m_ctx, NULL); type->pos_node = n; switch (n->code) { case N_POINTER: { - node_t type_qual = NL_HEAD (n->ops); + node_t type_qual = NL_HEAD (n->u.ops); type->mode = TM_PTR; type->pos_node = n; @@ -6393,7 +6520,7 @@ static struct type *check_declarator (c2m_ctx_t c2m_ctx, node_t r, int func_def_ } case N_ARR: { struct arr_type *arr_type; - node_t static_node = NL_HEAD (n->ops); + node_t static_node = NL_HEAD (n->u.ops); node_t type_qual = NL_NEXT (static_node); node_t size = NL_NEXT (type_qual); @@ -6410,8 +6537,8 @@ static struct type *check_declarator (c2m_ctx_t c2m_ctx, node_t r, int func_def_ } case N_FUNC: { struct func_type *func_type; - node_t first_param, param_list = NL_HEAD (n->ops); - node_t last = NL_TAIL (param_list->ops); + node_t first_param, param_list = NL_HEAD (n->u.ops); + node_t last = NL_TAIL (param_list->u.ops); int saved_in_params_p = in_params_p; type->mode = TM_FUNC; @@ -6420,21 +6547,21 @@ static struct type *check_declarator (c2m_ctx_t c2m_ctx, node_t r, int func_def_ func_type->ret_type = NULL; func_type->proto_item = NULL; if ((func_type->dots_p = last != NULL && last->code == N_DOTS)) - NL_REMOVE (param_list->ops, last); + NL_REMOVE (param_list->u.ops, last); if (!func_def_p) create_node_scope (c2m_ctx, n); func_type->param_list = param_list; in_params_p = TRUE; - first_param = NL_HEAD (param_list->ops); + first_param = NL_HEAD (param_list->u.ops); if (first_param != NULL && first_param->code != N_ID) check (c2m_ctx, first_param, n); if (void_param_p (first_param)) { struct decl_spec *ds = first_param->attr; if (non_reg_decl_spec_p (ds) || ds->register_p || !type_qual_eq_p (&ds->type->type_qual, &zero_type_qual)) { - error (c2m_ctx, first_param->pos, "qualified void parameter"); + error (c2m_ctx, POS (first_param), "qualified void parameter"); } if (NL_NEXT (first_param) != NULL) { - error (c2m_ctx, first_param->pos, "void must be the only parameter"); + error (c2m_ctx, POS (first_param), "void must be the only parameter"); } } else { for (node_t p = first_param; p != NULL; p = NL_NEXT (p)) { @@ -6442,7 +6569,7 @@ static struct type *check_declarator (c2m_ctx_t c2m_ctx, node_t r, int func_def_ if (p->code == N_ID) { if (!func_def_p) - error (c2m_ctx, p->pos, + error (c2m_ctx, POS (p), "parameters identifier list can be only in function definition"); break; } else { @@ -6469,10 +6596,10 @@ static int check_case_expr (c2m_ctx_t c2m_ctx, node_t case_expr, struct type *ty check (c2m_ctx, case_expr, target); expr = case_expr->attr; if (!expr->const_p) { - error (c2m_ctx, case_expr->pos, "case-expr is not a constant expression"); + error (c2m_ctx, POS (case_expr), "case-expr is not a constant expression"); return FALSE; } else if (!integer_type_p (expr->type)) { - error (c2m_ctx, case_expr->pos, "case-expr is not an integer type expression"); + error (c2m_ctx, POS (case_expr), "case-expr is not an integer type expression"); return FALSE; } else { convert_value (expr, type); @@ -6481,30 +6608,32 @@ static int check_case_expr (c2m_ctx_t c2m_ctx, node_t case_expr, struct type *ty } static void check_labels (c2m_ctx_t c2m_ctx, node_t labels, node_t target) { - for (node_t l = NL_HEAD (labels->ops); l != NULL; l = NL_NEXT (l)) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + + for (node_t l = NL_HEAD (labels->u.ops); l != NULL; l = NL_NEXT (l)) { if (l->code == N_LABEL) { symbol_t sym; - node_t id = NL_HEAD (l->ops); + node_t id = NL_HEAD (l->u.ops); if (symbol_find (c2m_ctx, S_LABEL, id, func_block_scope, &sym)) { - error (c2m_ctx, id->pos, "label %s redeclaration", id->u.s.s); + error (c2m_ctx, POS (id), "label %s redeclaration", id->u.s.s); } else { symbol_insert (c2m_ctx, S_LABEL, id, func_block_scope, target, NULL); } } else if (curr_switch == NULL) { - error (c2m_ctx, l->pos, "%s not within a switch-stmt", + error (c2m_ctx, POS (l), "%s not within a switch-stmt", l->code == N_CASE ? "case label" : "default label"); } else { struct switch_attr *switch_attr = curr_switch->attr; struct type *type = &switch_attr->type; - node_t case_expr = l->code == N_CASE ? NL_HEAD (l->ops) : NULL; - node_t case_expr2 = l->code == N_CASE ? NL_EL (l->ops, 1) : NULL; + node_t case_expr = l->code == N_CASE ? NL_HEAD (l->u.ops) : NULL; + node_t case_expr2 = l->code == N_CASE ? NL_EL (l->u.ops, 1) : NULL; case_t case_attr, tail = DLIST_TAIL (case_t, switch_attr->case_labels); int ok_p = FALSE, default_p = tail != NULL && tail->case_node->code == N_DEFAULT; if (case_expr == NULL) { if (default_p) { - error (c2m_ctx, l->pos, "multiple default labels in one switch"); + error (c2m_ctx, POS (l), "multiple default labels in one switch"); } else { ok_p = TRUE; } @@ -6512,7 +6641,7 @@ static void check_labels (c2m_ctx_t c2m_ctx, node_t labels, node_t target) { ok_p = check_case_expr (c2m_ctx, case_expr, type, target); if (case_expr2 != NULL) { ok_p = check_case_expr (c2m_ctx, case_expr2, type, target) && ok_p; - (c2m_options->pedantic_p ? error : warning) (c2m_ctx, l->pos, + (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (l), "range cases are not a part of C standard"); } } @@ -6549,6 +6678,8 @@ static node_code_t get_id_linkage (c2m_ctx_t c2m_ctx, int func_p, node_t id, nod } static void check_type (c2m_ctx_t c2m_ctx, struct type *type, int level, int func_def_p) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + switch (type->mode) { case TM_PTR: check_type (c2m_ctx, type->u.ptr_type, level + 1, FALSE); break; case TM_STRUCT: @@ -6559,30 +6690,30 @@ static void check_type (c2m_ctx_t c2m_ctx, struct type *type, int level, int fun struct type *el_type = arr_type->el_type; if (size_node->code == N_STAR) { - error (c2m_ctx, size_node->pos, "variable size arrays are not supported"); + error (c2m_ctx, POS (size_node), "variable size arrays are not supported"); } else if (size_node->code != N_IGNORE) { struct expr *cexpr = size_node->attr; if (!integer_type_p (cexpr->type)) { - error (c2m_ctx, size_node->pos, "non-integer array size type"); + error (c2m_ctx, POS (size_node), "non-integer array size type"); } else if (!cexpr->const_p) { - error (c2m_ctx, size_node->pos, "variable size arrays are not supported"); + error (c2m_ctx, POS (size_node), "variable size arrays are not supported"); } else if (signed_integer_type_p (cexpr->type) && cexpr->u.i_val < 0) { - error (c2m_ctx, size_node->pos, "array size should be not negative"); + error (c2m_ctx, POS (size_node), "array size should be not negative"); } else if (cexpr->u.i_val == 0) { - (c2m_options->pedantic_p ? error : warning) (c2m_ctx, size_node->pos, "zero array size"); + (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (size_node), "zero array size"); } } check_type (c2m_ctx, el_type, level + 1, FALSE); if (el_type->mode == TM_FUNC) { - error (c2m_ctx, type->pos_node->pos, "array of functions"); + error (c2m_ctx, POS (type->pos_node), "array of functions"); } else if (incomplete_type_p (c2m_ctx, el_type)) { - error (c2m_ctx, type->pos_node->pos, "incomplete array element type"); + error (c2m_ctx, POS (type->pos_node), "incomplete array element type"); } else if (!in_params_p || level != 0) { if (arr_type->static_p) - error (c2m_ctx, type->pos_node->pos, "static should be only in parameter outermost"); + error (c2m_ctx, POS (type->pos_node), "static should be only in parameter outermost"); else if (!type_qual_eq_p (&arr_type->ind_type_qual, &zero_type_qual)) - error (c2m_ctx, type->pos_node->pos, + error (c2m_ctx, POS (type->pos_node), "type qualifiers should be only in parameter outermost array"); } break; @@ -6595,11 +6726,11 @@ static void check_type (c2m_ctx_t c2m_ctx, struct type *type, int level, int fun check_type (c2m_ctx, ret_type, level + 1, FALSE); if (ret_type->mode == TM_FUNC) { - error (c2m_ctx, ret_type->pos_node->pos, "function returning a function"); + error (c2m_ctx, POS (ret_type->pos_node), "function returning a function"); } else if (ret_type->mode == TM_ARR) { - error (c2m_ctx, ret_type->pos_node->pos, "function returning an array"); + error (c2m_ctx, POS (ret_type->pos_node), "function returning an array"); } - first_param = NL_HEAD (param_list->ops); + first_param = NL_HEAD (param_list->u.ops); if (!void_param_p (first_param)) { for (node_t p = first_param; p != NULL; p = NL_NEXT (p)) { if (p->code == N_TYPE) { @@ -6613,12 +6744,12 @@ static void check_type (c2m_ctx_t c2m_ctx, struct type *type, int level, int fun break; } if (non_reg_decl_spec_p (&decl_spec)) { - error (c2m_ctx, p->pos, "prohibited specifier in a function parameter"); + error (c2m_ctx, POS (p), "prohibited specifier in a function parameter"); } else if (func_def_p) { if (p->code == N_TYPE) - error (c2m_ctx, p->pos, "parameter type without a name in function definition"); + error (c2m_ctx, POS (p), "parameter type without a name in function definition"); else if (incomplete_type_p (c2m_ctx, decl_spec.type)) - error (c2m_ctx, p->pos, "incomplete parameter type in function definition"); + error (c2m_ctx, POS (p), "incomplete parameter type in function definition"); } } } @@ -6631,7 +6762,6 @@ static void check_type (c2m_ctx_t c2m_ctx, struct type *type, int level, int fun static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct type *right, struct expr *expr, node_t assign_node) { node_code_t code = assign_node->code; - pos_t pos = assign_node->pos; const char *msg; if (right == NULL) right = expr->type; @@ -6643,14 +6773,14 @@ static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct = (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, "%s", msg); + (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"); - error (c2m_ctx, pos, "%s", msg); + error (c2m_ctx, POS (assign_node), "%s", msg); } } } else if (left->mode == TM_STRUCT || left->mode == TM_UNION) { @@ -6661,7 +6791,7 @@ static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct : code != N_RETURN ? "incompatible types in assignment to struct/union" : "incompatible return-expr type in function returning a struct/union"); - error (c2m_ctx, pos, "%s", msg); + error (c2m_ctx, POS (assign_node), "%s", msg); } } else if (left->mode == TM_PTR) { if (null_const_p (expr, right)) { @@ -6674,32 +6804,33 @@ static void check_assignment_types (c2m_ctx_t c2m_ctx, struct type *left, struct : code == N_RETURN ? "incompatible pointer types of return-expr and function result" : "incompatible pointer types in assignment"); - (c2m_options->pedantic_p ? error : warning) (c2m_ctx, pos, "%s", msg); + (c2m_options->pedantic_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"); - (c2m_options->pedantic_p ? error : warning) (c2m_ctx, pos, "%s", msg); + (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" : "incompatible types in assignment to a pointer"); - (c2m_options->pedantic_p || right->mode != TM_PTR ? error : warning) (c2m_ctx, pos, "%s", - msg); + (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"); - error (c2m_ctx, pos, "%s", msg); + 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"); - (c2m_options->pedantic_p ? error : warning) (c2m_ctx, pos, "%s", msg); + (c2m_options->pedantic_p ? error : warning) (c2m_ctx, POS (assign_node), "%s", msg); } } } @@ -6714,7 +6845,7 @@ static node_t get_adjacent_member (node_t member, int next_p) { assert (member->code == N_MEMBER); while ((member = next_p ? NL_NEXT (member) : NL_PREV (member)) != NULL) if (member->code == N_MEMBER - && (NL_EL (member->ops, 1)->code != N_IGNORE || anon_struct_union_type_member_p (member))) + && (NL_EL (member->u.ops, 1)->code != N_IGNORE || anon_struct_union_type_member_p (member))) break; return member; } @@ -6745,13 +6876,13 @@ static int update_init_object_path (c2m_ctx_t c2m_ctx, size_t mark, struct type assert (init_object.container_type->mode == TM_STRUCT || init_object.container_type->mode == TM_UNION); if (init_object.u.curr_member == NULL) { /* finding the first named member */ - node_t declaration_list = NL_EL (init_object.container_type->u.tag_type->ops, 1); + node_t declaration_list = NL_EL (init_object.container_type->u.tag_type->u.ops, 1); assert (declaration_list != NULL && declaration_list->code == N_LIST); - for (init_object.u.curr_member = NL_HEAD (declaration_list->ops); + for (init_object.u.curr_member = NL_HEAD (declaration_list->u.ops); init_object.u.curr_member != NULL && (init_object.u.curr_member->code != N_MEMBER - || (NL_EL (init_object.u.curr_member->ops, 1)->code == N_IGNORE + || (NL_EL (init_object.u.curr_member->u.ops, 1)->code == N_IGNORE && !anon_struct_union_type_member_p (init_object.u.curr_member))); init_object.u.curr_member = NL_NEXT (init_object.u.curr_member)) ; @@ -6828,6 +6959,7 @@ static int update_path_and_do (c2m_ctx_t c2m_ctx, static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_llong *offset, int *deref) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; struct expr *e = r->attr; struct type *type; node_t op1, op2, temp; @@ -6867,7 +6999,7 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll return TRUE; case N_DEREF: case N_ADDR: { - node_t op = NL_HEAD (r->ops); + node_t op = NL_HEAD (r->u.ops); struct expr *e = op->attr; if (!check_const_addr_p (c2m_ctx, op, base, offset, deref)) return FALSE; @@ -6880,7 +7012,7 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll } case N_FIELD: case N_DEREF_FIELD: - if (!check_const_addr_p (c2m_ctx, NL_HEAD (r->ops), base, offset, deref)) return FALSE; + if (!check_const_addr_p (c2m_ctx, NL_HEAD (r->u.ops), base, offset, deref)) return FALSE; if (*deref != (r->code == N_FIELD ? 1 : 0)) return FALSE; *deref = 1; e = r->attr; @@ -6888,9 +7020,9 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll *offset += decl->offset; return TRUE; case N_IND: - if (((struct expr *) NL_HEAD (r->ops)->attr)->type->mode != TM_PTR) return FALSE; - if (!check_const_addr_p (c2m_ctx, NL_HEAD (r->ops), base, offset, deref)) return FALSE; - if (!(e = NL_EL (r->ops, 1)->attr)->const_p) return FALSE; + if (((struct expr *) NL_HEAD (r->u.ops)->attr)->type->mode != TM_PTR) return FALSE; + if (!check_const_addr_p (c2m_ctx, NL_HEAD (r->u.ops), base, offset, deref)) return FALSE; + if (!(e = NL_EL (r->u.ops, 1)->attr)->const_p) return FALSE; type = ((struct expr *) r->attr)->type; size = type_size (c2m_ctx, type->arr_type != NULL ? type->arr_type : type); *deref = 1; @@ -6898,8 +7030,8 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll return TRUE; case N_ADD: case N_SUB: - if ((op2 = NL_EL (r->ops, 1)) == NULL) return FALSE; - op1 = NL_HEAD (r->ops); + if ((op2 = NL_EL (r->u.ops, 1)) == NULL) return FALSE; + op1 = NL_HEAD (r->u.ops); if (r->code == N_ADD && (e = op1->attr)->const_p) SWAP (op1, op2, temp); if (!check_const_addr_p (c2m_ctx, op1, base, offset, deref)) return FALSE; if (*deref != 0 && ((struct expr *) op1->attr)->type->arr_type == NULL) return FALSE; @@ -6916,9 +7048,9 @@ static int check_const_addr_p (c2m_ctx_t c2m_ctx, node_t r, node_t *base, mir_ll *offset -= e->u.i_val * size; return TRUE; case N_CAST: - decl_spec = NL_HEAD (r->ops)->attr; + decl_spec = NL_HEAD (r->u.ops)->attr; if (type_size (c2m_ctx, decl_spec->type) != sizeof (mir_size_t)) return FALSE; - return check_const_addr_p (c2m_ctx, NL_EL (r->ops, 1), base, offset, deref); + return check_const_addr_p (c2m_ctx, NL_EL (r->u.ops, 1), base, offset, deref); default: return FALSE; } } @@ -6975,7 +7107,7 @@ static void process_init_field_designator (c2m_ctx_t c2m_ctx, node_t designator_ } static node_t get_compound_literal (node_t n, int *addr_p) { - for (int addr = 0; n != NULL; n = NL_HEAD (n->ops)) { + for (int addr = 0; n != NULL; n = NL_HEAD (n->u.ops)) { switch (n->code) { case N_ADDR: addr++; break; case N_DEREF: addr--; break; @@ -7010,7 +7142,7 @@ static void check_initializer (c2m_ctx_t c2m_ctx, decl_t member_decl, struct typ if (literal != NULL && !addr_p && initializer->code != N_STR) { cexpr = initializer->attr; check_assignment_types (c2m_ctx, type, NULL, cexpr, initializer); - initializer = NL_EL (literal->ops, 1); + initializer = NL_EL (literal->u.ops, 1); } check_one_value: if (initializer->code != N_LIST @@ -7023,45 +7155,46 @@ check_one_value: if ((cexpr = initializer->attr)->const_addr_p || (literal != NULL && addr_p)) check_assignment_types (c2m_ctx, type, NULL, cexpr, initializer); else - error (c2m_ctx, initializer->pos, + error (c2m_ctx, POS (initializer), "initializer of non-auto or thread local object" " should be a constant expression or address"); } return; } - init = NL_HEAD (initializer->ops); + init = NL_HEAD (initializer->u.ops); if (((str = initializer)->code == N_STR /* string or string in parentheses */ - || (init != NULL && init->code == N_INIT && NL_EL (initializer->ops, 1) == NULL - && (des_list = NL_HEAD (init->ops))->code == N_LIST && NL_HEAD (des_list->ops) == NULL - && NL_EL (init->ops, 1) != NULL && (str = NL_EL (init->ops, 1))->code == N_STR)) + || (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)) { len = str->u.s.len; if (incomplete_type_p (c2m_ctx, type)) { assert (len < MIR_INT_MAX); - type->u.arr_type->size = new_i_node (c2m_ctx, len, type->u.arr_type->size->pos); + type->u.arr_type->size = new_i_node (c2m_ctx, len, POS (type->u.arr_type->size)); check (c2m_ctx, type->u.arr_type->size, NULL); make_type_complete (c2m_ctx, type); } else if (len > ((struct expr *) type->u.arr_type->size->attr)->u.i_val + 1) { - error (c2m_ctx, initializer->pos, "string is too long for array initializer"); + error (c2m_ctx, POS (initializer), "string is too long for array initializer"); } return; } if (init == NULL) return; assert (init->code == N_INIT); - des_list = NL_HEAD (init->ops); + des_list = NL_HEAD (init->u.ops); assert (des_list->code == N_LIST); if (type->mode != TM_ARR && type->mode != TM_STRUCT && type->mode != TM_UNION) { if ((temp = NL_NEXT (init)) != NULL) { - error (c2m_ctx, temp->pos, "excess elements in scalar initializer"); + error (c2m_ctx, POS (temp), "excess elements in scalar initializer"); return; } - if ((temp = NL_HEAD (des_list->ops)) != NULL) { - error (c2m_ctx, temp->pos, "designator in scalar initializer"); + if ((temp = NL_HEAD (des_list->u.ops)) != NULL) { + error (c2m_ctx, POS (temp), "designator in scalar initializer"); return; } initializer = NL_NEXT (des_list); if (!top_p) { - error (c2m_ctx, init->pos, "braces around scalar initializer"); + error (c2m_ctx, POS (init), "braces around scalar initializer"); return; } top_p = FALSE; @@ -7084,54 +7217,54 @@ check_one_value: max_index = -1; for (; init != NULL; init = NL_NEXT (init)) { assert (init->code == N_INIT); - des_list = NL_HEAD (init->ops); + des_list = NL_HEAD (init->u.ops); value = NL_NEXT (des_list); if ((value->code == N_LIST || value->code == N_COMPOUND_LITERAL) && type->mode != TM_ARR && type->mode != TM_STRUCT && type->mode != TM_UNION) { - error (c2m_ctx, init->pos, + error (c2m_ctx, POS (init), value->code == N_LIST ? "braces around scalar initializer" : "compound literal for scalar initializer"); break; } - if ((curr_des = NL_HEAD (des_list->ops)) == NULL) { + if ((curr_des = NL_HEAD (des_list->u.ops)) == NULL) { if (!update_path_and_do (c2m_ctx, check_initializer, mark, value, const_only_p, &max_index, - init->pos, "array/struct/union")) + POS (init), "array/struct/union")) break; } else { for (; curr_des != NULL; curr_des = NL_NEXT (curr_des)) { VARR_TRUNC (init_object_t, init_object_path, mark + 1); init_object = VARR_POP (init_object_t, init_object_path); if (curr_des->code == N_FIELD_ID) { - node_t id = NL_HEAD (curr_des->ops); + node_t id = NL_HEAD (curr_des->u.ops); if (type->mode != TM_STRUCT && type->mode != TM_UNION) { - error (c2m_ctx, curr_des->pos, "field name not in struct or union initializer"); + error (c2m_ctx, POS (curr_des), "field name not in struct or union initializer"); } else if (!symbol_find (c2m_ctx, S_REGULAR, id, type->u.tag_type, &sym)) { - error (c2m_ctx, curr_des->pos, "unknown field %s in initializer", id->u.s.s); + error (c2m_ctx, POS (curr_des), "unknown field %s in initializer", id->u.s.s); } else { process_init_field_designator (c2m_ctx, sym.def_node, init_object.container_type); if (!update_path_and_do (c2m_ctx, check_initializer, mark, value, const_only_p, NULL, - init->pos, "struct/union")) + POS (init), "struct/union")) break; } } else if (type->mode != TM_ARR) { - error (c2m_ctx, curr_des->pos, "array index in initializer for non-array"); + error (c2m_ctx, POS (curr_des), "array index in initializer for non-array"); } else if (!(cexpr = curr_des->attr)->const_p) { - error (c2m_ctx, curr_des->pos, "nonconstant array index in initializer"); + error (c2m_ctx, POS (curr_des), "nonconstant array index in initializer"); } else if (!integer_type_p (cexpr->type)) { - error (c2m_ctx, curr_des->pos, "array index in initializer not of integer type"); + error (c2m_ctx, POS (curr_des), "array index in initializer not of integer type"); } else if (incomplete_type_p (c2m_ctx, type) && signed_integer_type_p (cexpr->type) && cexpr->u.i_val < 0) { - error (c2m_ctx, curr_des->pos, + error (c2m_ctx, POS (curr_des), "negative array index in initializer for array without size"); } else if (size_val >= 0 && size_val <= cexpr->u.u_val) { - error (c2m_ctx, curr_des->pos, "array index in initializer exceeds array bounds"); + error (c2m_ctx, POS (curr_des), "array index in initializer exceeds array bounds"); } else { init_object.u.curr_index = cexpr->u.i_val - 1; /* previous el */ init_object.designator_p = FALSE; VARR_PUSH (init_object_t, init_object_path, init_object); if (!update_path_and_do (c2m_ctx, check_initializer, mark, value, const_only_p, - &max_index, init->pos, "array")) + &max_index, POS (init), "array")) break; } } @@ -7151,9 +7284,9 @@ check_one_value: 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, size_node->pos) - : max_index < MIR_LONG_MAX ? new_l_node (c2m_ctx, max_index + 1, size_node->pos) - : new_ll_node (c2m_ctx, max_index + 1, size_node->pos)); + ? 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); } @@ -7165,11 +7298,13 @@ check_one_value: static void check_decl_align (c2m_ctx_t c2m_ctx, struct decl_spec *decl_spec) { if (decl_spec->align < 0) return; if (decl_spec->align < type_align (decl_spec->type)) - error (c2m_ctx, decl_spec->align_node->pos, + error (c2m_ctx, POS (decl_spec->align_node), "requested alignment is less than minimum alignment for the type"); } static void init_decl (c2m_ctx_t c2m_ctx, decl_t decl) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + decl->addr_p = FALSE; decl->reg_p = decl->used_p = FALSE; decl->offset = 0; @@ -7184,6 +7319,7 @@ static void init_decl (c2m_ctx_t c2m_ctx, decl_t decl) { static void create_decl (c2m_ctx_t c2m_ctx, node_t scope, node_t decl_node, struct decl_spec decl_spec, node_t width, node_t initializer, int param_p) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; int func_def_p = decl_node->code == N_FUNC_DEF, func_p = FALSE; node_t id = NULL; /* to remove an uninitialized warning */ node_t list_head, declarator; @@ -7196,7 +7332,7 @@ static void create_decl (c2m_ctx_t c2m_ctx, node_t scope, node_t decl_node, decl->scope = scope; decl->decl_spec = decl_spec; decl_node->attr = decl; - declarator = NL_EL (decl_node->ops, 1); + declarator = NL_EL (decl_node->u.ops, 1); if (declarator->code == N_IGNORE) { assert (decl_node->code == N_MEMBER); decl->decl_spec.linkage = N_IGNORE; @@ -7207,8 +7343,8 @@ static void create_decl (c2m_ctx_t c2m_ctx, node_t scope, node_t decl_node, } check_type (c2m_ctx, decl->decl_spec.type, 0, func_def_p); if (declarator->code == N_DECL) { - id = NL_HEAD (declarator->ops); - list_head = NL_HEAD (NL_NEXT (id)->ops); + id = NL_HEAD (declarator->u.ops); + list_head = NL_HEAD (NL_NEXT (id)->u.ops); func_p = !param_p && list_head && list_head->code == N_FUNC; decl->decl_spec.linkage = get_id_linkage (c2m_ctx, func_p, id, scope, decl->decl_spec); } @@ -7217,7 +7353,7 @@ static void create_decl (c2m_ctx_t c2m_ctx, node_t scope, node_t decl_node, if (scope != top_scope && decl->decl_spec.linkage == N_EXTERN) def_symbol (c2m_ctx, S_REGULAR, id, top_scope, decl_node, N_EXTERN); if (func_p && decl->decl_spec.thread_local_p) { - error (c2m_ctx, id->pos, "thread local function declaration"); + error (c2m_ctx, POS (id), "thread local function declaration"); if (c2m_options->message_file != NULL) { if (id->code != N_IGNORE) fprintf (c2m_options->message_file, " of %s", id->u.s.s); fprintf (c2m_options->message_file, "\n"); @@ -7236,13 +7372,13 @@ static void create_decl (c2m_ctx_t c2m_ctx, node_t scope, node_t decl_node, || incomplete_type_p (c2m_ctx, decl->decl_spec.type->u.arr_type->el_type))) { if (decl->decl_spec.type->mode == TM_ARR && decl->decl_spec.type->u.arr_type->el_type->mode == TM_ARR) - error (c2m_ctx, initializer->pos, "initialization of incomplete sub-array"); + error (c2m_ctx, POS (initializer), "initialization of incomplete sub-array"); else - error (c2m_ctx, initializer->pos, "initialization of incomplete type variable"); + error (c2m_ctx, POS (initializer), "initialization of incomplete type variable"); return; } if (decl->decl_spec.linkage != N_IGNORE && scope != top_scope) { - error (c2m_ctx, initializer->pos, + error (c2m_ctx, POS (initializer), "initialization of %s in block scope with external or internal linkage", id->u.s.s); return; } @@ -7277,7 +7413,7 @@ static struct type *adjust_type (c2m_ctx_t c2m_ctx, struct type *type) { static void process_unop (c2m_ctx_t c2m_ctx, node_t r, node_t *op, struct expr **e, struct type **t, node_t context) { - *op = NL_HEAD (r->ops); + *op = NL_HEAD (r->u.ops); check (c2m_ctx, *op, context); *e = (*op)->attr; *t = (*e)->type; @@ -7286,7 +7422,7 @@ static void process_unop (c2m_ctx_t c2m_ctx, node_t r, node_t *op, struct expr * static void process_bin_ops (c2m_ctx_t c2m_ctx, node_t r, node_t *op1, node_t *op2, struct expr **e1, struct expr **e2, struct type **t1, struct type **t2, node_t context) { - *op1 = NL_HEAD (r->ops); + *op1 = NL_HEAD (r->u.ops); *op2 = NL_NEXT (*op1); check (c2m_ctx, *op1, context); check (c2m_ctx, *op2, context); @@ -7298,7 +7434,7 @@ static void process_bin_ops (c2m_ctx_t c2m_ctx, node_t r, node_t *op1, node_t *o static void process_type_bin_ops (c2m_ctx_t c2m_ctx, node_t r, node_t *op1, node_t *op2, struct expr **e2, struct type **t2, node_t context) { - *op1 = NL_HEAD (r->ops); + *op1 = NL_HEAD (r->u.ops); *op2 = NL_NEXT (*op1); check (c2m_ctx, *op1, context); check (c2m_ctx, *op2, context); @@ -7328,6 +7464,8 @@ static struct expr *create_basic_type_expr (c2m_ctx_t c2m_ctx, node_t r, enum ba static void get_int_node (c2m_ctx_t c2m_ctx, node_t *op, struct expr **e, struct type **t, mir_size_t i) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; + if (i == 1) { *op = n_i1_node; } else { @@ -7360,7 +7498,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (!integer_type_p (t1) || !integer_type_p (t2)) { - error (c2m_ctx, r->pos, "bitwise operation operands should be of an integer type"); + error (c2m_ctx, POS (r), "bitwise operation operands should be of an integer type"); } else { t = arithmetic_conversion (t1, t2); e->type->u.basic_type = t.u.basic_type; @@ -7387,7 +7525,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (!integer_type_p (t1) || !integer_type_p (t2)) { - error (c2m_ctx, r->pos, "shift operands should be of an integer type"); + error (c2m_ctx, POS (r), "shift operands should be of an integer type"); } else { t = integer_promotion (t1); e->type->u.basic_type = t.u.basic_type; @@ -7445,9 +7583,9 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no SWAP (e1, e2, te); } if (t1->mode != TM_PTR || !integer_type_p (t2)) { - error (c2m_ctx, r->pos, "invalid operand types of +"); + error (c2m_ctx, POS (r), "invalid operand types of +"); } else if (incomplete_type_p (c2m_ctx, t1->u.ptr_type)) { - error (c2m_ctx, r->pos, "pointer to incomplete type as an operand of +"); + error (c2m_ctx, POS (r), "pointer to incomplete type as an operand of +"); } else { *e->type = *t1; if (e1->const_p && e2->const_p) { @@ -7459,7 +7597,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no } } else if (t1->mode == TM_PTR && integer_type_p (t2)) { if (incomplete_type_p (c2m_ctx, t1->u.ptr_type)) { - error (c2m_ctx, r->pos, "pointer to incomplete type as an operand of -"); + error (c2m_ctx, POS (r), "pointer to incomplete type as an operand of -"); } else { *e->type = *t1; if (e1->const_p && e2->const_p) { @@ -7472,9 +7610,9 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no } else if (t1->mode == TM_PTR && t2->mode == TM_PTR && compatible_types_p (t1, t2, TRUE)) { if (incomplete_type_p (c2m_ctx, t1->u.ptr_type) && incomplete_type_p (c2m_ctx, t2->u.ptr_type)) { - error (c2m_ctx, r->pos, "pointer to incomplete type as an operand of -"); + error (c2m_ctx, POS (r), "pointer to incomplete type as an operand of -"); } else if (t1->u.ptr_type->type_qual.atomic_p || t2->u.ptr_type->type_qual.atomic_p) { - error (c2m_ctx, r->pos, "pointer to atomic type as an operand of -"); + error (c2m_ctx, POS (r), "pointer to atomic type as an operand of -"); } else { e->type->mode = TM_BASIC; e->type->u.basic_type = get_int_basic_type (sizeof (mir_ptrdiff_t)); @@ -7488,7 +7626,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no } } } else { - error (c2m_ctx, r->pos, "invalid operand types of -"); + error (c2m_ctx, POS (r), "invalid operand types of -"); } break; } @@ -7502,9 +7640,9 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (r->code == N_MOD && (!integer_type_p (t1) || !integer_type_p (t2))) { - error (c2m_ctx, r->pos, "invalid operand types of %%"); + error (c2m_ctx, POS (r), "invalid operand types of %%"); } else if (r->code != N_MOD && (!arithmetic_type_p (t1) || !arithmetic_type_p (t2))) { - error (c2m_ctx, r->pos, "invalid operand types of %s", r->code == N_MUL ? "*" : "/"); + error (c2m_ctx, POS (r), "invalid operand types of %s", r->code == N_MUL ? "*" : "/"); } else { t = arithmetic_conversion (t1, t2); e->type->u.basic_type = t.u.basic_type; @@ -7529,7 +7667,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no e->u.i_val = 0; else e->u.u_val = 0; - error (c2m_ctx, r->pos, "Division by zero"); + error (c2m_ctx, POS (r), "Division by zero"); } } else if (r->code != N_MOD && floating_type_p (&t)) { e->u.d_val = e1->u.d_val / e2->u.d_val; @@ -7547,7 +7685,7 @@ static struct expr *check_assign_op (c2m_ctx_t c2m_ctx, node_t r, node_t op1, no } static unsigned case_hash (case_t el, void *arg) { - node_t case_expr = NL_HEAD (el->case_node->ops); + node_t case_expr = NL_HEAD (el->case_node->u.ops); struct expr *expr; assert (el->case_node->code == N_CASE); @@ -7559,8 +7697,8 @@ static unsigned case_hash (case_t el, void *arg) { } static int case_eq (case_t el1, case_t el2, void *arg) { - node_t case_expr1 = NL_HEAD (el1->case_node->ops); - node_t case_expr2 = NL_HEAD (el2->case_node->ops); + node_t case_expr1 = NL_HEAD (el1->case_node->u.ops); + node_t case_expr2 = NL_HEAD (el2->case_node->u.ops); struct expr *expr1, *expr2; assert (el1->case_node->code == N_CASE && el2->case_node->code == N_CASE); @@ -7573,7 +7711,8 @@ static int case_eq (case_t el1, case_t el2, void *arg) { } static void update_call_arg_area_offset (c2m_ctx_t c2m_ctx, struct type *type, int update_scope_p) { - node_t block = NL_EL (curr_func_def->ops, 3); + check_ctx_t check_ctx = c2m_ctx->check_ctx; + node_t block = NL_EL (curr_func_def->u.ops, 3); struct node_scope *ns = block->attr; curr_call_arg_area_offset += round_size (type_size (c2m_ctx, type), MAX_ALIGNMENT); @@ -7616,23 +7755,23 @@ static void classify_node (node_t n, int *expr_attr_p, int *stmt_p) { beginning of func_block if it is necessary. */ static void add__func__def (c2m_ctx_t c2m_ctx, node_t func_block, str_t func_name) { static const char fdecl_name[] = "__func__"; - pos_t pos = func_block->pos; + pos_t pos = POS (func_block); node_t list, declarator, decl, decl_specs; - str_t str; + tab_str_t str; if (!str_exists_p (c2m_ctx, fdecl_name, strlen (fdecl_name) + 1, &str)) return; decl_specs = new_pos_node (c2m_ctx, N_LIST, pos); - NL_APPEND (decl_specs->ops, new_pos_node (c2m_ctx, N_STATIC, pos)); - NL_APPEND (decl_specs->ops, new_pos_node (c2m_ctx, N_CONST, pos)); - NL_APPEND (decl_specs->ops, new_pos_node (c2m_ctx, N_CHAR, pos)); + NL_APPEND (decl_specs->u.ops, new_pos_node (c2m_ctx, N_STATIC, pos)); + NL_APPEND (decl_specs->u.ops, new_pos_node (c2m_ctx, N_CONST, pos)); + NL_APPEND (decl_specs->u.ops, new_pos_node (c2m_ctx, N_CHAR, pos)); list = new_pos_node (c2m_ctx, N_LIST, pos); - NL_APPEND (list->ops, new_pos_node3 (c2m_ctx, N_ARR, pos, new_pos_node (c2m_ctx, N_IGNORE, pos), - new_pos_node (c2m_ctx, N_LIST, pos), - new_pos_node (c2m_ctx, N_IGNORE, pos))); - declarator = new_pos_node2 (c2m_ctx, N_DECL, pos, new_str_node (c2m_ctx, N_ID, str, pos), list); + NL_APPEND (list->u.ops, new_pos_node3 (c2m_ctx, N_ARR, pos, new_pos_node (c2m_ctx, N_IGNORE, pos), + new_pos_node (c2m_ctx, N_LIST, pos), + new_pos_node (c2m_ctx, N_IGNORE, pos))); + declarator = new_pos_node2 (c2m_ctx, N_DECL, pos, new_str_node (c2m_ctx, N_ID, str.str, pos), list); decl = new_pos_node3 (c2m_ctx, N_SPEC_DECL, pos, decl_specs, declarator, new_str_node (c2m_ctx, N_STR, func_name, pos)); - NL_PREPEND (NL_EL (func_block->ops, 1)->ops, decl); + NL_PREPEND (NL_EL (func_block->u.ops, 1)->u.ops, decl); } /* Sort by decl scope nesting (more nested scope has a bigger UID) and decl size. */ @@ -7649,6 +7788,7 @@ static int decl_cmp (const void *v1, const void *v2) { } static void process_func_decls_for_allocation (c2m_ctx_t c2m_ctx) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; size_t i, j; decl_t decl; struct type *type; @@ -7709,6 +7849,7 @@ static void process_func_decls_for_allocation (c2m_ctx_t c2m_ctx) { #define ALLOCA "alloca" static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { + check_ctx_t check_ctx = c2m_ctx->check_ctx; node_t op1, op2; struct expr *e = NULL, *e1, *e2; struct type t, *t1, *t2, *assign_expr_type; @@ -7721,7 +7862,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { case N_STAR: case N_FIELD_ID: break; /* do nothing */ case N_LIST: { - for (node_t n = NL_HEAD (r->ops); n != NULL; n = NL_NEXT (n)) check (c2m_ctx, n, r); + for (node_t n = NL_HEAD (r->u.ops); n != NULL; n = NL_NEXT (n)) check (c2m_ctx, n, r); break; } case N_I: @@ -7783,7 +7924,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { 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->size = new_i_node (c2m_ctx, r->u.s.len, r->pos); + arr_type->size = new_i_node (c2m_ctx, r->u.s.len, POS (r)); check (c2m_ctx, arr_type->size, NULL); break; } @@ -7795,14 +7936,14 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e = create_expr (c2m_ctx, r); e->def_node = op1; if (op1 == NULL) { - error (c2m_ctx, r->pos, "undeclared identifier %s", r->u.s.s); + error (c2m_ctx, POS (r), "undeclared identifier %s", r->u.s.s); } else if (op1->code == N_IGNORE) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; } else if (op1->code == N_SPEC_DECL) { decl = op1->attr; if (decl->decl_spec.typedef_p) - error (c2m_ctx, r->pos, "typedef name %s as an operand", r->u.s.s); + error (c2m_ctx, POS (r), "typedef name %s as an operand", r->u.s.s); decl->used_p = TRUE; *e->type = *decl->decl_spec.type; if (e->type->mode != TM_FUNC) e->lvalue_node = op1; @@ -7833,7 +7974,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (!scalar_type_p (t1) || !scalar_type_p (t2)) { - error (c2m_ctx, r->pos, "invalid operand types of %s", r->code == N_ANDAND ? "&&" : "||"); + error (c2m_ctx, POS (r), "invalid operand types of %s", r->code == N_ANDAND ? "&&" : "||"); } else if (e1->const_p) { int v; @@ -7878,9 +8019,9 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { else if (t1->mode == TM_PTR && t2->mode == TM_PTR) { if (!compatible_types_p (t1, t2, TRUE) && ((r->code != N_EQ && r->code != N_NE) || (!void_ptr_p (t1) && !void_ptr_p (t2)))) { - error (c2m_ctx, r->pos, "incompatible pointer types in comparison"); + error (c2m_ctx, POS (r), "incompatible pointer types in comparison"); } else if (t1->u.ptr_type->type_qual.atomic_p || t2->u.ptr_type->type_qual.atomic_p) { - error (c2m_ctx, r->pos, "pointer to atomic type as a comparison operand"); + 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 @@ -7931,7 +8072,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { : e1->u.u_val >= e2->u.u_val); } } else { - error (c2m_ctx, r->pos, "invalid types of comparison operands"); + error (c2m_ctx, POS (r), "invalid types of comparison operands"); } break; case N_BITWISE_NOT: @@ -7941,9 +8082,9 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (r->code == N_BITWISE_NOT && !integer_type_p (t1)) { - error (c2m_ctx, r->pos, "bitwise-not operand should be of an integer type"); + error (c2m_ctx, POS (r), "bitwise-not operand should be of an integer type"); } else if (r->code == N_NOT && !scalar_type_p (t1)) { - error (c2m_ctx, r->pos, "not operand should be of a scalar type"); + error (c2m_ctx, POS (r), "not operand should be of a scalar type"); } else if (r->code == N_BITWISE_NOT) { t = integer_promotion (t1); e->type->u.basic_type = t.u.basic_type; @@ -7987,13 +8128,13 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } case N_ADD: case N_SUB: - if (NL_NEXT (NL_HEAD (r->ops)) == NULL) { /* unary */ + if (NL_NEXT (NL_HEAD (r->u.ops)) == NULL) { /* unary */ process_unop (c2m_ctx, r, &op1, &e1, &t1, r); e = create_expr (c2m_ctx, r); e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (!arithmetic_type_p (t1)) { - error (c2m_ctx, r->pos, "unary + or - operand should be of an arithmentic type"); + error (c2m_ctx, POS (r), "unary + or - operand should be of an arithmentic type"); } else { if (e1->const_p) e->const_p = TRUE; if (floating_type_p (t1)) { @@ -8057,7 +8198,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { assign: e = create_expr (c2m_ctx, r); if (!e1->lvalue_node) { - error (c2m_ctx, r->pos, "lvalue required as left operand of assignment"); + error (c2m_ctx, POS (r), "lvalue required as left operand of assignment"); } check_assignment_types (c2m_ctx, t1, t2, e2, r); *e->type = *t1; @@ -8072,36 +8213,36 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { SWAP (t1, t2, temp); SWAP (e1, e2, e); SWAP (op1, op2, op); - NL_REMOVE (r->ops, op1); - NL_APPEND (r->ops, op1); + NL_REMOVE (r->u.ops, op1); + NL_APPEND (r->u.ops, op1); } e = create_expr (c2m_ctx, r); e->lvalue_node = r; e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (t1->mode != TM_PTR && t1->mode != TM_ARR) { - error (c2m_ctx, r->pos, "subscripted value is neither array nor pointer"); + error (c2m_ctx, POS (r), "subscripted value is neither array nor pointer"); } else if (t1->mode == TM_PTR) { *e->type = *t1->u.ptr_type; if (incomplete_type_p (c2m_ctx, t1->u.ptr_type)) { - error (c2m_ctx, r->pos, "pointer to incomplete type in array subscription"); + error (c2m_ctx, POS (r), "pointer to incomplete type in array subscription"); } } else { *e->type = *t1->u.arr_type->el_type; e->type->type_qual = t1->u.arr_type->ind_type_qual; if (incomplete_type_p (c2m_ctx, e->type)) { - error (c2m_ctx, r->pos, "array type has incomplete element type"); + error (c2m_ctx, POS (r), "array type has incomplete element type"); } } if (!integer_type_p (t2)) { - error (c2m_ctx, r->pos, "array subscript is not an integer"); + error (c2m_ctx, POS (r), "array subscript is not an integer"); } break; case N_ADDR: process_unop (c2m_ctx, r, &op1, &e1, &t1, r); e = create_expr (c2m_ctx, r); if (op1->code == N_DEREF) { - node_t deref_op = NL_HEAD (op1->ops); + node_t deref_op = NL_HEAD (op1->u.ops); *e->type = *((struct expr *) deref_op->attr)->type; break; @@ -8111,7 +8252,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } else if (!e1->lvalue_node) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; - error (c2m_ctx, r->pos, "lvalue required as unary & operand"); + error (c2m_ctx, POS (r), "lvalue required as unary & operand"); break; } if (op1->code == N_IND) { @@ -8122,20 +8263,20 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { decl->addr_p = TRUE; if (decl->decl_spec.register_p) - error (c2m_ctx, r->pos, "address of register variable %s requested", op1->u.s.s); + error (c2m_ctx, POS (r), "address of register variable %s requested", op1->u.s.s); t2 = create_type (c2m_ctx, decl->decl_spec.type); } else if (e1->lvalue_node->code == N_MEMBER) { - node_t declarator = NL_EL (e1->lvalue_node->ops, 1); + node_t declarator = NL_EL (e1->lvalue_node->u.ops, 1); node_t width = NL_NEXT (declarator); decl_t decl = e1->lvalue_node->attr; assert (declarator->code == N_DECL); if (width->code != N_IGNORE) { - error (c2m_ctx, r->pos, "cannot take address of bit-field %s", - NL_HEAD (declarator->ops)->u.s.s); + error (c2m_ctx, POS (r), "cannot take address of bit-field %s", + NL_HEAD (declarator->u.ops)->u.s.s); } t2 = create_type (c2m_ctx, decl->decl_spec.type); - if (op1->code == N_DEREF_FIELD && (e2 = NL_HEAD (op1->ops)->attr)->const_p) { + if (op1->code == N_DEREF_FIELD && (e2 = NL_HEAD (op1->u.ops)->attr)->const_p) { e->const_p = TRUE; e->u.u_val = e2->u.u_val + decl->offset; } @@ -8154,7 +8295,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (t1->mode != TM_PTR) { - error (c2m_ctx, r->pos, "invalid type argument of unary *"); + error (c2m_ctx, POS (r), "invalid type argument of unary *"); } else { *e->type = *t1->u.ptr_type; e->lvalue_node = r; @@ -8177,17 +8318,17 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { t1 = t1->u.ptr_type; } if (t1->mode != TM_STRUCT && t1->mode != TM_UNION) { - error (c2m_ctx, r->pos, "request for member %s in something not a structure or union", + error (c2m_ctx, POS (r), "request for member %s in something not a structure or union", op2->u.s.s); } else if (!symbol_find (c2m_ctx, S_REGULAR, op2, t1->u.tag_type, &sym)) { - error (c2m_ctx, r->pos, "%s has no member %s", t1->mode == TM_STRUCT ? "struct" : "union", + error (c2m_ctx, POS (r), "%s has no member %s", t1->mode == TM_STRUCT ? "struct" : "union", op2->u.s.s); } else { assert (sym.def_node->code == N_MEMBER); decl = sym.def_node->attr; *e->type = *decl->decl_spec.type; e->lvalue_node = sym.def_node; - if ((width = NL_EL (sym.def_node->ops, 2))->code != N_IGNORE && e->type->mode == TM_BASIC + if ((width = NL_EL (sym.def_node->u.ops, 2))->code != N_IGNORE && e->type->mode == TM_BASIC && (width_expr = width->attr)->const_p && width_expr->u.i_val < sizeof (mir_int) * MIR_CHAR_BIT) e->type->u.basic_type = TP_INT; @@ -8210,7 +8351,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; if (!scalar_type_p (t1)) { - error (c2m_ctx, r->pos, "condition should be of a scalar type"); + error (c2m_ctx, POS (r), "condition should be of a scalar type"); break; } if (e1->const_p) { @@ -8247,7 +8388,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { || (t3->mode == TM_PTR && null_const_p (e2, t2))) { e->type = null_const_p (e3, t2) ? t3 : t2; } else if (t2->mode != TM_PTR && t3->mode != TM_PTR) { - error (c2m_ctx, r->pos, "incompatible types in true and false parts of cond-expression"); + error (c2m_ctx, POS (r), "incompatible types in true and false parts of cond-expression"); break; } else if (compatible_types_p (t2, t3, TRUE)) { t = composite_type (c2m_ctx, t2->u.ptr_type, t3->u.ptr_type); @@ -8258,7 +8399,8 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { = type_qual_union (&t2->u.ptr_type->type_qual, &t3->u.ptr_type->type_qual); if ((t2->u.ptr_type->type_qual.atomic_p || t3->u.ptr_type->type_qual.atomic_p) && !null_const_p (e2, t2) && !null_const_p (e3, t3)) { - error (c2m_ctx, r->pos, "pointer to atomic type in true or false parts of cond-expression"); + error (c2m_ctx, POS (r), + "pointer to atomic type in true or false parts of cond-expression"); } } else if (void_ptr_p (t2) || void_ptr_p (t3)) { e->type->mode = TM_PTR; @@ -8271,7 +8413,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->u.ptr_type = e3->type->u.ptr_type; } else { if (t2->u.ptr_type->type_qual.atomic_p || t3->u.ptr_type->type_qual.atomic_p) { - error (c2m_ctx, r->pos, + error (c2m_ctx, POS (r), "pointer to atomic type in true or false parts of cond-expression"); } e->type->u.ptr_type->mode = TM_BASIC; @@ -8280,7 +8422,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->u.ptr_type->type_qual = type_qual_union (&t2->u.ptr_type->type_qual, &t3->u.ptr_type->type_qual); } else { - error (c2m_ctx, r->pos, + error (c2m_ctx, POS (r), "incompatible pointer types in true and false parts of cond-expression"); break; } @@ -8299,21 +8441,21 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { case N_SIZEOF: { struct decl_spec *decl_spec; - op1 = NL_HEAD (r->ops); + op1 = NL_HEAD (r->u.ops); check (c2m_ctx, op1, r); e = create_expr (c2m_ctx, r); *e->type = get_ptr_int_type (FALSE); if (r->code == N_ALIGNOF && op1->code == N_IGNORE) { - error (c2m_ctx, r->pos, "_Alignof of non-type"); + error (c2m_ctx, POS (r), "_Alignof of non-type"); break; } assert (op1->code == N_TYPE); decl_spec = op1->attr; if (incomplete_type_p (c2m_ctx, decl_spec->type)) { - error (c2m_ctx, r->pos, "%s of incomplete type requested", + error (c2m_ctx, POS (r), "%s of incomplete type requested", r->code == N_ALIGNOF ? "_Alignof" : "sizeof"); } else if (decl_spec->type->mode == TM_FUNC) { - error (c2m_ctx, r->pos, "%s of function type requested", + error (c2m_ctx, POS (r), "%s of function type requested", r->code == N_ALIGNOF ? "_Alignof" : "sizeof"); } else { e->const_p = TRUE; @@ -8328,17 +8470,17 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->type->mode = TM_BASIC; e->type->u.basic_type = TP_INT; // ??? if (incomplete_type_p (c2m_ctx, t1)) { - error (c2m_ctx, r->pos, "sizeof of incomplete type requested"); + error (c2m_ctx, POS (r), "sizeof of incomplete type requested"); } else if (t1->mode == TM_FUNC) { - error (c2m_ctx, r->pos, "sizeof of function type requested"); + error (c2m_ctx, POS (r), "sizeof of function type requested"); } else if (e1->lvalue_node && e1->lvalue_node->code == N_MEMBER) { - node_t declarator = NL_EL (e1->lvalue_node->ops, 1); + node_t declarator = NL_EL (e1->lvalue_node->u.ops, 1); node_t width = NL_NEXT (declarator); assert (declarator->code == N_DECL); if (width->code != N_IGNORE) { - error (c2m_ctx, r->pos, "sizeof applied to a bit-field %s", - NL_HEAD (declarator->ops)->u.s.s); + error (c2m_ctx, POS (r), "sizeof applied to a bit-field %s", + NL_HEAD (declarator->u.ops)->u.s.s); } } e->const_p = TRUE; @@ -8355,13 +8497,13 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { *e->type = *decl_spec->type; void_p = void_type_p (decl_spec->type); if (!void_p && !scalar_type_p (decl_spec->type)) { - error (c2m_ctx, r->pos, "conversion to non-scalar type requested"); + error (c2m_ctx, POS (r), "conversion to non-scalar type requested"); } else if (!scalar_type_p (t2) && !void_type_p (t2)) { - error (c2m_ctx, r->pos, "conversion of non-scalar value requested"); + error (c2m_ctx, POS (r), "conversion of non-scalar value requested"); } else if (t2->mode == TM_PTR && floating_type_p (decl_spec->type)) { - error (c2m_ctx, r->pos, "conversion of a pointer to floating value requested"); + error (c2m_ctx, POS (r), "conversion of a pointer to floating value requested"); } else if (decl_spec->type->mode == TM_PTR && floating_type_p (t2)) { - error (c2m_ctx, r->pos, "conversion of floating point value to a pointer requested"); + error (c2m_ctx, POS (r), "conversion of floating point value to a pointer requested"); } else if (e2->const_p && !void_p) { e->const_p = TRUE; cast_value (e, e2, decl_spec->type); @@ -8373,7 +8515,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { decl_t decl; int n_spec_index, addr_p; - op1 = NL_HEAD (r->ops); + op1 = NL_HEAD (r->u.ops); list = NL_NEXT (op1); assert (op1->code == N_TYPE && list->code == N_LIST); check (c2m_ctx, op1, r); @@ -8384,7 +8526,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if (incomplete_type_p (c2m_ctx, t1) && (t1->mode != TM_ARR || t1->u.arr_type->size->code != N_IGNORE || incomplete_type_p (c2m_ctx, t1->u.arr_type->el_type))) { - error (c2m_ctx, r->pos, "compound literal of incomplete type"); + error (c2m_ctx, POS (r), "compound literal of incomplete type"); break; } for (n_spec_index = VARR_LENGTH (node_t, context_stack) - 1; @@ -8417,7 +8559,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { struct type res_type; int builtin_call_p, alloca_p, va_arg_p = FALSE, va_start_p = FALSE; - op1 = NL_HEAD (r->ops); + op1 = NL_HEAD (r->u.ops); alloca_p = op1->code == N_ID && strcmp (op1->u.s.s, ALLOCA) == 0; if (op1->code == N_ID && find_def (c2m_ctx, S_REGULAR, op1, curr_scope, NULL) == NULL) { va_arg_p = strcmp (op1->u.s.s, BUILTIN_VA_ARG) == 0; @@ -8425,27 +8567,28 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if (!va_arg_p && !va_start_p && !alloca_p) { /* N_SPEC_DECL (N_SHARE (N_LIST (N_INT)), N_DECL (N_ID, N_FUNC (N_LIST)), N_IGNORE) */ spec_list = new_node (c2m_ctx, N_LIST); - op_append (spec_list, new_node (c2m_ctx, N_INT)); + op_append (c2m_ctx, spec_list, new_node (c2m_ctx, N_INT)); list = new_node (c2m_ctx, N_LIST); - op_append (list, new_node1 (c2m_ctx, N_FUNC, new_node (c2m_ctx, N_LIST))); + op_append (c2m_ctx, list, new_node1 (c2m_ctx, N_FUNC, new_node (c2m_ctx, N_LIST))); decl - = new_pos_node3 (c2m_ctx, N_SPEC_DECL, op1->pos, new_node1 (c2m_ctx, N_SHARE, spec_list), + = new_pos_node3 (c2m_ctx, N_SPEC_DECL, POS (op1), new_node1 (c2m_ctx, N_SHARE, spec_list), new_node2 (c2m_ctx, N_DECL, copy_node (c2m_ctx, op1), list), new_node (c2m_ctx, N_IGNORE)); curr_scope = top_scope; check (c2m_ctx, decl, NULL); curr_scope = saved_scope; assert (top_scope->code == N_MODULE); - list = NL_HEAD (top_scope->ops); + list = NL_HEAD (top_scope->u.ops); assert (list->code == N_LIST); - op_prepend (list, decl); + op_prepend (c2m_ctx, list, decl); } } builtin_call_p = alloca_p || va_arg_p || va_start_p; if (!builtin_call_p) VARR_PUSH (node_t, call_nodes, r); arg_list = NL_NEXT (op1); if (builtin_call_p) { - for (arg = NL_HEAD (arg_list->ops); arg != NULL; arg = NL_NEXT (arg)) check (c2m_ctx, arg, r); + for (arg = NL_HEAD (arg_list->u.ops); arg != NULL; arg = NL_NEXT (arg)) + check (c2m_ctx, arg, r); init_type (&res_type); if (alloca_p) { res_type.mode = TM_PTR; @@ -8455,20 +8598,20 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { res_type.u.basic_type = va_arg_p ? TP_INT : TP_VOID; } ret_type = &res_type; - if (va_start_p && NL_LENGTH (arg_list->ops) != 1) { - error (c2m_ctx, op1->pos, "wrong number of arguments in %s call", BUILTIN_VA_START); - } else if (alloca_p && NL_LENGTH (arg_list->ops) != 1) { - error (c2m_ctx, op1->pos, "wrong number of arguments in %s call", ALLOCA); - } else if (va_arg_p && NL_LENGTH (arg_list->ops) != 2) { - error (c2m_ctx, op1->pos, "wrong number of arguments in %s call", BUILTIN_VA_ARG); + if (va_start_p && NL_LENGTH (arg_list->u.ops) != 1) { + error (c2m_ctx, POS (op1), "wrong number of arguments in %s call", BUILTIN_VA_START); + } else if (alloca_p && NL_LENGTH (arg_list->u.ops) != 1) { + error (c2m_ctx, POS (op1), "wrong number of arguments in %s call", ALLOCA); + } else if (va_arg_p && NL_LENGTH (arg_list->u.ops) != 2) { + error (c2m_ctx, POS (op1), "wrong number of arguments in %s call", BUILTIN_VA_ARG); } else { /* first argument type ??? */ if (va_arg_p) { - arg = NL_EL (arg_list->ops, 1); + arg = NL_EL (arg_list->u.ops, 1); e2 = arg->attr; t2 = e2->type; if (t2->mode != TM_PTR) - error (c2m_ctx, arg->pos, "wrong type of 2nd argument of %s call", BUILTIN_VA_ARG); + error (c2m_ctx, POS (arg), "wrong type of 2nd argument of %s call", BUILTIN_VA_ARG); else ret_type = t2->u.ptr_type; } @@ -8478,7 +8621,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e1 = op1->attr; t1 = e1->type; if (t1->mode != TM_PTR || (t1 = t1->u.ptr_type)->mode != TM_FUNC) { - error (c2m_ctx, r->pos, "called object is not a function or function pointer"); + error (c2m_ctx, POS (r), "called object is not a function or function pointer"); break; } func_type = t1->u.func_type; @@ -8489,7 +8632,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e->builtin_call_p = builtin_call_p; if ((ret_type->mode != TM_BASIC || ret_type->u.basic_type != TP_VOID) && incomplete_type_p (c2m_ctx, ret_type)) { - error (c2m_ctx, r->pos, "function return type is incomplete"); + error (c2m_ctx, POS (r), "function return type is incomplete"); } if (ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION) { set_type_layout (c2m_ctx, ret_type); @@ -8497,18 +8640,19 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } if (builtin_call_p) break; param_list = func_type->param_list; - param = start_param = NL_HEAD (param_list->ops); + param = start_param = NL_HEAD (param_list->u.ops); if (void_param_p (start_param)) { /* f(void) */ - if ((arg = NL_HEAD (arg_list->ops)) != NULL) error (c2m_ctx, arg->pos, "too many arguments"); + if ((arg = NL_HEAD (arg_list->u.ops)) != NULL) + error (c2m_ctx, POS (arg), "too many arguments"); break; } saved_call_arg_area_offset_before_args = curr_call_arg_area_offset; - for (arg = NL_HEAD (arg_list->ops); arg != NULL; arg = NL_NEXT (arg)) { + for (arg = NL_HEAD (arg_list->u.ops); arg != NULL; arg = NL_NEXT (arg)) { check (c2m_ctx, arg, r); e2 = arg->attr; if (start_param == NULL || start_param->code == N_ID) continue; /* no params or ident list */ if (param == NULL) { - if (!func_type->dots_p) error (c2m_ctx, arg->pos, "too many arguments"); + if (!func_type->dots_p) error (c2m_ctx, POS (arg), "too many arguments"); start_param = NULL; /* ignore the rest args */ continue; } @@ -8518,7 +8662,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { param = NL_NEXT (param); } curr_call_arg_area_offset = saved_call_arg_area_offset_before_args; - if (param != NULL) error (c2m_ctx, r->pos, "too few arguments"); + if (param != NULL) error (c2m_ctx, POS (r), "too few arguments"); break; } case N_GENERIC: { @@ -8526,39 +8670,39 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { node_t default_case = NULL, ga_case = NULL; struct decl_spec *decl_spec; - op1 = NL_HEAD (r->ops); + op1 = NL_HEAD (r->u.ops); check (c2m_ctx, op1, r); e1 = op1->attr; t = *e1->type; if (integer_type_p (&t)) t = integer_promotion (&t); list = NL_NEXT (op1); - for (ga = NL_HEAD (list->ops); ga != NULL; ga = NL_NEXT (ga)) { + for (ga = NL_HEAD (list->u.ops); ga != NULL; ga = NL_NEXT (ga)) { assert (ga->code == N_GENERIC_ASSOC); - type_name = NL_HEAD (ga->ops); + type_name = NL_HEAD (ga->u.ops); expr = NL_NEXT (type_name); check (c2m_ctx, type_name, r); check (c2m_ctx, expr, r); if (type_name->code == N_IGNORE) { - if (default_case) error (c2m_ctx, ga->pos, "duplicate default case in _Generic"); + if (default_case) error (c2m_ctx, POS (ga), "duplicate default case in _Generic"); default_case = ga; continue; } assert (type_name->code == N_TYPE); decl_spec = type_name->attr; if (incomplete_type_p (c2m_ctx, decl_spec->type)) { - error (c2m_ctx, ga->pos, "_Generic case has incomplete type"); + error (c2m_ctx, POS (ga), "_Generic case has incomplete type"); } else if (compatible_types_p (&t, decl_spec->type, TRUE)) { if (ga_case) - error (c2m_ctx, ga_case->pos, + error (c2m_ctx, POS (ga_case), "_Generic expr type is compatible with more than one generic association type"); ga_case = ga; } else { - for (ga2 = NL_HEAD (list->ops); ga2 != ga; ga2 = NL_NEXT (ga2)) { - type_name2 = NL_HEAD (ga2->ops); + for (ga2 = NL_HEAD (list->u.ops); ga2 != ga; ga2 = NL_NEXT (ga2)) { + type_name2 = NL_HEAD (ga2->u.ops); if (type_name2->code != N_IGNORE && !(incomplete_type_p (c2m_ctx, t2 = ((struct decl_spec *) type_name2->attr)->type)) && compatible_types_p (t2, decl_spec->type, TRUE)) { - error (c2m_ctx, ga->pos, "two or more compatible generic association types"); + error (c2m_ctx, POS (ga), "two or more compatible generic association types"); break; } } @@ -8566,33 +8710,33 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } e = create_expr (c2m_ctx, r); if (default_case == NULL && ga_case == NULL) { - error (c2m_ctx, r->pos, "expression type is not compatible with generic association"); + error (c2m_ctx, POS (r), "expression type is not compatible with generic association"); } else { /* make compatible association a list head */ if (ga_case == NULL) ga_case = default_case; - NL_REMOVE (list->ops, ga_case); - NL_PREPEND (list->ops, ga_case); + NL_REMOVE (list->u.ops, ga_case); + NL_PREPEND (list->u.ops, ga_case); t2 = e->type; - *e = *(struct expr *) NL_EL (ga_case->ops, 1)->attr; + *e = *(struct expr *) NL_EL (ga_case->u.ops, 1)->attr; *t2 = *e->type; e->type = t2; } break; } case N_SPEC_DECL: { - node_t specs = NL_HEAD (r->ops); + node_t specs = NL_HEAD (r->u.ops); node_t declarator = NL_NEXT (specs); node_t initializer = NL_NEXT (declarator); - node_t unshared_specs = specs->code != N_SHARE ? specs : NL_HEAD (specs->ops); + node_t unshared_specs = specs->code != N_SHARE ? specs : NL_HEAD (specs->u.ops); struct decl_spec decl_spec = check_decl_spec (c2m_ctx, unshared_specs, r); if (declarator->code != N_IGNORE) { create_decl (c2m_ctx, curr_scope, r, decl_spec, NULL, initializer, context != NULL && context->code == N_FUNC); } else if (decl_spec.type->mode == TM_STRUCT || decl_spec.type->mode == TM_UNION) { - if (NL_HEAD (decl_spec.type->u.tag_type->ops)->code != N_ID) - error (c2m_ctx, r->pos, "unnamed struct/union with no instances"); + if (NL_HEAD (decl_spec.type->u.tag_type->u.ops)->code != N_ID) + error (c2m_ctx, POS (r), "unnamed struct/union with no instances"); } else if (decl_spec.type->mode != TM_ENUM) { - error (c2m_ctx, r->pos, "useless declaration"); + error (c2m_ctx, POS (r), "useless declaration"); } /* We have at least one enum constant according to the syntax. */ break; @@ -8600,14 +8744,14 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { case N_ST_ASSERT: { int ok_p; - op1 = NL_HEAD (r->ops); + op1 = NL_HEAD (r->u.ops); check (c2m_ctx, op1, r); e1 = op1->attr; t1 = e1->type; if (!e1->const_p) { - error (c2m_ctx, r->pos, "expression in static assertion is not constant"); + error (c2m_ctx, POS (r), "expression in static assertion is not constant"); } else if (!integer_type_p (t1)) { - error (c2m_ctx, r->pos, "expression in static assertion is not an integer"); + error (c2m_ctx, POS (r), "expression in static assertion is not an integer"); } else { if (signed_integer_type_p (t1)) ok_p = e1->u.i_val != 0; @@ -8615,17 +8759,18 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { ok_p = e1->u.u_val != 0; if (!ok_p) { assert (NL_NEXT (op1) != NULL && NL_NEXT (op1)->code == N_STR); - error (c2m_ctx, r->pos, "static assertion failed: \"%s\"", NL_NEXT (op1)->u.s.s); // ??? + error (c2m_ctx, POS (r), "static assertion failed: \"%s\"", + NL_NEXT (op1)->u.s.s); // ??? } } break; } case N_MEMBER: { struct type *type; - node_t specs = NL_HEAD (r->ops); + node_t specs = NL_HEAD (r->u.ops); node_t declarator = NL_NEXT (specs); node_t const_expr = NL_NEXT (declarator); - node_t unshared_specs = specs->code != N_SHARE ? specs : NL_HEAD (specs->ops); + node_t unshared_specs = specs->code != N_SHARE ? specs : NL_HEAD (specs->u.ops); struct decl_spec decl_spec = check_decl_spec (c2m_ctx, unshared_specs, r); create_decl (c2m_ctx, curr_scope, r, decl_spec, const_expr, NULL, FALSE); @@ -8636,59 +8781,59 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { check (c2m_ctx, const_expr, r); cexpr = const_expr->attr; if (cexpr != NULL) { - if (type->type_qual.atomic_p) error (c2m_ctx, const_expr->pos, "bit field with _Atomic"); + if (type->type_qual.atomic_p) error (c2m_ctx, POS (const_expr), "bit field with _Atomic"); if (!cexpr->const_p) { - error (c2m_ctx, const_expr->pos, "bit field is not a constant expr"); + error (c2m_ctx, POS (const_expr), "bit field is not a constant expr"); } else if (!integer_type_p (type) && (type->mode != TM_BASIC || type->u.basic_type != TP_BOOL)) { - error (c2m_ctx, const_expr->pos, + error (c2m_ctx, POS (const_expr), "bit field type should be _Bool, a signed integer, or an unsigned integer type"); } else if (!integer_type_p (cexpr->type) && (cexpr->type->mode != TM_BASIC || cexpr->type->u.basic_type != TP_BOOL)) { - error (c2m_ctx, const_expr->pos, "bit field width is not of an integer type"); + error (c2m_ctx, POS (const_expr), "bit field width is not of an integer type"); } else if (signed_integer_type_p (cexpr->type) && cexpr->u.i_val < 0) { - error (c2m_ctx, const_expr->pos, "bit field width is negative"); + error (c2m_ctx, POS (const_expr), "bit field width is negative"); } else if (cexpr->u.i_val == 0 && declarator->code == N_DECL) { - error (c2m_ctx, const_expr->pos, "zero bit field width for %s", - NL_HEAD (declarator->ops)->u.s.s); + error (c2m_ctx, POS (const_expr), "zero bit field width for %s", + NL_HEAD (declarator->u.ops)->u.s.s); } else if ((!signed_integer_type_p (cexpr->type) && cexpr->u.u_val > int_bit_size (type)) || (signed_integer_type_p (cexpr->type) && cexpr->u.i_val > int_bit_size (type))) { - error (c2m_ctx, const_expr->pos, "bit field width exceeds its type"); + error (c2m_ctx, POS (const_expr), "bit field width exceeds its type"); } } } if (declarator->code == N_IGNORE) { if (((decl_spec.type->mode != TM_STRUCT && decl_spec.type->mode != TM_UNION) - || NL_HEAD (decl_spec.type->u.tag_type->ops)->code != N_IGNORE) + || NL_HEAD (decl_spec.type->u.tag_type->u.ops)->code != N_IGNORE) && const_expr->code == N_IGNORE) - error (c2m_ctx, r->pos, "no declarator in struct or union declaration"); + error (c2m_ctx, POS (r), "no declarator in struct or union declaration"); } else { - node_t id = NL_HEAD (declarator->ops); + node_t id = NL_HEAD (declarator->u.ops); if (type->mode == TM_FUNC) { - error (c2m_ctx, id->pos, "field %s is declared as a function", id->u.s.s); + error (c2m_ctx, POS (id), "field %s is declared as a function", id->u.s.s); } else if (incomplete_type_p (c2m_ctx, type)) { /* el_type is checked on completness in N_ARR */ if (type->mode != TM_ARR || type->u.arr_type->size->code != N_IGNORE) - error (c2m_ctx, id->pos, "field %s has incomplete type", id->u.s.s); + error (c2m_ctx, POS (id), "field %s has incomplete type", id->u.s.s); } } break; } case N_INIT: { - node_t des_list = NL_HEAD (r->ops), initializer = NL_NEXT (des_list); + node_t des_list = NL_HEAD (r->u.ops), initializer = NL_NEXT (des_list); check (c2m_ctx, des_list, r); check (c2m_ctx, initializer, r); break; } case N_FUNC_DEF: { - node_t specs = NL_HEAD (r->ops); + node_t specs = NL_HEAD (r->u.ops); node_t declarator = NL_NEXT (specs); node_t declarations = NL_NEXT (declarator); node_t block = NL_NEXT (declarations); - node_t id = NL_HEAD (declarator->ops); + node_t id = NL_HEAD (declarator->u.ops); struct decl_spec decl_spec = check_decl_spec (c2m_ctx, specs, r); node_t decl_node, p, next_p, param_list, param_id, param_declarator, func; symbol_t sym; @@ -8696,7 +8841,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if (strcmp (id->u.s.s, ALLOCA) == 0 || strcmp (id->u.s.s, BUILTIN_VA_START) == 0 || strcmp (id->u.s.s, BUILTIN_VA_ARG) == 0) { - error (c2m_ctx, id->pos, "%s is a builtin function", id->u.s.s); + error (c2m_ctx, POS (id), "%s is a builtin function", id->u.s.s); break; } curr_func_scope_num = 0; @@ -8711,27 +8856,27 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { check (c2m_ctx, declarations, r); /* Process parameter identifier list: */ assert (declarator->code == N_DECL); - func = NL_HEAD (NL_EL (declarator->ops, 1)->ops); + func = NL_HEAD (NL_EL (declarator->u.ops, 1)->u.ops); assert (func != NULL && func->code == N_FUNC); - param_list = NL_HEAD (func->ops); - for (p = NL_HEAD (param_list->ops); p != NULL; p = next_p) { + param_list = NL_HEAD (func->u.ops); + for (p = NL_HEAD (param_list->u.ops); p != NULL; p = next_p) { next_p = NL_NEXT (p); if (p->code != N_ID) break; - NL_REMOVE (param_list->ops, p); + NL_REMOVE (param_list->u.ops, p); if (!symbol_find (c2m_ctx, S_REGULAR, p, curr_scope, &sym)) { if (c2m_options->pedantic_p) { - error (c2m_ctx, p->pos, "parameter %s has no type", p->u.s.s); + error (c2m_ctx, POS (p), "parameter %s has no type", p->u.s.s); } else { - warning (c2m_ctx, p->pos, "type of parameter %s defaults to int", p->u.s.s); - decl_node = new_pos_node3 (c2m_ctx, N_SPEC_DECL, p->pos, + warning (c2m_ctx, POS (p), "type of parameter %s defaults to int", p->u.s.s); + decl_node = new_pos_node3 (c2m_ctx, N_SPEC_DECL, POS (p), new_node1 (c2m_ctx, N_SHARE, new_node1 (c2m_ctx, N_LIST, - new_pos_node (c2m_ctx, N_INT, p->pos))), - new_pos_node2 (c2m_ctx, N_DECL, p->pos, - new_str_node (c2m_ctx, N_ID, p->u.s, p->pos), + new_pos_node (c2m_ctx, N_INT, POS (p)))), + new_pos_node2 (c2m_ctx, N_DECL, POS (p), + new_str_node (c2m_ctx, N_ID, p->u.s, POS (p)), new_node (c2m_ctx, N_LIST)), new_node (c2m_ctx, N_IGNORE)); - NL_APPEND (param_list->ops, decl_node); + NL_APPEND (param_list->u.ops, decl_node); check (c2m_ctx, decl_node, r); } } else { @@ -8739,33 +8884,33 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { decl_node = sym.def_node; assert (decl_node->code == N_SPEC_DECL); - NL_REMOVE (declarations->ops, decl_node); - NL_APPEND (param_list->ops, decl_node); - param_declarator = NL_EL (decl_node->ops, 1); + NL_REMOVE (declarations->u.ops, decl_node); + NL_APPEND (param_list->u.ops, decl_node); + param_declarator = NL_EL (decl_node->u.ops, 1); assert (param_declarator->code == N_DECL); - param_id = NL_HEAD (param_declarator->ops); + param_id = NL_HEAD (param_declarator->u.ops); if (NL_NEXT (param_declarator)->code != N_IGNORE) { - error (c2m_ctx, p->pos, "initialized parameter %s", param_id->u.s.s); + error (c2m_ctx, POS (p), "initialized parameter %s", param_id->u.s.s); } decl_spec_ptr = &((decl_t) decl_node->attr)->decl_spec; adjust_param_type (c2m_ctx, &decl_spec_ptr->type); decl_spec = *decl_spec_ptr; if (decl_spec.typedef_p || decl_spec.extern_p || decl_spec.static_p || decl_spec.auto_p || decl_spec.thread_local_p) { - error (c2m_ctx, param_id->pos, "storage specifier in a function parameter %s", + error (c2m_ctx, POS (param_id), "storage specifier in a function parameter %s", param_id->u.s.s); } } } /* Process the rest declarations: */ - for (p = NL_HEAD (declarations->ops); p != NULL; p = NL_NEXT (p)) { + for (p = NL_HEAD (declarations->u.ops); p != NULL; p = NL_NEXT (p)) { if (p->code == N_ST_ASSERT) continue; assert (p->code == N_SPEC_DECL); - param_declarator = NL_EL (p->ops, 1); + param_declarator = NL_EL (p->u.ops, 1); assert (param_declarator->code == N_DECL); - param_id = NL_HEAD (param_declarator->ops); + param_id = NL_HEAD (param_declarator->u.ops); assert (param_id->code == N_ID); - error (c2m_ctx, param_id->pos, "declaration for parameter %s but no such parameter", + error (c2m_ctx, POS (param_id), "declaration for parameter %s but no such parameter", param_id->u.s.s); } add__func__def (c2m_ctx, block, id->u.s); @@ -8774,10 +8919,10 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { for (size_t i = 0; i < VARR_LENGTH (node_t, gotos); i++) { symbol_t sym; node_t n = VARR_GET (node_t, gotos, i); - node_t id = NL_NEXT (NL_HEAD (n->ops)); + node_t id = NL_NEXT (NL_HEAD (n->u.ops)); if (!symbol_find (c2m_ctx, S_LABEL, id, func_block_scope, &sym)) { - error (c2m_ctx, id->pos, "undefined label %s", id->u.s.s); + error (c2m_ctx, POS (id), "undefined label %s", id->u.s.s); } else { n->attr = sym.def_node; } @@ -8794,12 +8939,12 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } case N_TYPE: { struct type *type; - node_t specs = NL_HEAD (r->ops); + node_t specs = NL_HEAD (r->u.ops); node_t abstract_declarator = NL_NEXT (specs); struct decl_spec decl_spec = check_decl_spec (c2m_ctx, specs, r); /* only spec_qual_list here */ type = check_declarator (c2m_ctx, abstract_declarator, FALSE); - assert (NL_HEAD (abstract_declarator->ops)->code == N_IGNORE); + assert (NL_HEAD (abstract_declarator->u.ops)->code == N_IGNORE); decl_spec.type = append_type (type, decl_spec.type); if (context && context->code == N_COMPOUND_LITERAL) { r->attr = reg_malloc (c2m_ctx, sizeof (struct decl)); @@ -8818,20 +8963,20 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { break; } case N_BLOCK: - check_labels (c2m_ctx, NL_HEAD (r->ops), r); + check_labels (c2m_ctx, NL_HEAD (r->u.ops), r); if (curr_scope != r) create_node_scope (c2m_ctx, r); /* it happens if it is the top func block */ - check (c2m_ctx, NL_EL (r->ops, 1), r); + check (c2m_ctx, NL_EL (r->u.ops, 1), r); finish_scope (c2m_ctx); break; case N_MODULE: create_node_scope (c2m_ctx, r); top_scope = curr_scope; - check (c2m_ctx, NL_HEAD (r->ops), r); + check (c2m_ctx, NL_HEAD (r->u.ops), r); finish_scope (c2m_ctx); break; case N_IF: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t expr = NL_NEXT (labels); node_t if_stmt = NL_NEXT (expr); node_t else_stmt = NL_NEXT (if_stmt); @@ -8841,7 +8986,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e1 = expr->attr; t1 = e1->type; if (!scalar_type_p (t1)) { - error (c2m_ctx, expr->pos, "if-expr should be of a scalar type"); + error (c2m_ctx, POS (expr), "if-expr should be of a scalar type"); } check (c2m_ctx, if_stmt, r); check (c2m_ctx, else_stmt, r); @@ -8850,7 +8995,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { case N_SWITCH: { node_t saved_switch = curr_switch; node_t saved_loop_switch = curr_loop_switch; - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t expr = NL_NEXT (labels); node_t stmt = NL_NEXT (expr); struct type t, *type; @@ -8867,7 +9012,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { init_type (&t); t.mode = TM_BASIC; t.u.basic_type = TP_INT; - error (c2m_ctx, expr->pos, "switch-expr is of non-integer type"); + error (c2m_ctx, POS (expr), "switch-expr is of non-integer type"); } else { t = integer_promotion (type); } @@ -8881,9 +9026,9 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { check (c2m_ctx, stmt, r); for (case_t c = DLIST_HEAD (case_t, switch_attr->case_labels); c != NULL; c = DLIST_NEXT (case_t, c)) { /* process simple cases */ - if (c->case_node->code == N_DEFAULT || NL_EL (c->case_node->ops, 1) != NULL) continue; + if (c->case_node->code == N_DEFAULT || NL_EL (c->case_node->u.ops, 1) != NULL) continue; if (HTAB_DO (case_t, case_tab, c, HTAB_FIND, el)) { - error (c2m_ctx, c->case_node->pos, "duplicate case value"); + error (c2m_ctx, POS (c->case_node), "duplicate case value"); continue; } HTAB_DO (case_t, case_tab, c, HTAB_INSERT, el); @@ -8891,11 +9036,11 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { switch_attr->min_val_case = switch_attr->max_val_case = c; continue; } - e = NL_HEAD (c->case_node->ops)->attr; - e2 = NL_HEAD (switch_attr->min_val_case->case_node->ops)->attr; + e = NL_HEAD (c->case_node->u.ops)->attr; + e2 = NL_HEAD (switch_attr->min_val_case->case_node->u.ops)->attr; if (signed_p ? e->u.i_val < e2->u.i_val : e->u.u_val < e2->u.u_val) switch_attr->min_val_case = c; - e2 = NL_HEAD (switch_attr->max_val_case->case_node->ops)->attr; + e2 = NL_HEAD (switch_attr->max_val_case->case_node->u.ops)->attr; if (signed_p ? e->u.i_val > e2->u.i_val : e->u.u_val > e2->u.u_val) switch_attr->max_val_case = c; } @@ -8903,10 +9048,10 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { /* Check range cases against *all* simple cases or range cases *before* it. */ for (case_t c = DLIST_HEAD (case_t, switch_attr->case_labels); c != NULL; c = DLIST_NEXT (case_t, c)) { - if (c->case_node->code == N_DEFAULT || (case_expr2 = NL_EL (c->case_node->ops, 1)) == NULL) + if (c->case_node->code == N_DEFAULT || (case_expr2 = NL_EL (c->case_node->u.ops, 1)) == NULL) continue; switch_attr->ranges_p = TRUE; - case_expr = NL_HEAD (c->case_node->ops); + case_expr = NL_HEAD (c->case_node->u.ops); e = case_expr->attr; e2 = case_expr2->attr; skip_range_p = FALSE; @@ -8917,8 +9062,8 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { skip_range_p = TRUE; continue; } - another_case_expr = NL_HEAD (c2->case_node->ops); - another_case_expr2 = NL_EL (c2->case_node->ops, 1); + another_case_expr = NL_HEAD (c2->case_node->u.ops); + another_case_expr2 = NL_EL (c2->case_node->u.ops, 1); if (skip_range_p && another_case_expr2 != NULL) continue; another_e = another_case_expr->attr; assert (another_e->const_p && integer_type_p (another_e->type)); @@ -8926,7 +9071,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { if ((signed_p && e->u.i_val <= another_e->u.i_val && another_e->u.i_val <= e2->u.i_val) || (!signed_p && e->u.u_val <= another_e->u.u_val && another_e->u.u_val <= e2->u.u_val)) { - error (c2m_ctx, c->case_node->pos, "duplicate value in a range case"); + error (c2m_ctx, POS (c->case_node), "duplicate value in a range case"); break; } } else { @@ -8939,7 +9084,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { && ((e->u.u_val <= another_e->u.u_val && another_e->u.u_val <= e2->u.u_val) || (e->u.u_val <= another_e2->u.u_val && another_e2->u.u_val <= e2->u.u_val)))) { - error (c2m_ctx, c->case_node->pos, "duplicate value in a range case"); + error (c2m_ctx, POS (c->case_node), "duplicate value in a range case"); break; } } @@ -8951,7 +9096,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } case N_DO: case N_WHILE: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t expr = NL_NEXT (labels); node_t stmt = NL_NEXT (expr); node_t saved_loop = curr_loop; @@ -8962,7 +9107,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e1 = expr->attr; t1 = e1->type; if (!scalar_type_p (t1)) { - error (c2m_ctx, expr->pos, "while-expr should be of a scalar type"); + error (c2m_ctx, POS (expr), "while-expr should be of a scalar type"); } curr_loop = curr_loop_switch = r; check (c2m_ctx, stmt, r); @@ -8971,7 +9116,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { break; } case N_FOR: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t init = NL_NEXT (labels); node_t cond = NL_NEXT (init); node_t iter = NL_NEXT (cond); @@ -8985,13 +9130,13 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { curr_loop = curr_loop_switch = r; check (c2m_ctx, init, r); if (init->code == N_LIST) { - for (node_t spec_decl = NL_HEAD (init->ops); spec_decl != NULL; + for (node_t spec_decl = NL_HEAD (init->u.ops); spec_decl != NULL; spec_decl = NL_NEXT (spec_decl)) { assert (spec_decl->code == N_SPEC_DECL); decl = spec_decl->attr; if (decl->decl_spec.typedef_p || decl->decl_spec.extern_p || decl->decl_spec.static_p || decl->decl_spec.thread_local_p) { - error (c2m_ctx, spec_decl->pos, + error (c2m_ctx, POS (spec_decl), "wrong storage specifier of for-loop initial declaration"); break; } @@ -9002,7 +9147,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { e1 = cond->attr; t1 = e1->type; if (!scalar_type_p (t1)) { - error (c2m_ctx, cond->pos, "for-condition should be of a scalar type"); + error (c2m_ctx, POS (cond), "for-condition should be of a scalar type"); } } check (c2m_ctx, iter, r); @@ -9013,7 +9158,7 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { break; } case N_GOTO: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); check_labels (c2m_ctx, labels, r); VARR_PUSH (node_t, gotos, r); @@ -9021,18 +9166,18 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { } case N_CONTINUE: case N_BREAK: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); if (r->code == N_BREAK && curr_loop_switch == NULL) { - error (c2m_ctx, r->pos, "break statement not within loop or switch"); + error (c2m_ctx, POS (r), "break statement not within loop or switch"); } else if (r->code == N_CONTINUE && curr_loop == NULL) { - error (c2m_ctx, r->pos, "continue statement not within a loop"); + error (c2m_ctx, POS (r), "continue statement not within a loop"); } check_labels (c2m_ctx, labels, r); break; } case N_RETURN: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t expr = NL_NEXT (labels); decl_t decl = curr_func_def->attr; struct type *ret_type, *type = decl->decl_spec.type; @@ -9042,17 +9187,17 @@ static void check (c2m_ctx_t c2m_ctx, node_t r, node_t context) { check (c2m_ctx, expr, r); ret_type = type->u.func_type->ret_type; if (expr->code != N_IGNORE && void_type_p (ret_type)) { - error (c2m_ctx, r->pos, "return with a value in function returning void"); + error (c2m_ctx, POS (r), "return with a value in function returning void"); } else if (expr->code == N_IGNORE && (ret_type->mode != TM_BASIC || ret_type->u.basic_type != TP_VOID)) { - error (c2m_ctx, r->pos, "return with no value in function returning non-void"); + error (c2m_ctx, POS (r), "return with no value in function returning non-void"); } else if (expr->code != N_IGNORE) { check_assignment_types (c2m_ctx, ret_type, NULL, expr->attr, r); } break; } case N_EXPR: { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); node_t expr = NL_NEXT (labels); check_labels (c2m_ctx, labels, r); @@ -9094,7 +9239,9 @@ static void do_context (c2m_ctx_t c2m_ctx, node_t r) { } static void context_init (c2m_ctx_t c2m_ctx) { - c2m_ctx->check_ctx = c2mir_calloc (c2m_ctx, sizeof (struct check_ctx)); + check_ctx_t check_ctx; + + c2m_ctx->check_ctx = check_ctx = c2mir_calloc (c2m_ctx, sizeof (struct check_ctx)); n_i1_node = new_i_node (c2m_ctx, 1, no_pos); VARR_CREATE (node_t, context_stack, 64); check (c2m_ctx, n_i1_node, NULL); @@ -9108,7 +9255,9 @@ static void context_init (c2m_ctx_t c2m_ctx) { } static void context_finish (c2m_ctx_t c2m_ctx) { - if (c2m_ctx == NULL || c2m_ctx->check_ctx == NULL) return; + check_ctx_t check_ctx; + + if (c2m_ctx == NULL || (check_ctx = c2m_ctx->check_ctx) == NULL) return; if (context_stack != NULL) VARR_DESTROY (node_t, context_stack); if (gotos != NULL) VARR_DESTROY (node_t, gotos); symbol_finish (c2m_ctx); @@ -9192,26 +9341,26 @@ struct gen_ctx { HTAB (MIR_item_t) * proto_tab; }; -#define zero_op c2m_ctx->gen_ctx->zero_op -#define one_op c2m_ctx->gen_ctx->one_op -#define minus_one_op c2m_ctx->gen_ctx->minus_one_op -#define curr_func c2m_ctx->gen_ctx->curr_func -#define reg_var_tab c2m_ctx->gen_ctx->reg_var_tab -#define reg_free_mark c2m_ctx->gen_ctx->reg_free_mark -#define continue_label c2m_ctx->gen_ctx->continue_label -#define break_label c2m_ctx->gen_ctx->break_label -#define proto_info c2m_ctx->gen_ctx->proto_info -#define init_els c2m_ctx->gen_ctx->init_els -#define memset_proto c2m_ctx->gen_ctx->memset_proto -#define memset_item c2m_ctx->gen_ctx->memset_item -#define memcpy_proto c2m_ctx->gen_ctx->memcpy_proto -#define memcpy_item c2m_ctx->gen_ctx->memcpy_item -#define call_ops c2m_ctx->gen_ctx->call_ops -#define ret_ops c2m_ctx->gen_ctx->ret_ops -#define switch_ops c2m_ctx->gen_ctx->switch_ops -#define switch_cases c2m_ctx->gen_ctx->switch_cases -#define curr_mir_proto_num c2m_ctx->gen_ctx->curr_mir_proto_num -#define proto_tab c2m_ctx->gen_ctx->proto_tab +#define zero_op gen_ctx->zero_op +#define one_op gen_ctx->one_op +#define minus_one_op gen_ctx->minus_one_op +#define curr_func gen_ctx->curr_func +#define reg_var_tab gen_ctx->reg_var_tab +#define reg_free_mark gen_ctx->reg_free_mark +#define continue_label gen_ctx->continue_label +#define break_label gen_ctx->break_label +#define proto_info gen_ctx->proto_info +#define init_els gen_ctx->init_els +#define memset_proto gen_ctx->memset_proto +#define memset_item gen_ctx->memset_item +#define memcpy_proto gen_ctx->memcpy_proto +#define memcpy_item gen_ctx->memcpy_item +#define call_ops gen_ctx->call_ops +#define ret_ops gen_ctx->ret_ops +#define switch_ops gen_ctx->switch_ops +#define switch_cases gen_ctx->switch_cases +#define curr_mir_proto_num gen_ctx->curr_mir_proto_num +#define proto_tab gen_ctx->proto_tab static op_t new_op (decl_t decl, MIR_op_t mir_op) { op_t res; @@ -9229,20 +9378,27 @@ static int reg_var_eq (reg_var_t r1, reg_var_t r2, void *arg) { } static void init_reg_vars (c2m_ctx_t c2m_ctx) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + reg_free_mark = 0; HTAB_CREATE (reg_var_t, reg_var_tab, 128, reg_var_hash, reg_var_eq, NULL); } static void finish_curr_func_reg_vars (c2m_ctx_t c2m_ctx) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + reg_free_mark = 0; HTAB_CLEAR (reg_var_t, reg_var_tab); } static void finish_reg_vars (c2m_ctx_t c2m_ctx) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + if (reg_var_tab != NULL) HTAB_DESTROY (reg_var_t, reg_var_tab); } static reg_var_t get_reg_var (c2m_ctx_t c2m_ctx, MIR_type_t t, const char *reg_name) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; reg_var_t reg_var, el; char *str; @@ -9262,12 +9418,14 @@ static reg_var_t get_reg_var (c2m_ctx_t c2m_ctx, MIR_type_t t, const char *reg_n } static int temp_reg_p (c2m_ctx_t c2m_ctx, MIR_op_t op) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; return op.mode == MIR_OP_REG && MIR_reg_name (ctx, op.u.reg, curr_func->u.func)[1] == '_'; } static MIR_type_t reg_type (c2m_ctx_t c2m_ctx, MIR_reg_t reg) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; const char *n = MIR_reg_name (ctx, reg, curr_func->u.func); MIR_type_t res; @@ -9288,6 +9446,7 @@ static MIR_type_t reg_type (c2m_ctx_t c2m_ctx, MIR_reg_t reg) { } static op_t get_new_temp (c2m_ctx_t c2m_ctx, MIR_type_t t) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; char reg_name[50]; MIR_reg_t reg; @@ -9380,12 +9539,15 @@ static MIR_insn_code_t tp_mov (MIR_type_t t) { } static void emit_insn (c2m_ctx_t c2m_ctx, MIR_insn_t insn) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + MIR_append_insn (c2m_ctx->ctx, curr_func, insn); } /* BCOND T, L1; JMP L2; L1: => BNCOND T, L2; L1: JMP L; L: => L: */ static void emit_label_insn_opt (c2m_ctx_t c2m_ctx, MIR_insn_t insn) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_insn_code_t rev_code; MIR_insn_t last, prev; @@ -9408,6 +9570,7 @@ static void emit_label_insn_opt (c2m_ctx_t c2m_ctx, MIR_insn_t insn) { /* Change t1 = expr; v = t1 to v = expr */ static void emit_insn_opt (c2m_ctx_t c2m_ctx, MIR_insn_t insn) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_insn_t tail; int out_p; @@ -9712,7 +9875,7 @@ static void gen_unary_op (c2m_ctx_t c2m_ctx, node_t r, op_t *op, op_t *res) { MIR_type_t t; assert (!((struct expr *) r->attr)->const_p); - *op = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, TRUE, NULL); + *op = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, TRUE, NULL); t = get_mir_type (c2m_ctx, ((struct expr *) r->attr)->type); *op = promote (c2m_ctx, *op, t, FALSE); *res = get_new_temp (c2m_ctx, t); @@ -9721,7 +9884,7 @@ static void gen_unary_op (c2m_ctx_t c2m_ctx, node_t r, op_t *op, op_t *res) { static void gen_assign_bin_op (c2m_ctx_t c2m_ctx, node_t r, struct type *assign_expr_type, op_t *op1, op_t *op2, op_t *var) { MIR_type_t t; - node_t e = NL_HEAD (r->ops); + node_t e = NL_HEAD (r->u.ops); assert (!((struct expr *) r->attr)->const_p); t = get_mir_type (c2m_ctx, assign_expr_type); @@ -9738,8 +9901,8 @@ static void gen_bin_op (c2m_ctx_t c2m_ctx, node_t r, op_t *op1, op_t *op2, op_t MIR_type_t t = get_mir_type (c2m_ctx, e->type); assert (!e->const_p); - *op1 = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, TRUE, NULL); - *op2 = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, TRUE, NULL); + *op1 = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, TRUE, NULL); + *op2 = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, TRUE, NULL); *op1 = promote (c2m_ctx, *op1, t, FALSE); *op2 = promote (c2m_ctx, *op2, t, FALSE); *res = get_new_temp (c2m_ctx, t); @@ -9750,8 +9913,8 @@ static void gen_cmp_op (c2m_ctx_t c2m_ctx, node_t r, struct type *type, op_t *op MIR_type_t t = get_mir_type (c2m_ctx, type), res_t = get_int_mir_type (sizeof (mir_int)); assert (!((struct expr *) r->attr)->const_p); - *op1 = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, TRUE, NULL); - *op2 = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, TRUE, NULL); + *op1 = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, TRUE, NULL); + *op2 = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, TRUE, NULL); *op1 = promote (c2m_ctx, *op1, t, FALSE); *op2 = promote (c2m_ctx, *op2, t, FALSE); *res = get_new_temp (c2m_ctx, res_t); @@ -9913,18 +10076,18 @@ static op_t force_reg_or_mem (c2m_ctx_t c2m_ctx, op_t op, MIR_type_t t) { } static void emit_label (c2m_ctx_t c2m_ctx, node_t r) { - node_t labels = NL_HEAD (r->ops); + node_t labels = NL_HEAD (r->u.ops); assert (labels->code == N_LIST); - if (NL_HEAD (labels->ops) == NULL) return; + if (NL_HEAD (labels->u.ops) == NULL) return; if (labels->attr == NULL) labels->attr = MIR_new_label (c2m_ctx->ctx); emit_label_insn_opt (c2m_ctx, labels->attr); } static MIR_label_t get_label (c2m_ctx_t c2m_ctx, node_t target) { - node_t labels = NL_HEAD (target->ops); + node_t labels = NL_HEAD (target->u.ops); - assert (labels->code == N_LIST && NL_HEAD (labels->ops) != NULL); + assert (labels->code == N_LIST && NL_HEAD (labels->u.ops) != NULL); if (labels->attr != NULL) return labels->attr; return labels->attr = MIR_new_label (c2m_ctx->ctx); } @@ -9961,6 +10124,7 @@ static void gen_memcpy (c2m_ctx_t c2m_ctx, MIR_disp_t disp, MIR_reg_t base, op_t mir_size_t len); static void block_move (c2m_ctx_t c2m_ctx, op_t var, op_t val, mir_size_t size) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_label_t repeat_label; op_t index; @@ -10008,6 +10172,8 @@ static const char *get_reg_var_name (c2m_ctx_t c2m_ctx, MIR_type_t promoted_type } static const char *get_func_var_name (c2m_ctx_t c2m_ctx, const char *prefix, const char *suffix) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + assert (curr_func != NULL); VARR_TRUNC (char, temp_string, 0); add_to_temp_string (c2m_ctx, prefix); @@ -10041,6 +10207,7 @@ static int simple_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) { static void MIR_UNUSED simple_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, void *arg_info, VARR (MIR_type_t) * res_types, VARR (MIR_var_t) * arg_vars) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_var_t var; if (void_type_p (ret_type)) return; @@ -10056,6 +10223,7 @@ static void MIR_UNUSED simple_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret static int MIR_UNUSED simple_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, void *arg_info, size_t call_arg_area_offset) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; op_t temp; @@ -10084,6 +10252,7 @@ static op_t MIR_UNUSED simple_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct } static void MIR_UNUSED simple_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t val) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_reg_t ret_addr_reg; op_t var; @@ -10115,6 +10284,7 @@ static void MIR_UNUSED simple_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name static void MIR_UNUSED simple_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, void *arg_info, op_t arg) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_type_t type; type = (arg_type->mode == TM_STRUCT || arg_type->mode == TM_UNION @@ -10152,6 +10322,7 @@ 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) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_op_t op, var_op; MIR_insn_t insn; @@ -10247,6 +10418,8 @@ static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, address offset on the stack. */ static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, target_arg_info_t *arg_info, size_t call_arg_area_offset) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + return simple_add_call_res_op (c2m_ctx, ret_type, arg_info, call_arg_area_offset); } /* Generate code to gather returned values of CALL into RES. Return @@ -10254,15 +10427,21 @@ static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, operands in call_ops for given call. */ static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res, MIR_insn_t call, size_t call_ops_start) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + return simple_gen_post_call_res_code (c2m_ctx, ret_type, res, call, call_ops_start); } /* Generate code and add operands to ret_ops which return VAL of RET_TYPE. */ static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t val) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + simple_add_ret_ops (c2m_ctx, ret_type, val); } /* 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) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + simple_add_arg_proto (c2m_ctx, name, arg_type, arg_info, arg_vars); } /* Add operands to call_ops which pass ARG of ARG_TYPE. */ @@ -10274,18 +10453,21 @@ static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, Return true if it was the case. */ static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, decl_t param_decl, target_arg_info_t *arg_info) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + return simple_gen_gather_arg (c2m_ctx, name, arg_type, param_decl, arg_info); } #endif static void collect_args_and_func_types (c2m_ctx_t c2m_ctx, struct func_type *func_type) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; node_t declarator, id, first_param, p; struct type *param_type; decl_t param_decl; const char *name; target_arg_info_t arg_info; - first_param = NL_HEAD (func_type->param_list->ops); + first_param = NL_HEAD (func_type->param_list->u.ops); VARR_TRUNC (MIR_var_t, proto_info.arg_vars, 0); VARR_TRUNC (MIR_type_t, proto_info.ret_types, 0); proto_info.res_ref_p = FALSE; @@ -10300,9 +10482,9 @@ static void collect_args_and_func_types (c2m_ctx_t c2m_ctx, struct func_type *fu param_type = ((struct decl_spec *) p->attr)->type; param_decl = NULL; } else { - declarator = NL_EL (p->ops, 1); + declarator = NL_EL (p->u.ops, 1); assert (p->code == N_SPEC_DECL && declarator != NULL && declarator->code == N_DECL); - id = NL_HEAD (declarator->ops); + id = NL_HEAD (declarator->u.ops); param_decl = p->attr; param_type = param_decl->decl_spec.type; name = get_param_name (c2m_ctx, param_type, id->u.s.s); @@ -10336,6 +10518,7 @@ static mir_size_t get_object_path_offset (c2m_ctx_t c2m_ctx) { /* The function has the same structure as check_initializer. Keep it this way. */ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type **type_ptr, node_t initializer, int const_only_p, int top_p) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; struct type *type = *type_ptr; struct expr *cexpr; node_t literal, des_list, curr_des, str, init, value, size_node; @@ -10350,7 +10533,7 @@ static void collect_init_els (c2m_ctx_t c2m_ctx, decl_t member_decl, struct type literal = get_compound_literal (initializer, &addr_p); if (literal != NULL && !addr_p && initializer->code != N_STR) - initializer = NL_EL (literal->ops, 1); + initializer = NL_EL (literal->u.ops, 1); check_one_value: if (initializer->code != N_LIST && !(initializer->code == N_STR && type->mode == TM_ARR @@ -10367,11 +10550,12 @@ check_one_value: VARR_PUSH (init_el_t, init_els, init_el); return; } - init = NL_HEAD (initializer->ops); + init = NL_HEAD (initializer->u.ops); if (((str = initializer)->code == N_STR /* string or string in parentheses */ - || (init != NULL && init->code == N_INIT && NL_EL (initializer->ops, 1) == NULL - && (des_list = NL_HEAD (init->ops))->code == N_LIST && NL_HEAD (des_list->ops) == NULL - && NL_EL (init->ops, 1) != NULL && (str = NL_EL (init->ops, 1))->code == N_STR)) + || (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)) { init_el.num = VARR_LENGTH (init_el_t, init_els); init_el.offset = get_object_path_offset (c2m_ctx); @@ -10383,10 +10567,10 @@ check_one_value: } if (init == NULL) return; assert (init->code == N_INIT); - des_list = NL_HEAD (init->ops); + des_list = NL_HEAD (init->u.ops); assert (des_list->code == N_LIST); if (type->mode != TM_ARR && type->mode != TM_STRUCT && type->mode != TM_UNION) { - assert (NL_NEXT (init) == NULL && NL_HEAD (des_list->ops) == NULL); + assert (NL_NEXT (init) == NULL && NL_HEAD (des_list->u.ops) == NULL); initializer = NL_NEXT (des_list); assert (top_p); top_p = FALSE; @@ -10408,20 +10592,20 @@ check_one_value: VARR_PUSH (init_object_t, init_object_path, init_object); for (; init != NULL; init = NL_NEXT (init)) { assert (init->code == N_INIT); - des_list = NL_HEAD (init->ops); + des_list = NL_HEAD (init->u.ops); value = NL_NEXT (des_list); assert ((value->code != N_LIST && value->code != N_COMPOUND_LITERAL) || type->mode == TM_ARR || type->mode == TM_STRUCT || type->mode == TM_UNION); - if ((curr_des = NL_HEAD (des_list->ops)) == NULL) { + if ((curr_des = NL_HEAD (des_list->u.ops)) == NULL) { ok_p = update_path_and_do (c2m_ctx, collect_init_els, mark, value, const_only_p, NULL, - init->pos, ""); + POS (init), ""); assert (ok_p); } else { for (; curr_des != NULL; curr_des = NL_NEXT (curr_des)) { VARR_TRUNC (init_object_t, init_object_path, mark + 1); init_object = VARR_POP (init_object_t, init_object_path); if (curr_des->code == N_FIELD_ID) { - node_t id = NL_HEAD (curr_des->ops); + node_t id = NL_HEAD (curr_des->u.ops); /* field should be only in struct/union initializer */ assert (type->mode == TM_STRUCT || type->mode == TM_UNION); @@ -10429,7 +10613,7 @@ check_one_value: assert (found_p); /* field should present */ process_init_field_designator (c2m_ctx, sym.def_node, init_object.container_type); ok_p = update_path_and_do (c2m_ctx, collect_init_els, mark, value, const_only_p, NULL, - init->pos, ""); + POS (init), ""); assert (ok_p); } else { cexpr = curr_des->attr; @@ -10441,7 +10625,7 @@ check_one_value: init_object.designator_p = FALSE; VARR_PUSH (init_object_t, init_object_path, init_object); ok_p = update_path_and_do (c2m_ctx, collect_init_els, mark, value, const_only_p, NULL, - init->pos, ""); + POS (init), ""); assert (ok_p); } } @@ -10477,6 +10661,8 @@ static void move_item_to_module_start (MIR_module_t module, MIR_item_t item) { } static void move_item_forward (c2m_ctx_t c2m_ctx, MIR_item_t item) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + assert (curr_func != NULL); if (DLIST_TAIL (MIR_item_t, curr_func->module->items) != item) return; DLIST_REMOVE (MIR_item_t, curr_func->module->items, item); @@ -10484,6 +10670,7 @@ static void move_item_forward (c2m_ctx_t c2m_ctx, MIR_item_t item) { } static void gen_memset (c2m_ctx_t c2m_ctx, MIR_disp_t disp, MIR_reg_t base, mir_size_t len) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t ret_type; MIR_var_t vars[3]; @@ -10521,6 +10708,7 @@ static void gen_memset (c2m_ctx_t c2m_ctx, MIR_disp_t disp, MIR_reg_t base, mir_ static void gen_memcpy (c2m_ctx_t c2m_ctx, MIR_disp_t disp, MIR_reg_t base, op_t val, mir_size_t len) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t ret_type; MIR_var_t vars[3]; @@ -10643,6 +10831,7 @@ static void add_bit_field (c2m_ctx_t c2m_ctx, uint64_t *u, uint64_t v, decl_t me 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; MIR_context_t ctx = c2m_ctx->ctx; op_t val; size_t str_len; @@ -10819,7 +11008,7 @@ static MIR_item_t get_ref_item (c2m_ctx_t c2m_ctx, node_t def, const char *name) struct decl *decl = def->attr; if (def->code == N_FUNC_DEF - || (def->code == N_SPEC_DECL && NL_EL (def->ops, 1)->code == N_DECL + || (def->code == N_SPEC_DECL && NL_EL (def->u.ops, 1)->code == N_DECL && decl->scope == top_scope && decl->decl_spec.type->mode != TM_FUNC && !decl->decl_spec.typedef_p && !decl->decl_spec.extern_p)) return (decl->decl_spec.linkage == N_EXTERN ? MIR_new_export (ctx, name) @@ -10835,7 +11024,7 @@ static void emit_bin_op (c2m_ctx_t c2m_ctx, node_t r, struct type *type, op_t re if (type->mode == TM_PTR) { /* ptr +/- int */ assert (r->code == N_ADD || r->code == N_SUB || r->code == N_ADD_ASSIGN || r->code == N_SUB_ASSIGN); - if (((struct expr *) NL_HEAD (r->ops)->attr)->type->mode != TM_PTR) /* int + ptr */ + if (((struct expr *) NL_HEAD (r->u.ops)->attr)->type->mode != TM_PTR) /* int + ptr */ SWAP (op1, op2, temp); if (op2.mir_op.mode == MIR_OP_INT || op2.mir_op.mode == MIR_OP_UINT) { op2 = new_op (NULL, @@ -10849,7 +11038,8 @@ static void emit_bin_op (c2m_ctx_t c2m_ctx, node_t r, struct type *type, op_t re } emit3 (c2m_ctx, get_mir_type_insn_code (c2m_ctx, type, r), res.mir_op, op1.mir_op, op2.mir_op); if (type->mode != TM_PTR - && (type = ((struct expr *) NL_HEAD (r->ops)->attr)->type)->mode == TM_PTR) { /* ptr - ptr */ + && (type = ((struct expr *) NL_HEAD (r->u.ops)->attr)->type)->mode + == TM_PTR) { /* ptr - ptr */ assert (r->code == N_SUB || r->code == N_SUB_ASSIGN); emit3 (c2m_ctx, sizeof (mir_size_t) == 8 ? MIR_DIV : MIR_DIVS, res.mir_op, res.mir_op, MIR_new_int_op (ctx, type_size (c2m_ctx, type->u.ptr_type))); @@ -10858,8 +11048,8 @@ static void emit_bin_op (c2m_ctx_t c2m_ctx, node_t r, struct type *type, op_t re static int signed_case_compare (const void *v1, const void *v2) { case_t c1 = *(const case_t *) v1, c2 = *(const case_t *) v2; - struct expr *e1 = NL_HEAD (c1->case_node->ops)->attr; - struct expr *e2 = NL_HEAD (c2->case_node->ops)->attr; + struct expr *e1 = NL_HEAD (c1->case_node->u.ops)->attr; + struct expr *e2 = NL_HEAD (c2->case_node->u.ops)->attr; assert (e1->u.i_val != e2->u.i_val); return e1->u.i_val < e2->u.i_val ? -1 : 1; @@ -10867,8 +11057,8 @@ static int signed_case_compare (const void *v1, const void *v2) { static int unsigned_case_compare (const void *v1, const void *v2) { case_t c1 = *(const case_t *) v1, c2 = *(const case_t *) v2; - struct expr *e1 = NL_HEAD (c1->case_node->ops)->attr; - struct expr *e2 = NL_HEAD (c2->case_node->ops)->attr; + struct expr *e1 = NL_HEAD (c1->case_node->u.ops)->attr; + struct expr *e2 = NL_HEAD (c2->case_node->u.ops)->attr; assert (e1->u.u_val != e2->u.u_val); return e1->u.u_val < e2->u.u_val ? -1 : 1; @@ -10876,6 +11066,8 @@ static int unsigned_case_compare (const void *v1, const void *v2) { static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_t false_label, int val_p, op_t *desirable_dest) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; + check_ctx_t check_ctx = c2m_ctx->check_ctx; /* check and gen share curr_scope */ MIR_context_t ctx = c2m_ctx->ctx; op_t res, op1, op2, var, val; MIR_type_t t = MIR_T_UNDEF; /* to remove an uninitialized warning */ @@ -10897,7 +11089,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ goto finish; switch (r->code) { case N_LIST: - for (node_t n = NL_HEAD (r->ops); n != NULL; n = NL_NEXT (n)) + for (node_t n = NL_HEAD (r->u.ops); n != NULL; n = NL_NEXT (n)) gen (c2m_ctx, n, true_label, false_label, val_p, NULL); break; case N_IGNORE: break; /* do nothing */ @@ -10933,8 +11125,8 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ // and str in initializer break; case N_COMMA: - gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); - res = gen (c2m_ctx, NL_EL (r->ops, 1), true_label, false_label, TRUE, NULL); + gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); + res = gen (c2m_ctx, NL_EL (r->u.ops, 1), true_label, false_label, TRUE, NULL); break; case N_ANDAND: case N_OROR: @@ -10947,10 +11139,10 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ f_label = MIR_new_label (ctx); } assert (t_label != NULL && f_label != NULL); - gen (c2m_ctx, NL_HEAD (r->ops), r->code == N_ANDAND ? temp_label : t_label, + gen (c2m_ctx, NL_HEAD (r->u.ops), r->code == N_ANDAND ? temp_label : t_label, r->code == N_ANDAND ? f_label : temp_label, FALSE, NULL); emit_label_insn_opt (c2m_ctx, temp_label); - gen (c2m_ctx, NL_EL (r->ops, 1), t_label, f_label, FALSE, NULL); + gen (c2m_ctx, NL_EL (r->u.ops, 1), t_label, f_label, FALSE, NULL); if (make_val_p) { MIR_label_t end_label = MIR_new_label (ctx); @@ -10985,14 +11177,14 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; case N_NOT: if (true_label != NULL) { - gen (c2m_ctx, NL_HEAD (r->ops), false_label, true_label, FALSE, NULL); + gen (c2m_ctx, NL_HEAD (r->u.ops), false_label, true_label, FALSE, NULL); true_label = false_label = NULL; } else { MIR_label_t end_label = MIR_new_label (ctx); MIR_label_t t_label = MIR_new_label (ctx), f_label = MIR_new_label (ctx); res = get_new_temp (c2m_ctx, MIR_T_I64); - gen (c2m_ctx, NL_HEAD (r->ops), t_label, f_label, FALSE, NULL); + gen (c2m_ctx, NL_HEAD (r->u.ops), t_label, f_label, FALSE, NULL); emit_label_insn_opt (c2m_ctx, t_label); emit2 (c2m_ctx, MIR_MOV, res.mir_op, zero_op.mir_op); emit1 (c2m_ctx, MIR_JMP, MIR_new_label_op (ctx, end_label)); @@ -11003,7 +11195,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; case N_ADD: case N_SUB: - if (NL_NEXT (NL_HEAD (r->ops)) == NULL) { /* unary */ + if (NL_NEXT (NL_HEAD (r->u.ops)) == NULL) { /* unary */ MIR_insn_code_t ic = get_mir_insn_code (c2m_ctx, r); gen_unary_op (c2m_ctx, r, &op1, &res); @@ -11039,8 +11231,8 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_LE: case N_GT: case N_GE: { - struct type *type1 = ((struct expr *) NL_HEAD (r->ops)->attr)->type; - struct type *type2 = ((struct expr *) NL_EL (r->ops, 1)->attr)->type; + struct type *type1 = ((struct expr *) NL_HEAD (r->u.ops)->attr)->type; + struct type *type2 = ((struct expr *) NL_EL (r->u.ops, 1)->attr)->type; struct type type, ptr_type = get_ptr_int_type (FALSE); type = arithmetic_conversion (type1->mode == TM_PTR ? &ptr_type : type1, @@ -11063,7 +11255,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ struct type *type = ((struct expr *) r->attr)->type2; t = get_mir_type (c2m_ctx, type); - var = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); + var = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); op1 = force_val (c2m_ctx, var, FALSE); if (val_p || true_label != NULL) { res = get_new_temp (c2m_ctx, t); @@ -11084,7 +11276,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ struct type *type = ((struct expr *) r->attr)->type2; t = get_mir_type (c2m_ctx, type); - var = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); + var = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); val = promote (c2m_ctx, force_val (c2m_ctx, var, FALSE), t, TRUE); op2 = promote (c2m_ctx, type->mode != TM_PTR @@ -11114,9 +11306,9 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ goto assign; break; case N_ASSIGN: - var = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); + var = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); t = get_op_type (c2m_ctx, var); - op2 = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, t != MIR_T_UNDEF, + op2 = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, t != MIR_T_UNDEF, t != MIR_T_UNDEF ? NULL : &var); if ((!val_p && true_label == NULL) || t == MIR_T_UNDEF) { res = var; @@ -11171,13 +11363,13 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ } case N_IND: { MIR_type_t ind_t; - node_t arr = NL_HEAD (r->ops); + node_t arr = NL_HEAD (r->u.ops); mir_size_t size = type_size (c2m_ctx, ((struct expr *) r->attr)->type); t = get_mir_type (c2m_ctx, ((struct expr *) r->attr)->type); op1 = gen (c2m_ctx, arr, NULL, NULL, TRUE, NULL); - op2 = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, TRUE, NULL); - ind_t = get_mir_type (c2m_ctx, ((struct expr *) NL_EL (r->ops, 1)->attr)->type); + op2 = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, TRUE, NULL); + ind_t = get_mir_type (c2m_ctx, ((struct expr *) NL_EL (r->u.ops, 1)->attr)->type); op2 = force_reg (c2m_ctx, op2, ind_t); if (((struct expr *) arr->attr)->type->arr_type != NULL) { /* it was an array */ size = type_size (c2m_ctx, ((struct expr *) arr->attr)->type->arr_type->u.arr_type->el_type); @@ -11212,7 +11404,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_ADDR: { int add_p = FALSE; - op1 = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); + op1 = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); if (op1.mir_op.mode == MIR_OP_REG || op1.mir_op.mode == MIR_OP_REF || op1.mir_op.mode == MIR_OP_STR) { /* array or func */ res = op1; @@ -11245,7 +11437,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_DEREF: - op1 = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, TRUE, NULL); + op1 = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, TRUE, NULL); op1 = force_reg (c2m_ctx, op1, MIR_T_I64); assert (op1.mir_op.mode == MIR_OP_REG); if ((type = ((struct expr *) r->attr)->type)->mode == TM_PTR @@ -11265,7 +11457,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ def_node = e->lvalue_node; assert (def_node != NULL && def_node->code == N_MEMBER); decl = def_node->attr; - op1 = gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, r->code == N_DEREF_FIELD, NULL); + op1 = gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, r->code == N_DEREF_FIELD, NULL); t = get_mir_type (c2m_ctx, decl->decl_spec.type); if (r->code == N_FIELD) { assert (op1.mir_op.mode == MIR_OP_MEM); @@ -11281,7 +11473,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_COND: { - node_t cond = NL_HEAD (r->ops); + node_t cond = NL_HEAD (r->u.ops); node_t true_expr = NL_NEXT (cond); node_t false_expr = NL_NEXT (true_expr); MIR_label_t true_label = MIR_new_label (ctx), false_label = MIR_new_label (ctx); @@ -11333,7 +11525,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_CAST: assert (!((struct expr *) r->attr)->const_p); type = ((struct expr *) r->attr)->type; - op1 = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, !void_type_p (type), NULL); + op1 = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, !void_type_p (type), NULL); if (void_type_p (type)) { res = op1; res.decl = NULL; @@ -11346,7 +11538,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_COMPOUND_LITERAL: { const char *global_name = NULL; char buff[50]; - node_t type_name = NL_HEAD (r->ops); + node_t type_name = NL_HEAD (r->u.ops); decl_t decl = type_name->attr; struct expr *expr = r->attr; MIR_module_t module = DLIST_TAIL (MIR_module_t, *MIR_get_module_list (ctx)); @@ -11358,7 +11550,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ global_name = buff; } init_start = VARR_LENGTH (init_el_t, init_els); - collect_init_els (c2m_ctx, NULL, &decl->decl_spec.type, NL_EL (r->ops, 1), + collect_init_els (c2m_ctx, NULL, &decl->decl_spec.type, NL_EL (r->u.ops, 1), decl->scope == top_scope || decl->decl_spec.linkage == N_STATIC || decl->decl_spec.linkage == N_EXTERN || decl->decl_spec.static_p || decl->decl_spec.thread_local_p, @@ -11382,7 +11574,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_CALL: { - node_t func = NL_HEAD (r->ops), param_list, param, args = NL_EL (r->ops, 1); + node_t func = NL_HEAD (r->u.ops), param_list, param, args = NL_EL (r->u.ops, 1); struct decl_spec *decl_spec; size_t ops_start; struct expr *call_expr = r->attr, *func_expr; @@ -11395,7 +11587,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ int va_start_p = call_expr->builtin_call_p && strcmp (func->u.s.s, BUILTIN_VA_START) == 0; int alloca_p = call_expr->builtin_call_p && strcmp (func->u.s.s, ALLOCA) == 0; int builtin_call_p = alloca_p || va_arg_p || va_start_p, inline_p = FALSE; - node_t block = NL_EL (curr_func_def->ops, 3); + node_t block = NL_EL (curr_func_def->u.ops, 3); struct node_scope *ns = block->attr; target_arg_info_t arg_info; int n, struct_p; @@ -11440,7 +11632,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ saved_call_arg_area_offset_before_args = curr_call_arg_area_offset; if (va_arg_p) { op1 = get_new_temp (c2m_ctx, MIR_T_I64); - op2 = gen (c2m_ctx, NL_HEAD (args->ops), NULL, NULL, TRUE, NULL); + op2 = gen (c2m_ctx, NL_HEAD (args->u.ops), NULL, NULL, TRUE, NULL); if (op2.mir_op.mode == MIR_OP_MEM && op2.mir_op.u.mem.type == MIR_T_UNDEF) op2 = mem_to_address (c2m_ctx, op2, FALSE); if (type->mode == TM_STRUCT || type->mode == TM_UNION) { @@ -11464,22 +11656,22 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ res.mir_op.u.mem.base = op2.mir_op.u.reg; } } else if (va_start_p) { - op1 = gen (c2m_ctx, NL_HEAD (args->ops), NULL, NULL, TRUE, NULL); + op1 = gen (c2m_ctx, NL_HEAD (args->u.ops), NULL, NULL, TRUE, NULL); if (op1.mir_op.mode == MIR_OP_MEM && op1.mir_op.u.mem.type == MIR_T_UNDEF) op1 = mem_to_address (c2m_ctx, op1, FALSE); MIR_append_insn (ctx, curr_func, MIR_new_insn (ctx, MIR_VA_START, op1.mir_op)); } else if (alloca_p) { res = get_new_temp (c2m_ctx, t); - op1 = gen (c2m_ctx, NL_HEAD (args->ops), NULL, NULL, TRUE, NULL); + op1 = gen (c2m_ctx, NL_HEAD (args->u.ops), NULL, NULL, TRUE, NULL); MIR_append_insn (ctx, curr_func, MIR_new_insn (ctx, MIR_ALLOCA, res.mir_op, op1.mir_op)); } else { param_list = func_type->u.func_type->param_list; - param = NL_HEAD (param_list->ops); - for (node_t arg = NL_HEAD (args->ops); arg != NULL; arg = NL_NEXT (arg)) { + param = NL_HEAD (param_list->u.ops); + for (node_t arg = NL_HEAD (args->u.ops); arg != NULL; arg = NL_NEXT (arg)) { e = arg->attr; struct_p = e->type->mode == TM_STRUCT || e->type->mode == TM_UNION; op2 = gen (c2m_ctx, arg, NULL, NULL, !struct_p, NULL); - assert (param != NULL || NL_HEAD (param_list->ops) == NULL + assert (param != NULL || NL_HEAD (param_list->u.ops) == NULL || func_type->u.func_type->dots_p); if (struct_p) { } else if (param != NULL) { @@ -11508,17 +11700,17 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_GENERIC: { - node_t list = NL_EL (r->ops, 1); - node_t ga_case = NL_HEAD (list->ops); + node_t list = NL_EL (r->u.ops, 1); + node_t ga_case = NL_HEAD (list->u.ops); /* first element is now a compatible generic association case */ - op1 = gen (c2m_ctx, NL_EL (ga_case->ops, 1), NULL, NULL, TRUE, NULL); + op1 = gen (c2m_ctx, NL_EL (ga_case->u.ops, 1), NULL, NULL, TRUE, NULL); t = get_mir_type (c2m_ctx, ((struct expr *) r->attr)->type); res = promote (c2m_ctx, op1, t, TRUE); break; } case N_SPEC_DECL: { // ??? export and defintion with external declaration - node_t specs = NL_HEAD (r->ops); + node_t specs = NL_HEAD (r->u.ops); node_t declarator = NL_NEXT (specs); node_t initializer = NL_NEXT (declarator); node_t id, curr_node; @@ -11529,7 +11721,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ decl = (decl_t) r->attr; if (declarator != NULL && declarator->code != N_IGNORE && decl->item == NULL) { - id = NL_HEAD (declarator->ops); + id = NL_HEAD (declarator->u.ops); name = (decl->scope != top_scope && decl->decl_spec.static_p ? get_func_static_var_name (c2m_ctx, id->u.s.s, decl) : id->u.s.s); @@ -11560,7 +11752,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ curr_node = VARR_GET (node_t, sym.defs, i); curr_decl = curr_node->attr; if ((curr_decl->item != NULL && curr_decl->item->item_type == MIR_bss_item) - || NL_EL (curr_node->ops, 2)->code != N_IGNORE) + || NL_EL (curr_node->u.ops, 2)->code != N_IGNORE) break; } if (i >= VARR_LENGTH (node_t, sym.defs)) /* No item yet or no decl with intializer: */ @@ -11610,7 +11802,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_ST_ASSERT: /* do nothing */ break; case N_INIT: break; // ??? case N_FUNC_DEF: { - node_t decl_specs = NL_HEAD (r->ops); + node_t decl_specs = NL_HEAD (r->u.ops); node_t declarator = NL_NEXT (decl_specs); node_t decls = NL_NEXT (declarator); node_t stmt = NL_NEXT (decls); @@ -11626,7 +11818,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ const char *name; assert (declarator != NULL && declarator->code == N_DECL - && NL_HEAD (declarator->ops)->code == N_ID); + && NL_HEAD (declarator->u.ops)->code == N_ID); assert (decl_type->mode == TM_FUNC); reg_free_mark = 0; curr_func_def = r; @@ -11637,7 +11829,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ : VARR_GET (MIR_type_t, proto_info.ret_types, 0)); curr_func = ((decl_type->u.func_type->dots_p ? MIR_new_vararg_func_arr - : MIR_new_func_arr) (ctx, NL_HEAD (declarator->ops)->u.s.s, + : MIR_new_func_arr) (ctx, NL_HEAD (declarator->u.ops)->u.s.s, VARR_LENGTH (MIR_type_t, proto_info.ret_types), VARR_ADDR (MIR_type_t, proto_info.ret_types), VARR_LENGTH (MIR_var_t, proto_info.arg_vars), @@ -11653,13 +11845,13 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ for (size_t i = 0; i < VARR_LENGTH (MIR_var_t, proto_info.arg_vars); i++) get_reg_var (c2m_ctx, MIR_T_UNDEF, VARR_GET (MIR_var_t, proto_info.arg_vars, i).name); target_init_arg_vars (c2m_ctx, &arg_info); - if ((first_param = NL_HEAD (decl_type->u.func_type->param_list->ops)) != NULL + if ((first_param = NL_HEAD (decl_type->u.func_type->param_list->u.ops)) != NULL && !void_param_p (first_param)) { for (param = first_param; param != NULL; param = NL_NEXT (param)) { - param_declarator = NL_EL (param->ops, 1); + param_declarator = NL_EL (param->u.ops, 1); assert (param_declarator != NULL && param_declarator->code == N_DECL); param_decl = param->attr; - param_id = NL_HEAD (param_declarator->ops); + param_id = NL_HEAD (param_declarator->u.ops); param_type = param_decl->decl_spec.type; assert (!param_decl->reg_p || (param_type->mode != TM_STRUCT && param_type->mode != TM_UNION)); @@ -11700,17 +11892,18 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ assert (FALSE); /* ??? not implemented */ } MIR_finish_func (ctx); - if (decl->decl_spec.linkage == N_EXTERN) MIR_new_export (ctx, NL_HEAD (declarator->ops)->u.s.s); + if (decl->decl_spec.linkage == N_EXTERN) + MIR_new_export (ctx, NL_HEAD (declarator->u.ops)->u.s.s); finish_curr_func_reg_vars (c2m_ctx); break; } case N_BLOCK: emit_label (c2m_ctx, r); - gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, FALSE, NULL); + gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, FALSE, NULL); break; - case N_MODULE: gen (c2m_ctx, NL_HEAD (r->ops), NULL, NULL, FALSE, NULL); break; // ??? + case N_MODULE: gen (c2m_ctx, NL_HEAD (r->u.ops), NULL, NULL, FALSE, NULL); break; // ??? case N_IF: { - node_t expr = NL_EL (r->ops, 1); + node_t expr = NL_EL (r->u.ops, 1); node_t if_stmt = NL_NEXT (expr); node_t else_stmt = NL_NEXT (if_stmt); MIR_label_t if_label = MIR_new_label (ctx), else_label = MIR_new_label (ctx); @@ -11728,7 +11921,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_SWITCH: { - node_t expr = NL_EL (r->ops, 1); + node_t expr = NL_EL (r->u.ops, 1); node_t stmt = NL_NEXT (expr); struct switch_attr *switch_attr = r->attr; op_t case_reg_op; @@ -11749,8 +11942,8 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ short_p = mir_type != MIR_T_I64 && mir_type != MIR_T_U64; case_reg_op = force_reg (c2m_ctx, case_reg_op, mir_type); if (switch_attr->min_val_case != NULL) { - e = NL_HEAD (switch_attr->min_val_case->case_node->ops)->attr; - e2 = NL_HEAD (switch_attr->max_val_case->case_node->ops)->attr; + e = NL_HEAD (switch_attr->min_val_case->case_node->u.ops)->attr; + e2 = NL_HEAD (switch_attr->max_val_case->case_node->u.ops)->attr; range = signed_p ? e2->u.i_val - e->u.i_val : e2->u.u_val - e->u.u_val; } len = DLIST_LENGTH (case_t, switch_attr->case_labels); @@ -11779,7 +11972,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ VARR_PUSH (MIR_op_t, switch_ops, index.mir_op); for (size_t i = 0; i < VARR_LENGTH (case_t, switch_cases); i++) { c = VARR_GET (case_t, switch_cases, i); - e2 = NL_HEAD (c->case_node->ops)->attr; + e2 = NL_HEAD (c->case_node->u.ops)->attr; curr_val = signed_p ? e2->u.i_val - e->u.i_val : e2->u.u_val - e->u.u_val; if (i != 0) { for (n = prev_val + 1; n < curr_val; n++) @@ -11802,7 +11995,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ emit1 (c2m_ctx, MIR_JMP, MIR_new_label_op (ctx, label)); break; } - case_expr = NL_HEAD (c->case_node->ops); + case_expr = NL_HEAD (c->case_node->u.ops); case_expr2 = NL_NEXT (case_expr); e = case_expr->attr; assert (e->const_p && integer_type_p (e->type)); @@ -11836,7 +12029,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_DO: { - node_t expr = NL_EL (r->ops, 1); + node_t expr = NL_EL (r->u.ops, 1); node_t stmt = NL_NEXT (expr); MIR_label_t saved_continue_label = continue_label, saved_break_label = break_label; MIR_label_t start_label = MIR_new_label (ctx); @@ -11855,7 +12048,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_WHILE: { - node_t expr = NL_EL (r->ops, 1); + node_t expr = NL_EL (r->u.ops, 1); node_t stmt = NL_NEXT (expr); MIR_label_t stmt_label = MIR_new_label (ctx); MIR_label_t saved_continue_label = continue_label, saved_break_label = break_label; @@ -11875,7 +12068,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ break; } case N_FOR: { - node_t init = NL_EL (r->ops, 1); + node_t init = NL_EL (r->u.ops, 1); node_t cond = NL_NEXT (init); node_t iter = NL_NEXT (cond); node_t stmt = NL_NEXT (iter); @@ -11930,7 +12123,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ assert (false_label == NULL && true_label == NULL); emit_label (c2m_ctx, r); - if (NL_EL (r->ops, 1)->code == N_IGNORE) { + if (NL_EL (r->u.ops, 1)->code == N_IGNORE) { emit_insn (c2m_ctx, MIR_new_ret_insn (ctx, 0)); break; } @@ -11939,7 +12132,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ var = new_op (NULL, MIR_new_mem_op (ctx, MIR_T_I8, 0, ret_addr_reg, 0, 1)); } - val = gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL, !ret_by_addr_p && scalar_p, + val = gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL, !ret_by_addr_p && scalar_p, !ret_by_addr_p || scalar_p ? NULL : &var); if (!ret_by_addr_p && scalar_p) { t = get_mir_type (c2m_ctx, ret_type); @@ -11955,7 +12148,7 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ case N_EXPR: assert (false_label == NULL && true_label == NULL); emit_label (c2m_ctx, r); - top_gen (c2m_ctx, NL_EL (r->ops, 1), NULL, NULL); + top_gen (c2m_ctx, NL_EL (r->u.ops, 1), NULL, NULL); break; default: abort (); } @@ -12019,6 +12212,7 @@ static int proto_eq (MIR_item_t pi1, MIR_item_t pi2, void *arg) { static MIR_item_t get_mir_proto (c2m_ctx_t c2m_ctx, int vararg_p, VARR (MIR_type_t) * ret_types, VARR (MIR_var_t) * vars) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; struct MIR_item pi, *el; struct MIR_proto p; char buff[30]; @@ -12039,6 +12233,7 @@ static MIR_item_t get_mir_proto (c2m_ctx_t c2m_ctx, int vararg_p, VARR (MIR_type } static void gen_mir_protos (c2m_ctx_t c2m_ctx) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; node_t call, func; struct type *type; struct func_type *func_type; @@ -12048,7 +12243,7 @@ static void gen_mir_protos (c2m_ctx_t c2m_ctx) { for (size_t i = 0; i < VARR_LENGTH (node_t, call_nodes); i++) { call = VARR_GET (node_t, call_nodes, i); assert (call->code == N_CALL); - func = NL_HEAD (call->ops); + func = NL_HEAD (call->u.ops); type = ((struct expr *) func->attr)->type; assert (type->mode == TM_PTR && type->u.ptr_type->mode == TM_FUNC); set_type_layout (c2m_ctx, type); @@ -12056,14 +12251,16 @@ static void gen_mir_protos (c2m_ctx_t c2m_ctx) { assert (func_type->param_list->code == N_LIST); collect_args_and_func_types (c2m_ctx, func_type); func_type->proto_item - = get_mir_proto (c2m_ctx, func_type->dots_p || NL_HEAD (func_type->param_list->ops) == NULL, + = get_mir_proto (c2m_ctx, func_type->dots_p || NL_HEAD (func_type->param_list->u.ops) == NULL, proto_info.ret_types, proto_info.arg_vars); } HTAB_DESTROY (MIR_item_t, proto_tab); } static void gen_finish (c2m_ctx_t c2m_ctx) { - if (c2m_ctx == NULL || c2m_ctx->gen_ctx == NULL) return; + gen_ctx_t gen_ctx; + + if (c2m_ctx == NULL || (gen_ctx = c2m_ctx->gen_ctx) == NULL) return; finish_reg_vars (c2m_ctx); if (proto_info.arg_vars != NULL) VARR_DESTROY (MIR_var_t, proto_info.arg_vars); if (proto_info.ret_types != NULL) VARR_DESTROY (MIR_type_t, proto_info.ret_types); @@ -12076,9 +12273,10 @@ static void gen_finish (c2m_ctx_t c2m_ctx) { } static void gen_mir (c2m_ctx_t c2m_ctx, node_t r) { + gen_ctx_t gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; - c2m_ctx->gen_ctx = c2mir_calloc (c2m_ctx, sizeof (struct gen_ctx)); + c2m_ctx->gen_ctx = gen_ctx = c2mir_calloc (c2m_ctx, sizeof (struct gen_ctx)); zero_op = new_op (NULL, MIR_new_int_op (ctx, 0)); one_op = new_op (NULL, MIR_new_int_op (ctx, 1)); minus_one_op = new_op (NULL, MIR_new_int_op (ctx, -1)); @@ -12183,25 +12381,25 @@ static void print_type (c2m_ctx_t c2m_ctx, FILE *f, struct type *type) { default: assert (FALSE); } break; - case TM_ENUM: fprintf (f, "enum node %lu", type->u.tag_type->uid); break; + case TM_ENUM: fprintf (f, "enum node %u", type->u.tag_type->uid); break; case TM_PTR: fprintf (f, "ptr ("); print_type (c2m_ctx, f, type->u.ptr_type); fprintf (f, ")"); break; - case TM_STRUCT: fprintf (f, "struct node %lu", type->u.tag_type->uid); break; - case TM_UNION: fprintf (f, "union node %lu", type->u.tag_type->uid); break; + case TM_STRUCT: fprintf (f, "struct node %u", type->u.tag_type->uid); break; + case TM_UNION: fprintf (f, "union node %u", type->u.tag_type->uid); break; case TM_ARR: fprintf (f, "array [%s", type->u.arr_type->static_p ? "static " : ""); print_qual (f, type->u.arr_type->ind_type_qual); - fprintf (f, "size node %lu] (", type->u.arr_type->size->uid); + fprintf (f, "size node %u] (", type->u.arr_type->size->uid); print_type (c2m_ctx, f, type->u.arr_type->el_type); fprintf (f, ")"); break; case TM_FUNC: fprintf (f, "func "); print_type (c2m_ctx, f, type->u.func_type->ret_type); - fprintf (f, "(params node %lu", type->u.func_type->param_list->uid); + fprintf (f, "(params node %u", type->u.func_type->param_list->uid); fprintf (f, type->u.func_type->dots_p ? ", ...)" : ")"); break; default: assert (FALSE); @@ -12225,7 +12423,7 @@ static void print_decl_spec (c2m_ctx_t c2m_ctx, FILE *f, struct decl_spec *decl_ if (decl_spec->no_return_p) fprintf (f, " no return, "); if (decl_spec->align >= 0) fprintf (f, " align = %d, ", decl_spec->align); if (decl_spec->align_node != NULL) - fprintf (f, " strictest align node %lu, ", decl_spec->align_node->uid); + fprintf (f, " strictest align node %u, ", decl_spec->align_node->uid); if (decl_spec->linkage != N_IGNORE) fprintf (f, " %s linkage, ", decl_spec->linkage == N_STATIC ? "static" : "extern"); print_type (c2m_ctx, f, decl_spec->type); @@ -12234,7 +12432,7 @@ static void print_decl_spec (c2m_ctx_t c2m_ctx, FILE *f, struct decl_spec *decl_ static void print_decl (c2m_ctx_t c2m_ctx, FILE *f, decl_t decl) { if (decl == NULL) return; fprintf (f, ": "); - if (decl->scope != NULL) fprintf (f, "scope node = %lu, ", decl->scope->uid); + if (decl->scope != NULL) fprintf (f, "scope node = %u, ", decl->scope->uid); print_decl_spec (c2m_ctx, f, &decl->decl_spec); if (decl->addr_p) fprintf (f, ", addressable"); if (decl->used_p) fprintf (f, ", used"); @@ -12266,14 +12464,14 @@ static void print_expr (c2m_ctx_t c2m_ctx, FILE *f, struct expr *e) { static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int attr_p) { int i; - fprintf (f, "%6lu: ", n->uid); + fprintf (f, "%6u: ", n->uid); for (i = 0; i < indent; i++) fprintf (f, " "); if (n == err_node) { fprintf (f, "\n"); return; } fprintf (f, "%s (", get_node_name (n->code)); - print_pos (f, n->pos, FALSE); + print_pos (f, POS (n), FALSE); fprintf (f, ")"); switch (n->code) { case N_IGNORE: fprintf (f, "\n"); break; @@ -12432,12 +12630,12 @@ static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int at case N_FOR: if (!attr_p || ((n->code == N_STRUCT || n->code == N_UNION) - && (NL_EL (n->ops, 1) == NULL || NL_EL (n->ops, 1)->code == N_IGNORE))) + && (NL_EL (n->u.ops, 1) == NULL || NL_EL (n->u.ops, 1)->code == N_IGNORE))) fprintf (f, "\n"); else if (n->code == N_MODULE) fprintf (f, ": the top scope"); else if (n->attr != NULL) - fprintf (f, ": higher scope node %lu", ((struct node_scope *) n->attr)->scope->uid); + fprintf (f, ": higher scope node %u", ((struct node_scope *) n->attr)->scope->uid); if (n->code == N_STRUCT || n->code == N_UNION) fprintf (f, "\n"); else if (attr_p && n->attr != NULL) @@ -12455,7 +12653,7 @@ static void print_node (c2m_ctx_t c2m_ctx, FILE *f, node_t n, int indent, int at print_ops (c2m_ctx, f, n, indent, attr_p); break; case N_GOTO: - if (attr_p && n->attr != NULL) fprintf (f, ": target node %lu\n", ((node_t) n->attr)->uid); + if (attr_p && n->attr != NULL) fprintf (f, ": target node %u\n", ((node_t) n->attr)->uid); print_ops (c2m_ctx, f, n, indent, attr_p); break; case N_ENUM_CONST: @@ -12542,6 +12740,7 @@ static int check_id_p (c2m_ctx_t c2m_ctx, const char *str) { } static void define_cmd_macro (c2m_ctx_t c2m_ctx, const char *name, const char *def) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; pos_t pos; token_t t, id; struct macro macro; @@ -12573,6 +12772,7 @@ static void define_cmd_macro (c2m_ctx_t c2m_ctx, const char *name, const char *d } static void undefine_cmd_macro (c2m_ctx_t c2m_ctx, const char *name) { + pre_ctx_t pre_ctx = c2m_ctx->pre_ctx; pos_t pos; token_t id; struct macro macro; @@ -12605,8 +12805,8 @@ static void compile_init (c2m_ctx_t c2m_ctx, struct c2mir_options *ops, int (*ge c_getc_data = getc_data; VARR_CREATE (char, symbol_text, 128); VARR_CREATE (char, temp_string, 128); + VARR_CREATE (pos_t, node_positions, 128); parse_init (c2m_ctx); - curr_scope = NULL; context_init (c2m_ctx); init_include_dirs (c2m_ctx); process_macro_commands (c2m_ctx); @@ -12618,6 +12818,7 @@ static void compile_init (c2m_ctx_t c2m_ctx, struct c2mir_options *ops, int (*ge static void compile_finish (c2m_ctx_t c2m_ctx) { if (symbol_text != NULL) VARR_DESTROY (char, symbol_text); if (temp_string != NULL) VARR_DESTROY (char, temp_string); + if (node_positions != NULL) VARR_DESTROY (pos_t, node_positions); parse_finish (c2m_ctx); context_finish (c2m_ctx); if (headers != NULL) VARR_DESTROY (char_ptr_t, headers); diff --git a/mir/c2mir/c2mir.h b/mir/c2mir/c2mir.h index 83a830a..d94f701 100644 --- a/mir/c2mir/c2mir.h +++ b/mir/c2mir/c2mir.h @@ -10,7 +10,8 @@ struct c2mir_macro_command { struct c2mir_options { FILE *message_file; - int debug_p, verbose_p, no_prepro_p, prepro_only_p, syntax_only_p, pedantic_p, asm_p, object_p; + int debug_p, verbose_p, ignore_warnings_p, no_prepro_p, prepro_only_p; + int syntax_only_p, pedantic_p, asm_p, object_p; size_t module_num; FILE *prepro_output_file; /* non-null for prepro_only_p */ const char *output_file_name; diff --git a/mir/c2mir/ppc64/cppc64-ABI-code.c b/mir/c2mir/ppc64/cppc64-ABI-code.c index 40cba61..25a4148 100644 --- a/mir/c2mir/ppc64/cppc64-ABI-code.c +++ b/mir/c2mir/ppc64/cppc64-ABI-code.c @@ -14,6 +14,7 @@ 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; @@ -33,7 +34,7 @@ static MIR_type_t fp_homogeneous_type_1 (c2m_ctx_t c2m_ctx, MIR_type_t curr_type case TM_UNION: t = curr_type; *num = 0; - for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->ops, 1)->ops); el != NULL; + for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL; el = NL_NEXT (el)) if (el->code == N_MEMBER) { decl_t decl = el->attr; @@ -108,6 +109,7 @@ static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, target_arg_info_t *arg_info, size_t call_arg_area_offset) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; op_t temp; @@ -149,6 +151,7 @@ static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res, MIR_insn_t call, size_t call_ops_start) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; MIR_insn_t insn; @@ -177,6 +180,7 @@ static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_t } static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; MIR_insn_t insn; @@ -241,6 +245,7 @@ static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct ty 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; @@ -274,6 +279,7 @@ static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, 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; diff --git a/mir/c2mir/s390x/cs390x-ABI-code.c b/mir/c2mir/s390x/cs390x-ABI-code.c index 531265e..a494121 100644 --- a/mir/c2mir/s390x/cs390x-ABI-code.c +++ b/mir/c2mir/s390x/cs390x-ABI-code.c @@ -55,6 +55,7 @@ static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct ty 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; op_t temp; if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) { @@ -75,6 +76,7 @@ static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, 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; diff --git a/mir/c2mir/x86_64/cx86_64-ABI-code.c b/mir/c2mir/x86_64/cx86_64-ABI-code.c index 9674791..fe731e8 100644 --- a/mir/c2mir/x86_64/cx86_64-ABI-code.c +++ b/mir/c2mir/x86_64/cx86_64-ABI-code.c @@ -45,7 +45,7 @@ static int classify_arg (c2m_ctx_t c2m_ctx, struct type *type, MIR_type_t types[ if (n_qwords > MAX_QWORDS) return 0; /* too big aggregate */ #ifndef _WIN64 - for (i = 0; i < n_qwords; i++) types[i] = NO_CLASS; + for (i = 0; i < n_qwords; i++) types[i] = (MIR_type_t) NO_CLASS; switch (type->mode) { case TM_ARR: { /* Arrays are handled as small records. */ @@ -58,7 +58,7 @@ static int classify_arg (c2m_ctx_t c2m_ctx, struct type *type, MIR_type_t types[ } case TM_STRUCT: case TM_UNION: - for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->ops, 1)->ops); el != NULL; + for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL; el = NL_NEXT (el)) if (el->code == N_MEMBER) { decl_t decl = el->attr; @@ -98,7 +98,7 @@ static int classify_arg (c2m_ctx_t c2m_ctx, struct type *type, MIR_type_t types[ case MIR_T_D: types[0] = MIR_T_D; return 1; case MIR_T_LD: types[0] = MIR_T_LD; - types[1] = X87UP_CLASS; + types[1] = (MIR_type_t) X87UP_CLASS; return 2; default: types[0] = MIR_T_I64; return 1; } @@ -204,6 +204,7 @@ static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type, static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, target_arg_info_t *arg_info, size_t call_arg_area_offset) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; MIR_type_t qword_types[MAX_QWORDS]; @@ -239,6 +240,7 @@ static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type, static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res, MIR_insn_t call, size_t call_ops_start) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; MIR_insn_t insn; @@ -263,6 +265,7 @@ static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_t } static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) { + gen_ctx_t gen_ctx = c2m_ctx->gen_ctx; MIR_context_t ctx = c2m_ctx->ctx; MIR_type_t type; MIR_type_t qword_types[MAX_QWORDS]; @@ -356,6 +359,7 @@ static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct ty 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_type_t type; MIR_type_t qword_types[MAX_QWORDS]; @@ -394,6 +398,7 @@ static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type, static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type, 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; reg_var_t reg_var; diff --git a/mir/mir-aarch64.c b/mir/mir-aarch64.c index b242e96..bb45b13 100644 --- a/mir/mir-aarch64.c +++ b/mir/mir-aarch64.c @@ -97,7 +97,7 @@ void va_start_interp_builtin (MIR_context_t ctx, void *p, void *a) { void va_end_interp_builtin (MIR_context_t ctx, void *p) {} -static int setup_imm64_insns (MIR_context_t ctx, uint32_t *to, int reg, uint64_t imm64) { +static int setup_imm64_insns (uint32_t *to, int reg, uint64_t imm64) { /* xd=imm64 */ static const uint32_t imm64_pat[] = { 0xd2800000, /* 0: mov xd, xxxx(0-15) */ @@ -115,19 +115,19 @@ static int setup_imm64_insns (MIR_context_t ctx, uint32_t *to, int reg, uint64_t return sizeof (imm64_pat) / sizeof (uint32_t); } -static uint8_t *push_insns (MIR_context_t ctx, const uint32_t *pat, size_t pat_len) { +static uint8_t *push_insns (VARR (uint8_t) * insn_varr, const uint32_t *pat, size_t pat_len) { uint8_t *p = (uint8_t *) pat; - for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, machine_insns, p[i]); - return VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns) - pat_len; + for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, insn_varr, p[i]); + return VARR_ADDR (uint8_t, insn_varr) + VARR_LENGTH (uint8_t, insn_varr) - pat_len; } -static size_t gen_mov_addr (MIR_context_t ctx, int reg, void *addr) { +static size_t gen_mov_addr (VARR (uint8_t) * insn_varr, int reg, void *addr) { uint32_t insns[4]; - int insns_num = setup_imm64_insns (ctx, insns, reg, (uint64_t) addr); + int insns_num = setup_imm64_insns (insns, reg, (uint64_t) addr); mir_assert (insns_num == 4 && sizeof (insns) == insns_num * sizeof (uint32_t)); - push_insns (ctx, insns, insns_num * sizeof (uint32_t)); + push_insns (insn_varr, insns, insns_num * sizeof (uint32_t)); return insns_num * sizeof (uint32_t); } @@ -135,7 +135,8 @@ static size_t gen_mov_addr (MIR_context_t ctx, int reg, void *addr) { #define MAX_BR_OFFSET (1 << (BR_OFFSET_BITS - 1)) /* 1 for sign */ #define BR_OFFSET_MASK (~(-1 << BR_OFFSET_BITS)) -static void gen_call_addr (MIR_context_t ctx, void *base_addr, int temp_reg, void *call_addr) { +static void gen_call_addr (VARR (uint8_t) * insn_varr, void *base_addr, int temp_reg, + void *call_addr) { static const uint32_t call_pat1 = 0x94000000; /* bl x */ static const uint32_t call_pat2 = 0xd63f0000; /* blr x */ uint32_t insn; @@ -145,10 +146,10 @@ static void gen_call_addr (MIR_context_t ctx, void *base_addr, int temp_reg, voi if (base_addr != NULL && -(int64_t) MAX_BR_OFFSET <= offset && offset < (int64_t) MAX_BR_OFFSET) { insn = call_pat1 | ((uint32_t) offset & BR_OFFSET_MASK); } else { - gen_mov_addr (ctx, temp_reg, call_addr); + gen_mov_addr (insn_varr, temp_reg, call_addr); insn = call_pat2 | (temp_reg << 5); } - push_insns (ctx, &insn, sizeof (insn)); + push_insns (insn_varr, &insn, sizeof (insn)); } #define NOP 0xd503201f @@ -170,7 +171,7 @@ void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) { code[0] = branch_pat2 | ((uint32_t) offset & BR_OFFSET_MASK); _MIR_change_code (ctx, thunk, (uint8_t *) &code[0], sizeof (code[0])); } else { - int n = setup_imm64_insns (ctx, code, 9, (uint64_t) to); + int n = setup_imm64_insns (code, 9, (uint64_t) to); mir_assert (n == 4); code[4] = branch_pat1; @@ -178,8 +179,8 @@ void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) { } } -static void gen_blk_mov (MIR_context_t ctx, uint32_t offset, uint32_t addr_offset, uint32_t qwords, - uint32_t addr_reg) { +static void gen_blk_mov (VARR (uint8_t) * insn_varr, uint32_t offset, uint32_t addr_offset, + uint32_t qwords, uint32_t addr_reg) { static const uint32_t blk_mov_pat[] = { /* 0:*/ 0xf940026c, /* ldr x12, [x19,]*/ /* 4:*/ 0x910003e0, /* add , sp, */ @@ -194,9 +195,9 @@ static void gen_blk_mov (MIR_context_t ctx, uint32_t offset, uint32_t addr_offse }; if (qwords == 0) { uint32_t pat = 0x910003e0 | addr_reg | (offset << 10); /* add , sp, */ - push_insns (ctx, &pat, sizeof (pat)); + push_insns (insn_varr, &pat, sizeof (pat)); } else { - uint32_t *addr = (uint32_t *) push_insns (ctx, blk_mov_pat, sizeof (blk_mov_pat)); + uint32_t *addr = (uint32_t *) push_insns (insn_varr, blk_mov_pat, sizeof (blk_mov_pat)); mir_assert (offset < (1 << 12) && addr_offset % 8 == 0 && (addr_offset >> 3) < (1 << 12)); mir_assert (addr_reg < 32 && qwords < (1 << 16)); addr[0] |= (addr_offset >> 3) << 10; @@ -272,7 +273,10 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s uint32_t sp = 31, addr_reg, qwords; uint32_t *addr; const uint32_t temp_reg = 10; /* x10 */ + VARR (uint8_t) * code; + void *res; + 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 */ type = arg_descs[i].type; @@ -286,12 +290,11 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s } else if (type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) { if (n_vregs++ >= 8) blk_offset += type == MIR_T_LD ? 16 : 8; } else { - (*error_func) (MIR_call_op_error, "wrong type of arg value"); + MIR_get_error_func (ctx) (MIR_call_op_error, "wrong type of arg value"); } } blk_offset = (blk_offset + 15) / 16 * 16; - VARR_TRUNC (uint8_t, machine_insns, 0); - push_insns (ctx, prolog, sizeof (prolog)); + push_insns (code, prolog, sizeof (prolog)); n_xregs = n_vregs = 0; for (size_t i = 0; i < nargs; i++) { /* args */ type = arg_descs[i].type; @@ -302,29 +305,29 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s if (qwords <= 2) { addr_reg = 13; pat = ld_pat | offset_imm | addr_reg; - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); if (n_xregs + qwords <= 8) { for (int n = 0; n < qwords; n++) { pat = gen_ld_pat | (((n * 8) >> scale) << 10) | (n_xregs + n) | (addr_reg << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); } } else { for (int n = 0; n < qwords; n++) { pat = gen_ld_pat | (((n * 8) >> scale) << 10) | temp_reg | (addr_reg << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); pat = st_pat | ((sp_offset >> scale) << 10) | temp_reg | (sp << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); sp_offset += 8; } } n_xregs += qwords; } else { addr_reg = n_xregs < 8 ? n_xregs : 13; - gen_blk_mov (ctx, blk_offset, (i + nres) * sizeof (long double), qwords, addr_reg); + gen_blk_mov (code, blk_offset, (i + nres) * sizeof (long double), qwords, addr_reg); blk_offset += qwords * 8; if (n_xregs++ >= 8) { pat = st_pat | ((sp_offset >> scale) << 10) | addr_reg | (sp << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); sp_offset += 8; } } @@ -335,11 +338,11 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s pat = ld_pat | offset_imm | n_xregs++; } else { pat = ld_pat | offset_imm | temp_reg; - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); pat = st_pat | ((sp_offset >> scale) << 10) | temp_reg | (sp << 5); sp_offset += 8; } - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); } else if (type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) { pat = type == MIR_T_F ? lds_pat : type == MIR_T_D ? ldd_pat : ldld_pat; if (n_vregs < 8) { @@ -347,22 +350,23 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s } else { if (type == MIR_T_LD) sp_offset = (sp_offset + 15) % 16; pat |= offset_imm | temp_reg; - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); pat = type == MIR_T_F ? sts_pat : type == MIR_T_D ? std_pat : stld_pat; pat |= ((sp_offset >> scale) << 10) | temp_reg | (sp << 5); sp_offset += type == MIR_T_LD ? 16 : 8; } - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); + } else { + MIR_get_error_func (ctx) (MIR_call_op_error, "wrong type of arg value"); } } sp_offset = (sp_offset + 15) / 16 * 16; blk_offset = (blk_offset + 15) / 16 * 16; if (blk_offset != 0) sp_offset = blk_offset; mir_assert (sp_offset < (1 << 12)); - ((uint32_t *) VARR_ADDR (uint8_t, machine_insns))[1] |= sp_offset << 10; /* sub sp,sp, */ - push_insns (ctx, call_end, sizeof (call_end)); - ((uint32_t *) (VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns)))[-1] - |= sp_offset << 10; + ((uint32_t *) VARR_ADDR (uint8_t, code))[1] |= sp_offset << 10; /* sub sp,sp, */ + push_insns (code, call_end, sizeof (call_end)); + ((uint32_t *) (VARR_ADDR (uint8_t, code) + VARR_LENGTH (uint8_t, code)))[-1] |= sp_offset << 10; n_xregs = n_vregs = 0; for (size_t i = 0; i < nres; i++) { /* results */ offset_imm = i * sizeof (long double) << 10; @@ -370,20 +374,22 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s && n_xregs < 8) { offset_imm >>= 3; pat = st_pat | offset_imm | n_xregs++ | (19 << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); } else if ((res_types[i] == MIR_T_F || res_types[i] == MIR_T_D || res_types[i] == MIR_T_LD) && n_vregs < 8) { offset_imm >>= res_types[i] == MIR_T_F ? 2 : res_types[i] == MIR_T_D ? 3 : 4; pat = res_types[i] == MIR_T_F ? sts_pat : res_types[i] == MIR_T_D ? std_pat : stld_pat; pat |= offset_imm | n_vregs++ | (19 << 5); - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); } else { - (*error_func) (MIR_ret_error, "aarch64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "aarch64 can not handle this combination of return values"); } } - push_insns (ctx, epilog, sizeof (epilog)); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + push_insns (code, epilog, sizeof (epilog)); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } /* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item, @@ -423,22 +429,23 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl 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; - VARR_TRUNC (uint8_t, machine_insns, 0); - push_insns (ctx, &save_x19_pat, sizeof (save_x19_pat)); - push_insns (ctx, save_insns, sizeof (save_insns)); + VARR_CREATE (uint8_t, code, 128); + push_insns (code, &save_x19_pat, sizeof (save_x19_pat)); + push_insns (code, save_insns, sizeof (save_insns)); if (x8_res_p) - push_insns (ctx, &set_x8_gr_offs, sizeof (set_x8_gr_offs)); + push_insns (code, &set_x8_gr_offs, sizeof (set_x8_gr_offs)); else - push_insns (ctx, &set_gr_offs, sizeof (set_gr_offs)); - push_insns (ctx, prepare_pat, sizeof (prepare_pat)); + push_insns (code, &set_gr_offs, sizeof (set_gr_offs)); + push_insns (code, prepare_pat, sizeof (prepare_pat)); imm = (nres + 1) * 16; mir_assert (imm < (1 << 16)); - ((uint32_t *) (VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns)))[-5] - |= imm << 5; - gen_mov_addr (ctx, 0, ctx); /* mov x0, ctx */ - gen_mov_addr (ctx, 1, func_item); /* mov x1, func_item */ - gen_call_addr (ctx, NULL, 9, handler); + ((uint32_t *) (VARR_ADDR (uint8_t, code) + VARR_LENGTH (uint8_t, code)))[-5] |= imm << 5; + gen_mov_addr (code, 0, ctx); /* mov x0, ctx */ + gen_mov_addr (code, 1, func_item); /* mov x1, func_item */ + gen_call_addr (code, NULL, 9, handler); /* move results: */ n_xregs = n_vregs = offset = 0; mir_assert (sizeof (long double) == 16); @@ -451,21 +458,22 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl pat = ld_pat | n_xregs; n_xregs++; } else { - (*error_func) (MIR_ret_error, "aarch64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "aarch64 can not handle this combination of return values"); } offset_imm = offset >> (results[i] == MIR_T_F ? 2 : results[i] == MIR_T_LD ? 4 : 3); mir_assert (offset_imm < (1 << 12)); pat |= offset_imm << 10; - push_insns (ctx, &pat, sizeof (pat)); + push_insns (code, &pat, sizeof (pat)); offset += 16; } - push_insns (ctx, shim_end, sizeof (shim_end)); + push_insns (code, shim_end, sizeof (shim_end)); imm = 240 + (nres + 1) * 16; mir_assert (imm < (1 << 16)); - ((uint32_t *) (VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns)))[-4] - |= imm << 5; - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + ((uint32_t *) (VARR_ADDR (uint8_t, code) + VARR_LENGTH (uint8_t, code)))[-4] |= imm << 5; + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } /* Save regs x8, x0-x7, q0-q7; x9 = call hook_address (ctx, called_func); restore regs; br x9 */ @@ -474,26 +482,36 @@ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_ad static const uint32_t move_insn = 0xaa0003e9; /* mov x9, x0 */ static const uint32_t save_fplr = 0xa9bf7bfd; /* stp R29, R30, [SP, #-16]! */ static const uint32_t restore_fplr = 0xa8c17bfd; /* ldp R29, R30, SP, #16 */ - uint8_t *base_addr, *curr_addr, *code; - size_t len = sizeof (save_insns) + sizeof (restore_insns); - - for (;;) { + uint8_t *base_addr, *curr_addr, *res_code = NULL; + size_t len = sizeof (save_insns) + sizeof (restore_insns); /* initial code length */ + VARR (uint8_t) * code; + +#if MIR_PARALLEL_GEN + pthread_mutex_lock (&code_mutex); +#endif + VARR_CREATE (uint8_t, code, 128); + for (;;) { /* dealing with moving code to another page */ curr_addr = base_addr = _MIR_get_new_code_addr (ctx, len); - if (curr_addr == NULL) return NULL; - VARR_TRUNC (uint8_t, machine_insns, 0); - push_insns (ctx, &save_fplr, sizeof (save_fplr)); + if (curr_addr == NULL) break; + VARR_TRUNC (uint8_t, code, 0); + push_insns (code, &save_fplr, sizeof (save_fplr)); curr_addr += 4; - push_insns (ctx, save_insns, sizeof (save_insns)); + push_insns (code, save_insns, sizeof (save_insns)); curr_addr += sizeof (save_insns); - curr_addr += gen_mov_addr (ctx, 0, ctx); /*mov x0,ctx */ - curr_addr += gen_mov_addr (ctx, 1, called_func); /*mov x1,called_func */ - gen_call_addr (ctx, curr_addr, 10, hook_address); /*call , use x10 as temp */ - push_insns (ctx, &move_insn, sizeof (move_insn)); - push_insns (ctx, restore_insns, sizeof (restore_insns)); - push_insns (ctx, &restore_fplr, sizeof (restore_fplr)); - push_insns (ctx, &jmp_insn, sizeof (jmp_insn)); - len = VARR_LENGTH (uint8_t, machine_insns); - code = _MIR_publish_code_by_addr (ctx, base_addr, VARR_ADDR (uint8_t, machine_insns), len); - if (code != NULL) return code; + curr_addr += gen_mov_addr (code, 0, ctx); /*mov x0,ctx */ + curr_addr += gen_mov_addr (code, 1, called_func); /*mov x1,called_func */ + gen_call_addr (code, curr_addr, 10, hook_address); /*call , use x10 as temp */ + push_insns (code, &move_insn, sizeof (move_insn)); + push_insns (code, restore_insns, sizeof (restore_insns)); + push_insns (code, &restore_fplr, sizeof (restore_fplr)); + push_insns (code, &jmp_insn, sizeof (jmp_insn)); + len = VARR_LENGTH (uint8_t, code); + res_code = _MIR_publish_code_by_addr (ctx, base_addr, VARR_ADDR (uint8_t, code), len); + if (res_code != NULL) break; } + VARR_DESTROY (uint8_t, code); +#if MIR_PARALLEL_GEN + pthread_mutex_unlock (&code_mutex); +#endif + return res_code; } diff --git a/mir/mir-gen-aarch64.c b/mir/mir-gen-aarch64.c index 89beb94..bd9282a 100644 --- a/mir/mir-gen-aarch64.c +++ b/mir/mir-gen-aarch64.c @@ -1649,9 +1649,10 @@ static const struct pattern patterns[] = { {MIR_BSTART, "r", "91000000:fffffc00 rd0 hn1f"}, /* Rd = sp */ {MIR_BEND, "r", "91000000:fffffc00 hd1f rn0"}, /* sp = Rn */ - /* adr r9,PC-relative TableAddress; ldr r9,(r9,r,8);br r9; TableContent */ + /* adr r10,PC-relative TableAddress; ldr r10,(r10,r,8);br r10; TableContent + We use r10 as r9 can be used if switch operand is memory. */ {MIR_SWITCH, "r $", - "10000000:ff000000 hd9 T; f8607800:ffe0fc00 hd9 hn9 rm0; d61f0000:fffffc00 hn9;"}, + "10000000:ff000000 hda T; f8607800:ffe0fc00 hda hna rm0; d61f0000:fffffc00 hna;"}, }; diff --git a/mir/mir-gen-x86_64.c b/mir/mir-gen-x86_64.c index 1db3f42..fc15cfd 100644 --- a/mir/mir-gen-x86_64.c +++ b/mir/mir-gen-x86_64.c @@ -978,6 +978,7 @@ struct pattern { X - match everything $ - finish successfully matching r - register (we don't care about bp and sp because they are fixed and used correctly) + t - ax, cx, dx, or bx register h[0-31] - hard register with given number z - operand is zero i[0-3] - immediate of size 8,16,32,64-bits @@ -1068,12 +1069,12 @@ struct pattern { /* cmp ...; setx r0; movzbl r0,r0: */ #define CMP0(ICODE, SUFF, PREF, SETX) \ - {ICODE##SUFF, "r r r", #PREF " 3B r1 R2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,r2;...*/ \ - {ICODE##SUFF, "r r m3", #PREF " 3B r1 m2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,m2;...*/ \ - {ICODE##SUFF, "r r i0", #PREF " 83 /7 R1 i2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,i2;...*/ \ - {ICODE##SUFF, "r r i2", #PREF " 81 /7 R1 I2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,i2;...*/ \ - {ICODE##SUFF, "r m3 i0", #PREF " 83 /7 m1 i2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp m1,i2;...*/ \ - {ICODE##SUFF, "r m3 i2", #PREF " 81 /7 m1 I2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp m1,i2;...*/ + {ICODE##SUFF, "t r r", #PREF " 3B r1 R2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,r2;...*/ \ + {ICODE##SUFF, "t r m3", #PREF " 3B r1 m2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,m2;...*/ \ + {ICODE##SUFF, "t r i0", #PREF " 83 /7 R1 i2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,i2;...*/ \ + {ICODE##SUFF, "t r i2", #PREF " 81 /7 R1 I2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp r1,i2;...*/ \ + {ICODE##SUFF, "t m3 i0", #PREF " 83 /7 m1 i2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp m1,i2;...*/ \ + {ICODE##SUFF, "t m3 i2", #PREF " 81 /7 m1 I2;" SETX " R0;X 0F B6 r0 R0"}, /* cmp m1,i2;...*/ #define CMP(ICODE, SET_OPCODE) \ CMP0 (ICODE, , X, SET_OPCODE) \ @@ -1444,6 +1445,11 @@ static int pattern_match_p (gen_ctx_t gen_ctx, const struct pattern *pat, MIR_in case 'r': if (op.mode != MIR_OP_HARD_REG) return FALSE; break; + case 't': + if (op.mode != MIR_OP_HARD_REG + || !(AX_HARD_REG <= op.u.hard_reg && op.u.hard_reg <= BX_HARD_REG)) + return FALSE; + break; case 'h': if (op.mode != MIR_OP_HARD_REG) return FALSE; ch = *++p; @@ -2107,7 +2113,7 @@ static uint8_t *target_translate (gen_ctx_t gen_ctx, size_t *len) { } else { replacement = find_insn_pattern_replacement (gen_ctx, insn); if (replacement == NULL) { - fprintf (stderr, "fatal failure in matching insn:"); + fprintf (stderr, "%d: fatal failure in matching insn:", gen_ctx->gen_num); MIR_output_insn (ctx, stderr, insn, curr_func_item->u.func, TRUE); exit (1); } else { diff --git a/mir/mir-gen.c b/mir/mir-gen.c index 84bb87d..f7d3c8d 100644 --- a/mir/mir-gen.c +++ b/mir/mir-gen.c @@ -125,10 +125,27 @@ struct fg_ctx; typedef struct loop_node *loop_node_t; DEF_VARR (loop_node_t); +typedef struct dead_var *dead_var_t; +DEF_DLIST_LINK (dead_var_t); + +struct dead_var { + MIR_reg_t var; + DLIST_LINK (dead_var_t) dead_var_link; +}; +DEF_DLIST (dead_var_t, dead_var_link); + +struct all_gen_ctx; + typedef struct bb_insn *bb_insn_t; DEF_VARR (bb_insn_t); struct gen_ctx { + struct all_gen_ctx *all_gen_ctx; + int gen_num; /* always 1 for non-parallel generation */ +#if MIR_PARALLEL_GEN + pthread_t gen_thread; + int busy_p; +#endif MIR_context_t ctx; unsigned optimize_level; /* 0:fast gen; 1:RA+combiner; 2: +GVN/CCP (default); >=3: everything */ MIR_item_t curr_func_item; @@ -139,6 +156,7 @@ struct gen_ctx { bitmap_t call_used_hard_regs[MIR_T_BOUND], func_used_hard_regs; func_cfg_t curr_cfg; uint32_t curr_bb_index, curr_loop_node_index; + DLIST (dead_var_t) free_dead_vars; struct target_ctx *target_ctx; struct data_flow_ctx *data_flow_ctx; struct ssa_ctx *ssa_ctx; @@ -155,8 +173,6 @@ struct gen_ctx { size_t func_stack_slots_num; }; -static inline gen_ctx_t *gen_ctx_loc (MIR_context_t ctx) { return (gen_ctx_t *) ctx; } - #define optimize_level gen_ctx->optimize_level #define curr_func_item gen_ctx->curr_func_item #define debug_file gen_ctx->debug_file @@ -168,6 +184,7 @@ static inline gen_ctx_t *gen_ctx_loc (MIR_context_t ctx) { return (gen_ctx_t *) #define curr_cfg gen_ctx->curr_cfg #define curr_bb_index gen_ctx->curr_bb_index #define curr_loop_node_index gen_ctx->curr_loop_node_index +#define free_dead_vars gen_ctx->free_dead_vars #define dead_bb_insns gen_ctx->dead_bb_insns #define loop_nodes gen_ctx->loop_nodes #define queue_nodes gen_ctx->queue_nodes @@ -176,6 +193,31 @@ static inline gen_ctx_t *gen_ctx_loc (MIR_context_t ctx) { return (gen_ctx_t *) #define max_fp_hard_regs gen_ctx->max_fp_hard_regs #define func_stack_slots_num gen_ctx->func_stack_slots_num +DEF_VARR (MIR_item_t); +struct all_gen_ctx { +#if MIR_PARALLEL_GEN + mir_mutex_t queue_mutex; + mir_cond_t generate_signal, done_signal; + size_t funcs_start; + VARR (MIR_item_t) * funcs_to_generate; +#endif + MIR_context_t ctx; + size_t gens_num; /* size of the following array: */ + struct gen_ctx gen_ctx[1]; +}; + +#if MIR_PARALLEL_GEN +#define queue_mutex all_gen_ctx->queue_mutex +#define generate_signal all_gen_ctx->generate_signal +#define done_signal all_gen_ctx->done_signal +#define funcs_start all_gen_ctx->funcs_start +#define funcs_to_generate all_gen_ctx->funcs_to_generate +#endif + +static inline struct all_gen_ctx **all_gen_ctx_loc (MIR_context_t ctx) { + return (struct all_gen_ctx **) ctx; +} + #if defined(__x86_64__) || defined(_M_AMD64) #include "mir-gen-x86_64.c" #elif defined(__aarch64__) @@ -251,10 +293,6 @@ static void make_io_dup_op_insns (gen_ctx_t gen_ctx) { } } -typedef struct dead_var *dead_var_t; - -DEF_DLIST_LINK (dead_var_t); - typedef struct bb *bb_t; DEF_DLIST_LINK (bb_t); @@ -283,13 +321,6 @@ struct edge { DEF_DLIST (in_edge_t, in_link); DEF_DLIST (out_edge_t, out_link); -struct dead_var { - MIR_reg_t var; - DLIST_LINK (dead_var_t) dead_var_link; -}; - -DEF_DLIST (dead_var_t, dead_var_link); - struct insn_data { /* used only for calls/labels in -O0 mode */ bb_t bb; union { @@ -410,11 +441,11 @@ struct func_cfg { loop_node_t root_loop_node; }; -static DLIST (dead_var_t) free_dead_vars; +static void init_dead_vars (gen_ctx_t gen_ctx) { DLIST_INIT (dead_var_t, free_dead_vars); } -static void init_dead_vars (void) { DLIST_INIT (dead_var_t, free_dead_vars); } - -static void free_dead_var (dead_var_t dv) { DLIST_APPEND (dead_var_t, free_dead_vars, dv); } +static void free_dead_var (gen_ctx_t gen_ctx, dead_var_t dv) { + DLIST_APPEND (dead_var_t, free_dead_vars, dv); +} static dead_var_t get_dead_var (gen_ctx_t gen_ctx) { dead_var_t dv; @@ -425,7 +456,7 @@ static dead_var_t get_dead_var (gen_ctx_t gen_ctx) { return dv; } -static void finish_dead_vars (void) { +static void finish_dead_vars (gen_ctx_t gen_ctx) { dead_var_t dv; while ((dv = DLIST_HEAD (dead_var_t, free_dead_vars)) != NULL) { @@ -454,16 +485,16 @@ static dead_var_t find_bb_insn_dead_var (bb_insn_t bb_insn, MIR_reg_t var) { return NULL; } -static void clear_bb_insn_dead_vars (bb_insn_t bb_insn) { +static void clear_bb_insn_dead_vars (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { dead_var_t dv; while ((dv = DLIST_HEAD (dead_var_t, bb_insn->dead_vars)) != NULL) { DLIST_REMOVE (dead_var_t, bb_insn->dead_vars, dv); - free_dead_var (dv); + free_dead_var (gen_ctx, dv); } } -static void remove_bb_insn_dead_var (bb_insn_t bb_insn, MIR_reg_t hr) { +static void remove_bb_insn_dead_var (gen_ctx_t gen_ctx, bb_insn_t bb_insn, MIR_reg_t hr) { dead_var_t dv, next_dv; gen_assert (hr <= MAX_HARD_REG); @@ -471,7 +502,7 @@ static void remove_bb_insn_dead_var (bb_insn_t bb_insn, MIR_reg_t hr) { next_dv = DLIST_NEXT (dead_var_t, dv); if (dv->var != hr) continue; DLIST_REMOVE (dead_var_t, bb_insn->dead_vars, dv); - free_dead_var (dv); + free_dead_var (gen_ctx, dv); } } @@ -521,7 +552,7 @@ static bb_insn_t create_bb_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, bb_t bb) { bb_insn->insn = insn; bb_insn->flag = FALSE; bb_insn->call_hard_reg_args = NULL; - gen_assert (curr_cfg->curr_bb_insn_index < (1ull << 32)); + gen_assert (curr_cfg->curr_bb_insn_index != (uint32_t) ~0ull); bb_insn->index = curr_cfg->curr_bb_insn_index++; bb_insn->gvn_val = bb_insn->index; DLIST_INIT (dead_var_t, bb_insn->dead_vars); @@ -536,10 +567,10 @@ static bb_insn_t add_new_bb_insn (gen_ctx_t gen_ctx, MIR_insn_t insn, bb_t bb) { return bb_insn; } -static void delete_bb_insn (bb_insn_t bb_insn) { +static void delete_bb_insn (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { DLIST_REMOVE (bb_insn_t, bb_insn->bb->bb_insns, bb_insn); bb_insn->insn->data = NULL; - clear_bb_insn_dead_vars (bb_insn); + clear_bb_insn_dead_vars (gen_ctx, bb_insn); if (bb_insn->call_hard_reg_args != NULL) bitmap_destroy (bb_insn->call_hard_reg_args); free (bb_insn); } @@ -588,7 +619,7 @@ static void gen_delete_insn (gen_ctx_t gen_ctx, MIR_insn_t insn) { if (optimize_level == 0) delete_insn_data (insn); else - delete_bb_insn (insn->data); + delete_bb_insn (gen_ctx, insn->data); MIR_remove_insn (gen_ctx->ctx, curr_func_item, insn); } @@ -612,6 +643,16 @@ static void gen_add_insn_after (gen_ctx_t gen_ctx, MIR_insn_t after, MIR_insn_t create_new_bb_insns (gen_ctx, after, DLIST_NEXT (MIR_insn_t, insn), after); } +static void gen_move_insn_before (gen_ctx_t gen_ctx, MIR_insn_t before, MIR_insn_t insn) { + DLIST_REMOVE (MIR_insn_t, curr_func_item->u.func->insns, insn); + MIR_insert_insn_before (gen_ctx->ctx, curr_func_item, before, insn); + if (optimize_level != 0) { + bb_insn_t bb_insn = insn->data, before_bb_insn = before->data; + DLIST_REMOVE (bb_insn_t, bb_insn->bb->bb_insns, bb_insn); + DLIST_INSERT_BEFORE (bb_insn_t, before_bb_insn->bb->bb_insns, before_bb_insn, bb_insn); + } +} + static void 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; @@ -1302,7 +1343,7 @@ static void destroy_func_cfg (gen_ctx_t gen_ctx) { } else { bb_insn = insn->data; gen_assert (bb_insn != NULL); - delete_bb_insn (bb_insn); + delete_bb_insn (gen_ctx, bb_insn); } for (bb = DLIST_HEAD (bb_t, curr_cfg->bbs); bb != NULL; bb = next_bb) { next_bb = DLIST_NEXT (bb_t, bb); @@ -3412,7 +3453,7 @@ static void add_bb_insn_dead_vars (gen_ctx_t gen_ctx) { bitmap_copy (live, bb->live_out); for (bb_insn = DLIST_TAIL (bb_insn_t, bb->bb_insns); bb_insn != NULL; bb_insn = prev_bb_insn) { prev_bb_insn = DLIST_PREV (bb_insn_t, bb_insn); - clear_bb_insn_dead_vars (bb_insn); + clear_bb_insn_dead_vars (gen_ctx, bb_insn); insn = bb_insn->insn; FOREACH_INSN_VAR (gen_ctx, insn_var_iter, insn, var, op_num, out_p, mem_p, passed_mem_num) { if (out_p) bitmap_clear_bit_p (live, var); @@ -4438,7 +4479,7 @@ static void combine_delete_insn (gen_ctx_t gen_ctx, MIR_insn_t def_insn, bb_insn fprintf (debug_file, " deleting now dead insn "); print_bb_insn (gen_ctx, def_insn->data, TRUE); }); - remove_bb_insn_dead_var (bb_insn, hr); + remove_bb_insn_dead_var (gen_ctx, bb_insn, hr); move_bb_insn_dead_vars (bb_insn, def_insn->data); /* We should delete the def insn here because of possible substitution of the def insn 'r0 = ... r0 ...'. We still @@ -4459,20 +4500,35 @@ static int64_t power2 (int64_t p) { static int64_t int_log2 (int64_t i) { int64_t n; - if (i == 0) return -1; + if (i <= 0) return -1; for (n = 0; (i & 1) == 0; n++, i >>= 1) ; return i == 1 ? n : -1; } -static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { +static MIR_insn_t get_uptodate_def_insn (gen_ctx_t gen_ctx, int hr) { + MIR_insn_t def_insn; + + if (!hreg_refs_addr[hr].def_p) return NULL; + gen_assert (!hreg_refs_addr[hr].del_p); + def_insn = hreg_refs_addr[hr].insn; + /* Checking hr0 = ... hr1 ...; ...; hr1 = ...; ...; insn */ + if ((def_insn->nops > 1 && obsolete_op_p (gen_ctx, def_insn->ops[1], hreg_refs_addr[hr].insn_num)) + || (def_insn->nops > 2 + && obsolete_op_p (gen_ctx, def_insn->ops[2], hreg_refs_addr[hr].insn_num))) + return NULL; + return def_insn; +} + +static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t *bb_insn_ref) { MIR_context_t ctx = gen_ctx->ctx; MIR_insn_code_t code, new_code; + bb_insn_t bb_insn = *bb_insn_ref; MIR_insn_t insn = bb_insn->insn, def_insn, new_insn; size_t i, nops = insn->nops; int out_p, insn_change_p, insn_hr_change_p, op_change_p, mem_reg_change_p, success_p; - MIR_op_t *op_ref, *src_op_ref, *src_op2_ref; - MIR_reg_t hr; + MIR_op_t *op_ref, *src_op_ref, *src_op2_ref, saved_op; + MIR_reg_t hr, early_clobbered_hard_reg1, early_clobbered_hard_reg2; int64_t scale, sh; if (nops == 0) return FALSE; @@ -4485,17 +4541,51 @@ static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { if (out_p && insn->ops[i].mode != MIR_OP_HARD_REG_MEM) continue; combine_process_op (gen_ctx, &insn->ops[i], bb_insn); } + if (move_code_p (insn->code) && VARR_LENGTH (MIR_reg_t, insn_hard_regs) == 1) { + /* We processed all other regs already. Try to change insn the following way: + hr0 = hr2 op hr3; ...; ... = hr0 => ...; ... = hr2 op hr3 */ + hr = VARR_GET (MIR_reg_t, insn_hard_regs, 0); + if ((def_insn = get_uptodate_def_insn (gen_ctx, hr)) == NULL + || MIR_call_code_p (def_insn->code)) + return FALSE; + target_get_early_clobbered_hard_regs (def_insn, &early_clobbered_hard_reg1, + &early_clobbered_hard_reg2); + if (!move_code_p (def_insn->code) && early_clobbered_hard_reg1 == MIR_NON_HARD_REG + && early_clobbered_hard_reg2 == MIR_NON_HARD_REG && insn->ops[1].mode == MIR_OP_HARD_REG + && insn->ops[1].u.hard_reg == hr + /* Check that insn->ops[0] is not mem[...hr0...]: */ + && (insn->ops[0].mode != MIR_OP_HARD_REG_MEM + || (insn->ops[0].u.hard_reg_mem.base != hr + && insn->ops[0].u.hard_reg_mem.index != hr))) { + saved_op = def_insn->ops[0]; + def_insn->ops[0] = insn->ops[0]; + success_p = target_insn_ok_p (gen_ctx, def_insn); + def_insn->ops[0] = saved_op; + if (!success_p) return FALSE; + gen_move_insn_before (gen_ctx, insn, def_insn); + DEBUG ({ + 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 ({ + 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); + *bb_insn_ref = def_insn->data; + return TRUE; + } + } insn_change_p = FALSE; while (VARR_LENGTH (MIR_reg_t, insn_hard_regs) != 0) { hr = VARR_POP (MIR_reg_t, insn_hard_regs); - if (!hreg_refs_addr[hr].def_p) continue; - gen_assert (!hreg_refs_addr[hr].del_p); - def_insn = hreg_refs_addr[hr].insn; - if ((def_insn->nops > 1 - && obsolete_op_p (gen_ctx, def_insn->ops[1], hreg_refs_addr[hr].insn_num)) - || (def_insn->nops > 2 - && obsolete_op_p (gen_ctx, def_insn->ops[2], hreg_refs_addr[hr].insn_num))) - continue; /* hr0 = ... hr1 ...; ...; hr1 = ...; ...; insn */ + if ((def_insn = get_uptodate_def_insn (gen_ctx, hr)) == NULL) continue; insn_hr_change_p = FALSE; for (i = 0; i < nops; i++) { /* Change all hr occurences: */ op_ref = &insn->ops[i]; @@ -4589,28 +4679,6 @@ static int combine_substitute (gen_ctx_t gen_ctx, bb_insn_t bb_insn) { } if (op_change_p) VARR_PUSH (size_t, changed_op_numbers, i); } - code = insn->code; - if (i >= nops && (code == MIR_MUL || code == MIR_MULS || code == MIR_UDIV || code == MIR_UDIVS) - && insn->ops[2].mode == MIR_OP_INT && (sh = int_log2 (insn->ops[2].u.i)) >= 0) { - new_code = code; /* to remove an initialized warning */ - switch (code) { - case MIR_MUL: new_code = MIR_LSH; break; - case MIR_MULS: new_code = MIR_LSHS; break; - case MIR_UDIV: new_code = MIR_URSH; break; - case MIR_UDIVS: new_code = MIR_URSHS; break; - default: gen_assert (FALSE); - } - new_insn = MIR_new_insn (ctx, new_code, insn->ops[0], insn->ops[1], MIR_new_int_op (ctx, sh)); - MIR_insert_insn_after (ctx, curr_func_item, insn, new_insn); - if (target_insn_ok_p (gen_ctx, new_insn)) { - insn->code = new_insn->code; - insn->ops[0] = new_insn->ops[0]; - insn->ops[1] = new_insn->ops[1]; - insn->ops[2] = new_insn->ops[2]; - } - MIR_remove_insn (ctx, curr_func_item, new_insn); - insn_hr_change_p = TRUE; - } if (insn_hr_change_p) { if ((success_p = i >= nops && target_insn_ok_p (gen_ctx, insn))) insn_change_p = TRUE; while (VARR_LENGTH (size_t, changed_op_numbers)) { @@ -4714,6 +4782,110 @@ static MIR_insn_t combine_branch_and_cmp (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) { + 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; + int n, sh, ok_p; + MIR_op_t op, temp; + + switch (code) { + case MIR_MUL: new_code = MIR_LSH; break; + case MIR_MULS: new_code = MIR_LSHS; break; + case MIR_UDIV: new_code = MIR_URSH; break; + case MIR_UDIVS: new_code = MIR_URSHS; break; + case MIR_DIV: new_code = MIR_RSH; break; + case MIR_DIVS: new_code = MIR_RSHS; break; + default: return NULL; + } + op = insn->ops[2]; + if (op.mode == MIR_OP_HARD_REG && safe_hreg_substitution_p (gen_ctx, op.u.hard_reg, bb_insn)) { + def_insn = hreg_refs_addr[op.u.hard_reg].insn; + if (def_insn->code != MIR_MOV) return NULL; + op = def_insn->ops[1]; + } + if (op.mode != MIR_OP_INT && op.mode != MIR_OP_UINT) return NULL; + if ((sh = int_log2 (op.u.i)) < 0) return NULL; + if (sh == 0) { + 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 ({ + 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 ({ + fprintf (debug_file, " deleting now dead insn "); + print_bb_insn (gen_ctx, def_insn->data, TRUE); + }); + gen_delete_insn (gen_ctx, def_insn); + } + return new_insns[0]; + } else if (code == MIR_MUL || code == MIR_MULS || code == MIR_UDIV || code == MIR_UDIVS) { + new_insns[0] + = MIR_new_insn (ctx, new_code, insn->ops[0], insn->ops[1], MIR_new_int_op (ctx, sh)); + MIR_insert_insn_after (ctx, curr_func_item, insn, new_insns[0]); + 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 ({ + fprintf (debug_file, " changing to "); + print_bb_insn (gen_ctx, bb_insn, TRUE); + }); + } + MIR_remove_insn (ctx, curr_func_item, new_insns[0]); + return ok_p ? insn : NULL; + } else if (insn->ops[1].mode == MIR_OP_HARD_REG + && insn->ops[1].u.hard_reg == TEMP_INT_HARD_REG2) { + } else if (insn->ops[1].mode == MIR_OP_HARD_REG_MEM + && (insn->ops[1].u.hard_reg_mem.base == TEMP_INT_HARD_REG2 + || insn->ops[1].u.hard_reg_mem.index == TEMP_INT_HARD_REG2)) { + } else { + temp = _MIR_new_hard_reg_op (ctx, TEMP_INT_HARD_REG2); + gen_assert (code == MIR_DIV || code == MIR_DIVS); + new_insns[0] = MIR_new_insn (ctx, MIR_MOV, temp, insn->ops[1]); + if (code == MIR_DIV) { + new_insns[1] = MIR_new_insn (ctx, MIR_RSH, temp, temp, MIR_new_int_op (ctx, 63)); + new_insns[2] = MIR_new_insn (ctx, MIR_AND, temp, temp, MIR_new_int_op (ctx, op.u.i - 1)); + new_insns[3] = MIR_new_insn (ctx, MIR_ADD, temp, temp, insn->ops[1]); + } else { + new_insns[1] = MIR_new_insn (ctx, MIR_RSHS, temp, temp, MIR_new_int_op (ctx, 31)); + new_insns[2] = MIR_new_insn (ctx, MIR_ANDS, temp, temp, MIR_new_int_op (ctx, op.u.i - 1)); + new_insns[3] = MIR_new_insn (ctx, MIR_ADDS, temp, temp, insn->ops[1]); + } + new_insns[4] = MIR_new_insn (ctx, new_code, temp, temp, MIR_new_int_op (ctx, sh)); + new_insns[5] = MIR_new_insn (ctx, MIR_MOV, insn->ops[0], temp); + for (n = 0; n < 6; n++) gen_add_insn_before (gen_ctx, insn, new_insns[n]); + for (n = 0; n < 6; n++) + if (!target_insn_ok_p (gen_ctx, new_insns[n])) break; + if (n < 6) { + for (n = 0; n < 6; n++) gen_delete_insn (gen_ctx, new_insns[n]); + } 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 ({ + fprintf (debug_file, " changing to "); + for (n = 0; n < 6; n++) { + if (n != 0) fprintf (debug_file, " "); + print_bb_insn (gen_ctx, new_insns[n]->data, TRUE); + } + }); + gen_delete_insn (gen_ctx, insn); + if (def_insn != NULL) { + DEBUG ({ + fprintf (debug_file, " deleting now dead insn "); + print_bb_insn (gen_ctx, def_insn->data, TRUE); + }); + gen_delete_insn (gen_ctx, def_insn); + } + return new_insns[0]; + } + } + return NULL; +} + static void setup_hreg_ref (gen_ctx_t gen_ctx, MIR_reg_t hr, MIR_insn_t insn, size_t nop, size_t insn_num, int def_p) { if (hr == MIR_NON_HARD_REG) return; @@ -4771,20 +4943,27 @@ static void combine (gen_ctx_t gen_ctx) { last_mem_ref_insn_num = curr_insn_num; /* Potentially call can 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) { + } else if ((new_insn = combine_branch_and_cmp (gen_ctx, bb_insn)) != NULL + || (new_insn = combine_mul_div_substitute (gen_ctx, bb_insn)) != NULL) { + bb_insn = new_insn->data; insn = new_insn; nops = MIR_insn_nops (ctx, insn); block_change_p = TRUE; } else { - change_p = combine_substitute (gen_ctx, bb_insn); - if (!change_p && (new_code = commutative_insn_code (insn->code)) != MIR_INSN_BOUND) { + if ((change_p = combine_substitute (gen_ctx, &bb_insn))) { + insn = bb_insn->insn; + nops = MIR_insn_nops (ctx, insn); + } else if (!change_p + && (new_code = commutative_insn_code (insn->code)) != MIR_INSN_BOUND) { insn->code = new_code; 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)) { + insn = bb_insn->insn; + nops = MIR_insn_nops (ctx, insn); change_p = TRUE; - else { + } else { insn->code = code; temp_op = insn->ops[1]; insn->ops[1] = insn->ops[2]; @@ -4992,7 +5171,7 @@ static void ssa_dead_code_elimination (gen_ctx_t gen_ctx) { static void print_code (gen_ctx_t gen_ctx, uint8_t *code, size_t code_len, void *start_addr) { size_t i; int ch; - char cfname[30]; + char cfname[50]; char command[500]; FILE *f; #if !defined(__APPLE__) @@ -5000,7 +5179,7 @@ static void print_code (gen_ctx_t gen_ctx, uint8_t *code, size_t code_len, void FILE *bf; #endif - sprintf (cfname, "_mir_%lu.c", (unsigned long) getpid ()); + sprintf (cfname, "_mir_%d_%lu.c", gen_ctx->gen_num, (unsigned long) getpid ()); if ((f = fopen (cfname, "w")) == NULL) return; #if defined(__APPLE__) fprintf (f, "unsigned char code[] = {"); @@ -5013,7 +5192,7 @@ static void print_code (gen_ctx_t gen_ctx, uint8_t *code, size_t code_len, void sprintf (command, "gcc -c -o %s.o %s 2>&1 && objdump --section=.data -D %s.o; rm -f %s.o %s", cfname, cfname, cfname, cfname, cfname); #else - sprintf (bfname, "_mir_%lu.bin", (unsigned long) getpid ()); + sprintf (bfname, "_mir_%d_%lu.bin", gen_ctx->gen_num, (unsigned long) getpid ()); if ((bf = fopen (bfname, "w")) == NULL) return; fprintf (f, "void code (void) {}\n"); for (i = 0; i < code_len; i++) fputc (code[i], bf); @@ -5045,14 +5224,23 @@ static void *print_and_execute_wrapper (gen_ctx_t gen_ctx, MIR_item_t called_fun } #endif -void *MIR_gen (MIR_context_t ctx, MIR_item_t func_item) { - gen_ctx_t gen_ctx = *gen_ctx_loc (ctx); +static void parallel_error (MIR_context_t ctx, const char *err_message) { + MIR_get_error_func (ctx) (MIR_parallel_error, err_message); +} + +void *MIR_gen (MIR_context_t ctx, int gen_num, MIR_item_t func_item) { + struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); + gen_ctx_t gen_ctx; uint8_t *code; + void *machine_code; size_t code_len; -#if !MIR_NO_GEN_DEBUG - double start_time = 0.0; -#endif + double start_time = real_usec_time (); +#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]; gen_assert (func_item->item_type == MIR_func_item && func_item->data == NULL); if (func_item->u.func->machine_code != NULL) { gen_assert (func_item->u.func->call_addr != NULL); @@ -5064,7 +5252,6 @@ void *MIR_gen (MIR_context_t ctx, MIR_item_t func_item) { return func_item->addr; } DEBUG ({ - start_time = real_usec_time (); fprintf (debug_file, "+++++++++++++MIR before generator:\n"); MIR_output_item (ctx, debug_file, func_item); }); @@ -5180,15 +5367,13 @@ void *MIR_gen (MIR_context_t ctx, MIR_item_t func_item) { print_CFG (gen_ctx, FALSE, FALSE, TRUE, FALSE, NULL); }); code = target_translate (gen_ctx, &code_len); - func_item->u.func->machine_code = func_item->u.func->call_addr - = _MIR_publish_code (ctx, code, code_len); - target_rebase (gen_ctx, func_item->u.func->machine_code); + machine_code = func_item->u.func->call_addr = _MIR_publish_code (ctx, code, code_len); + target_rebase (gen_ctx, func_item->u.func->call_addr); #if MIR_GEN_CALL_TRACE func_item->u.func->call_addr = _MIR_get_wrapper (ctx, func_item, print_and_execute_wrapper); #endif DEBUG ({ - print_code (gen_ctx, func_item->u.func->machine_code, code_len, - func_item->u.func->machine_code); + print_code (gen_ctx, machine_code, code_len, machine_code); fprintf (debug_file, "code size = %lu:\n", (unsigned long) code_len); }); _MIR_redirect_thunk (ctx, func_item->addr, func_item->u.func->call_addr); @@ -5196,118 +5381,296 @@ void *MIR_gen (MIR_context_t ctx, MIR_item_t func_item) { if (optimize_level != 0) destroy_loop_tree (gen_ctx, curr_cfg->root_loop_node); destroy_func_cfg (gen_ctx); DEBUG ({ - fprintf (debug_file, "Generation of code for %s: %lu MIR insns -- time %.0f usec\n", + fprintf (debug_file, + "Generation of code for %s: %lu MIR insns (addr=%lx, len=%lu) -- time %.2f ms\n", MIR_item_name (ctx, func_item), DLIST_LENGTH (MIR_insn_t, func_item->u.func->insns), - real_usec_time () - start_time); + (unsigned long) machine_code, (unsigned long) code_len, + (real_usec_time () - start_time) / 1000.0); }); _MIR_restore_func_insns (ctx, func_item); + /* ??? We should use atomic here but c2mir does not implement them yet. */ +#if MIR_PARALLEL_GEN + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); +#endif + func_item->u.func->machine_code = machine_code; +#if MIR_PARALLEL_GEN + if (mir_cond_broadcast (&done_signal)) parallel_error (ctx, "error in cond broadcast"); + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); +#endif return func_item->addr; } -void MIR_gen_set_debug_file (MIR_context_t ctx, FILE *f) { +void MIR_gen_set_debug_file (MIR_context_t ctx, int gen_num, FILE *f) { #if !MIR_NO_GEN_DEBUG - gen_ctx_t gen_ctx = *gen_ctx_loc (ctx); + struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); + gen_ctx_t gen_ctx; - if (gen_ctx == NULL) { + if (all_gen_ctx == NULL) { fprintf (stderr, "Calling MIR_gen_set_debug_file 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_file = f; #endif } -void MIR_gen_set_optimize_level (MIR_context_t ctx, unsigned int level) { - gen_ctx_t gen_ctx = *gen_ctx_loc (ctx); +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; +#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]; optimize_level = level; } -void MIR_gen_init (MIR_context_t ctx) { - gen_ctx_t *gen_ctx_ptr = gen_ctx_loc (ctx), gen_ctx; - MIR_reg_t i; +#if MIR_PARALLEL_GEN +static void *gen (void *arg) { + MIR_item_t func_item; + gen_ctx_t gen_ctx = arg; + struct all_gen_ctx *all_gen_ctx = gen_ctx->all_gen_ctx; + MIR_context_t ctx = all_gen_ctx->ctx; + size_t len; + + for (;;) { + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + while (VARR_LENGTH (MIR_item_t, funcs_to_generate) <= funcs_start) + if (mir_cond_wait (&generate_signal, &queue_mutex)) + parallel_error (ctx, "error in cond wait"); + if ((func_item = VARR_GET (MIR_item_t, funcs_to_generate, funcs_start)) == NULL) { + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + break; + } + funcs_start++; + if (funcs_start > 64 && VARR_LENGTH (MIR_item_t, funcs_to_generate) < 2 * funcs_start) { + len = VARR_LENGTH (MIR_item_t, funcs_to_generate) - funcs_start; + memmove (VARR_ADDR (MIR_item_t, funcs_to_generate), /* compact */ + VARR_ADDR (MIR_item_t, funcs_to_generate) + funcs_start, len * sizeof (MIR_item_t)); + VARR_TRUNC (MIR_item_t, funcs_to_generate, len); + funcs_start = 0; + } + gen_ctx->busy_p = TRUE; + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + MIR_gen (gen_ctx->ctx, gen_ctx->gen_num, func_item); + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + gen_ctx->busy_p = FALSE; + if (mir_cond_signal (&done_signal)) parallel_error (ctx, "error in cond signal"); + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + } + return NULL; +} - *gen_ctx_ptr = gen_ctx = gen_malloc (NULL, sizeof (struct gen_ctx)); - gen_ctx->ctx = ctx; - optimize_level = 2; - gen_ctx->target_ctx = NULL; - gen_ctx->data_flow_ctx = NULL; - gen_ctx->gvn_ctx = NULL; - gen_ctx->ccp_ctx = NULL; - gen_ctx->lr_ctx = NULL; - gen_ctx->ra_ctx = NULL; - gen_ctx->selection_ctx = NULL; +static void signal_threads_to_finish (struct all_gen_ctx *all_gen_ctx) { + MIR_context_t ctx = all_gen_ctx->ctx; + + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + funcs_start = 0; + VARR_TRUNC (MIR_item_t, funcs_to_generate, 0); + VARR_PUSH (MIR_item_t, funcs_to_generate, NULL); /* flag to finish threads */ + if (mir_cond_broadcast (&generate_signal)) parallel_error (ctx, "error in cond broadcast"); + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); +} +#endif + +void MIR_gen_init (MIR_context_t ctx, int gens_num) { + struct all_gen_ctx **all_gen_ctx_ptr = all_gen_ctx_loc (ctx), *all_gen_ctx; + gen_ctx_t gen_ctx; + MIR_reg_t reg; + +#if !MIR_PARALLEL_GEN + gens_num = 1; +#else + if (gens_num < 1) gens_num = 1; +#endif + *all_gen_ctx_ptr = all_gen_ctx + = gen_malloc (NULL, sizeof (struct all_gen_ctx) + sizeof (struct gen_ctx) * (gens_num - 1)); + all_gen_ctx->ctx = ctx; + all_gen_ctx->gens_num = gens_num; +#if MIR_PARALLEL_GEN + funcs_start = 0; + VARR_CREATE (MIR_item_t, funcs_to_generate, 0); + if (mir_mutex_init (&queue_mutex, NULL) != 0) { + (*MIR_get_error_func (ctx)) (MIR_parallel_error, "can not create a generator thread lock"); + } else if (mir_cond_init (&generate_signal, NULL) != 0) { + mir_mutex_destroy (&queue_mutex); + (*MIR_get_error_func (ctx)) (MIR_parallel_error, "can not create a generator thread signal"); + } else if (mir_cond_init (&done_signal, NULL) != 0) { + mir_cond_destroy (&generate_signal); + mir_mutex_destroy (&queue_mutex); + (*MIR_get_error_func (ctx)) (MIR_parallel_error, "can not create a generator thread signal"); + } else { + for (int i = 0; i < gens_num; i++) { + gen_ctx = &all_gen_ctx->gen_ctx[i]; + gen_ctx->busy_p = FALSE; + gen_ctx->gen_num = i; + gen_ctx->all_gen_ctx = all_gen_ctx; + if (mir_thread_create (&gen_ctx->gen_thread, NULL, gen, gen_ctx) != 0) { + signal_threads_to_finish (all_gen_ctx); + for (int j = 0; j < i; j++) mir_thread_join (all_gen_ctx->gen_ctx[j].gen_thread, NULL); + mir_cond_destroy (&done_signal); + mir_cond_destroy (&generate_signal); + mir_mutex_destroy (&queue_mutex); + (*MIR_get_error_func (ctx)) (MIR_parallel_error, "can not create a generator thread"); + } + } + } +#endif + for (int n = 0; n < gens_num; n++) { + gen_ctx = &all_gen_ctx->gen_ctx[n]; +#if !MIR_PARALLEL_GEN + gen_ctx->all_gen_ctx = all_gen_ctx; + gen_ctx->gen_num = n; +#endif + gen_ctx->ctx = ctx; + optimize_level = 2; + gen_ctx->target_ctx = NULL; + gen_ctx->data_flow_ctx = NULL; + gen_ctx->gvn_ctx = NULL; + gen_ctx->ccp_ctx = NULL; + gen_ctx->lr_ctx = NULL; + gen_ctx->ra_ctx = NULL; + gen_ctx->selection_ctx = NULL; #if !MIR_NO_GEN_DEBUG - debug_file = NULL; + debug_file = NULL; #endif - VARR_CREATE (bb_insn_t, dead_bb_insns, 16); - VARR_CREATE (loop_node_t, loop_nodes, 32); - VARR_CREATE (loop_node_t, queue_nodes, 32); - VARR_CREATE (loop_node_t, loop_entries, 16); - init_dead_vars (); - init_data_flow (gen_ctx); - init_ssa (gen_ctx); - init_gvn (gen_ctx); - init_ccp (gen_ctx); - temp_bitmap = bitmap_create2 (DEFAULT_INIT_BITMAP_BITS_NUM); - temp_bitmap2 = bitmap_create2 (DEFAULT_INIT_BITMAP_BITS_NUM); - init_live_ranges (gen_ctx); - init_ra (gen_ctx); - init_selection (gen_ctx); - target_init (gen_ctx); - max_int_hard_regs = max_fp_hard_regs = 0; - for (i = 0; i <= MAX_HARD_REG; i++) { - if (target_fixed_hard_reg_p (i)) continue; - target_hard_reg_type_ok_p (i, MIR_T_I32) ? max_int_hard_regs++ : max_fp_hard_regs++; - } - for (MIR_type_t type = MIR_T_I8; type < MIR_T_BOUND; type++) { - call_used_hard_regs[type] = bitmap_create2 (MAX_HARD_REG + 1); - for (i = 0; i <= MAX_HARD_REG; i++) { - /* We need call_used_hard_regs even for fixed regs in combine. */ - if (target_call_used_hard_reg_p (i, type)) bitmap_set_bit_p (call_used_hard_regs[type], i); + VARR_CREATE (bb_insn_t, dead_bb_insns, 16); + VARR_CREATE (loop_node_t, loop_nodes, 32); + VARR_CREATE (loop_node_t, queue_nodes, 32); + VARR_CREATE (loop_node_t, loop_entries, 16); + init_dead_vars (gen_ctx); + init_data_flow (gen_ctx); + init_ssa (gen_ctx); + init_gvn (gen_ctx); + init_ccp (gen_ctx); + temp_bitmap = bitmap_create2 (DEFAULT_INIT_BITMAP_BITS_NUM); + temp_bitmap2 = bitmap_create2 (DEFAULT_INIT_BITMAP_BITS_NUM); + init_live_ranges (gen_ctx); + init_ra (gen_ctx); + init_selection (gen_ctx); + target_init (gen_ctx); + max_int_hard_regs = max_fp_hard_regs = 0; + for (int i = 0; i <= MAX_HARD_REG; i++) { + if (target_fixed_hard_reg_p (i)) continue; + target_hard_reg_type_ok_p (i, MIR_T_I32) ? max_int_hard_regs++ : max_fp_hard_regs++; } + for (MIR_type_t type = MIR_T_I8; type < MIR_T_BOUND; type++) { + call_used_hard_regs[type] = bitmap_create2 (MAX_HARD_REG + 1); + for (int i = 0; i <= MAX_HARD_REG; i++) { + /* We need call_used_hard_regs even for fixed regs in combine. */ + if (target_call_used_hard_reg_p (i, type)) bitmap_set_bit_p (call_used_hard_regs[type], i); + } + } + insn_to_consider = bitmap_create2 (1024); + func_used_hard_regs = bitmap_create2 (MAX_HARD_REG + 1); } - insn_to_consider = bitmap_create2 (1024); - func_used_hard_regs = bitmap_create2 (MAX_HARD_REG + 1); } void MIR_gen_finish (MIR_context_t ctx) { - gen_ctx_t *gen_ctx_ptr = gen_ctx_loc (ctx); - gen_ctx_t gen_ctx = *gen_ctx_ptr; - - finish_data_flow (gen_ctx); - finish_ssa (gen_ctx); - finish_gvn (gen_ctx); - finish_ccp (gen_ctx); - bitmap_destroy (temp_bitmap); - bitmap_destroy (temp_bitmap2); - finish_live_ranges (gen_ctx); - finish_ra (gen_ctx); - finish_selection (gen_ctx); - for (MIR_type_t type = MIR_T_I8; type < MIR_T_BOUND; type++) - bitmap_destroy (call_used_hard_regs[type]); - bitmap_destroy (insn_to_consider); - bitmap_destroy (func_used_hard_regs); - target_finish (gen_ctx); - finish_dead_vars (); - free (gen_ctx->data_flow_ctx); - VARR_DESTROY (bb_insn_t, dead_bb_insns); - VARR_DESTROY (loop_node_t, loop_nodes); - VARR_DESTROY (loop_node_t, queue_nodes); - VARR_DESTROY (loop_node_t, loop_entries); - free (gen_ctx); - *gen_ctx_ptr = NULL; + struct all_gen_ctx **all_gen_ctx_ptr = all_gen_ctx_loc (ctx), *all_gen_ctx = *all_gen_ctx_ptr; + gen_ctx_t gen_ctx; + +#if MIR_PARALLEL_GEN + signal_threads_to_finish (all_gen_ctx); + for (int i = 0; i < all_gen_ctx->gens_num; i++) + mir_thread_join (all_gen_ctx->gen_ctx[i].gen_thread, NULL); + if (mir_mutex_destroy (&queue_mutex) != 0 || mir_cond_destroy (&generate_signal) != 0 + || mir_cond_destroy (&done_signal) != 0) { // ??? + (*MIR_get_error_func (all_gen_ctx->ctx)) (MIR_parallel_error, + "can not destroy generator mutex or signals"); + } +#endif + for (int i = 0; i < all_gen_ctx->gens_num; i++) { + gen_ctx = &all_gen_ctx->gen_ctx[i]; + finish_data_flow (gen_ctx); + finish_ssa (gen_ctx); + finish_gvn (gen_ctx); + finish_ccp (gen_ctx); + bitmap_destroy (temp_bitmap); + bitmap_destroy (temp_bitmap2); + finish_live_ranges (gen_ctx); + finish_ra (gen_ctx); + finish_selection (gen_ctx); + for (MIR_type_t type = MIR_T_I8; type < MIR_T_BOUND; type++) + bitmap_destroy (call_used_hard_regs[type]); + bitmap_destroy (insn_to_consider); + bitmap_destroy (func_used_hard_regs); + target_finish (gen_ctx); + finish_dead_vars (gen_ctx); + free (gen_ctx->data_flow_ctx); + VARR_DESTROY (bb_insn_t, dead_bb_insns); + VARR_DESTROY (loop_node_t, loop_nodes); + VARR_DESTROY (loop_node_t, queue_nodes); + VARR_DESTROY (loop_node_t, loop_entries); + } + free (all_gen_ctx); + *all_gen_ctx_ptr = NULL; +} + +void MIR_set_gen_interface (MIR_context_t ctx, MIR_item_t func_item) { + if (func_item == NULL) return; /* finish setting interfaces */ + MIR_gen (ctx, 0, func_item); +} + +void MIR_set_parallel_gen_interface (MIR_context_t ctx, MIR_item_t func_item) { + struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); + +#if !MIR_PARALLEL_GEN + if (func_item == NULL) return; /* finish setting interfaces */ + MIR_gen (ctx, 0, func_item); +#else + if (func_item == NULL) { + size_t i; + + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + for (;;) { + for (i = 0; i < all_gen_ctx->gens_num; i++) + if (all_gen_ctx->gen_ctx[i].busy_p) break; + if (VARR_LENGTH (MIR_item_t, funcs_to_generate) <= funcs_start && i >= all_gen_ctx->gens_num) + break; /* nothing to generate and nothing is being generated */ + if (mir_cond_wait (&done_signal, &queue_mutex)) parallel_error (ctx, "error in cond wait"); + } + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + } else { + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + VARR_PUSH (MIR_item_t, funcs_to_generate, func_item); + if (mir_cond_broadcast (&generate_signal)) parallel_error (ctx, "error in cond broadcast"); + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + } +#endif } -void MIR_set_gen_interface (MIR_context_t ctx, MIR_item_t func_item) { MIR_gen (ctx, func_item); } - static void *gen_and_redirect (MIR_context_t ctx, MIR_item_t func_item) { - MIR_gen (ctx, func_item); +#if !MIR_PARALLEL_GEN + MIR_gen (ctx, 0, func_item); +#else + struct all_gen_ctx *all_gen_ctx = *all_gen_ctx_loc (ctx); + MIR_func_t func = func_item->u.func; + + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + VARR_PUSH (MIR_item_t, funcs_to_generate, func_item); + if (mir_cond_broadcast (&generate_signal)) parallel_error (ctx, "error in cond broadcast"); + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); + if (mir_mutex_lock (&queue_mutex)) parallel_error (ctx, "error in mutex lock"); + for (;;) { + if (func->machine_code != NULL) break; + if (mir_cond_wait (&done_signal, &queue_mutex)) parallel_error (ctx, "error in cond wait"); + } + if (mir_mutex_unlock (&queue_mutex)) parallel_error (ctx, "error in mutex unlock"); +#endif return func_item->u.func->machine_code; } void MIR_set_lazy_gen_interface (MIR_context_t ctx, MIR_item_t func_item) { - void *addr = _MIR_get_wrapper (ctx, func_item, gen_and_redirect); + void *addr; + if (func_item == NULL) return; + addr = _MIR_get_wrapper (ctx, func_item, gen_and_redirect); _MIR_redirect_thunk (ctx, func_item->addr, addr); } diff --git a/mir/mir-gen.h b/mir/mir-gen.h index 9c18e31..2635fe1 100644 --- a/mir/mir-gen.h +++ b/mir/mir-gen.h @@ -12,11 +12,12 @@ #define MIR_NO_GEN_DEBUG 0 #endif -extern void MIR_gen_init (MIR_context_t ctx); -extern void MIR_gen_set_debug_file (MIR_context_t ctx, FILE *f); -extern void MIR_gen_set_optimize_level (MIR_context_t ctx, unsigned int level); -extern void *MIR_gen (MIR_context_t ctx, MIR_item_t func_item); +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_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); +extern void MIR_set_parallel_gen_interface (MIR_context_t ctx, MIR_item_t func_item); 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); diff --git a/mir/mir-interp.c b/mir/mir-interp.c index f82dac8..1752440 100644 --- a/mir/mir-interp.c +++ b/mir/mir-interp.c @@ -1527,7 +1527,7 @@ static void interp_init (MIR_context_t ctx) { struct interp_ctx *interp_ctx; if ((interp_ctx = ctx->interp_ctx = malloc (sizeof (struct interp_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); #if DIRECT_THREADED_DISPATCH eval (ctx, NULL, NULL, NULL); #endif @@ -1696,7 +1696,7 @@ static void redirect_interface_to_interp (MIR_context_t ctx, MIR_item_t func_ite } void MIR_set_interp_interface (MIR_context_t ctx, MIR_item_t func_item) { - redirect_interface_to_interp (ctx, func_item); + if (func_item != NULL) redirect_interface_to_interp (ctx, func_item); } #endif /* #ifdef MIR_NO_INTERP */ diff --git a/mir/mir-ppc64.c b/mir/mir-ppc64.c index e7c9581..71deaaa 100644 --- a/mir/mir-ppc64.c +++ b/mir/mir-ppc64.c @@ -17,13 +17,13 @@ #define PPC64_FUNC_DESC_LEN 24 #endif -static void ppc64_push_func_desc (MIR_context_t ctx); -void (*ppc64_func_desc) (MIR_context_t ctx) = ppc64_push_func_desc; +static void ppc64_push_func_desc (VARR (uint8_t) ** insn_varr); +void (*ppc64_func_desc) (VARR (uint8_t) ** insn_varr) = ppc64_push_func_desc; -static void ppc64_push_func_desc (MIR_context_t ctx) { - VARR_TRUNC (uint8_t, machine_insns, 0); +static void ppc64_push_func_desc (VARR (uint8_t) ** insn_varr) { + VARR_CREATE (uint8_t, *insn_varr, 128); for (int i = 0; i < PPC64_FUNC_DESC_LEN; i++) - VARR_PUSH (uint8_t, machine_insns, ((uint8_t *) ppc64_func_desc)[i]); + VARR_PUSH (uint8_t, *insn_varr, ((uint8_t *) ppc64_func_desc)[i]); } #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ @@ -33,99 +33,102 @@ static void ppc64_redirect_func_desc (MIR_context_t ctx, void *desc, void *to) { } #endif -static void *ppc64_publish_func_and_redirect (MIR_context_t ctx) { - void *res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); +static void *ppc64_publish_func_and_redirect (MIR_context_t ctx, VARR (uint8_t) * insn_varr) { + void *res + = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, insn_varr), VARR_LENGTH (uint8_t, insn_varr)); #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ppc64_redirect_func_desc (ctx, res, (uint8_t *) res + PPC64_FUNC_DESC_LEN); #endif + VARR_DESTROY (uint8_t, insn_varr); return res; } -static void push_insn (MIR_context_t ctx, uint32_t insn) { +static void push_insn (VARR (uint8_t) * insn_varr, uint32_t insn) { uint8_t *p = (uint8_t *) &insn; - for (size_t i = 0; i < 4; i++) VARR_PUSH (uint8_t, machine_insns, p[i]); + for (size_t i = 0; i < 4; i++) VARR_PUSH (uint8_t, insn_varr, p[i]); } -static void push_insns (MIR_context_t ctx, const uint32_t *pat, size_t pat_len) { +static void push_insns (VARR (uint8_t) * insn_varr, const uint32_t *pat, size_t pat_len) { uint8_t *p = (uint8_t *) pat; - for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, machine_insns, p[i]); + for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, insn_varr, p[i]); } -static void ppc64_gen_mov (MIR_context_t ctx, unsigned to, unsigned from) { +static void ppc64_gen_mov (VARR (uint8_t) * insn_varr, unsigned to, unsigned from) { /* or to,from,from: */ - push_insn (ctx, (31 << 26) | (444 << 1) | (from << 21) | (to << 16) | (from << 11)); + push_insn (insn_varr, (31 << 26) | (444 << 1) | (from << 21) | (to << 16) | (from << 11)); } -static void ppc64_gen_addi (MIR_context_t ctx, unsigned rt_reg, unsigned ra_reg, int disp) { - push_insn (ctx, (14 << 26) | (rt_reg << 21) | (ra_reg << 16) | (disp & 0xffff)); +static void ppc64_gen_addi (VARR (uint8_t) * insn_varr, unsigned rt_reg, unsigned ra_reg, + int disp) { + push_insn (insn_varr, (14 << 26) | (rt_reg << 21) | (ra_reg << 16) | (disp & 0xffff)); } -static void ppc64_gen_add (MIR_context_t ctx, unsigned rt_reg, unsigned ra_reg, unsigned rb_reg) { - push_insn (ctx, (31 << 26) | (266 << 1) | (rt_reg << 21) | (ra_reg << 16) | (rb_reg << 11)); +static void ppc64_gen_add (VARR (uint8_t) * insn_varr, unsigned rt_reg, unsigned ra_reg, + unsigned rb_reg) { + push_insn (insn_varr, (31 << 26) | (266 << 1) | (rt_reg << 21) | (ra_reg << 16) | (rb_reg << 11)); } -static void ppc64_gen_ld (MIR_context_t ctx, unsigned to, unsigned base, int disp, +static void ppc64_gen_ld (VARR (uint8_t) * insn_varr, unsigned to, unsigned base, int disp, MIR_type_t type) { int single_p = type == MIR_T_F; int double_p = type == MIR_T_D || type == MIR_T_LD; /* (ld | lf[sd]) to, disp(base): */ assert (base != 0 && base < 32 && to < 32 && (single_p || double_p || (disp & 0x3) == 0)); - push_insn (ctx, ((single_p ? 48 : double_p ? 50 : 58) << 26) | (to << 21) | (base << 16) - | (disp & 0xffff)); + push_insn (insn_varr, ((single_p ? 48 : double_p ? 50 : 58) << 26) | (to << 21) | (base << 16) + | (disp & 0xffff)); } -static void ppc64_gen_st (MIR_context_t ctx, unsigned from, unsigned base, int disp, +static void ppc64_gen_st (VARR (uint8_t) * insn_varr, unsigned from, unsigned base, int disp, MIR_type_t type) { int single_p = type == MIR_T_F; int double_p = type == MIR_T_D || type == MIR_T_LD; /* std|stf[sd] from, disp(base): */ assert (base != 0 && base < 32 && from < 32 && (single_p || double_p || (disp & 0x3) == 0)); - push_insn (ctx, ((single_p ? 52 : double_p ? 54 : 62) << 26) | (from << 21) | (base << 16) - | (disp & 0xffff)); + push_insn (insn_varr, ((single_p ? 52 : double_p ? 54 : 62) << 26) | (from << 21) | (base << 16) + | (disp & 0xffff)); } -static void ppc64_gen_stdu (MIR_context_t ctx, int disp) { +static void ppc64_gen_stdu (VARR (uint8_t) * insn_varr, int disp) { assert ((disp & 0x3) == 0); - push_insn (ctx, 0xf8210001 | disp & 0xfffc); /* stdu 1, disp (1) */ + push_insn (insn_varr, 0xf8210001 | disp & 0xfffc); /* stdu 1, disp (1) */ } -static void ppc64_gen_address (MIR_context_t ctx, unsigned int reg, void *p) { +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 (ctx, (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 (ctx, (31 << 26) | (316 << 1) | (reg << 21) | (reg << 16) | (reg << 11)); - push_insn (ctx, (25 << 26) | (reg << 21) | (reg << 16) | (a >> 16) & 0xffff); + 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); } } else { /* lis r,0,Z0; ori r,r,Z1; rldicr r,r,32,31; oris r,r,Z2; ori r,r,Z3: */ - push_insn (ctx, (15 << 26) | (reg << 21) | (0 << 16) | (a >> 48)); - push_insn (ctx, (24 << 26) | (reg << 21) | (reg << 16) | (a >> 32) & 0xffff); - push_insn (ctx, (30 << 26) | (reg << 21) | (reg << 16) | 0x07c6); - push_insn (ctx, (25 << 26) | (reg << 21) | (reg << 16) | (a >> 16) & 0xffff); + 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, (30 << 26) | (reg << 21) | (reg << 16) | 0x07c6); + push_insn (insn_varr, (25 << 26) | (reg << 21) | (reg << 16) | (a >> 16) & 0xffff); } - push_insn (ctx, (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 (MIR_context_t ctx, unsigned int reg, int call_p) { +static void ppc64_gen_jump (VARR (uint8_t) * insn_varr, unsigned int reg, int call_p) { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ assert (reg != 0); - ppc64_gen_ld (ctx, 0, reg, 0, MIR_T_I64); /* 0 = func addr */ - ppc64_gen_ld (ctx, 2, reg, 8, MIR_T_I64); /* r2 = TOC */ - push_insn (ctx, (31 << 26) | (467 << 1) | (0 << 21) | (9 << 16)); /* mctr 0 */ + ppc64_gen_ld (insn_varr, 0, reg, 0, MIR_T_I64); /* 0 = func addr */ + ppc64_gen_ld (insn_varr, 2, reg, 8, MIR_T_I64); /* r2 = TOC */ + push_insn (insn_varr, (31 << 26) | (467 << 1) | (0 << 21) | (9 << 16)); /* mctr 0 */ #else - if (reg != 12) ppc64_gen_mov (ctx, 12, reg); /* 12 = func addr */ - push_insn (ctx, (31 << 26) | (467 << 1) | (12 << 21) | (9 << 16)); /* mctr 12 */ + if (reg != 12) ppc64_gen_mov (insn_varr, 12, reg); /* 12 = func addr */ + push_insn (insn_varr, (31 << 26) | (467 << 1) | (12 << 21) | (9 << 16)); /* mctr 12 */ #endif - push_insn (ctx, (19 << 26) | (528 << 1) | (20 << 21) | (call_p ? 1 : 0)); /* bcctr[l] */ + push_insn (insn_varr, (19 << 26) | (528 << 1) | (20 << 21) | (call_p ? 1 : 0)); /* bcctr[l] */ } /* r11=addr_reg+addr_disp; r15=r1(sp)+sp_offset; r0=qwords-1; ctr=r0; L: r0=mem[r11]; r11+=8; mem[r15]=r0; r15+=8; bdnz L; */ -static void gen_blk_mov (MIR_context_t ctx, size_t sp_offset, unsigned int addr_reg, int addr_disp, - size_t qwords) { +static void gen_blk_mov (VARR (uint8_t) * insn_varr, size_t sp_offset, unsigned int addr_reg, + int addr_disp, size_t qwords) { static const uint32_t blk_mov_loop[] = { /*0:*/ 0x7c0903a6, /*mctr r0*/ /*4:*/ 0xe80b0000, /*ld r0,0(r11)*/ @@ -135,15 +138,15 @@ static void gen_blk_mov (MIR_context_t ctx, size_t sp_offset, unsigned int addr_ /*20:*/ 0x4200fff0, /*bdnz 4*/ }; /* r11=addr_reg+addr_disp: */ - if (addr_reg != 11 || addr_disp != 0) ppc64_gen_addi (ctx, 11, addr_reg, addr_disp); + if (addr_reg != 11 || addr_disp != 0) ppc64_gen_addi (insn_varr, 11, addr_reg, addr_disp); if (sp_offset < 0x10000) { - ppc64_gen_addi (ctx, 15, 1, sp_offset); + ppc64_gen_addi (insn_varr, 15, 1, sp_offset); } else { - ppc64_gen_address (ctx, 15, (void *) sp_offset); - ppc64_gen_add (ctx, 15, 15, 1); + ppc64_gen_address (insn_varr, 15, (void *) sp_offset); + ppc64_gen_add (insn_varr, 15, 15, 1); } - ppc64_gen_address (ctx, 0, (void *) qwords); /*r0 = qwords*/ - push_insns (ctx, blk_mov_loop, sizeof (blk_mov_loop)); + ppc64_gen_address (insn_varr, 0, (void *) qwords); /*r0 = qwords*/ + push_insns (insn_varr, blk_mov_loop, sizeof (blk_mov_loop)); } void *_MIR_get_bstart_builtin (MIR_context_t ctx) { @@ -151,9 +154,11 @@ void *_MIR_get_bstart_builtin (MIR_context_t ctx) { 0x7c230b78, /* mr 3,1 */ 0x4e800020, /* blr */ }; - ppc64_push_func_desc (ctx); - push_insns (ctx, bstart_code, sizeof (bstart_code)); - return ppc64_publish_func_and_redirect (ctx); + VARR (uint8_t) * code; + + ppc64_push_func_desc (&code); + push_insns (code, bstart_code, sizeof (bstart_code)); + return ppc64_publish_func_and_redirect (ctx, code); } void *_MIR_get_bend_builtin (MIR_context_t ctx) { @@ -161,26 +166,33 @@ void *_MIR_get_bend_builtin (MIR_context_t ctx) { 0x7c611b78, /* mr r1,r3 */ 0x4e800020, /* blr */ }; - ppc64_push_func_desc (ctx); - ppc64_gen_ld (ctx, 0, 1, 0, MIR_T_I64); /* r0 = 0(r1) */ - ppc64_gen_st (ctx, 0, 3, 0, MIR_T_I64); /* 0(r3) = r0 */ - ppc64_gen_ld (ctx, 0, 1, PPC64_TOC_OFFSET, MIR_T_I64); /* r0 = toc_offset(r1) */ - ppc64_gen_st (ctx, 0, 3, PPC64_TOC_OFFSET, MIR_T_I64); /* toc_offset(r3) = r0 */ - push_insns (ctx, bend_finish_code, sizeof (bend_finish_code)); - return ppc64_publish_func_and_redirect (ctx); + VARR (uint8_t) * code; + + ppc64_push_func_desc (&code); + ppc64_gen_ld (code, 0, 1, 0, MIR_T_I64); /* r0 = 0(r1) */ + ppc64_gen_st (code, 0, 3, 0, MIR_T_I64); /* 0(r3) = r0 */ + ppc64_gen_ld (code, 0, 1, PPC64_TOC_OFFSET, MIR_T_I64); /* r0 = toc_offset(r1) */ + ppc64_gen_st (code, 0, 3, PPC64_TOC_OFFSET, MIR_T_I64); /* toc_offset(r3) = r0 */ + push_insns (code, bend_finish_code, sizeof (bend_finish_code)); + return ppc64_publish_func_and_redirect (ctx, code); } void *_MIR_get_thunk (MIR_context_t ctx) { /* emit 3 doublewords for func descriptor: */ - ppc64_push_func_desc (ctx); + VARR (uint8_t) * code; + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return ppc64_publish_func_and_redirect (ctx); + ppc64_push_func_desc (&code); + return ppc64_publish_func_and_redirect (ctx, code); #else - const uint32_t nop_insn = 24 << (32 - 6); /* ori 0,0,0 */ + const uint32_t nop_insn = 24 << (32 - 6); /* ori 0,0,0 */ const int max_thunk_len = (7 * 8); - VARR_TRUNC (uint8_t, machine_insns, 0); - for (int i = 0; i < max_thunk_len; i++) push_insn (ctx, nop_insn); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + void *res; + + VARR_CREATE (uint8_t, code, 128); + for (int i = 0; i < max_thunk_len; i++) push_insn (code, nop_insn); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; #endif } @@ -192,11 +204,13 @@ void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) { 0x7d8903a6, /* mtctr r12 */ 0x4e800420, /* bctr */ }; - VARR_TRUNC (uint8_t, machine_insns, 0); - ppc64_gen_address (ctx, 12, to); - push_insns (ctx, global_entry_end, sizeof (global_entry_end)); - _MIR_change_code (ctx, thunk, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + VARR (uint8_t) * code; + + VARR_CREATE (uint8_t, code, 256); + ppc64_gen_address (code, 12, to); + push_insns (code, global_entry_end, sizeof (global_entry_end)); + _MIR_change_code (ctx, thunk, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); #endif } @@ -259,8 +273,9 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s MIR_type_t type; int n_gpregs = 0, n_fpregs = 0, res_reg = 14, qwords, frame_size; int disp, blk_disp, param_offset, param_size = 0; + VARR (uint8_t) * code; - ppc64_push_func_desc (ctx); + ppc64_push_func_desc (&code); for (uint32_t i = 0; i < nargs; i++) if ((type = arg_descs[i].type) == MIR_T_BLK) param_size += (arg_descs[i].size + 7) / 8 * 8; @@ -269,102 +284,104 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s if (param_size < 64) param_size = 64; frame_size = PPC64_STACK_HEADER_SIZE + param_size + 16; /* +local var to save res_reg and 15 */ if (frame_size % 16 != 0) frame_size += 8; /* align */ - ppc64_gen_st (ctx, 2, 1, PPC64_TOC_OFFSET, MIR_T_I64); - push_insns (ctx, start_pattern, sizeof (start_pattern)); - ppc64_gen_stdu (ctx, -frame_size); - ppc64_gen_st (ctx, res_reg, 1, PPC64_STACK_HEADER_SIZE + param_size, - MIR_T_I64); /* save res_reg */ - ppc64_gen_st (ctx, 15, 1, PPC64_STACK_HEADER_SIZE + param_size + 8, MIR_T_I64); /* save 15 */ + ppc64_gen_st (code, 2, 1, PPC64_TOC_OFFSET, MIR_T_I64); + push_insns (code, start_pattern, sizeof (start_pattern)); + ppc64_gen_stdu (code, -frame_size); + ppc64_gen_st (code, res_reg, 1, PPC64_STACK_HEADER_SIZE + param_size, + MIR_T_I64); /* save res_reg */ + ppc64_gen_st (code, 15, 1, PPC64_STACK_HEADER_SIZE + param_size + 8, MIR_T_I64); /* save 15 */ mir_assert (sizeof (long double) == 16); - ppc64_gen_mov (ctx, res_reg, 4); /* results & args */ - ppc64_gen_mov (ctx, 12, 3); /* func addr */ + ppc64_gen_mov (code, res_reg, 4); /* results & args */ + ppc64_gen_mov (code, 12, 3); /* func addr */ n_gpregs = n_fpregs = 0; param_offset = nres * 16; /* args start */ disp = PPC64_STACK_HEADER_SIZE; /* param area start */ for (uint32_t i = 0; i < nargs; i++) { /* load args: */ type = arg_descs[i].type; if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && n_fpregs < 13) { - ppc64_gen_ld (ctx, 1 + n_fpregs, res_reg, param_offset, type); + ppc64_gen_ld (code, 1 + n_fpregs, res_reg, param_offset, type); if (vararg_p) { if (n_gpregs >= 8) { - ppc64_gen_st (ctx, 1 + n_fpregs, 1, disp, MIR_T_D); + ppc64_gen_st (code, 1 + n_fpregs, 1, disp, MIR_T_D); } else { /* load into gp reg too */ - ppc64_gen_st (ctx, 1 + n_fpregs, 1, -8, MIR_T_D); - ppc64_gen_ld (ctx, 3 + n_gpregs, 1, -8, MIR_T_I64); + ppc64_gen_st (code, 1 + n_fpregs, 1, -8, MIR_T_D); + ppc64_gen_ld (code, 3 + n_gpregs, 1, -8, MIR_T_I64); } } n_fpregs++; if (type == MIR_T_LD) { if (n_fpregs < 13) { - ppc64_gen_ld (ctx, 1 + n_fpregs, res_reg, param_offset + 8, type); + ppc64_gen_ld (code, 1 + n_fpregs, res_reg, param_offset + 8, type); if (vararg_p) { if (n_gpregs + 1 >= 8) { - ppc64_gen_st (ctx, 1 + n_fpregs, 1, disp + 8, MIR_T_D); + ppc64_gen_st (code, 1 + n_fpregs, 1, disp + 8, MIR_T_D); } else { /* load gp reg to */ - ppc64_gen_st (ctx, 1 + n_fpregs, 1, -8, MIR_T_D); - ppc64_gen_ld (ctx, 4 + n_gpregs, 1, -8, MIR_T_I64); + ppc64_gen_st (code, 1 + n_fpregs, 1, -8, MIR_T_D); + ppc64_gen_ld (code, 4 + n_gpregs, 1, -8, MIR_T_I64); } } n_fpregs++; } else { - ppc64_gen_ld (ctx, 0, res_reg, param_offset + 8, type); - ppc64_gen_st (ctx, 0, 1, disp + 8, MIR_T_D); + ppc64_gen_ld (code, 0, res_reg, param_offset + 8, type); + ppc64_gen_st (code, 0, 1, disp + 8, MIR_T_D); } } } else if (type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) { - ppc64_gen_ld (ctx, 0, res_reg, param_offset, type); - ppc64_gen_st (ctx, 0, 1, disp, MIR_T_D); + ppc64_gen_ld (code, 0, res_reg, param_offset, type); + ppc64_gen_st (code, 0, 1, disp, MIR_T_D); if (type == MIR_T_LD) { - ppc64_gen_ld (ctx, 0, res_reg, param_offset + 8, type); - ppc64_gen_st (ctx, 0, 1, disp + 8, MIR_T_D); + ppc64_gen_ld (code, 0, res_reg, param_offset + 8, type); + ppc64_gen_st (code, 0, 1, disp + 8, MIR_T_D); } } else if (type == MIR_T_BLK) { qwords = (arg_descs[i].size + 7) / 8; - if (qwords > 0) ppc64_gen_ld (ctx, 11, res_reg, param_offset, MIR_T_I64); + if (qwords > 0) ppc64_gen_ld (code, 11, res_reg, param_offset, MIR_T_I64); for (blk_disp = 0; qwords > 0 && n_gpregs < 8; qwords--, n_gpregs++, blk_disp += 8, disp += 8) - ppc64_gen_ld (ctx, n_gpregs + 3, 11, blk_disp, MIR_T_I64); - if (qwords > 0) gen_blk_mov (ctx, disp, 11, blk_disp, qwords); + ppc64_gen_ld (code, n_gpregs + 3, 11, blk_disp, MIR_T_I64); + if (qwords > 0) gen_blk_mov (code, disp, 11, blk_disp, qwords); disp += qwords * 8; param_offset += 16; continue; } else if (n_gpregs < 8) { /* including RBLK */ - ppc64_gen_ld (ctx, n_gpregs + 3, res_reg, param_offset, MIR_T_I64); + ppc64_gen_ld (code, n_gpregs + 3, res_reg, param_offset, MIR_T_I64); } else { - ppc64_gen_ld (ctx, 0, res_reg, param_offset, MIR_T_I64); - ppc64_gen_st (ctx, 0, 1, disp, MIR_T_I64); + ppc64_gen_ld (code, 0, res_reg, param_offset, MIR_T_I64); + ppc64_gen_st (code, 0, 1, disp, MIR_T_I64); } disp += type == MIR_T_LD ? 16 : 8; param_offset += 16; n_gpregs += type == MIR_T_LD ? 2 : 1; } - ppc64_gen_jump (ctx, 12, TRUE); /* call func_addr */ + ppc64_gen_jump (code, 12, TRUE); /* call func_addr */ n_gpregs = n_fpregs = 0; disp = 0; for (uint32_t i = 0; i < nres; i++) { type = res_types[i]; if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && n_fpregs < 8) { - ppc64_gen_st (ctx, n_fpregs + 1, res_reg, disp, type); + ppc64_gen_st (code, n_fpregs + 1, res_reg, disp, type); n_fpregs++; if (type == MIR_T_LD) { if (n_fpregs >= 8) - (*error_func) (MIR_ret_error, "ppc64 can not handle this combination of return values"); - ppc64_gen_st (ctx, n_fpregs + 1, res_reg, disp + 8, type); + MIR_get_error_func (ctx) (MIR_ret_error, + "ppc64 can not handle this combination of return values"); + ppc64_gen_st (code, n_fpregs + 1, res_reg, disp + 8, type); n_fpregs++; } } else if (n_gpregs < 2) { // just one-two gp reg - ppc64_gen_st (ctx, n_gpregs + 3, res_reg, disp, MIR_T_I64); + ppc64_gen_st (code, n_gpregs + 3, res_reg, disp, MIR_T_I64); n_gpregs++; } else { - (*error_func) (MIR_ret_error, "ppc64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "ppc64 can not handle this combination of return values"); } disp += 16; } - ppc64_gen_ld (ctx, res_reg, 1, PPC64_STACK_HEADER_SIZE + param_size, + ppc64_gen_ld (code, res_reg, 1, PPC64_STACK_HEADER_SIZE + param_size, MIR_T_I64); /* restore res_reg */ - ppc64_gen_ld (ctx, 15, 1, PPC64_STACK_HEADER_SIZE + param_size + 8, MIR_T_I64); /* restore r15 */ - ppc64_gen_addi (ctx, 1, 1, frame_size); - push_insns (ctx, finish_pattern, sizeof (finish_pattern)); - return ppc64_publish_func_and_redirect (ctx); + ppc64_gen_ld (code, 15, 1, PPC64_STACK_HEADER_SIZE + param_size + 8, MIR_T_I64); /* restore r15 */ + ppc64_gen_addi (code, 1, 1, frame_size); + push_insns (code, finish_pattern, sizeof (finish_pattern)); + return ppc64_publish_func_and_redirect (ctx, code); } /* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item, @@ -390,16 +407,18 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl 0x7c0803a6, /* mtlr r0 */ 0x4e800020, /* blr */ }; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); + VARR_CREATE (uint8_t, code, 256); frame_size = PPC64_STACK_HEADER_SIZE + 64; /* header + 8(param area) */ local_var_size = nres * 16 + 16; /* saved r14, r15, results */ if (vararg_p) { for (unsigned reg = 3; reg <= 10; reg++) /* std rn,dispn(r1) : */ - ppc64_gen_st (ctx, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8, MIR_T_I64); - ppc64_gen_addi (ctx, va_reg, 1, PPC64_STACK_HEADER_SIZE); + ppc64_gen_st (code, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8, MIR_T_I64); + ppc64_gen_addi (code, va_reg, 1, PPC64_STACK_HEADER_SIZE); } else { - ppc64_gen_mov (ctx, caller_r1, 1); /* caller frame r1 */ + ppc64_gen_mov (code, caller_r1, 1); /* caller frame r1 */ for (uint32_t i = 0; i < nargs; i++) if ((type = arg_vars[i].type) == MIR_T_BLK) local_var_size += (arg_vars[i].size + 7) / 8 * 8; @@ -408,10 +427,10 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl } frame_size += local_var_size; if (frame_size % 16 != 0) frame_size += 8; /* align */ - push_insns (ctx, start_pattern, sizeof (start_pattern)); - ppc64_gen_stdu (ctx, -frame_size); - ppc64_gen_st (ctx, res_reg, 1, PPC64_STACK_HEADER_SIZE + 64, MIR_T_I64); /* save res_reg */ - ppc64_gen_st (ctx, 15, 1, PPC64_STACK_HEADER_SIZE + 72, MIR_T_I64); /* save r15 */ + push_insns (code, start_pattern, sizeof (start_pattern)); + ppc64_gen_stdu (code, -frame_size); + ppc64_gen_st (code, res_reg, 1, PPC64_STACK_HEADER_SIZE + 64, MIR_T_I64); /* save res_reg */ + ppc64_gen_st (code, 15, 1, PPC64_STACK_HEADER_SIZE + 72, MIR_T_I64); /* save r15 */ if (!vararg_p) { /* save args in local vars: */ /* header_size + 64 + nres * 16 + 16 -- start of stack memory to keep args: */ start_disp = disp = PPC64_STACK_HEADER_SIZE + 64 + nres * 16 + 16; @@ -420,80 +439,83 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl for (uint32_t i = 0; i < nargs; i++) { type = arg_vars[i].type; if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && n_fpregs < 13) { - ppc64_gen_st (ctx, n_fpregs + 1, 1, disp, MIR_T_D); + ppc64_gen_st (code, n_fpregs + 1, 1, disp, MIR_T_D); n_fpregs++; if (type == MIR_T_LD) { if (n_fpregs < 13) { - ppc64_gen_st (ctx, n_fpregs + 1, 1, disp + 8, MIR_T_D); + ppc64_gen_st (code, n_fpregs + 1, 1, disp + 8, MIR_T_D); n_fpregs++; } else { - ppc64_gen_ld (ctx, 0, caller_r1, param_offset + 8, MIR_T_D); - ppc64_gen_st (ctx, 0, 1, disp + 8, MIR_T_D); + ppc64_gen_ld (code, 0, caller_r1, param_offset + 8, MIR_T_D); + ppc64_gen_st (code, 0, 1, disp + 8, MIR_T_D); } } } else if (type == MIR_T_BLK) { qwords = (arg_vars[i].size + 7) / 8; for (; qwords > 0 && n_gpregs < 8; qwords--, n_gpregs++, disp += 8, param_offset += 8) - ppc64_gen_st (ctx, n_gpregs + 3, 1, disp, MIR_T_I64); + ppc64_gen_st (code, n_gpregs + 3, 1, disp, MIR_T_I64); if (qwords > 0) { - gen_blk_mov (ctx, disp, caller_r1, param_offset, qwords); + gen_blk_mov (code, disp, caller_r1, param_offset, qwords); disp += qwords * 8; param_offset += qwords * 8; } continue; } else if (n_gpregs < 8) { - ppc64_gen_st (ctx, n_gpregs + 3, 1, disp, MIR_T_I64); + ppc64_gen_st (code, n_gpregs + 3, 1, disp, MIR_T_I64); } else if (type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) { - ppc64_gen_ld (ctx, 0, caller_r1, param_offset + (type == MIR_T_F ? 4 : 0), type); - ppc64_gen_st (ctx, 0, 1, disp, MIR_T_D); + ppc64_gen_ld (code, 0, caller_r1, param_offset + (type == MIR_T_F ? 4 : 0), type); + ppc64_gen_st (code, 0, 1, disp, MIR_T_D); if (type == MIR_T_LD) { - ppc64_gen_ld (ctx, 0, caller_r1, param_offset + 8, MIR_T_D); - ppc64_gen_st (ctx, 0, 1, disp + 8, MIR_T_D); + ppc64_gen_ld (code, 0, caller_r1, param_offset + 8, MIR_T_D); + ppc64_gen_st (code, 0, 1, disp + 8, MIR_T_D); } } else { - ppc64_gen_ld (ctx, 0, caller_r1, param_offset, MIR_T_I64); - ppc64_gen_st (ctx, 0, 1, disp, MIR_T_I64); + ppc64_gen_ld (code, 0, caller_r1, param_offset, MIR_T_I64); + ppc64_gen_st (code, 0, 1, disp, MIR_T_I64); } size = type == MIR_T_LD ? 16 : 8; disp += size; param_offset += size; n_gpregs += type == MIR_T_LD ? 2 : 1; } - ppc64_gen_addi (ctx, va_reg, 1, start_disp); + ppc64_gen_addi (code, va_reg, 1, start_disp); } - ppc64_gen_addi (ctx, res_reg, 1, 64 + PPC64_STACK_HEADER_SIZE + 16); - ppc64_gen_address (ctx, 3, ctx); - ppc64_gen_address (ctx, 4, func_item); - ppc64_gen_mov (ctx, 5, va_reg); - ppc64_gen_mov (ctx, 6, res_reg); - ppc64_gen_address (ctx, 12, handler); - ppc64_gen_jump (ctx, 12, TRUE); + ppc64_gen_addi (code, res_reg, 1, 64 + PPC64_STACK_HEADER_SIZE + 16); + ppc64_gen_address (code, 3, ctx); + ppc64_gen_address (code, 4, func_item); + ppc64_gen_mov (code, 5, va_reg); + ppc64_gen_mov (code, 6, res_reg); + ppc64_gen_address (code, 12, handler); + ppc64_gen_jump (code, 12, TRUE); disp = n_gpregs = n_fpregs = 0; for (uint32_t i = 0; i < nres; i++) { type = res_types[i]; if ((type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD) && n_fpregs < 8) { - ppc64_gen_ld (ctx, n_fpregs + 1, res_reg, disp, type); + ppc64_gen_ld (code, n_fpregs + 1, res_reg, disp, type); n_fpregs++; if (type == MIR_T_LD) { if (n_fpregs >= 8) - (*error_func) (MIR_ret_error, "ppc64 can not handle this combination of return values"); - ppc64_gen_ld (ctx, n_fpregs + 1, res_reg, disp + 8, type); + MIR_get_error_func (ctx) (MIR_ret_error, + "ppc64 can not handle this combination of return values"); + ppc64_gen_ld (code, n_fpregs + 1, res_reg, disp + 8, type); n_fpregs++; } } else if (n_gpregs < 2) { // just one-two gp reg - ppc64_gen_ld (ctx, n_gpregs + 3, res_reg, disp, MIR_T_I64); + ppc64_gen_ld (code, n_gpregs + 3, res_reg, disp, MIR_T_I64); n_gpregs++; } else { - (*error_func) (MIR_ret_error, "ppc64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "ppc64 can not handle this combination of return values"); } disp += 16; } - ppc64_gen_ld (ctx, res_reg, 1, PPC64_STACK_HEADER_SIZE + 64, MIR_T_I64); /* restore res_reg */ - ppc64_gen_ld (ctx, 15, 1, PPC64_STACK_HEADER_SIZE + 72, MIR_T_I64); /* restore r15 */ - ppc64_gen_addi (ctx, 1, 1, frame_size); - push_insns (ctx, finish_pattern, sizeof (finish_pattern)); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + ppc64_gen_ld (code, res_reg, 1, PPC64_STACK_HEADER_SIZE + 64, MIR_T_I64); /* restore res_reg */ + ppc64_gen_ld (code, 15, 1, PPC64_STACK_HEADER_SIZE + 72, MIR_T_I64); /* restore r15 */ + ppc64_gen_addi (code, 1, 1, frame_size); + push_insns (code, finish_pattern, sizeof (finish_pattern)); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } /* Brief: save lr (r1+16); update r1, save all param regs (r1+header+64); @@ -510,29 +532,32 @@ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_ad 0x7c0803a6, /* mtlr r0 */ }; int frame_size = PPC64_STACK_HEADER_SIZE + 8 * 8 + 13 * 8 + 8 * 8; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); - push_insns (ctx, prologue, sizeof (prologue)); + VARR_CREATE (uint8_t, code, 256); + push_insns (code, prologue, sizeof (prologue)); /* stdu r1,n(r1): header + 8(gp args) + 13(fp args) + 8(param area): */ if (frame_size % 16 != 0) frame_size += 8; - ppc64_gen_stdu (ctx, -frame_size); + ppc64_gen_stdu (code, -frame_size); for (unsigned reg = 3; reg <= 10; reg++) /* std rn,dispn(r1) : */ - ppc64_gen_st (ctx, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8 + 64, MIR_T_I64); + ppc64_gen_st (code, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8 + 64, MIR_T_I64); for (unsigned reg = 1; reg <= 13; reg++) /* stfd fn,dispn(r1) : */ - ppc64_gen_st (ctx, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 1 + 8) * 8 + 64, MIR_T_D); - ppc64_gen_address (ctx, 3, ctx); - ppc64_gen_address (ctx, 4, called_func); - ppc64_gen_address (ctx, 12, hook_address); - ppc64_gen_jump (ctx, 12, TRUE); - ppc64_gen_mov (ctx, 12, 3); + ppc64_gen_st (code, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 1 + 8) * 8 + 64, MIR_T_D); + ppc64_gen_address (code, 3, ctx); + ppc64_gen_address (code, 4, called_func); + ppc64_gen_address (code, 12, hook_address); + ppc64_gen_jump (code, 12, TRUE); + ppc64_gen_mov (code, 12, 3); for (unsigned reg = 3; reg <= 10; reg++) /* ld rn,dispn(r1) : */ - ppc64_gen_ld (ctx, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8 + 64, MIR_T_I64); + ppc64_gen_ld (code, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 3) * 8 + 64, MIR_T_I64); for (unsigned reg = 1; reg <= 13; reg++) /* lfd fn,dispn(r1) : */ - ppc64_gen_ld (ctx, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 1 + 8) * 8 + 64, MIR_T_D); - ppc64_gen_addi (ctx, 1, 1, frame_size); - push_insns (ctx, epilogue, sizeof (epilogue)); - push_insn (ctx, (31 << 26) | (467 << 1) | (12 << 21) | (9 << 16)); /* mctr 12 */ - push_insn (ctx, (19 << 26) | (528 << 1) | (20 << 21)); /* bcctr */ - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + ppc64_gen_ld (code, reg, 1, PPC64_STACK_HEADER_SIZE + (reg - 1 + 8) * 8 + 64, MIR_T_D); + ppc64_gen_addi (code, 1, 1, frame_size); + push_insns (code, epilogue, sizeof (epilogue)); + push_insn (code, (31 << 26) | (467 << 1) | (12 << 21) | (9 << 16)); /* mctr 12 */ + push_insn (code, (19 << 26) | (528 << 1) | (20 << 21)); /* bcctr */ + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } diff --git a/mir/mir-s390x.c b/mir/mir-s390x.c index dfc661f..e9d1a2d 100644 --- a/mir/mir-s390x.c +++ b/mir/mir-s390x.c @@ -14,25 +14,25 @@ #define S390X_STACK_HEADER_SIZE 160 -static uint8_t *push_insns (MIR_context_t ctx, const uint8_t *pat, size_t pat_len) { - for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, machine_insns, pat[i]); - return VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns) - pat_len; +static uint8_t *push_insns (VARR (uint8_t) * insn_varr, const uint8_t *pat, size_t pat_len) { + for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, insn_varr, pat[i]); + return VARR_ADDR (uint8_t, insn_varr) + VARR_LENGTH (uint8_t, insn_varr) - pat_len; } -static void s390x_gen_mov (MIR_context_t ctx, unsigned to, unsigned from) { +static void s390x_gen_mov (VARR (uint8_t) * insn_varr, unsigned to, unsigned from) { uint32_t lgr = (0xb904 << 16) | (to << 4) | from; /* lgr to,from: */ assert (to < 16 && from < 16); - push_insns (ctx, (uint8_t *) &lgr, 4); + push_insns (insn_varr, (uint8_t *) &lgr, 4); } -static void s390x_gen_mvi (MIR_context_t ctx, int val, unsigned base, int disp) { +static void s390x_gen_mvi (VARR (uint8_t) * insn_varr, int val, unsigned base, int disp) { uint64_t mvghi /* mvghi disp(base), val: */ = ((0xe548l << 32) | ((uint64_t) base << 28) | ((disp & 0xfff) << 16) | (val & 0xffff)) << 16; assert (base < 16 && 0 <= disp && disp < (1 << 12) && -(1 << 15) < val && val < (1 << 15)); - push_insns (ctx, (uint8_t *) &mvghi, 6); + push_insns (insn_varr, (uint8_t *) &mvghi, 6); } -static void s390x_gen_ld_st (MIR_context_t ctx, unsigned reg, unsigned base, int disp, +static void s390x_gen_ld_st (VARR (uint8_t) * insn_varr, unsigned reg, unsigned base, int disp, MIR_type_t type, int ld_p) { int single_p = type == MIR_T_F; int double_p = type == MIR_T_D; @@ -54,66 +54,66 @@ static void s390x_gen_ld_st (MIR_context_t ctx, unsigned reg, unsigned base, int uint64_t dy = ((0xedl << 40) | common | (ld_p ? 0x65 : 0x67)) << 16; /* (lg|lgf|llgf|lgb|llgc|lhy|llgh|ley|ldy|stg|sty|sthy|stcy|stey|stdy) reg, disp(base): */ assert (type != MIR_T_LD && reg < 16 && base < 16 && -(1 << 19) < disp && disp < (1 << 19)); - push_insns (ctx, (uint8_t *) (single_p ? &ey : double_p ? &dy : &g), 6); + push_insns (insn_varr, (uint8_t *) (single_p ? &ey : double_p ? &dy : &g), 6); } -static void s390x_gen_ld (MIR_context_t ctx, unsigned to, unsigned base, int disp, +static void s390x_gen_ld (VARR (uint8_t) * insn_varr, unsigned to, unsigned base, int disp, MIR_type_t type) { - s390x_gen_ld_st (ctx, to, base, disp, type, TRUE); + s390x_gen_ld_st (insn_varr, to, base, disp, type, TRUE); } -static void s390x_gen_st (MIR_context_t ctx, unsigned from, unsigned base, int disp, +static void s390x_gen_st (VARR (uint8_t) * insn_varr, unsigned from, unsigned base, int disp, MIR_type_t type) { - s390x_gen_ld_st (ctx, from, base, disp, type, FALSE); + s390x_gen_ld_st (insn_varr, from, base, disp, type, FALSE); } -static void s390x_gen_ldstm (MIR_context_t ctx, unsigned from, unsigned to, unsigned base, int disp, - int ld_p) { +static void s390x_gen_ldstm (VARR (uint8_t) * insn_varr, unsigned from, unsigned to, unsigned base, + int disp, int ld_p) { uint64_t dl = disp & 0xfff, dh = (disp >> 12) & 0xff; uint64_t common = ((uint64_t) from << 36) | ((uint64_t) to << 32) | ((uint64_t) base << 28) | (dl << 16) | (dh << 8); uint64_t g = ((0xebl << 40) | common | (ld_p ? 0x4 : 0x24)) << 16; /* (lmg|stmg) from,to,disp(base): */ assert (from < 16 && to < 16 && base < 16 && -(1 << 19) < disp && disp < (1 << 19)); - push_insns (ctx, (uint8_t *) &g, 6); + push_insns (insn_varr, (uint8_t *) &g, 6); } -static void s390x_gen_jump (MIR_context_t ctx, unsigned int reg, int call_p) { +static void s390x_gen_jump (VARR (uint8_t) * insn_varr, unsigned int reg, int call_p) { uint16_t bcr = (0x7 << 8) | (15 << 4) | reg; /* bcr 15,reg: */ uint16_t balr = (0x5 << 8) | (14 << 4) | reg; /* balr 14,reg: */ assert (reg < 16); - push_insns (ctx, (uint8_t *) (call_p ? &balr : &bcr), 2); + push_insns (insn_varr, (uint8_t *) (call_p ? &balr : &bcr), 2); } -static void s390x_gen_addi (MIR_context_t ctx, unsigned dst, unsigned src, int disp) { +static void s390x_gen_addi (VARR (uint8_t) * insn_varr, unsigned dst, unsigned src, int disp) { uint64_t dl = disp & 0xfff, dh = (disp >> 12) & 0xff; uint64_t ops = ((uint64_t) dst << 36) | ((uint64_t) src << 28) | (dl << 16) | (dh << 8); uint64_t lay = ((0xe3l << 40) | ops | 0x71) << 16; /* lay dst,disp(src) */ assert (dst < 16 && src < 16 && -(1 << 19) < disp && disp < (1 << 19)); - push_insns (ctx, (uint8_t *) &lay, 6); + push_insns (insn_varr, (uint8_t *) &lay, 6); } -static void s390x_gen_3addrs (MIR_context_t ctx, unsigned int r1, void *a1, unsigned int r2, - void *a2, unsigned int r3, void *a3) { +static void s390x_gen_3addrs (VARR (uint8_t) * insn_varr, unsigned int r1, void *a1, + unsigned int r2, void *a2, unsigned int r3, void *a3) { /* 6b:lalr r3,22+align;6b:lg r1,0(r3);6b:lg r2,8(r3);6b:lg r3,16(r3);4b:bc m15,28;align;a1-a3 */ - size_t rem = (VARR_LENGTH (uint8_t, machine_insns) + 28) % 8; + size_t rem = (VARR_LENGTH (uint8_t, insn_varr) + 28) % 8; size_t padding = rem == 0 ? 0 : 8 - rem; uint64_t lalr = ((0xc0l << 40) | ((uint64_t) r1 << 36) | (28 + padding) / 2) << 16; uint32_t brc = (0xa7 << 24) | (15 << 20) | (4 << 16) | (28 + padding) / 2; /* brc m15,28: */ assert (r1 != 0); - push_insns (ctx, (uint8_t *) &lalr, 6); - s390x_gen_ld (ctx, r3, r1, 16, MIR_T_I64); /* lg r3,16(r1) */ - s390x_gen_ld (ctx, r2, r1, 8, MIR_T_I64); /* lg r2,8(r1) */ - s390x_gen_ld (ctx, r1, r1, 0, MIR_T_I64); /* lg r1,0(r1) */ - push_insns (ctx, (uint8_t *) &brc, 4); - for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, machine_insns, 0); - push_insns (ctx, (uint8_t *) &a1, 8); - push_insns (ctx, (uint8_t *) &a2, 8); - push_insns (ctx, (uint8_t *) &a3, 8); + push_insns (insn_varr, (uint8_t *) &lalr, 6); + s390x_gen_ld (insn_varr, r3, r1, 16, MIR_T_I64); /* lg r3,16(r1) */ + s390x_gen_ld (insn_varr, r2, r1, 8, MIR_T_I64); /* lg r2,8(r1) */ + s390x_gen_ld (insn_varr, r1, r1, 0, MIR_T_I64); /* lg r1,0(r1) */ + push_insns (insn_varr, (uint8_t *) &brc, 4); + for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, insn_varr, 0); + push_insns (insn_varr, (uint8_t *) &a1, 8); + push_insns (insn_varr, (uint8_t *) &a2, 8); + push_insns (insn_varr, (uint8_t *) &a3, 8); } -static void s390x_gen_blk_mov (MIR_context_t ctx, uint32_t param_offset, uint32_t addr_offset, - uint32_t qwords, uint32_t addr_reg) { +static void s390x_gen_blk_mov (VARR (uint8_t) * insn_varr, uint32_t param_offset, + uint32_t addr_offset, uint32_t qwords, uint32_t addr_reg) { uint16_t *addr; static const uint16_t blk_mov_pat[] = { /*0:*/ 0xa7a9, 0x0000, /* lghi %r10, */ @@ -123,63 +123,77 @@ static void s390x_gen_blk_mov (MIR_context_t ctx, uint32_t param_offset, uint32_ /*20:*/ 0xb902, 0x00aa, /* ltgr %r10,%r10 */ /*24:*/ 0xa724, 0xfff6, /* jh 4 */ }; - s390x_gen_addi (ctx, addr_reg, 15, addr_offset); /* lay ,addr_offset(r15) */ + s390x_gen_addi (insn_varr, addr_reg, 15, addr_offset); /* lay ,addr_offset(r15) */ if (qwords == 0) return; assert (qwords * 8 < (1 << 15) && addr_reg < 16 && addr_offset % 8 == 0); - s390x_gen_ld (ctx, 9, 7, param_offset, MIR_T_I64); /* lg* 9,param_offset(r7) */ - addr = (uint16_t *) push_insns (ctx, (uint8_t *) blk_mov_pat, sizeof (blk_mov_pat)); + s390x_gen_ld (insn_varr, 9, 7, param_offset, MIR_T_I64); /* lg* 9,param_offset(r7) */ + addr = (uint16_t *) push_insns (insn_varr, (uint8_t *) blk_mov_pat, sizeof (blk_mov_pat)); addr[1] |= qwords * 8; /* lghi */ addr[8] |= addr_reg << 12; /* stg */ } void *_MIR_get_bstart_builtin (MIR_context_t ctx) { - VARR_TRUNC (uint8_t, machine_insns, 0); - s390x_gen_mov (ctx, 2, 15); /* lgr r2,15 */ - s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */ - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + VARR (uint8_t) * code; + void *res; + + VARR_CREATE (uint8_t, code, 128); + s390x_gen_mov (code, 2, 15); /* lgr r2,15 */ + s390x_gen_jump (code, 14, FALSE); /* bcr m15,r14 */ + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } void *_MIR_get_bend_builtin (MIR_context_t ctx) { - VARR_TRUNC (uint8_t, machine_insns, 0); - s390x_gen_ld (ctx, 0, 15, 0, MIR_T_I64); /* r0 = 0(r15) */ - s390x_gen_st (ctx, 0, 2, 0, MIR_T_I64); /* 0(r2) = r0 */ - s390x_gen_mov (ctx, 15, 2); /* lgr r15,2 */ - s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */ - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + VARR (uint8_t) * code; + void *res; + + VARR_CREATE (uint8_t, code, 128); + s390x_gen_ld (code, 0, 15, 0, MIR_T_I64); /* r0 = 0(r15) */ + s390x_gen_st (code, 0, 2, 0, MIR_T_I64); /* 0(r2) = r0 */ + s390x_gen_mov (code, 15, 2); /* lgr r15,2 */ + s390x_gen_jump (code, 14, FALSE); /* bcr m15,r14 */ + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } void *_MIR_get_thunk (MIR_context_t ctx) { const int max_thunk_len = (4 * 8); /* see _MIR_redirect_thunk */ - VARR_TRUNC (uint8_t, machine_insns, 0); - for (int i = 0; i < max_thunk_len; i++) VARR_PUSH (uint8_t, machine_insns, 0); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + VARR (uint8_t) * code; + void *res; + + VARR_CREATE (uint8_t, code, 128); + for (int i = 0; i < max_thunk_len; i++) VARR_PUSH (uint8_t, code, 0); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) { int64_t offset = (uint8_t *) to - (uint8_t *) thunk; - VARR_TRUNC (uint8_t, machine_insns, 0); + VARR (uint8_t) * code; + + VARR_CREATE (uint8_t, code, 128); 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; - push_insns (ctx, (uint8_t *) &brcl, 6); + 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, machine_insns) + 14) % 8; + size_t rem = (VARR_LENGTH (uint8_t, code) + 14) % 8; size_t padding = rem == 0 ? 0 : 8 - rem; uint64_t lalr = ((0xc0l << 40) | (1l << 36) | (14 + padding) / 2) << 16; uint64_t lg = ((0xe3l << 40) | (1l << 36) | (1l << 28) | 0x4) << 16; uint16_t bcr = (0x7 << 8) | (15 << 4) | 1; /* bcr 15,r1: */ - push_insns (ctx, (uint8_t *) &lalr, 6); - push_insns (ctx, (uint8_t *) &lg, 6); - push_insns (ctx, (uint8_t *) &bcr, 2); - for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, machine_insns, 0); - push_insns (ctx, (uint8_t *) &to, 8); + push_insns (code, (uint8_t *) &lalr, 6); + push_insns (code, (uint8_t *) &lg, 6); + push_insns (code, (uint8_t *) &bcr, 2); + for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, code, 0); + push_insns (code, (uint8_t *) &to, 8); } - _MIR_change_code (ctx, thunk, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + _MIR_change_code (ctx, thunk, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); } struct s390x_va_list { @@ -242,8 +256,10 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s MIR_type_t type; int n_gpregs = 0, n_fpregs = 0, res_reg = 7, frame_size, disp, param_offset, blk_offset; uint32_t qwords, addr_reg; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); + VARR_CREATE (uint8_t, code, 128); blk_offset = frame_size = S390X_STACK_HEADER_SIZE; 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: */ @@ -258,84 +274,86 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s blk_offset += 8; } } - s390x_gen_ldstm (ctx, 6, 7, 15, 48, FALSE); /* stmg 6,7,48(r15) : */ - s390x_gen_ldstm (ctx, 8, 9, 15, 64, FALSE); /* stmg 8,9,64(r15) : */ - s390x_gen_st (ctx, 10, 15, 80, MIR_T_I64); /* stg r10,80(r15) */ - s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg r14,112(r15) */ - s390x_gen_addi (ctx, 15, 15, -frame_size); /* lay r15,-frame_size(r15) */ - s390x_gen_mov (ctx, 1, 2); /* fun_addr */ - s390x_gen_mov (ctx, res_reg, 3); /* results & args */ + s390x_gen_ldstm (code, 6, 7, 15, 48, FALSE); /* stmg 6,7,48(r15) : */ + s390x_gen_ldstm (code, 8, 9, 15, 64, FALSE); /* stmg 8,9,64(r15) : */ + s390x_gen_st (code, 10, 15, 80, MIR_T_I64); /* stg r10,80(r15) */ + s390x_gen_st (code, 14, 15, 112, MIR_T_I64); /* stg r14,112(r15) */ + s390x_gen_addi (code, 15, 15, -frame_size); /* lay r15,-frame_size(r15) */ + s390x_gen_mov (code, 1, 2); /* fun_addr */ + s390x_gen_mov (code, res_reg, 3); /* results & args */ n_gpregs = n_fpregs = 0; param_offset = nres * 16; /* args start */ disp = S390X_STACK_HEADER_SIZE; /* param area start */ if (nres > 0 && res_types[0] == MIR_T_LD) { /* ld address: */ - s390x_gen_mov (ctx, 2, res_reg); /* lgr r2,r7 */ + s390x_gen_mov (code, 2, res_reg); /* lgr r2,r7 */ n_gpregs++; } for (uint32_t i = 0; i < nargs; i++) { /* load args: */ type = arg_descs[i].type; if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) { /* (le,ld) (f0,f2,f4,f6),param_ofset(r7) */ - s390x_gen_ld (ctx, n_fpregs * 2, res_reg, param_offset, type); + s390x_gen_ld (code, n_fpregs * 2, res_reg, param_offset, type); n_fpregs++; } else if (type == MIR_T_F || type == MIR_T_D) { - s390x_gen_ld (ctx, 1, res_reg, param_offset, type); /* (le,ld) f1,param_offset(r7) */ - s390x_gen_st (ctx, 1, 15, disp, type); /* (ste,std) f1,disp(r15) */ + s390x_gen_ld (code, 1, res_reg, param_offset, type); /* (le,ld) f1,param_offset(r7) */ + s390x_gen_st (code, 1, 15, disp, type); /* (ste,std) f1,disp(r15) */ disp += 8; - } else if (type == MIR_T_LD && n_gpregs < 5) { /* ld address */ - s390x_gen_addi (ctx, n_gpregs + 2, res_reg, param_offset); /* lay rn,param_offset(r7) */ + } else if (type == MIR_T_LD && n_gpregs < 5) { /* ld address */ + s390x_gen_addi (code, n_gpregs + 2, res_reg, param_offset); /* lay rn,param_offset(r7) */ n_gpregs++; - } else if (type == MIR_T_LD) { /* pass address of location in the result: */ - s390x_gen_addi (ctx, 0, res_reg, param_offset); /* lay r0,param_offset(r7) */ - s390x_gen_st (ctx, 0, 15, disp, MIR_T_I64); /* stg r0,disp(r15) */ + } else if (type == MIR_T_LD) { /* pass address of location in the result: */ + s390x_gen_addi (code, 0, res_reg, param_offset); /* lay r0,param_offset(r7) */ + s390x_gen_st (code, 0, 15, disp, MIR_T_I64); /* stg r0,disp(r15) */ disp += 8; } else if (type == MIR_T_BLK) { qwords = (arg_descs[i].size + 7) / 8; addr_reg = n_gpregs < 5 ? n_gpregs + 2 : 8; - s390x_gen_blk_mov (ctx, param_offset, blk_offset, qwords, addr_reg); + s390x_gen_blk_mov (code, param_offset, blk_offset, qwords, addr_reg); blk_offset += qwords * 8; if (n_gpregs < 5) { n_gpregs++; } else { - s390x_gen_st (ctx, 8, 15, disp, MIR_T_I64); /* stg r8,disp(r15) */ + s390x_gen_st (code, 8, 15, disp, MIR_T_I64); /* stg r8,disp(r15) */ disp += 8; } } else if (n_gpregs < 5) { /* RBLK too */ - s390x_gen_ld (ctx, n_gpregs + 2, res_reg, param_offset, + s390x_gen_ld (code, n_gpregs + 2, res_reg, param_offset, MIR_T_I64); /* lg* rn,param_offset(r7) */ n_gpregs++; } else { - s390x_gen_ld (ctx, 0, res_reg, param_offset, MIR_T_I64); /* lg* r0,param_offset(r7) */ - s390x_gen_st (ctx, 0, 15, disp, MIR_T_I64); /* stg* r0,disp(r15) */ + s390x_gen_ld (code, 0, res_reg, param_offset, MIR_T_I64); /* lg* r0,param_offset(r7) */ + s390x_gen_st (code, 0, 15, disp, MIR_T_I64); /* stg* r0,disp(r15) */ disp += 8; } param_offset += 16; } - s390x_gen_jump (ctx, 1, TRUE); /* call *r1 */ + s390x_gen_jump (code, 1, TRUE); /* call *r1 */ n_gpregs = n_fpregs = 0; disp = 0; for (uint32_t i = 0; i < nres; i++) { type = res_types[i]; if (type == MIR_T_LD) continue; /* do nothing: the result value is already in results */ if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) { - s390x_gen_st (ctx, n_fpregs * 2, res_reg, disp, type); + s390x_gen_st (code, n_fpregs * 2, res_reg, disp, type); n_fpregs++; } else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 1) { // just one gp reg - s390x_gen_st (ctx, n_gpregs + 2, res_reg, disp, MIR_T_I64); + s390x_gen_st (code, n_gpregs + 2, res_reg, disp, MIR_T_I64); n_gpregs++; } else { - (*error_func) (MIR_ret_error, "s390x can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "s390x can not handle this combination of return values"); } disp += 16; } - s390x_gen_addi (ctx, 15, 15, frame_size); /* lay 15,frame_size(15) */ - s390x_gen_ldstm (ctx, 6, 7, 15, 48, TRUE); /* lmg 6,7,48(r15) : */ - s390x_gen_ldstm (ctx, 8, 9, 15, 64, TRUE); /* lmg 8,9,64(r15) : */ - s390x_gen_ld (ctx, 10, 15, 80, MIR_T_I64); /* lg 10,80(r15) */ - s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ - s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */ - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + s390x_gen_addi (code, 15, 15, frame_size); /* lay 15,frame_size(15) */ + s390x_gen_ldstm (code, 6, 7, 15, 48, TRUE); /* lmg 6,7,48(r15) : */ + s390x_gen_ldstm (code, 8, 9, 15, 64, TRUE); /* lmg 8,9,64(r15) : */ + s390x_gen_ld (code, 10, 15, 80, MIR_T_I64); /* lg 10,80(r15) */ + 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)); + VARR_DESTROY (uint8_t, code); + return res; } /* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item, @@ -348,63 +366,67 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl uint32_t nres = func->nres, nargs = func->nargs; 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_TRUNC (uint8_t, machine_insns, 0); - frame_size = S390X_STACK_HEADER_SIZE; /* register save area */ - s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */ - s390x_gen_ldstm (ctx, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */ - for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */ - s390x_gen_st (ctx, reg, 15, reg * 4 + 128, MIR_T_D); + VARR (uint8_t) * code; + void *res; + + VARR_CREATE (uint8_t, code, 128); + frame_size = S390X_STACK_HEADER_SIZE; /* register save area */ + s390x_gen_st (code, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */ + s390x_gen_ldstm (code, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */ + for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */ + s390x_gen_st (code, reg, 15, reg * 4 + 128, MIR_T_D); local_var_size = sizeof (struct s390x_va_list) + nres * 16; /* allocate va and results */ va_list_disp = frame_size; results_disp = va_list_disp + sizeof (struct s390x_va_list); frame_size += local_var_size; assert (frame_size % 8 == 0); - s390x_gen_addi (ctx, 15, 15, -frame_size); + s390x_gen_addi (code, 15, 15, -frame_size); /* setup va: mvghi va(15),(0,1): __gpr */ - s390x_gen_mvi (ctx, nres > 0 && res_types[0] == MIR_T_LD ? 1 : 0, 15, va_list_disp); - s390x_gen_mvi (ctx, 0, 15, va_list_disp + 8); /* mvghi va+8(15),0: __fpr */ - s390x_gen_addi (ctx, 1, 15, frame_size); /* lay 1,frame_size(15) */ - s390x_gen_st (ctx, 1, 15, va_list_disp + 24, MIR_T_I64); /* stg 1,va+24(r15): __reg_save_area */ - s390x_gen_addi (ctx, 1, 1, S390X_STACK_HEADER_SIZE); /* lay 1,S390X_STACK_HEADER_SIZE(1) */ + s390x_gen_mvi (code, nres > 0 && res_types[0] == MIR_T_LD ? 1 : 0, 15, va_list_disp); + s390x_gen_mvi (code, 0, 15, va_list_disp + 8); /* mvghi va+8(15),0: __fpr */ + s390x_gen_addi (code, 1, 15, frame_size); /* lay 1,frame_size(15) */ + s390x_gen_st (code, 1, 15, va_list_disp + 24, MIR_T_I64); /* stg 1,va+24(r15): __reg_save_area */ + s390x_gen_addi (code, 1, 1, S390X_STACK_HEADER_SIZE); /* lay 1,S390X_STACK_HEADER_SIZE(1) */ /* stg 1,va+16(r15):__overflow_arg_area: */ - s390x_gen_st (ctx, 1, 15, va_list_disp + 16, MIR_T_I64); + s390x_gen_st (code, 1, 15, va_list_disp + 16, MIR_T_I64); /* call handler: */ - s390x_gen_3addrs (ctx, 2, ctx, 3, func_item, 1, handler); - s390x_gen_addi (ctx, 4, 15, va_list_disp); - s390x_gen_addi (ctx, 5, 15, results_disp); - s390x_gen_jump (ctx, 1, TRUE); + s390x_gen_3addrs (code, 2, ctx, 3, func_item, 1, handler); + s390x_gen_addi (code, 4, 15, va_list_disp); + s390x_gen_addi (code, 5, 15, results_disp); + s390x_gen_jump (code, 1, TRUE); /* setup result regs: */ disp = results_disp; n_gpregs = n_fpregs = 0; for (uint32_t i = 0; i < nres; i++) { type = res_types[i]; if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) { - s390x_gen_ld (ctx, n_fpregs * 2, 15, disp, type); + s390x_gen_ld (code, n_fpregs * 2, 15, disp, type); n_fpregs++; } else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 1) { // just one gp reg if (type != MIR_T_LD) { - s390x_gen_ld (ctx, n_gpregs + 2, 15, disp, MIR_T_I64); + s390x_gen_ld (code, n_gpregs + 2, 15, disp, MIR_T_I64); } else { /* ld address: lg r2,16+frame_size(r15) */ - s390x_gen_ld (ctx, 2, 15, 16 + frame_size, MIR_T_I64); - s390x_gen_ld (ctx, 0, 15, disp, MIR_T_D); /* ld f0,disp(r15) */ - s390x_gen_ld (ctx, 2, 15, disp + 8, MIR_T_D); /* ld f2,disp + 8(r15) */ - s390x_gen_st (ctx, 0, 2, 0, MIR_T_D); /* st f0,0(r2) */ - s390x_gen_st (ctx, 2, 2, 8, MIR_T_D); /* st f2,8(r2) */ + s390x_gen_ld (code, 2, 15, 16 + frame_size, MIR_T_I64); + s390x_gen_ld (code, 0, 15, disp, MIR_T_D); /* ld f0,disp(r15) */ + s390x_gen_ld (code, 2, 15, disp + 8, MIR_T_D); /* ld f2,disp + 8(r15) */ + s390x_gen_st (code, 0, 2, 0, MIR_T_D); /* st f0,0(r2) */ + s390x_gen_st (code, 2, 2, 8, MIR_T_D); /* st f2,8(r2) */ } n_gpregs++; } else { - (*error_func) (MIR_ret_error, "s390x can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "s390x can not handle this combination of return values"); } disp += 16; } - s390x_gen_addi (ctx, 15, 15, frame_size); /* lay 15,frame_size(15) */ - s390x_gen_ld (ctx, 6, 15, 48, MIR_T_I64); /* lg 6,48(r15) : */ - s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ - s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */ - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + s390x_gen_addi (code, 15, 15, frame_size); /* lay 15,frame_size(15) */ + s390x_gen_ld (code, 6, 15, 48, MIR_T_I64); /* lg 6,48(r15) : */ + 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)); + VARR_DESTROY (uint8_t, code); + return res; } /* Brief: save r14 (r15+120); save all param regs r2-r6 (r15+16),f0,f2,f4,f6 (r15+128); @@ -412,23 +434,26 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl r2 = call hook_address (ctx, called_func); r1=r2; restore all params regs, r15, r14; bcr r1 */ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_address) { int frame_size = S390X_STACK_HEADER_SIZE; - - VARR_TRUNC (uint8_t, machine_insns, 0); - s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */ - s390x_gen_ldstm (ctx, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */ - for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */ - s390x_gen_st (ctx, reg, 15, reg * 4 + 128, MIR_T_D); + VARR (uint8_t) * code; + void *res; + + VARR_CREATE (uint8_t, code, 128); + s390x_gen_st (code, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */ + s390x_gen_ldstm (code, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */ + for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */ + s390x_gen_st (code, reg, 15, reg * 4 + 128, MIR_T_D); /* r15 -= frame_size: */ - s390x_gen_addi (ctx, 15, 15, -frame_size); - s390x_gen_3addrs (ctx, 2, ctx, 3, called_func, 4, hook_address); - s390x_gen_jump (ctx, 4, TRUE); - s390x_gen_mov (ctx, 1, 2); - s390x_gen_addi (ctx, 15, 15, frame_size); + s390x_gen_addi (code, 15, 15, -frame_size); + s390x_gen_3addrs (code, 2, ctx, 3, called_func, 4, hook_address); + s390x_gen_jump (code, 4, TRUE); + s390x_gen_mov (code, 1, 2); + s390x_gen_addi (code, 15, 15, frame_size); for (unsigned reg = 0; reg <= 6; reg += 2) /* ldy fn,disp(r15) : */ - s390x_gen_ld (ctx, reg, 15, reg * 4 + 128, MIR_T_D); - s390x_gen_ldstm (ctx, 2, 6, 15, 16, TRUE); /* lmg 2,6,16(r15) : */ - s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ - s390x_gen_jump (ctx, 1, FALSE); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + s390x_gen_ld (code, reg, 15, reg * 4 + 128, MIR_T_D); + s390x_gen_ldstm (code, 2, 6, 15, 16, TRUE); /* lmg 2,6,16(r15) : */ + s390x_gen_ld (code, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */ + s390x_gen_jump (code, 1, FALSE); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } diff --git a/mir/mir-x86_64.c b/mir/mir-x86_64.c index 7b8943c..fe9fd58 100644 --- a/mir/mir-x86_64.c +++ b/mir/mir-x86_64.c @@ -167,15 +167,15 @@ static const uint8_t restore_pat[] = { #endif }; -static uint8_t *push_insns (MIR_context_t ctx, const uint8_t *pat, size_t pat_len) { - for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, machine_insns, pat[i]); - return VARR_ADDR (uint8_t, machine_insns) + VARR_LENGTH (uint8_t, machine_insns) - pat_len; +static uint8_t *push_insns (VARR (uint8_t) * insn_varr, const uint8_t *pat, size_t pat_len) { + for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, insn_varr, pat[i]); + return VARR_ADDR (uint8_t, insn_varr) + VARR_LENGTH (uint8_t, insn_varr) - pat_len; } -static void gen_mov (MIR_context_t ctx, uint32_t offset, uint32_t reg, int ld_p) { +static void gen_mov (VARR (uint8_t) * insn_varr, uint32_t offset, uint32_t reg, int ld_p) { static const uint8_t ld_gp_reg[] = {0x48, 0x8b, 0x83, 0, 0, 0, 0 /* mov (%rbx),%reg */}; static const uint8_t st_gp_reg[] = {0x48, 0x89, 0x83, 0, 0, 0, 0 /* mov %reg,(%rbx) */}; - uint8_t *addr = push_insns (ctx, ld_p ? ld_gp_reg : st_gp_reg, + uint8_t *addr = push_insns (insn_varr, ld_p ? ld_gp_reg : st_gp_reg, ld_p ? sizeof (ld_gp_reg) : sizeof (st_gp_reg)); memcpy (addr + 3, &offset, sizeof (uint32_t)); assert (reg <= 15); @@ -183,7 +183,7 @@ static void gen_mov (MIR_context_t ctx, uint32_t offset, uint32_t reg, int ld_p) addr[2] |= (reg & 7) << 3; } -static void gen_blk_mov (MIR_context_t ctx, uint32_t offset, uint32_t addr_offset, +static void gen_blk_mov (VARR (uint8_t) * insn_varr, uint32_t offset, uint32_t addr_offset, uint32_t qwords) { static const uint8_t blk_mov_pat[] = { /*0:*/ 0x4c, 0x8b, 0xa3, 0, 0, 0, 0, /*mov (%rbx),%r12*/ @@ -194,20 +194,21 @@ static void gen_blk_mov (MIR_context_t ctx, uint32_t offset, uint32_t addr_offse /*1e:*/ 0x48, 0x85, 0xc0, /*test %rax,%rax*/ /*21:*/ 0x7f, 0xeb, /*jg e */ }; - uint8_t *addr = push_insns (ctx, blk_mov_pat, sizeof (blk_mov_pat)); + uint8_t *addr = push_insns (insn_varr, blk_mov_pat, sizeof (blk_mov_pat)); memcpy (addr + 3, &addr_offset, sizeof (uint32_t)); memcpy (addr + 10, &qwords, sizeof (uint32_t)); memcpy (addr + 26, &offset, sizeof (uint32_t)); } -static void gen_movxmm (MIR_context_t ctx, uint32_t offset, uint32_t reg, int b32_p, int ld_p) { +static void gen_movxmm (VARR (uint8_t) * insn_varr, uint32_t offset, uint32_t reg, int b32_p, + int ld_p) { static const uint8_t ld_xmm_reg_pat[] = { 0xf2, 0x0f, 0x10, 0x83, 0, 0, 0, 0 /* movs[sd] (%rbx),%xmm */ }; static const uint8_t st_xmm_reg_pat[] = { 0xf2, 0x0f, 0x11, 0x83, 0, 0, 0, 0 /* movs[sd] %xmm, (%rbx) */ }; - uint8_t *addr = push_insns (ctx, ld_p ? ld_xmm_reg_pat : st_xmm_reg_pat, + uint8_t *addr = push_insns (insn_varr, ld_p ? ld_xmm_reg_pat : st_xmm_reg_pat, ld_p ? sizeof (ld_xmm_reg_pat) : sizeof (st_xmm_reg_pat)); memcpy (addr + 4, &offset, sizeof (uint32_t)); assert (reg <= 7); @@ -215,12 +216,13 @@ static void gen_movxmm (MIR_context_t ctx, uint32_t offset, uint32_t reg, int b3 if (b32_p) addr[0] |= 1; } -static void gen_ldst (MIR_context_t ctx, uint32_t sp_offset, uint32_t src_offset, int b64_p) { +static void gen_ldst (VARR (uint8_t) * insn_varr, uint32_t sp_offset, uint32_t src_offset, + int b64_p) { static const uint8_t ldst_pat[] = { 0x44, 0x8b, 0x93, 0, 0, 0, 0, /* mov (%rbx),%r10 */ 0x44, 0x89, 0x94, 0x24, 0, 0, 0, 0, /* mov %r10,(%sp) */ }; - uint8_t *addr = push_insns (ctx, ldst_pat, sizeof (ldst_pat)); + uint8_t *addr = push_insns (insn_varr, ldst_pat, sizeof (ldst_pat)); memcpy (addr + 3, &src_offset, sizeof (uint32_t)); memcpy (addr + 11, &sp_offset, sizeof (uint32_t)); if (b64_p) { @@ -229,19 +231,19 @@ static void gen_ldst (MIR_context_t ctx, uint32_t sp_offset, uint32_t src_offset } } -static void gen_ldst80 (MIR_context_t ctx, uint32_t sp_offset, uint32_t src_offset) { +static void gen_ldst80 (VARR (uint8_t) * insn_varr, uint32_t sp_offset, uint32_t src_offset) { static uint8_t const ldst80_pat[] = { 0xdb, 0xab, 0, 0, 0, 0, /* fldt (%rbx) */ 0xdb, 0xbc, 0x24, 0, 0, 0, 0, /* fstpt (%sp) */ }; - uint8_t *addr = push_insns (ctx, ldst80_pat, sizeof (ldst80_pat)); + uint8_t *addr = push_insns (insn_varr, ldst80_pat, sizeof (ldst80_pat)); memcpy (addr + 2, &src_offset, sizeof (uint32_t)); memcpy (addr + 9, &sp_offset, sizeof (uint32_t)); } -static void gen_st80 (MIR_context_t ctx, uint32_t src_offset) { +static void gen_st80 (VARR (uint8_t) * insn_varr, uint32_t src_offset) { static const uint8_t st80_pat[] = {0xdb, 0xbb, 0, 0, 0, 0 /* fstpt (%rbx) */}; - memcpy (push_insns (ctx, st80_pat, sizeof (st80_pat)) + 2, &src_offset, sizeof (uint32_t)); + memcpy (push_insns (insn_varr, st80_pat, sizeof (st80_pat)) + 2, &src_offset, sizeof (uint32_t)); } /* Generation: fun (fun_addr, res_arg_addresses): @@ -293,69 +295,74 @@ void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, s #endif uint32_t n_iregs = 0, n_xregs = 0, n_fregs, qwords; uint8_t *addr; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); - push_insns (ctx, prolog, sizeof (prolog)); + VARR_CREATE (uint8_t, code, 128); + push_insns (code, prolog, sizeof (prolog)); for (size_t i = 0; i < nargs; i++) { MIR_type_t type = arg_descs[i].type; if ((MIR_T_I8 <= type && type <= MIR_T_U64) || type == MIR_T_P || type == MIR_T_RBLK) { if (n_iregs < max_iregs) { - gen_mov (ctx, (i + nres) * sizeof (long double), iregs[n_iregs++], TRUE); + gen_mov (code, (i + nres) * sizeof (long double), iregs[n_iregs++], TRUE); #ifdef _WIN64 n_xregs++; #endif } else { - gen_ldst (ctx, sp_offset, (i + nres) * sizeof (long double), TRUE); + gen_ldst (code, sp_offset, (i + nres) * sizeof (long double), TRUE); sp_offset += 8; } } else if (type == MIR_T_F || type == MIR_T_D) { if (n_xregs < max_xregs) { - gen_movxmm (ctx, (i + nres) * sizeof (long double), n_xregs++, type == MIR_T_F, TRUE); + gen_movxmm (code, (i + nres) * sizeof (long double), n_xregs++, type == MIR_T_F, TRUE); #ifdef _WIN64 - gen_mov (ctx, (i + nres) * sizeof (long double), iregs[n_iregs++], TRUE); + gen_mov (code, (i + nres) * sizeof (long double), iregs[n_iregs++], TRUE); #endif } else { - gen_ldst (ctx, sp_offset, (i + nres) * sizeof (long double), type == MIR_T_D); + gen_ldst (code, sp_offset, (i + nres) * sizeof (long double), type == MIR_T_D); sp_offset += 8; } } else if (type == MIR_T_LD) { - gen_ldst80 (ctx, sp_offset, (i + nres) * sizeof (long double)); + gen_ldst80 (code, sp_offset, (i + nres) * sizeof (long double)); sp_offset += 16; } else if (type == MIR_T_BLK) { qwords = (arg_descs[i].size + 7) / 8; - gen_blk_mov (ctx, sp_offset, (i + nres) * sizeof (long double), qwords); + gen_blk_mov (code, sp_offset, (i + nres) * sizeof (long double), qwords); sp_offset += qwords * 8; } else { - (*error_func) (MIR_call_op_error, "wrong type of arg value"); + MIR_get_error_func (ctx) (MIR_call_op_error, "wrong type of arg value"); } } sp_offset = (sp_offset + 15) / 16 * 16; sp_offset += 8; - addr = VARR_ADDR (uint8_t, machine_insns); + addr = VARR_ADDR (uint8_t, code); memcpy (addr + 6, &sp_offset, sizeof (uint32_t)); - addr = push_insns (ctx, call_end, sizeof (call_end)); + addr = push_insns (code, call_end, sizeof (call_end)); memcpy (addr + sizeof (call_end) - 4, &sp_offset, sizeof (uint32_t)); #ifdef _WIN64 if (nres > 1) - (*error_func) (MIR_call_op_error, "Windows x86-64 doesn't support multiple return values"); + MIR_get_error_func (ctx) (MIR_call_op_error, + "Windows x86-64 doesn't support multiple return values"); #endif n_iregs = n_xregs = n_fregs = 0; for (size_t i = 0; i < nres; i++) { if (((MIR_T_I8 <= res_types[i] && res_types[i] <= MIR_T_U64) || res_types[i] == MIR_T_P) && n_iregs < 2) { - gen_mov (ctx, i * sizeof (long double), n_iregs++ == 0 ? 0 : 2, FALSE); /* rax or rdx */ + gen_mov (code, i * sizeof (long double), n_iregs++ == 0 ? 0 : 2, FALSE); /* rax or rdx */ } else if ((res_types[i] == MIR_T_F || res_types[i] == MIR_T_D) && n_xregs < 2) { - gen_movxmm (ctx, i * sizeof (long double), n_xregs++, res_types[i] == MIR_T_F, FALSE); + gen_movxmm (code, i * sizeof (long double), n_xregs++, res_types[i] == MIR_T_F, FALSE); } else if (res_types[i] == MIR_T_LD && n_fregs < 2) { - gen_st80 (ctx, i * sizeof (long double)); + gen_st80 (code, i * sizeof (long double)); } else { - (*error_func) (MIR_ret_error, "x86-64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "x86-64 can not handle this combination of return values"); } } - push_insns (ctx, epilog, sizeof (epilog)); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + push_insns (code, epilog, sizeof (epilog)); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } /* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item, @@ -419,13 +426,15 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl uint32_t imm, n_iregs, n_xregs, n_fregs, offset; uint32_t nres = func_item->u.func->nres; MIR_type_t *results = func_item->u.func->res_types; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); + VARR_CREATE (uint8_t, code, 128); #ifndef _WIN64 - push_insns (ctx, push_rbx, sizeof (push_rbx)); + push_insns (code, push_rbx, sizeof (push_rbx)); #endif - push_insns (ctx, save_pat, sizeof (save_pat)); - addr = push_insns (ctx, prepare_pat, sizeof (prepare_pat)); + push_insns (code, save_pat, sizeof (save_pat)); + addr = push_insns (code, prepare_pat, sizeof (prepare_pat)); imm = nres * 16; memcpy (addr + nres_offset, &imm, sizeof (uint32_t)); memcpy (addr + ctx_offset, &ctx, sizeof (void *)); @@ -434,40 +443,43 @@ void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handl /* move results: */ #ifdef _WIN64 if (nres > 1) - (*error_func) (MIR_call_op_error, "Windows x86-64 doesn't support multiple return values"); + MIR_get_error_func (ctx) (MIR_call_op_error, + "Windows x86-64 doesn't support multiple return values"); #endif n_iregs = n_xregs = n_fregs = offset = 0; for (uint32_t i = 0; i < nres; i++) { if (results[i] == MIR_T_F && n_xregs < 2) { - addr = push_insns (ctx, movss_pat, sizeof (movss_pat)); + addr = push_insns (code, movss_pat, sizeof (movss_pat)); addr[3] |= n_xregs << 3; memcpy (addr + 4, &offset, sizeof (uint32_t)); n_xregs++; } else if (results[i] == MIR_T_D && n_xregs < 2) { - addr = push_insns (ctx, movsd_pat, sizeof (movsd_pat)); + addr = push_insns (code, movsd_pat, sizeof (movsd_pat)); addr[3] |= n_xregs << 3; memcpy (addr + 4, &offset, sizeof (uint32_t)); n_xregs++; } else if (results[i] == MIR_T_LD && n_fregs < 2) { - addr = push_insns (ctx, fldt_pat, sizeof (fldt_pat)); + addr = push_insns (code, fldt_pat, sizeof (fldt_pat)); memcpy (addr + 2, &offset, sizeof (uint32_t)); - if (n_fregs == 1) push_insns (ctx, fxch_pat, sizeof (fxch_pat)); + if (n_fregs == 1) push_insns (code, fxch_pat, sizeof (fxch_pat)); n_fregs++; } else if (n_iregs < 2) { - addr = push_insns (ctx, ld_pat, sizeof (ld_pat)); + addr = push_insns (code, ld_pat, sizeof (ld_pat)); addr[2] |= n_iregs << 4; memcpy (addr + 3, &offset, sizeof (uint32_t)); n_iregs++; } else { - (*error_func) (MIR_ret_error, "x86-64 can not handle this combination of return values"); + MIR_get_error_func (ctx) (MIR_ret_error, + "x86-64 can not handle this combination of return values"); } offset += 16; } - addr = push_insns (ctx, shim_end, sizeof (shim_end)); + addr = push_insns (code, shim_end, sizeof (shim_end)); imm = prep_stack_size + nres * 16; memcpy (addr + 3, &imm, sizeof (uint32_t)); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + res = _MIR_publish_code (ctx, VARR_ADDR (uint8_t, code), VARR_LENGTH (uint8_t, code)); + VARR_DESTROY (uint8_t, code); + return res; } /* save regs; r10 = call hook_address (ctx, called_func); restore regs; jmp *r10 @@ -500,18 +512,21 @@ void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_ad #endif }; uint8_t *addr; + VARR (uint8_t) * code; + void *res; - VARR_TRUNC (uint8_t, machine_insns, 0); + VARR_CREATE (uint8_t, code, 128); #ifndef _WIN64 - push_insns (ctx, push_rax, sizeof (push_rax)); + push_insns (code, push_rax, sizeof (push_rax)); #endif - push_insns (ctx, save_pat, sizeof (save_pat)); - addr = push_insns (ctx, call_pat, sizeof (call_pat)); + 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 *)); - push_insns (ctx, restore_pat, sizeof (restore_pat)); - push_insns (ctx, wrap_end, sizeof (wrap_end)); - return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns), - VARR_LENGTH (uint8_t, machine_insns)); + 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)); + VARR_DESTROY (uint8_t, code); + return res; } diff --git a/mir/mir.c b/mir/mir.c index 25cfe54..9ebb6a4 100644 --- a/mir/mir.c +++ b/mir/mir.c @@ -28,20 +28,17 @@ struct interp_ctx; struct MIR_context { struct gen_ctx *gen_ctx; /* should be the 1st member */ struct c2mir_ctx *c2mir_ctx; /* should be the 2nd member */ +#if MIR_PARALLEL_GEN + mir_mutex_t ctx_mutex; +#endif MIR_error_func_t error_func; - VARR (MIR_proto_t) * unspec_protos; /* protos of unspec insns */ - VARR (MIR_insn_t) * temp_insns, *temp_insns2; - VARR (MIR_op_t) * temp_insn_ops; - VARR (MIR_var_t) * temp_vars; - VARR (MIR_type_t) * temp_types; - VARR (size_t) * insn_nops; + VARR (size_t) * insn_nops; /* constant after initialization */ + VARR (MIR_proto_t) * unspec_protos; /* protos of unspec insns (set only during initialization) */ VARR (char) * temp_string; VARR (uint8_t) * temp_data; - char temp_buff[30]; HTAB (MIR_item_t) * module_item_tab; /* Module to keep items potentially used by all modules: */ struct MIR_module environment_module; - VARR (MIR_reg_t) * inline_reg_map; MIR_module_t curr_module; MIR_func_t curr_func; int curr_label_num; @@ -54,31 +51,21 @@ struct MIR_context { struct io_ctx *io_ctx; struct scan_ctx *scan_ctx; struct interp_ctx *interp_ctx; - size_t inlined_calls, inline_insns_before, inline_insns_after; }; +#define ctx_mutex ctx->ctx_mutex #define error_func ctx->error_func #define unspec_protos ctx->unspec_protos -#define temp_insns ctx->temp_insns -#define temp_insns2 ctx->temp_insns2 -#define temp_insn_ops ctx->temp_insn_ops -#define temp_vars ctx->temp_vars -#define temp_types ctx->temp_types #define insn_nops ctx->insn_nops #define temp_string ctx->temp_string #define temp_data ctx->temp_data -#define temp_buff ctx->temp_buff #define module_item_tab ctx->module_item_tab #define environment_module ctx->environment_module -#define inline_reg_map ctx->inline_reg_map #define curr_module ctx->curr_module #define curr_func ctx->curr_func #define curr_label_num ctx->curr_label_num #define all_modules ctx->all_modules #define modules_to_link ctx->modules_to_link -#define inlined_calls ctx->inlined_calls -#define inline_insns_before ctx->inline_insns_before -#define inline_insns_after ctx->inline_insns_after static void util_error (MIR_context_t ctx, const char *message); #define MIR_VARR_ERROR util_error @@ -109,7 +96,7 @@ static void MIR_NO_RETURN default_error (enum MIR_error_type error_type, const c } static void MIR_NO_RETURN MIR_UNUSED util_error (MIR_context_t ctx, const char *message) { - (*error_func) (MIR_alloc_error, message); + MIR_get_error_func (ctx) (MIR_alloc_error, message); } #define HARD_REG_NAME_PREFIX "hr" @@ -391,7 +378,7 @@ static string_t string_store (MIR_context_t ctx, VARR (string_t) * *strs, if (string_find (strs, str_tab, str, &el)) return el; if ((heap_str = malloc (str.len)) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for strings"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for strings"); memcpy (heap_str, str.s, str.len); string.str.s = heap_str; string.str.len = str.len; @@ -401,6 +388,14 @@ static string_t string_store (MIR_context_t ctx, VARR (string_t) * *strs, return string; } +static struct string get_ctx_string (MIR_context_t ctx, MIR_str_t str) { + return string_store (ctx, &strings, &string_tab, str); +} + +static const char *get_ctx_str (MIR_context_t ctx, const char *string) { + return get_ctx_string (ctx, (MIR_str_t){strlen (string) + 1, string}).str.s; +} + static void string_finish (VARR (string_t) * *strs, HTAB (string_t) * *str_tab) { size_t i; @@ -413,8 +408,7 @@ static void string_finish (VARR (string_t) * *strs, HTAB (string_t) * *str_tab) /* New Page */ typedef struct reg_desc { - size_t name_num; /* 1st key for the namenum2rdn hash tab */ - MIR_func_t func; /* 2nd key for hash the both tabs */ + char *name; /* 1st key for the name2rdn hash tab */ MIR_type_t type; MIR_reg_t reg; /* 1st key reg2rdn hash tab */ } reg_desc_t; @@ -423,99 +417,92 @@ DEF_VARR (reg_desc_t); DEF_HTAB (size_t); -struct reg_type_cache { - MIR_func_t func; - VARR (MIR_type_t) * types; -}; - -struct reg_ctx { +typedef struct func_regs { VARR (reg_desc_t) * reg_descs; - HTAB (size_t) * namenum2rdn_tab; + HTAB (size_t) * name2rdn_tab; HTAB (size_t) * reg2rdn_tab; - struct reg_type_cache reg_type_cache; -}; +} * func_regs_t; -#define reg_descs ctx->reg_ctx->reg_descs -#define namenum2rdn_tab ctx->reg_ctx->namenum2rdn_tab -#define reg2rdn_tab ctx->reg_ctx->reg2rdn_tab -#define reg_type_cache ctx->reg_ctx->reg_type_cache +static int name2rdn_eq (size_t rdn1, size_t rdn2, void *arg) { + func_regs_t func_regs = arg; + reg_desc_t *addr = VARR_ADDR (reg_desc_t, func_regs->reg_descs); -static int namenum2rdn_eq (size_t rdn1, size_t rdn2, void *arg) { - MIR_context_t ctx = arg; - reg_desc_t *addr = VARR_ADDR (reg_desc_t, reg_descs); - - return (addr[rdn1].name_num == addr[rdn2].name_num && addr[rdn1].func == addr[rdn2].func); + return strcmp (addr[rdn1].name, addr[rdn2].name) == 0; } -static htab_hash_t namenum2rdn_hash (size_t rdn, void *arg) { - MIR_context_t ctx = arg; - reg_desc_t *addr = VARR_ADDR (reg_desc_t, reg_descs); +static htab_hash_t name2rdn_hash (size_t rdn, void *arg) { + func_regs_t func_regs = arg; + reg_desc_t *addr = VARR_ADDR (reg_desc_t, func_regs->reg_descs); - return mir_hash_finish ( - mir_hash_step (mir_hash_step (mir_hash_init (0), (uint64_t) addr[rdn].func), - (uint64_t) addr[rdn].name_num)); + return mir_hash (addr[rdn].name, strlen (addr[rdn].name), 0); } static int reg2rdn_eq (size_t rdn1, size_t rdn2, void *arg) { - MIR_context_t ctx = arg; - reg_desc_t *addr = VARR_ADDR (reg_desc_t, reg_descs); + func_regs_t func_regs = arg; + reg_desc_t *addr = VARR_ADDR (reg_desc_t, func_regs->reg_descs); - return addr[rdn1].reg == addr[rdn2].reg && addr[rdn1].func == addr[rdn2].func; + return addr[rdn1].reg == addr[rdn2].reg; } static htab_hash_t reg2rdn_hash (size_t rdn, void *arg) { - MIR_context_t ctx = arg; - reg_desc_t *addr = VARR_ADDR (reg_desc_t, reg_descs); + func_regs_t func_regs = arg; + reg_desc_t *addr = VARR_ADDR (reg_desc_t, func_regs->reg_descs); - return mir_hash_finish ( - mir_hash_step (mir_hash_step (mir_hash_init (0), (uint64_t) addr[rdn].func), addr[rdn].reg)); + return mir_hash_finish (mir_hash_step (mir_hash_init (0), addr[rdn].reg)); } -static void reg_init (MIR_context_t ctx) { - reg_desc_t rd = {0, NULL, MIR_T_I64, 0}; +static void func_regs_init (MIR_context_t ctx, MIR_func_t func) { + func_regs_t func_regs; + reg_desc_t rd = {NULL, MIR_T_I64, 0}; - if ((ctx->reg_ctx = malloc (sizeof (struct reg_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); - VARR_CREATE (reg_desc_t, reg_descs, 300); - VARR_PUSH (reg_desc_t, reg_descs, rd); /* for 0 reg */ - HTAB_CREATE (size_t, namenum2rdn_tab, 300, namenum2rdn_hash, namenum2rdn_eq, ctx); - HTAB_CREATE (size_t, reg2rdn_tab, 300, reg2rdn_hash, reg2rdn_eq, ctx); - reg_type_cache.func = NULL; - VARR_CREATE (MIR_type_t, reg_type_cache.types, 1000); + if ((func_regs = func->internal = malloc (sizeof (struct func_regs))) == NULL) + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for func regs info"); + VARR_CREATE (reg_desc_t, func_regs->reg_descs, 50); + VARR_PUSH (reg_desc_t, func_regs->reg_descs, rd); /* for 0 reg */ + HTAB_CREATE (size_t, func_regs->name2rdn_tab, 100, name2rdn_hash, name2rdn_eq, func_regs); + HTAB_CREATE (size_t, func_regs->reg2rdn_tab, 100, reg2rdn_hash, reg2rdn_eq, func_regs); } static MIR_reg_t create_func_reg (MIR_context_t ctx, MIR_func_t func, const char *name, - MIR_reg_t reg, MIR_type_t type, int any_p) { + MIR_reg_t reg, MIR_type_t type, int any_p, char **name_ptr) { + func_regs_t func_regs = func->internal; reg_desc_t rd; size_t rdn, tab_rdn; int htab_res; if (!any_p && _MIR_reserved_name_p (ctx, name)) - (*error_func) (MIR_reserved_name_error, "redefining a reserved name %s", name); - rd.name_num = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).num; - rd.func = func; + MIR_get_error_func (ctx) (MIR_reserved_name_error, "redefining a reserved name %s", name); + rd.name = (char *) name; rd.type = type; rd.reg = reg; /* 0 is reserved */ - rdn = VARR_LENGTH (reg_desc_t, reg_descs); - VARR_PUSH (reg_desc_t, reg_descs, rd); - if (HTAB_DO (size_t, namenum2rdn_tab, rdn, HTAB_FIND, tab_rdn)) { - VARR_POP (reg_desc_t, reg_descs); - (*error_func) (MIR_repeated_decl_error, "Repeated reg declaration %s", name); + rdn = VARR_LENGTH (reg_desc_t, func_regs->reg_descs); + VARR_PUSH (reg_desc_t, func_regs->reg_descs, rd); + if (HTAB_DO (size_t, func_regs->name2rdn_tab, rdn, HTAB_FIND, tab_rdn)) { + VARR_POP (reg_desc_t, func_regs->reg_descs); + MIR_get_error_func (ctx) (MIR_repeated_decl_error, "Repeated reg declaration %s", name); } - htab_res = HTAB_DO (size_t, namenum2rdn_tab, rdn, HTAB_INSERT, tab_rdn); + if ((rd.name = malloc (strlen (name) + 1)) == NULL) + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for reg names"); + VARR_ADDR (reg_desc_t, func_regs->reg_descs)[rdn].name = *name_ptr = rd.name; + strcpy (*name_ptr, name); + htab_res = HTAB_DO (size_t, func_regs->name2rdn_tab, rdn, HTAB_INSERT, tab_rdn); mir_assert (!htab_res); - htab_res = HTAB_DO (size_t, reg2rdn_tab, rdn, HTAB_INSERT, tab_rdn); + htab_res = HTAB_DO (size_t, func_regs->reg2rdn_tab, rdn, HTAB_INSERT, tab_rdn); mir_assert (!htab_res); return reg; } -static void reg_finish (MIR_context_t ctx) { - VARR_DESTROY (reg_desc_t, reg_descs); - HTAB_DESTROY (size_t, namenum2rdn_tab); - HTAB_DESTROY (size_t, reg2rdn_tab); - VARR_DESTROY (MIR_type_t, reg_type_cache.types); - free (ctx->reg_ctx); - ctx->reg_ctx = NULL; +static void func_regs_finish (MIR_context_t ctx, MIR_func_t func) { + func_regs_t func_regs = func->internal; + char *name; + + for (size_t i = 0; i < VARR_LENGTH (reg_desc_t, func_regs->reg_descs); i++) + if ((name = VARR_GET (reg_desc_t, func_regs->reg_descs, i).name) != NULL) free (name); + VARR_DESTROY (reg_desc_t, func_regs->reg_descs); + HTAB_DESTROY (size_t, func_regs->name2rdn_tab); + HTAB_DESTROY (size_t, func_regs->reg2rdn_tab); + free (func->internal); + func->internal = NULL; } /* New Page */ @@ -550,12 +537,14 @@ static void scan_init (MIR_context_t ctx); static void scan_finish (MIR_context_t ctx); #endif -static void vn_init (MIR_context_t ctx); -static void vn_finish (MIR_context_t ctx); +static void simplify_init (MIR_context_t ctx); +static void simplify_finish (MIR_context_t ctx); -MIR_error_func_t MIR_get_error_func (MIR_context_t ctx) { return error_func; } +MIR_error_func_t MIR_get_error_func (MIR_context_t ctx) { return error_func; } // ??? atomic -void MIR_set_error_func (MIR_context_t ctx, MIR_error_func_t func) { error_func = func; } +void MIR_set_error_func (MIR_context_t ctx, MIR_error_func_t func) { // ?? atomic access + error_func = func; +} static htab_hash_t item_hash (MIR_item_t it, void *arg) { return mir_hash_finish ( @@ -566,7 +555,7 @@ static int item_eq (MIR_item_t it1, MIR_item_t it2, void *arg) { return it1->module == it2->module && MIR_item_name (NULL, it1) == MIR_item_name (NULL, it2); } -static MIR_item_t find_item (MIR_context_t ctx, const char *name, MIR_module_t module) { +static MIR_item_t item_tab_find (MIR_context_t ctx, const char *name, MIR_module_t module) { MIR_item_t tab_item; struct MIR_item item_s; struct MIR_func func_s; @@ -579,16 +568,31 @@ static MIR_item_t find_item (MIR_context_t ctx, const char *name, MIR_module_t m return NULL; } +static MIR_item_t item_tab_insert (MIR_context_t ctx, MIR_item_t item) { + MIR_item_t tab_item; + + HTAB_DO (MIR_item_t, module_item_tab, item, HTAB_INSERT, tab_item); + return tab_item; +} + +static void item_tab_remove (MIR_context_t ctx, MIR_item_t item) { + HTAB_DO (MIR_item_t, module_item_tab, item, HTAB_DELETE, item); +} + static void init_module (MIR_context_t ctx, MIR_module_t m, const char *name) { m->data = NULL; m->last_temp_item_num = 0; - m->name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + m->name = get_ctx_str (ctx, name); DLIST_INIT (MIR_item_t, m->items); } static void code_init (MIR_context_t ctx); static void code_finish (MIR_context_t ctx); +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) { MIR_context_t ctx; @@ -601,6 +605,7 @@ MIR_context_t MIR_init (void) { ctx->io_ctx = NULL; ctx->scan_ctx = NULL; ctx->interp_ctx = NULL; + if (mir_mutex_init (&ctx_mutex, NULL)) parallel_error (ctx, "error in mutex init"); #ifndef NDEBUG for (MIR_insn_code_t c = 0; c < MIR_INVALID_INSN; c++) mir_assert (c == insn_descs[c].code); #endif @@ -609,19 +614,12 @@ MIR_context_t MIR_init (void) { curr_func = NULL; curr_label_num = 0; if ((ctx->string_ctx = malloc (sizeof (struct string_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); string_init (&strings, &string_tab); - reg_init (ctx); VARR_CREATE (MIR_proto_t, unspec_protos, 0); - VARR_CREATE (MIR_insn_t, temp_insns, 0); - VARR_CREATE (MIR_insn_t, temp_insns2, 0); - VARR_CREATE (MIR_op_t, temp_insn_ops, 0); - VARR_CREATE (MIR_var_t, temp_vars, 0); - VARR_CREATE (MIR_type_t, temp_types, 0); check_and_prepare_insn_descs (ctx); DLIST_INIT (MIR_module_t, all_modules); - vn_init (ctx); - VARR_CREATE (MIR_reg_t, inline_reg_map, 256); + simplify_init (ctx); VARR_CREATE (char, temp_string, 64); VARR_CREATE (uint8_t, temp_data, 512); #if !MIR_NO_IO @@ -635,14 +633,13 @@ MIR_context_t MIR_init (void) { HTAB_CREATE (MIR_item_t, module_item_tab, 512, item_hash, item_eq, NULL); code_init (ctx); interp_init (ctx); - inlined_calls = inline_insns_before = inline_insns_after = 0; return ctx; } void MIR_remove_insn (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t insn) { mir_assert (func_item != NULL); if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_remove_insn: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_remove_insn: wrong func item"); DLIST_REMOVE (MIR_insn_t, func_item->u.func->insns, insn); free (insn); } @@ -663,6 +660,7 @@ static void remove_item (MIR_context_t ctx, MIR_item_t item) { remove_func_insns (ctx, item, &item->u.func->insns); remove_func_insns (ctx, item, &item->u.func->original_insns); VARR_DESTROY (MIR_var_t, item->u.func->vars); + func_regs_finish (ctx, item->u.func); free (item->u.func); break; case MIR_proto_item: @@ -728,44 +726,35 @@ void MIR_finish (MIR_context_t ctx) { #endif VARR_DESTROY (uint8_t, temp_data); VARR_DESTROY (char, temp_string); - VARR_DESTROY (MIR_reg_t, inline_reg_map); while (VARR_LENGTH (MIR_proto_t, unspec_protos) != 0) { MIR_proto_t proto = VARR_POP (MIR_proto_t, unspec_protos); VARR_DESTROY (MIR_var_t, proto->args); free (proto); } VARR_DESTROY (MIR_proto_t, unspec_protos); - reg_finish (ctx); string_finish (&strings, &string_tab); - vn_finish (ctx); - VARR_DESTROY (MIR_var_t, temp_vars); + simplify_finish (ctx); VARR_DESTROY (size_t, insn_nops); - VARR_DESTROY (MIR_op_t, temp_insn_ops); - VARR_DESTROY (MIR_insn_t, temp_insns2); - VARR_DESTROY (MIR_insn_t, temp_insns); - VARR_DESTROY (MIR_type_t, temp_types); code_finish (ctx); if (curr_func != NULL) - (*error_func) (MIR_finish_error, "finish when function %s is not finished", curr_func->name); + MIR_get_error_func (ctx) (MIR_finish_error, "finish when function %s is not finished", + curr_func->name); if (curr_module != NULL) - (*error_func) (MIR_finish_error, "finish when module %s is not finished", curr_module->name); -#if 0 - if (inlined_calls != 0) - fprintf (stderr, "inlined calls = %lu, insns before = %lu, insns_after = %lu, ratio = %.2f\n", - inlined_calls, inline_insns_before, inline_insns_after, - (double) inline_insns_after / inline_insns_before); -#endif + MIR_get_error_func (ctx) (MIR_finish_error, "finish when module %s is not finished", + curr_module->name); free (ctx->string_ctx); + if (mir_mutex_destroy (&ctx_mutex)) parallel_error (ctx, "error in mutex destroy"); free (ctx); ctx = NULL; } MIR_module_t MIR_new_module (MIR_context_t ctx, const char *name) { if (curr_module != NULL) - (*error_func) (MIR_nested_module_error, - "Creating module when previous module %s is not finished", curr_module->name); + MIR_get_error_func (ctx) (MIR_nested_module_error, + "Creating module when previous module %s is not finished", + curr_module->name); if ((curr_module = malloc (sizeof (struct MIR_module))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for module %s creation", name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for module %s creation", name); init_module (ctx, curr_module, name); DLIST_APPEND (MIR_module_t, all_modules, curr_module); return curr_module; @@ -798,7 +787,7 @@ const char *MIR_type_str (MIR_context_t ctx, MIR_type_t tp) { const char *str = type_str (tp); if (strcmp (str, "") == 0) - (*error_func) (MIR_wrong_param_value_error, "MIR_type_str: wrong type"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_type_str: wrong type"); return str; } @@ -826,7 +815,7 @@ static MIR_item_t add_item (MIR_context_t ctx, MIR_item_t item) { int replace_p; MIR_item_t tab_item; - if ((tab_item = find_item (ctx, MIR_item_name (ctx, item), item->module)) == NULL) { + if ((tab_item = item_tab_find (ctx, MIR_item_name (ctx, item), item->module)) == NULL) { DLIST_APPEND (MIR_item_t, curr_module->items, item); HTAB_DO (MIR_item_t, module_item_tab, item, HTAB_INSERT, item); return item; @@ -834,16 +823,17 @@ static MIR_item_t add_item (MIR_context_t ctx, MIR_item_t item) { switch (tab_item->item_type) { case MIR_import_item: if (item->item_type != MIR_import_item) - (*error_func) (MIR_import_export_error, - "existing module definition %s already defined as import", - tab_item->u.import_id); + MIR_get_error_func (ctx) (MIR_import_export_error, + "existing module definition %s already defined as import", + tab_item->u.import_id); item = tab_item; break; case MIR_export_item: case MIR_forward_item: replace_p = FALSE; if (item->item_type == MIR_import_item) { - (*error_func) (MIR_import_export_error, "export/forward of import %s", item->u.import_id); + MIR_get_error_func (ctx) (MIR_import_export_error, "export/forward of import %s", + item->u.import_id); } else if (item->item_type != MIR_export_item && item->item_type != MIR_forward_item) { replace_p = TRUE; DLIST_APPEND (MIR_item_t, curr_module->items, item); @@ -858,14 +848,14 @@ static MIR_item_t add_item (MIR_context_t ctx, MIR_item_t item) { if (replace_p) { /* replace forward by export or export/forward by its definition: */ tab_item->ref_def = item; if (tab_item->item_type == MIR_export_item) item->export_p = TRUE; - HTAB_DO (MIR_item_t, module_item_tab, tab_item, HTAB_DELETE, tab_item); - HTAB_DO (MIR_item_t, module_item_tab, item, HTAB_INSERT, tab_item); + item_tab_remove (ctx, tab_item); + tab_item = item_tab_insert (ctx, item); mir_assert (item == tab_item); } break; case MIR_proto_item: - (*error_func) (MIR_repeated_decl_error, "item %s was already defined as proto", - tab_item->u.proto->name); + MIR_get_error_func (ctx) (MIR_repeated_decl_error, "item %s was already defined as proto", + tab_item->u.proto->name); break; case MIR_bss_item: case MIR_data_item: @@ -884,10 +874,11 @@ static MIR_item_t add_item (MIR_context_t ctx, MIR_item_t item) { DLIST_APPEND (MIR_item_t, curr_module->items, item); item->ref_def = tab_item; } else if (item->item_type == MIR_import_item) { - (*error_func) (MIR_import_export_error, "import of local definition %s", item->u.import_id); + MIR_get_error_func (ctx) (MIR_import_export_error, "import of local definition %s", + item->u.import_id); } else { - (*error_func) (MIR_repeated_decl_error, "Repeated item declaration %s", - MIR_item_name (ctx, item)); + MIR_get_error_func (ctx) (MIR_repeated_decl_error, "Repeated item declaration %s", + MIR_item_name (ctx, item)); } break; default: mir_assert (FALSE); @@ -899,9 +890,11 @@ static MIR_item_t create_item (MIR_context_t ctx, MIR_item_type_t item_type, const char *item_name) { MIR_item_t item; - if (curr_module == NULL) (*error_func) (MIR_no_module_error, "%s outside module", item_name); + if (curr_module == NULL) + MIR_get_error_func (ctx) (MIR_no_module_error, "%s outside module", item_name); if ((item = malloc (sizeof (struct MIR_item))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for creation of item %s", item_name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of item %s", + item_name); item->data = NULL; item->module = curr_module; item->item_type = item_type; @@ -919,7 +912,7 @@ static MIR_item_t new_export_import_forward (MIR_context_t ctx, const char *name const char *uniq_name; item = create_item (ctx, item_type, item_name); - uniq_name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + uniq_name = get_ctx_str (ctx, name); if (item_type == MIR_export_item) item->u.export_id = uniq_name; else if (item_type == MIR_import_item) @@ -952,10 +945,9 @@ MIR_item_t MIR_new_bss (MIR_context_t ctx, const char *name, size_t len) { item->u.bss = malloc (sizeof (struct MIR_bss)); if (item->u.bss == NULL) { free (item); - (*error_func) (MIR_alloc_error, "Not enough memory for creation of bss %s", name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of bss %s", name); } - if (name != NULL) - name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + if (name != NULL) name = get_ctx_str (ctx, name); item->u.bss->name = name; item->u.bss->len = len; if (name == NULL) { @@ -1002,17 +994,16 @@ MIR_item_t MIR_new_data (MIR_context_t ctx, const char *name, MIR_type_t el_type if (wrong_type_p (el_type)) { free (item); - (*error_func) (MIR_wrong_type_error, "wrong type in data %s", name); + MIR_get_error_func (ctx) (MIR_wrong_type_error, "wrong type in data %s", name); } el_len = _MIR_type_size (ctx, el_type); item->u.data = data = malloc (sizeof (struct MIR_data) + el_len * nel); if (data == NULL) { free (item); - (*error_func) (MIR_alloc_error, "Not enough memory for creation of data %s", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of data %s", + name == NULL ? "" : name); } - if (name != NULL) - name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + if (name != NULL) name = get_ctx_str (ctx, name); data->name = name; if (name == NULL) { DLIST_APPEND (MIR_item_t, curr_module->items, item); @@ -1038,11 +1029,10 @@ MIR_item_t MIR_new_ref_data (MIR_context_t ctx, const char *name, MIR_item_t ref item->u.ref_data = ref_data = malloc (sizeof (struct MIR_ref_data)); if (ref_data == NULL) { free (item); - (*error_func) (MIR_alloc_error, "Not enough memory for creation of ref data %s", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of ref data %s", + name == NULL ? "" : name); } - if (name != NULL) - name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + if (name != NULL) name = get_ctx_str (ctx, name); ref_data->name = name; ref_data->ref_item = ref_item; ref_data->disp = disp; @@ -1062,17 +1052,17 @@ MIR_item_t MIR_new_expr_data (MIR_context_t ctx, const char *name, MIR_item_t ex item->u.expr_data = expr_data = malloc (sizeof (struct MIR_expr_data)); if (expr_data == NULL) { free (item); - (*error_func) (MIR_alloc_error, "Not enough memory for creation of expr data %s", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of expr data %s", + name == NULL ? "" : name); } mir_assert (expr_item != NULL); if (expr_item->item_type != MIR_func_item || expr_item->u.func->vararg_p || expr_item->u.func->nargs != 0 || expr_item->u.func->nres != 1) - (*error_func) (MIR_binary_io_error, - "%s can not be an expr which should be non-argument, one result function", - MIR_item_name (ctx, expr_item)); - if (name != NULL) - name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + MIR_get_error_func ( + ctx) (MIR_binary_io_error, + "%s can not be an expr which should be non-argument, one result function", + MIR_item_name (ctx, expr_item)); + if (name != NULL) name = get_ctx_str (ctx, name); expr_data->name = name; expr_data->expr_item = expr_item; if (name == NULL) { @@ -1090,11 +1080,10 @@ static MIR_proto_t create_proto (MIR_context_t ctx, const char *name, size_t nre MIR_proto_t proto = malloc (sizeof (struct MIR_proto) + nres * sizeof (MIR_type_t)); if (proto == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for creation of proto %s", name); - proto->name - = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of proto %s", name); + proto->name = get_ctx_str (ctx, name); proto->res_types = (MIR_type_t *) ((char *) proto + sizeof (struct MIR_proto)); - memcpy (proto->res_types, res_types, nres * sizeof (MIR_type_t)); + if (nres != 0) memcpy (proto->res_types, res_types, nres * sizeof (MIR_type_t)); proto->nres = nres; proto->vararg_p = vararg_p != 0; VARR_CREATE (MIR_var_t, proto->args, nargs); @@ -1108,10 +1097,10 @@ static MIR_item_t new_proto_arr (MIR_context_t ctx, const char *name, size_t nre MIR_item_t proto_item, tab_item; if (curr_module == NULL) - (*error_func) (MIR_no_module_error, "Creating proto %s outside module", name); + MIR_get_error_func (ctx) (MIR_no_module_error, "Creating proto %s outside module", name); for (size_t i = 0; i < nres; i++) if (wrong_type_p (res_types[i])) - (*error_func) (MIR_wrong_type_error, "wrong result type in proto %s", name); + MIR_get_error_func (ctx) (MIR_wrong_type_error, "wrong result type in proto %s", name); proto_item = create_item (ctx, MIR_proto_item, "proto"); proto_item->u.proto = create_proto (ctx, name, nres, res_types, nargs, vararg_p, args); tab_item = add_item (ctx, proto_item); @@ -1129,19 +1118,20 @@ MIR_item_t MIR_new_vararg_proto_arr (MIR_context_t ctx, const char *name, size_t return new_proto_arr (ctx, name, nres, res_types, nargs, TRUE, args); } +#if defined(_MSC_VER) +#define alloca _alloca +#endif + static MIR_item_t new_proto (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, size_t nargs, int vararg_p, va_list argp) { - MIR_var_t arg; + MIR_var_t *args = alloca (nargs * sizeof (MIR_var_t)); size_t i; - VARR_TRUNC (MIR_var_t, temp_vars, 0); for (i = 0; i < nargs; i++) { - arg.type = va_arg (argp, MIR_type_t); - arg.name = va_arg (argp, const char *); - VARR_PUSH (MIR_var_t, temp_vars, arg); + args[i].type = va_arg (argp, MIR_type_t); + args[i].name = va_arg (argp, const char *); } - return new_proto_arr (ctx, name, nres, res_types, nargs, vararg_p, - VARR_ADDR (MIR_var_t, temp_vars)); + return new_proto_arr (ctx, name, nres, res_types, nargs, vararg_p, args); } MIR_item_t MIR_new_proto (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, @@ -1173,23 +1163,23 @@ static MIR_item_t new_func_arr (MIR_context_t ctx, const char *name, size_t nres MIR_func_t func; if (curr_func != NULL) - (*error_func) (MIR_nested_func_error, - "Creating function when previous function %s is not finished", curr_func->name); + MIR_get_error_func (ctx) (MIR_nested_func_error, + "Creating function when previous function %s is not finished", + curr_func->name); if (nargs == 0 && vararg_p) - (*error_func) (MIR_vararg_func_error, "Variable arg function %s w/o any mandatory argument", - name); + MIR_get_error_func (ctx) (MIR_vararg_func_error, + "Variable arg function %s w/o any mandatory argument", name); for (size_t i = 0; i < nres; i++) if (wrong_type_p (res_types[i])) - (*error_func) (MIR_wrong_type_error, "wrong result type in func %s", name); + MIR_get_error_func (ctx) (MIR_wrong_type_error, "wrong result type in func %s", name); func_item = create_item (ctx, MIR_func_item, "function"); curr_func = func_item->u.func = func = malloc (sizeof (struct MIR_func) + nres * sizeof (MIR_type_t)); if (func == NULL) { free (func_item); - (*error_func) (MIR_alloc_error, "Not enough memory for creation of func %s", name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for creation of func %s", name); } - func->name - = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + func->name = get_ctx_str (ctx, name); 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]); @@ -1204,13 +1194,16 @@ static MIR_item_t new_func_arr (MIR_context_t ctx, const char *name, size_t nres func->expr_p = FALSE; func->n_inlines = 0; func->machine_code = func->call_addr = NULL; + func_regs_init (ctx, func); for (size_t i = 0; i < nargs; i++) { + char *stored_name; MIR_type_t type = canon_type (vars[i].type); - VARR_PUSH (MIR_var_t, func->vars, vars[i]); create_func_reg (ctx, func, vars[i].name, i + 1, type == MIR_T_F || type == MIR_T_D || type == MIR_T_LD ? type : MIR_T_I64, - FALSE); + FALSE, &stored_name); + vars[i].name = stored_name; + VARR_PUSH (MIR_var_t, func->vars, vars[i]); } return func_item; } @@ -1227,17 +1220,14 @@ MIR_item_t MIR_new_vararg_func_arr (MIR_context_t ctx, const char *name, size_t static MIR_item_t new_func (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, size_t nargs, int vararg_p, va_list argp) { - MIR_var_t var; size_t i; + MIR_var_t *vars = alloca (sizeof (MIR_var_t) * nargs); - VARR_TRUNC (MIR_var_t, temp_vars, 0); for (i = 0; i < nargs; i++) { - var.type = va_arg (argp, MIR_type_t); - var.name = va_arg (argp, const char *); - VARR_PUSH (MIR_var_t, temp_vars, var); + vars[i].type = va_arg (argp, MIR_type_t); + vars[i].name = va_arg (argp, const char *); } - return new_func_arr (ctx, name, nres, res_types, nargs, vararg_p, - VARR_ADDR (MIR_var_t, temp_vars)); + return new_func_arr (ctx, name, nres, res_types, nargs, vararg_p, vars); } MIR_item_t MIR_new_func (MIR_context_t ctx, const char *name, size_t nres, MIR_type_t *res_types, @@ -1264,51 +1254,56 @@ MIR_item_t MIR_new_vararg_func (MIR_context_t ctx, const char *name, size_t nres MIR_reg_t MIR_new_func_reg (MIR_context_t ctx, MIR_func_t func, MIR_type_t type, const char *name) { MIR_var_t var; + MIR_reg_t res; + char *stored_name; if (type != MIR_T_I64 && type != MIR_T_F && type != MIR_T_D && type != MIR_T_LD) - (*error_func) (MIR_reg_type_error, "wrong type for register %s: got '%s'", name, - type_str (type)); - var.type = type; - var.name = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).str.s; + MIR_get_error_func (ctx) (MIR_reg_type_error, "wrong type for register %s: got '%s'", name, + type_str (type)); mir_assert (func != NULL); + res = create_func_reg (ctx, func, name, VARR_LENGTH (MIR_var_t, func->vars) + 1, type, FALSE, + &stored_name); + var.type = type; + var.name = stored_name; VARR_PUSH (MIR_var_t, func->vars, var); - return create_func_reg (ctx, func, name, VARR_LENGTH (MIR_var_t, func->vars), type, FALSE); + return res; } -static reg_desc_t *find_rd_by_name_num (MIR_context_t ctx, size_t name_num, MIR_func_t func) { +static reg_desc_t *find_rd_by_name (MIR_context_t ctx, const char *name, MIR_func_t func) { + func_regs_t func_regs = func->internal; size_t rdn, temp_rdn; reg_desc_t rd; - rd.name_num = name_num; - rd.func = func; /* keys */ + rd.name = (char *) name; rd.type = MIR_T_I64; rd.reg = 0; /* to eliminate warnings */ - temp_rdn = VARR_LENGTH (reg_desc_t, reg_descs); - VARR_PUSH (reg_desc_t, reg_descs, rd); - if (!HTAB_DO (size_t, namenum2rdn_tab, temp_rdn, HTAB_FIND, rdn)) { - VARR_POP (reg_desc_t, reg_descs); + temp_rdn = VARR_LENGTH (reg_desc_t, func_regs->reg_descs); + VARR_PUSH (reg_desc_t, func_regs->reg_descs, rd); + if (!HTAB_DO (size_t, func_regs->name2rdn_tab, temp_rdn, HTAB_FIND, rdn)) { + VARR_POP (reg_desc_t, func_regs->reg_descs); return NULL; /* undeclared */ } - VARR_POP (reg_desc_t, reg_descs); - return &VARR_ADDR (reg_desc_t, reg_descs)[rdn]; + VARR_POP (reg_desc_t, func_regs->reg_descs); + return &VARR_ADDR (reg_desc_t, func_regs->reg_descs)[rdn]; } static reg_desc_t *find_rd_by_reg (MIR_context_t ctx, MIR_reg_t reg, MIR_func_t func) { + func_regs_t func_regs = func->internal; size_t rdn, temp_rdn; reg_desc_t rd; rd.reg = reg; - rd.func = func; /* keys */ - rd.name_num = 0; + rd.name = NULL; rd.type = MIR_T_I64; /* to eliminate warnings */ - temp_rdn = VARR_LENGTH (reg_desc_t, reg_descs); - VARR_PUSH (reg_desc_t, reg_descs, rd); - if (!HTAB_DO (size_t, reg2rdn_tab, temp_rdn, HTAB_FIND, rdn)) { - VARR_POP (reg_desc_t, reg_descs); - (*error_func) (MIR_undeclared_func_reg_error, "undeclared reg %u of func %s", reg, func->name); + temp_rdn = VARR_LENGTH (reg_desc_t, func_regs->reg_descs); + VARR_PUSH (reg_desc_t, func_regs->reg_descs, rd); + if (!HTAB_DO (size_t, func_regs->reg2rdn_tab, temp_rdn, HTAB_FIND, rdn)) { + VARR_POP (reg_desc_t, func_regs->reg_descs); + MIR_get_error_func (ctx) (MIR_undeclared_func_reg_error, "undeclared reg %u of func %s", reg, + func->name); } - VARR_POP (reg_desc_t, reg_descs); - return &VARR_ADDR (reg_desc_t, reg_descs)[rdn]; + VARR_POP (reg_desc_t, func_regs->reg_descs); + return &VARR_ADDR (reg_desc_t, func_regs->reg_descs)[rdn]; } void MIR_finish_func (MIR_context_t ctx) { @@ -1317,7 +1312,8 @@ void MIR_finish_func (MIR_context_t ctx) { MIR_insn_code_t code; const char *func_name; - if (curr_func == NULL) (*error_func) (MIR_no_func_error, "finish of non-existing function"); + if (curr_func == NULL) + MIR_get_error_func (ctx) (MIR_no_func_error, "finish of non-existing function"); func_name = curr_func->name; if (curr_func->vararg_p || curr_func->nargs != 0 || curr_func->nres != 1) expr_p = FALSE; for (insn = DLIST_HEAD (MIR_insn_t, curr_func->insns); insn != NULL; @@ -1330,19 +1326,19 @@ void MIR_finish_func (MIR_context_t ctx) { code = insn->code; if (code == MIR_PHI) { curr_func = NULL; - (*error_func) (MIR_vararg_func_error, "phi can be used only internally"); + MIR_get_error_func (ctx) (MIR_vararg_func_error, "phi can be used only internally"); } else if (!curr_func->vararg_p && code == MIR_VA_START) { curr_func = NULL; - (*error_func) (MIR_vararg_func_error, "func %s: va_start is not in vararg function", - func_name); + MIR_get_error_func (ctx) (MIR_vararg_func_error, "va_start is not in vararg function"); } else if (code == MIR_RET && actual_nops != curr_func->nres) { int nres = curr_func->nres; curr_func = NULL; - (*error_func) (MIR_vararg_func_error, - "func %s: in instruction '%s': number of operands in return does not " - "correspond number of function returns. Expected %d, got %d", - func_name, insn_descs[code].name, nres, actual_nops); + MIR_get_error_func ( + ctx) (MIR_vararg_func_error, + "func %s: in instruction '%s': number of operands in return does not " + "correspond number of function returns. Expected %d, got %d", + func_name, insn_descs[code].name, nres, actual_nops); } else if (MIR_call_code_p (code)) expr_p = FALSE; for (i = 0; i < actual_nops; i++) { @@ -1387,24 +1383,26 @@ void MIR_finish_func (MIR_context_t ctx) { if (wrong_type_p (insn->ops[i].u.mem.type) && (!MIR_blk_type_p (insn->ops[i].u.mem.type) || !MIR_call_code_p (code))) { curr_func = NULL; - (*error_func) (MIR_wrong_type_error, "func %s: in instruction '%s': wrong type memory", - func_name, insn_descs[code].name); + MIR_get_error_func (ctx) (MIR_wrong_type_error, + "func %s: in instruction '%s': wrong type memory", func_name, + insn_descs[code].name); } if (MIR_blk_type_p (insn->ops[i].u.mem.type) && insn->ops[i].u.mem.disp < 0) { curr_func = NULL; - (*error_func) (MIR_wrong_type_error, - "func %s: in instruction '%s': block type memory with disp < 0", func_name, - insn_descs[code].name); + MIR_get_error_func (ctx) (MIR_wrong_type_error, + "func %s: in instruction '%s': block type memory with disp < 0", + func_name, insn_descs[code].name); } if (insn->ops[i].u.mem.base != 0) { rd = find_rd_by_reg (ctx, insn->ops[i].u.mem.base, curr_func); mir_assert (rd != NULL && insn->ops[i].u.mem.base == rd->reg); if (type2mode (rd->type) != MIR_OP_INT) { curr_func = NULL; - (*error_func) (MIR_reg_type_error, - "func %s: in instruction '%s': base reg of non-integer type for operand " - "#%d", - func_name, insn_descs[code].name, i + 1); + MIR_get_error_func ( + ctx) (MIR_reg_type_error, + "func %s: in instruction '%s': base reg of non-integer type for operand " + "#%d", + func_name, insn_descs[code].name, i + 1); } } if (insn->ops[i].u.mem.index != 0) { @@ -1412,10 +1410,11 @@ void MIR_finish_func (MIR_context_t ctx) { mir_assert (rd != NULL && insn->ops[i].u.mem.index == rd->reg); if (type2mode (rd->type) != MIR_OP_INT) { curr_func = NULL; - (*error_func) (MIR_reg_type_error, - "func %s: in instruction '%s': index reg of non-integer type for " - "operand #%d", - func_name, insn_descs[code].name, i + 1); + MIR_get_error_func ( + ctx) (MIR_reg_type_error, + "func %s: in instruction '%s': index reg of non-integer type for " + "operand #%d", + func_name, insn_descs[code].name, i + 1); } } mode = type2mode (insn->ops[i].u.mem.type); @@ -1441,17 +1440,17 @@ void MIR_finish_func (MIR_context_t ctx) { } else if (expected_mode != MIR_OP_UNDEF && (mode == MIR_OP_UINT ? MIR_OP_INT : mode) != expected_mode) { curr_func = NULL; - (*error_func) (MIR_op_mode_error, - "func %s: in instruction '%s': unexpected operand mode for operand #%d. Got " - "'%s', expected '%s'", - func_name, insn_descs[code].name, i + 1, mode_str (mode), - mode_str (expected_mode)); + MIR_get_error_func ( + ctx) (MIR_op_mode_error, + "func %s: in instruction '%s': unexpected operand mode for operand #%d. Got " + "'%s', expected '%s'", + func_name, insn_descs[code].name, i + 1, mode_str (mode), mode_str (expected_mode)); } if (out_p && !can_be_out_p) { curr_func = NULL; - (*error_func) (MIR_out_op_error, - "func %s; in instruction '%s': wrong operand #%d for insn output", func_name, - insn_descs[code].name, i + 1); + MIR_get_error_func (ctx) (MIR_out_op_error, + "func %s; in instruction '%s': wrong operand #%d for insn output", + func_name, insn_descs[code].name, i + 1); } } } @@ -1460,7 +1459,8 @@ void MIR_finish_func (MIR_context_t ctx) { } void MIR_finish_module (MIR_context_t ctx) { - if (curr_module == NULL) (*error_func) (MIR_no_module_error, "finish of non-existing module"); + if (curr_module == NULL) + MIR_get_error_func (ctx) (MIR_no_module_error, "finish of non-existing module"); curr_module = NULL; } @@ -1471,7 +1471,7 @@ static void setup_global (MIR_context_t ctx, const char *name, void *addr, MIR_i curr_module = &environment_module; /* Use import for proto representation: */ item = new_export_import_forward (ctx, name, MIR_import_item, "import", TRUE); - if ((tab_item = find_item (ctx, MIR_item_name (ctx, item), &environment_module)) != item + if ((tab_item = item_tab_find (ctx, MIR_item_name (ctx, item), &environment_module)) != item && tab_item != NULL) { free (item); } else { @@ -1485,7 +1485,7 @@ static void setup_global (MIR_context_t ctx, const char *name, void *addr, MIR_i } static void undefined_interface (MIR_context_t ctx) { - (*error_func) (MIR_call_op_error, "undefined call interface"); + MIR_get_error_func (ctx) (MIR_call_op_error, "undefined call interface"); } static MIR_item_t load_bss_data_section (MIR_context_t ctx, MIR_item_t item, int first_only_p) { @@ -1512,16 +1512,17 @@ static MIR_item_t load_bss_data_section (MIR_context_t ctx, MIR_item_t item, int expr_item = curr_item->u.expr_data->expr_item; if (expr_item->item_type != MIR_func_item || !expr_item->u.func->expr_p || expr_item->u.func->nres != 1) - (*error_func) (MIR_binary_io_error, - "%s can not be an expr which should be a func w/o calls and memory ops", - MIR_item_name (ctx, expr_item)); + MIR_get_error_func ( + ctx) (MIR_binary_io_error, + "%s can not be an expr which should be a func w/o calls and memory ops", + MIR_item_name (ctx, expr_item)); section_size += _MIR_type_size (ctx, expr_item->u.func->res_types[0]); } else break; if ((item->addr = malloc (section_size)) == NULL) { name = MIR_item_name (ctx, item); - (*error_func) (MIR_alloc_error, "Not enough memory to allocate data/bss %s", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory to allocate data/bss %s", + name == NULL ? "" : name); } item->section_head_p = TRUE; } @@ -1619,26 +1620,26 @@ void MIR_link (MIR_context_t ctx, void (*set_interface) (MIR_context_t ctx, MIR_ assert (item->data == NULL); if (simplify_func (ctx, item, TRUE)) item->data = (void *) 1; /* flag inlining */ } else if (item->item_type == MIR_import_item) { - if ((tab_item = find_item (ctx, item->u.import_id, &environment_module)) == NULL) { + if ((tab_item = item_tab_find (ctx, item->u.import_id, &environment_module)) == NULL) { if (import_resolver == NULL || (addr = import_resolver (item->u.import_id)) == NULL) - (*error_func) (MIR_undeclared_op_ref_error, "import of undefined item %s", - item->u.import_id); + MIR_get_error_func (ctx) (MIR_undeclared_op_ref_error, "import of undefined item %s", + item->u.import_id); MIR_load_external (ctx, item->u.import_id, addr); - tab_item = find_item (ctx, item->u.import_id, &environment_module); + tab_item = item_tab_find (ctx, item->u.import_id, &environment_module); mir_assert (tab_item != NULL); } item->addr = tab_item->addr; item->ref_def = tab_item; } else if (item->item_type == MIR_export_item) { - if ((tab_item = find_item (ctx, item->u.export_id, m)) == NULL) - (*error_func) (MIR_undeclared_op_ref_error, "export of undefined item %s", - item->u.export_id); + if ((tab_item = item_tab_find (ctx, item->u.export_id, m)) == NULL) + MIR_get_error_func (ctx) (MIR_undeclared_op_ref_error, "export of undefined item %s", + item->u.export_id); item->addr = tab_item->addr; item->ref_def = tab_item; } else if (item->item_type == MIR_forward_item) { - if ((tab_item = find_item (ctx, item->u.forward_id, m)) == NULL) - (*error_func) (MIR_undeclared_op_ref_error, "forward of undefined item %s", - item->u.forward_id); + if ((tab_item = item_tab_find (ctx, item->u.forward_id, m)) == NULL) + MIR_get_error_func (ctx) (MIR_undeclared_op_ref_error, "forward of undefined item %s", + item->u.forward_id); item->addr = tab_item->addr; item->ref_def = tab_item; } @@ -1683,7 +1684,7 @@ void MIR_link (MIR_context_t ctx, void (*set_interface) (MIR_context_t ctx, MIR_ _MIR_type_size (ctx, expr_item->u.func->res_types[0])); } } - if (set_interface != NULL) + if (set_interface != NULL) { while (VARR_LENGTH (MIR_module_t, modules_to_link) != 0) { m = VARR_POP (MIR_module_t, modules_to_link); for (item = DLIST_HEAD (MIR_item_t, m->items); item != NULL; @@ -1693,6 +1694,8 @@ void MIR_link (MIR_context_t ctx, void (*set_interface) (MIR_context_t ctx, MIR_ set_interface (ctx, item); } } + set_interface (ctx, NULL); /* finish interface setting */ + } } static const char *insn_name (MIR_insn_code_t code) { @@ -1701,13 +1704,15 @@ static const char *insn_name (MIR_insn_code_t code) { const char *MIR_insn_name (MIR_context_t ctx, MIR_insn_code_t code) { if ((unsigned) code >= MIR_INSN_BOUND) - (*error_func) (MIR_wrong_param_value_error, "MIR_insn_name: wrong insn code %d", (int) code); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_insn_name: wrong insn code %d", + (int) code); return insn_descs[code].name; } static size_t insn_code_nops (MIR_context_t ctx, MIR_insn_code_t code) { /* 0 for calls */ if ((unsigned) code >= MIR_INSN_BOUND) - (*error_func) (MIR_wrong_param_value_error, "insn_code_nops: wrong insn code %d", (int) code); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "insn_code_nops: wrong insn code %d", + (int) code); return VARR_GET (size_t, insn_nops, code); } @@ -1780,7 +1785,8 @@ static MIR_insn_t create_insn (MIR_context_t ctx, size_t nops, MIR_insn_code_t c if (nops == 0) nops = 1; insn = malloc (sizeof (struct MIR_insn) + sizeof (MIR_op_t) * (nops - 1)); - if (insn == NULL) (*error_func) (MIR_alloc_error, "Not enough memory for insn creation"); + if (insn == NULL) + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for insn creation"); #if __SIZEOF_LONG_DOUBLE__ == 8 switch (code) { case MIR_LDMOV: code = MIR_DMOV; break; @@ -1827,65 +1833,71 @@ MIR_insn_t MIR_new_insn_arr (MIR_context_t ctx, MIR_insn_code_t code, size_t nop if (!MIR_call_code_p (code) && code != MIR_UNSPEC && code != MIR_PHI && code != MIR_RET && code != MIR_SWITCH && nops != expected_nops) { - (*error_func) (MIR_ops_num_error, "wrong number of operands for insn %s", - insn_descs[code].name); + MIR_get_error_func (ctx) (MIR_ops_num_error, "wrong number of operands for insn %s", + insn_descs[code].name); } else if (code == MIR_SWITCH) { - if (nops < 2) (*error_func) (MIR_ops_num_error, "number of MIR_SWITCH operands is less 2"); + if (nops < 2) + MIR_get_error_func (ctx) (MIR_ops_num_error, "number of MIR_SWITCH operands is less 2"); } else if (code == MIR_PHI) { - if (nops < 3) (*error_func) (MIR_ops_num_error, "number of MIR_PHI operands is less 3"); + if (nops < 3) + MIR_get_error_func (ctx) (MIR_ops_num_error, "number of MIR_PHI operands is less 3"); } else if (MIR_call_code_p (code) || code == MIR_UNSPEC) { args_start = code == MIR_UNSPEC ? 1 : 2; if (nops < args_start) - (*error_func) (MIR_ops_num_error, "wrong number of call/unspec operands"); + MIR_get_error_func (ctx) (MIR_ops_num_error, "wrong number of call/unspec operands"); if (code == MIR_UNSPEC) { if (ops[0].mode != MIR_OP_INT || ops[0].u.u >= VARR_LENGTH (MIR_proto_t, unspec_protos)) - (*error_func) (MIR_unspec_op_error, "the 1st unspec operand should be valid unspec code"); + MIR_get_error_func (ctx) (MIR_unspec_op_error, + "the 1st unspec operand should be valid unspec code"); proto = VARR_GET (MIR_proto_t, unspec_protos, ops[0].u.u); } else { if (ops[0].mode != MIR_OP_REF || ops[0].u.ref->item_type != MIR_proto_item) - (*error_func) (MIR_call_op_error, "the 1st call operand should be a prototype"); + MIR_get_error_func (ctx) (MIR_call_op_error, "the 1st call operand should be a prototype"); proto = ops[0].u.ref->u.proto; } i = proto->nres; if (proto->args != NULL) i += VARR_LENGTH (MIR_var_t, proto->args); if (nops < i + args_start || (nops != i + args_start && !proto->vararg_p)) - (*error_func) (code == MIR_UNSPEC ? MIR_unspec_op_error : MIR_call_op_error, - "number of %s operands or results does not correspond to prototype %s", - code == MIR_UNSPEC ? "unspec" : "call", proto->name); + MIR_get_error_func ( + ctx) (code == MIR_UNSPEC ? MIR_unspec_op_error : MIR_call_op_error, + "number of %s operands or results does not correspond to prototype %s", + code == MIR_UNSPEC ? "unspec" : "call", proto->name); for (i = args_start; i < nops; i++) { if (ops[i].mode == MIR_OP_MEM && MIR_blk_type_p (ops[i].u.mem.type)) { if (i - args_start < proto->nres) - (*error_func) (MIR_wrong_type_error, "result of %s is block type memory", - code == MIR_UNSPEC ? "unspec" : "call"); + MIR_get_error_func (ctx) (MIR_wrong_type_error, "result of %s is block type memory", + code == MIR_UNSPEC ? "unspec" : "call"); else if ((narg = i - args_start - proto->nres) < VARR_LENGTH (MIR_var_t, proto->args)) { if (VARR_GET (MIR_var_t, proto->args, narg).type != ops[i].u.mem.type) { - (*error_func) (MIR_wrong_type_error, - "arg of %s is block type memory but param is not of block type", - code == MIR_UNSPEC ? "unspec" : "call"); + MIR_get_error_func ( + ctx) (MIR_wrong_type_error, + "arg of %s is block type memory but param is not of block type", + code == MIR_UNSPEC ? "unspec" : "call"); } else if (VARR_GET (MIR_var_t, proto->args, narg).size != ops[i].u.mem.disp) { - (*error_func) (MIR_wrong_type_error, - "different sizes (%lu vs %lu) of arg and param block memory in %s insn", - (unsigned long) VARR_GET (MIR_var_t, proto->args, narg).size, - (unsigned long) ops[i].u.mem.disp, - code == MIR_UNSPEC ? "unspec" : "call"); + MIR_get_error_func ( + ctx) (MIR_wrong_type_error, + "different sizes (%lu vs %lu) of arg and param block memory in %s insn", + (unsigned long) VARR_GET (MIR_var_t, proto->args, narg).size, + (unsigned long) ops[i].u.mem.disp, code == MIR_UNSPEC ? "unspec" : "call"); } } else if (ops[i].u.mem.type == MIR_T_RBLK) { - (*error_func) (MIR_wrong_type_error, - "RBLK memory can not correspond to unnamed param in %s insn", - code == MIR_UNSPEC ? "unspec" : "call"); + MIR_get_error_func (ctx) (MIR_wrong_type_error, + "RBLK memory can not correspond to unnamed param in %s insn", + code == MIR_UNSPEC ? "unspec" : "call"); } } else if (i - args_start >= proto->nres && (narg = i - args_start - proto->nres) < VARR_LENGTH (MIR_var_t, proto->args) && MIR_blk_type_p (VARR_GET (MIR_var_t, proto->args, narg).type)) { - (*error_func) (MIR_wrong_type_error, - "param of %s is of block type but arg is not of block type memory", - code == MIR_UNSPEC ? "unspec" : "call"); + MIR_get_error_func ( + ctx) (MIR_wrong_type_error, + "param of %s is of block type but arg is not of block type memory", + code == MIR_UNSPEC ? "unspec" : "call"); } } } else if (code == MIR_VA_ARG) { // undef mem ??? if (ops[2].mode != MIR_OP_MEM) - (*error_func) (MIR_op_mode_error, - "3rd operand of va_arg should be any memory with given type"); + MIR_get_error_func (ctx) (MIR_op_mode_error, + "3rd operand of va_arg should be any memory with given type"); } insn = create_insn (ctx, nops, code); insn->nops = nops; @@ -1894,14 +1906,11 @@ MIR_insn_t MIR_new_insn_arr (MIR_context_t ctx, MIR_insn_code_t code, size_t nop } static MIR_insn_t new_insn (MIR_context_t ctx, MIR_insn_code_t code, size_t nops, va_list argp) { - VARR_TRUNC (MIR_op_t, temp_insn_ops, 0); - for (size_t i = 0; i < nops; i++) { - MIR_op_t op = va_arg (argp, MIR_op_t); + MIR_op_t *insn_ops = alloca (sizeof (MIR_op_t) * nops); - VARR_PUSH (MIR_op_t, temp_insn_ops, op); - } + for (size_t i = 0; i < nops; i++) insn_ops[i] = va_arg (argp, MIR_op_t); va_end (argp); - return MIR_new_insn_arr (ctx, code, nops, VARR_ADDR (MIR_op_t, temp_insn_ops)); + return MIR_new_insn_arr (ctx, code, nops, insn_ops); } MIR_insn_t MIR_new_insn (MIR_context_t ctx, MIR_insn_code_t code, ...) { @@ -1909,11 +1918,13 @@ MIR_insn_t MIR_new_insn (MIR_context_t ctx, MIR_insn_code_t code, ...) { size_t nops = insn_code_nops (ctx, code); if (code == MIR_PHI) - (*error_func) (MIR_call_op_error, "Use only MIR_new_insn_arr for creating a phi insn"); + MIR_get_error_func (ctx) (MIR_call_op_error, + "Use only MIR_new_insn_arr for creating a phi insn"); else if (MIR_call_code_p (code) || code == MIR_UNSPEC || code == MIR_RET || code == MIR_SWITCH) - (*error_func) (MIR_call_op_error, - "Use only MIR_new_insn_arr or MIR_new_{call,unspec,ret}_insn for creating a " - "call/unspec/ret/switch insn"); + MIR_get_error_func ( + ctx) (MIR_call_op_error, + "Use only MIR_new_insn_arr or MIR_new_{call,unspec,ret}_insn for creating a " + "call/unspec/ret/switch insn"); va_start (argp, code); return new_insn (ctx, code, nops, argp); } @@ -1961,7 +1972,8 @@ MIR_insn_t MIR_copy_insn (MIR_context_t ctx, MIR_insn_t insn) { MIR_insn_t new_insn = malloc (size); if (new_insn == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory to copy insn %s", insn_name (insn->code)); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory to copy insn %s", + insn_name (insn->code)); memcpy (new_insn, insn, size); return new_insn; } @@ -1977,29 +1989,28 @@ static MIR_insn_t create_label (MIR_context_t ctx, int64_t label_num) { MIR_insn_t MIR_new_label (MIR_context_t ctx) { return create_label (ctx, ++curr_label_num); } MIR_reg_t _MIR_new_temp_reg (MIR_context_t ctx, MIR_type_t type, MIR_func_t func) { - string_t string; + char reg_name[30]; if (type != MIR_T_I64 && type != MIR_T_F && type != MIR_T_D && type != MIR_T_LD) - (*error_func) (MIR_reg_type_error, "wrong type %s for temporary register", type_str (type)); + MIR_get_error_func (ctx) (MIR_reg_type_error, "wrong type %s for temporary register", + type_str (type)); mir_assert (func != NULL); for (;;) { func->last_temp_num++; - if (func->last_temp_num == 0) (*error_func) (MIR_unique_reg_error, "out of unique regs"); - sprintf (temp_buff, "%s%d", TEMP_REG_NAME_PREFIX, func->last_temp_num); - string - = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (temp_buff) + 1, temp_buff}); - if (find_rd_by_name_num (ctx, string.num, func) == NULL) - return MIR_new_func_reg (ctx, func, type, string.str.s); + if (func->last_temp_num == 0) + MIR_get_error_func (ctx) (MIR_unique_reg_error, "out of unique regs"); + sprintf (reg_name, "%s%d", TEMP_REG_NAME_PREFIX, func->last_temp_num); + if (find_rd_by_name (ctx, reg_name, func) == NULL) + return MIR_new_func_reg (ctx, func, type, reg_name); } } static reg_desc_t *get_func_rd_by_name (MIR_context_t ctx, const char *reg_name, MIR_func_t func) { - string_t string - = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (reg_name) + 1, reg_name}); reg_desc_t *rd; - rd = find_rd_by_name_num (ctx, string.num, func); - if (rd == NULL) (*error_func) (MIR_undeclared_func_reg_error, "undeclared func reg %s", reg_name); + rd = find_rd_by_name (ctx, reg_name, func); + if (rd == NULL) + MIR_get_error_func (ctx) (MIR_undeclared_func_reg_error, "undeclared func reg %s", reg_name); return rd; } @@ -2015,24 +2026,11 @@ MIR_reg_t MIR_reg (MIR_context_t ctx, const char *reg_name, MIR_func_t func) { } MIR_type_t MIR_reg_type (MIR_context_t ctx, MIR_reg_t reg, MIR_func_t func) { - MIR_type_t type; - - if (reg_type_cache.func != func) { - reg_type_cache.func = func; - VARR_TRUNC (MIR_type_t, reg_type_cache.types, 0); - } - if (VARR_LENGTH (MIR_type_t, reg_type_cache.types) > reg - && (type = VARR_GET (MIR_type_t, reg_type_cache.types, reg)) != MIR_T_UNDEF) - return type; - type = get_func_rd_by_reg (ctx, reg, func)->type; - while (VARR_LENGTH (MIR_type_t, reg_type_cache.types) <= reg) - VARR_PUSH (MIR_type_t, reg_type_cache.types, MIR_T_UNDEF); - VARR_SET (MIR_type_t, reg_type_cache.types, reg, type); - return type; + return get_func_rd_by_reg (ctx, reg, func)->type; } const char *MIR_reg_name (MIR_context_t ctx, MIR_reg_t reg, MIR_func_t func) { - return VARR_ADDR (string_t, strings)[get_func_rd_by_reg (ctx, reg, func)->name_num].str.s; + return get_func_rd_by_reg (ctx, reg, func)->name; } /* Functions to create operands. */ @@ -2116,7 +2114,7 @@ MIR_op_t MIR_new_str_op (MIR_context_t ctx, MIR_str_t str) { MIR_op_t op; init_op (&op, MIR_OP_STR); - op.u.str = string_store (ctx, &strings, &string_tab, str).str; + op.u.str = get_ctx_string (ctx, str).str; return op; } @@ -2237,14 +2235,14 @@ htab_hash_t MIR_op_hash_step (MIR_context_t ctx, htab_hash_t h, MIR_op_t op) { void MIR_append_insn (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t insn) { mir_assert (func_item != NULL); if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_append_insn: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_append_insn: wrong func item"); DLIST_APPEND (MIR_insn_t, func_item->u.func->insns, insn); } void MIR_prepend_insn (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t insn) { mir_assert (func_item != NULL); if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_prepend_insn: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_prepend_insn: wrong func item"); DLIST_PREPEND (MIR_insn_t, func_item->u.func->insns, insn); } @@ -2252,7 +2250,8 @@ void MIR_insert_insn_after (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t MIR_insn_t insn) { mir_assert (func_item != NULL); if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_insert_insn_after: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, + "MIR_insert_insn_after: wrong func item"); DLIST_INSERT_AFTER (MIR_insn_t, func_item->u.func->insns, after, insn); } @@ -2260,27 +2259,31 @@ void MIR_insert_insn_before (MIR_context_t ctx, MIR_item_t func_item, MIR_insn_t MIR_insn_t insn) { mir_assert (func_item != NULL); if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_insert_insn_before: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, + "MIR_insert_insn_before: wrong func item"); DLIST_INSERT_BEFORE (MIR_insn_t, func_item->u.func->insns, before, insn); } -static void store_labels_for_duplication (MIR_context_t ctx, MIR_insn_t insn, MIR_insn_t new_insn) { +static void store_labels_for_duplication (MIR_context_t ctx, VARR (MIR_insn_t) * labels, + VARR (MIR_insn_t) * branch_insns, MIR_insn_t insn, + MIR_insn_t new_insn) { if (MIR_branch_code_p (insn->code) || insn->code == MIR_SWITCH) { - VARR_PUSH (MIR_insn_t, temp_insns2, new_insn); + VARR_PUSH (MIR_insn_t, branch_insns, new_insn); } else if (insn->code == MIR_LABEL) { mir_assert (insn->data == NULL); insn->data = new_insn; - VARR_PUSH (MIR_insn_t, temp_insns, insn); + VARR_PUSH (MIR_insn_t, labels, insn); } } -static void redirect_duplicated_labels (MIR_context_t ctx) { +static void redirect_duplicated_labels (MIR_context_t ctx, VARR (MIR_insn_t) * labels, + VARR (MIR_insn_t) * branch_insns) { MIR_insn_t insn; - while (VARR_LENGTH (MIR_insn_t, temp_insns2) != 0) { /* redirect new label operands */ + while (VARR_LENGTH (MIR_insn_t, branch_insns) != 0) { /* redirect new label operands */ size_t start_label_nop = 0, bound_label_nop = 1, n; - insn = VARR_POP (MIR_insn_t, temp_insns2); + insn = VARR_POP (MIR_insn_t, branch_insns); if (insn->code == MIR_SWITCH) { start_label_nop = 1; bound_label_nop = start_label_nop + insn->nops - 1; @@ -2288,8 +2291,8 @@ static void redirect_duplicated_labels (MIR_context_t ctx) { for (n = start_label_nop; n < bound_label_nop; n++) insn->ops[n].u.label = insn->ops[n].u.label->data; } - while (VARR_LENGTH (MIR_insn_t, temp_insns) != 0) { /* reset data */ - insn = VARR_POP (MIR_insn_t, temp_insns); + while (VARR_LENGTH (MIR_insn_t, labels) != 0) { /* reset data */ + insn = VARR_POP (MIR_insn_t, labels); insn->data = NULL; } } @@ -2297,21 +2300,24 @@ static void redirect_duplicated_labels (MIR_context_t ctx) { void _MIR_duplicate_func_insns (MIR_context_t ctx, MIR_item_t func_item) { MIR_func_t func; MIR_insn_t insn, new_insn; + VARR (MIR_insn_t) * labels, *branch_insns; 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_insns = func->insns; DLIST_INIT (MIR_insn_t, func->insns); - VARR_TRUNC (MIR_insn_t, temp_insns, 0); - VARR_TRUNC (MIR_insn_t, temp_insns2, 0); + VARR_CREATE (MIR_insn_t, labels, 0); + VARR_CREATE (MIR_insn_t, branch_insns, 0); for (insn = DLIST_HEAD (MIR_insn_t, func->original_insns); insn != NULL; insn = DLIST_NEXT (MIR_insn_t, insn)) { /* copy insns and collect label info */ new_insn = MIR_copy_insn (ctx, insn); DLIST_APPEND (MIR_insn_t, func->insns, new_insn); - store_labels_for_duplication (ctx, insn, new_insn); + store_labels_for_duplication (ctx, labels, branch_insns, insn, new_insn); } - redirect_duplicated_labels (ctx); + redirect_duplicated_labels (ctx, labels, branch_insns); + VARR_DESTROY (MIR_insn_t, labels); + VARR_DESTROY (MIR_insn_t, branch_insns); } void _MIR_restore_func_insns (MIR_context_t ctx, MIR_item_t func_item) { @@ -2326,6 +2332,68 @@ void _MIR_restore_func_insns (MIR_context_t ctx, MIR_item_t func_item) { DLIST_INIT (MIR_insn_t, func->original_insns); } +static void set_item_name (MIR_item_t item, const char *name) { + mir_assert (item != NULL); + switch (item->item_type) { + case MIR_func_item: item->u.func->name = name; break; + case MIR_proto_item: item->u.proto->name = name; break; + case MIR_import_item: item->u.import_id = name; break; + case MIR_export_item: item->u.export_id = name; break; + case MIR_forward_item: item->u.forward_id = name; break; + case MIR_bss_item: item->u.bss->name = name; break; + case MIR_data_item: item->u.data->name = name; break; + case MIR_ref_data_item: item->u.ref_data->name = name; break; + case MIR_expr_data_item: item->u.expr_data->name = name; break; + default: mir_assert (FALSE); + } +} + +static void change_var_names (MIR_context_t new_ctx, VARR (MIR_var_t) * vars) { + for (size_t i = 0; i < VARR_LENGTH (MIR_var_t, vars); i++) { + MIR_var_t *var_ptr = &VARR_ADDR (MIR_var_t, vars)[i]; + var_ptr->name = get_ctx_str (new_ctx, var_ptr->name); + } +} + +/* It is not thread-safe */ +void MIR_change_module_ctx (MIR_context_t old_ctx, MIR_module_t m, MIR_context_t new_ctx) { + MIR_item_t item, tab_item; + MIR_op_mode_t mode; + const char *name, *new_name; + + DLIST_REMOVE (MIR_module_t, *MIR_get_module_list (old_ctx), m); + DLIST_APPEND (MIR_module_t, *MIR_get_module_list (new_ctx), m); + m->name = get_ctx_str (new_ctx, m->name); + for (item = DLIST_HEAD (MIR_item_t, m->items); item != NULL; + item = DLIST_NEXT (MIR_item_t, item)) { + if (item->addr != NULL) + MIR_get_error_func (old_ctx) (MIR_ctx_change_error, "Change context of a loaded module"); + if ((name = MIR_item_name (old_ctx, item)) != NULL) { + new_name = get_ctx_str (new_ctx, name); + if (item_tab_find (old_ctx, name, m) != item) { + set_item_name (item, new_name); + } else { + item_tab_remove (old_ctx, item); + set_item_name (item, new_name); + tab_item = item_tab_insert (new_ctx, item); + mir_assert (item == tab_item); + } + } + if (item->item_type == MIR_proto_item) { + change_var_names (new_ctx, item->u.proto->args); + } else if (item->item_type == MIR_func_item) { + func_regs_t func_regs = item->u.func->internal; + change_var_names (new_ctx, item->u.func->vars); + for (MIR_insn_t insn = DLIST_HEAD (MIR_insn_t, item->u.func->insns); insn != NULL; + insn = DLIST_NEXT (MIR_insn_t, insn)) + for (size_t i = 0; i < insn->nops; i++) { + if ((mode = insn->ops[i].mode) == MIR_OP_STR) + insn->ops[i].u.str = get_ctx_string (new_ctx, insn->ops[i].u.str).str; + } + } + } +} + static void output_type (FILE *f, MIR_type_t tp) { fprintf (f, "%s", MIR_type_str (NULL, tp)); } static void output_disp (FILE *f, MIR_disp_t disp) { fprintf (f, "%" PRId64, (int64_t) disp); } @@ -2575,6 +2643,9 @@ void MIR_output (MIR_context_t ctx, FILE *f) { MIR_output_module (ctx, f, module); } +/* New Page */ +/* This page contains code for simplification and inlining */ + static MIR_insn_t insert_op_insn (MIR_context_t ctx, int out_p, MIR_item_t func_item, MIR_insn_t anchor, MIR_insn_t insn) { if (!out_p) { @@ -2596,9 +2667,18 @@ DEF_HTAB (val_t); struct simplify_ctx { HTAB (val_t) * val_tab; + VARR (MIR_insn_t) * temp_insns, *labels; /* temp_insns is for branch or ret insns */ + VARR (MIR_reg_t) * inline_reg_map; + size_t inlined_calls, inline_insns_before, inline_insns_after; }; #define val_tab ctx->simplify_ctx->val_tab +#define temp_insns ctx->simplify_ctx->temp_insns +#define labels ctx->simplify_ctx->labels +#define inline_reg_map ctx->simplify_ctx->inline_reg_map +#define inlined_calls ctx->simplify_ctx->inlined_calls +#define inline_insns_before ctx->simplify_ctx->inline_insns_before +#define inline_insns_after ctx->simplify_ctx->inline_insns_after static htab_hash_t val_hash (val_t v, void *arg) { MIR_context_t ctx = arg; @@ -2618,13 +2698,26 @@ static int val_eq (val_t v1, val_t v2, void *arg) { return v1.code == MIR_INSN_BOUND || MIR_op_eq_p (ctx, v1.op2, v2.op2); } -static void vn_init (MIR_context_t ctx) { +static void simplify_init (MIR_context_t ctx) { if ((ctx->simplify_ctx = malloc (sizeof (struct simplify_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); HTAB_CREATE (val_t, val_tab, 512, val_hash, val_eq, ctx); + VARR_CREATE (MIR_insn_t, temp_insns, 0); + VARR_CREATE (MIR_insn_t, labels, 0); + VARR_CREATE (MIR_reg_t, inline_reg_map, 256); + inlined_calls = inline_insns_before = inline_insns_after = 0; } -static void vn_finish (MIR_context_t ctx) { +static void simplify_finish (MIR_context_t ctx) { + VARR_DESTROY (MIR_reg_t, inline_reg_map); +#if 0 + if (inlined_calls != 0) + fprintf (stderr, "inlined calls = %lu, insns before = %lu, insns_after = %lu, ratio = %.2f\n", + inlined_calls, inline_insns_before, inline_insns_after, + (double) inline_insns_after / inline_insns_before); +#endif + VARR_DESTROY (MIR_insn_t, labels); + VARR_DESTROY (MIR_insn_t, temp_insns); HTAB_DESTROY (val_t, val_tab); free (ctx->simplify_ctx); ctx->simplify_ctx = NULL; @@ -2931,8 +3024,8 @@ static void make_one_ret (MIR_context_t ctx, MIR_item_t func_item) { } static void remove_unused_labels (MIR_context_t ctx, MIR_item_t func_item) { - while (VARR_LENGTH (MIR_insn_t, temp_insns2) != 0) { - MIR_insn_t label = VARR_POP (MIR_insn_t, temp_insns2); + while (VARR_LENGTH (MIR_insn_t, labels) != 0) { + MIR_insn_t label = VARR_POP (MIR_insn_t, labels); int64_t label_num = label->ops[0].u.i; if (label_num < VARR_LENGTH (uint8_t, temp_data) && VARR_GET (uint8_t, temp_data, label_num)) @@ -2987,7 +3080,7 @@ static int simplify_func (MIR_context_t ctx, MIR_item_t func_item, int mem_float int jmps_num = 0, inline_p = FALSE; if (func_item->item_type != MIR_func_item) - (*error_func) (MIR_wrong_param_value_error, "MIR_remove_simplify: wrong func item"); + MIR_get_error_func (ctx) (MIR_wrong_param_value_error, "MIR_remove_simplify: wrong func item"); vn_empty (ctx); func = func_item->u.func; for (size_t i = 0; i < func->nargs; i++) { @@ -3014,7 +3107,7 @@ static int simplify_func (MIR_context_t ctx, MIR_item_t func_item, int mem_float } } VARR_TRUNC (MIR_insn_t, temp_insns, 0); - VARR_TRUNC (MIR_insn_t, temp_insns2, 0); + VARR_TRUNC (MIR_insn_t, labels, 0); VARR_TRUNC (uint8_t, temp_data, 0); for (insn = DLIST_HEAD (MIR_insn_t, func->insns); insn != NULL; insn = next_insn) { MIR_insn_code_t code = insn->code; @@ -3034,7 +3127,7 @@ static int simplify_func (MIR_context_t ctx, MIR_item_t func_item, int mem_float insn->ops[0] = temp_op; } if (code == MIR_RET) VARR_PUSH (MIR_insn_t, temp_insns, insn); - if (code == MIR_LABEL) VARR_PUSH (MIR_insn_t, temp_insns2, insn); + if (code == MIR_LABEL) VARR_PUSH (MIR_insn_t, labels, insn); next_insn = DLIST_NEXT (MIR_insn_t, insn); if (code == MIR_ALLOCA && (insn->ops[1].mode == MIR_OP_INT || insn->ops[1].mode == MIR_OP_UINT)) { @@ -3114,7 +3207,8 @@ static int simplify_func (MIR_context_t ctx, MIR_item_t func_item, int mem_float } else if (MIR_branch_code_p (code) && insn->ops[0].mode == MIR_OP_LABEL && (jmp_insn = skip_labels (insn->ops[0].u.label, NULL)) != NULL && jmp_insn->code == MIR_JMP && ++jmps_num < MAX_JUMP_CHAIN_LEN) { - /* B L;...;L:JMP L2 => B L2; ... Also constrain processing to avoid infinite loops */ + /* B L;...;L:JMP L2 => B L2; ... Also constrain processing to avoid infinite loops + */ insn->ops[0] = jmp_insn->ops[0]; next_insn = insn; continue; @@ -3301,7 +3395,7 @@ static void process_inlines (MIR_context_t ctx, MIR_item_t func_item) { ret_reg = 0; alloca_p = FALSE; VARR_TRUNC (MIR_insn_t, temp_insns, 0); - VARR_TRUNC (MIR_insn_t, temp_insns2, 0); + VARR_TRUNC (MIR_insn_t, labels, 0); VARR_TRUNC (uint8_t, temp_data, 0); for (insn = DLIST_HEAD (MIR_insn_t, called_func->insns); insn != NULL; insn = DLIST_NEXT (MIR_insn_t, insn)) { @@ -3326,7 +3420,7 @@ static void process_inlines (MIR_context_t ctx, MIR_item_t func_item) { } if (new_insn->code != MIR_RET) { MIR_insert_insn_before (ctx, func_item, ret_label, new_insn); - store_labels_for_duplication (ctx, insn, new_insn); + store_labels_for_duplication (ctx, labels, temp_insns, insn, new_insn); } else { /* should be the last insn after simplification */ mir_assert (DLIST_NEXT (MIR_insn_t, insn) == NULL && call->ops[0].mode == MIR_OP_REF @@ -3348,7 +3442,7 @@ static void process_inlines (MIR_context_t ctx, MIR_item_t func_item) { free (ret_insn); } } - redirect_duplicated_labels (ctx); + redirect_duplicated_labels (ctx, labels, temp_insns); if (alloca_p) { temp_reg = _MIR_new_temp_reg (ctx, MIR_T_I64, func); new_insn = MIR_new_insn (ctx, MIR_BSTART, MIR_new_reg_op (ctx, temp_reg)); @@ -3360,9 +3454,9 @@ static void process_inlines (MIR_context_t ctx, MIR_item_t func_item) { } } -const char *_MIR_uniq_string (MIR_context_t ctx, const char *str) { - return string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (str) + 1, str}).str.s; -} +/* New Page */ + +const char *_MIR_uniq_string (MIR_context_t ctx, const char *str) { return get_ctx_str (ctx, str); } /* The next two function can be called any time relative to load/linkage. You can also call them many times for the same name @@ -3372,20 +3466,19 @@ MIR_item_t _MIR_builtin_proto (MIR_context_t ctx, MIR_module_t module, const cha size_t nres, MIR_type_t *res_types, size_t nargs, ...) { size_t i; va_list argp; - MIR_var_t arg; + MIR_var_t *args = alloca (nargs * sizeof (MIR_var_t)); MIR_item_t proto_item; MIR_module_t saved_module = curr_module; va_start (argp, nargs); - VARR_TRUNC (MIR_var_t, temp_vars, 0); + if (mir_mutex_lock (&ctx_mutex)) parallel_error (ctx, "error in mutex lock"); for (i = 0; i < nargs; i++) { - arg.type = va_arg (argp, MIR_type_t); - arg.name = va_arg (argp, const char *); - VARR_PUSH (MIR_var_t, temp_vars, arg); + args[i].type = va_arg (argp, MIR_type_t); + args[i].name = va_arg (argp, const char *); } va_end (argp); name = _MIR_uniq_string (ctx, name); - proto_item = find_item (ctx, name, module); + proto_item = item_tab_find (ctx, name, module); if (proto_item != NULL) { if (proto_item->item_type == MIR_proto_item && proto_item->u.proto->nres == nres && VARR_LENGTH (MIR_var_t, proto_item->u.proto->args) == nargs) { @@ -3393,22 +3486,24 @@ MIR_item_t _MIR_builtin_proto (MIR_context_t ctx, MIR_module_t module, const cha if (res_types[i] != proto_item->u.proto->res_types[i]) break; if (i >= nres) { for (i = 0; i < nargs; i++) - if (VARR_GET (MIR_var_t, temp_vars, i).type - != VARR_GET (MIR_var_t, proto_item->u.proto->args, i).type) - break; - if (i >= nargs) return proto_item; + if (args[i].type != VARR_GET (MIR_var_t, proto_item->u.proto->args, i).type) break; + if (i >= nargs) { + if (mir_mutex_unlock (&ctx_mutex)) parallel_error (ctx, "error in mutex unlock"); + return proto_item; + } } } - (*error_func) (MIR_repeated_decl_error, - "_MIR_builtin_proto: proto item %s was already defined differently", name); + MIR_get_error_func (ctx) (MIR_repeated_decl_error, + "_MIR_builtin_proto: proto item %s was already defined differently", + name); } saved_module = curr_module; curr_module = module; - proto_item - = MIR_new_proto_arr (ctx, name, nres, res_types, nargs, VARR_ADDR (MIR_var_t, temp_vars)); + proto_item = MIR_new_proto_arr (ctx, name, nres, res_types, nargs, args); DLIST_REMOVE (MIR_item_t, curr_module->items, proto_item); DLIST_PREPEND (MIR_item_t, curr_module->items, proto_item); /* make it first in the list */ curr_module = saved_module; + if (mir_mutex_unlock (&ctx_mutex)) parallel_error (ctx, "error in mutex unlock"); return proto_item; } @@ -3417,11 +3512,12 @@ MIR_item_t _MIR_builtin_func (MIR_context_t ctx, MIR_module_t module, const char MIR_item_t item, ref_item; MIR_module_t saved_module = curr_module; + if (mir_mutex_lock (&ctx_mutex)) parallel_error (ctx, "error in mutex lock"); name = _MIR_uniq_string (ctx, name); - if ((ref_item = find_item (ctx, name, &environment_module)) != NULL) { + if ((ref_item = item_tab_find (ctx, name, &environment_module)) != NULL) { if (ref_item->item_type != MIR_import_item || ref_item->addr != addr) - (*error_func) (MIR_repeated_decl_error, - "_MIR_builtin_func: func %s has already another address", name); + MIR_get_error_func (ctx) (MIR_repeated_decl_error, + "_MIR_builtin_func: func %s has already another address", name); } else { curr_module = &environment_module; /* Use import for builtin func: */ @@ -3432,12 +3528,13 @@ MIR_item_t _MIR_builtin_func (MIR_context_t ctx, MIR_module_t module, const char ref_item->addr = addr; curr_module = saved_module; } - if ((item = find_item (ctx, name, module)) != NULL) { + if ((item = item_tab_find (ctx, name, module)) != NULL) { if (item->item_type != MIR_import_item || item->addr != addr || item->ref_def != ref_item) - (*error_func) (MIR_repeated_decl_error, - "_MIR_builtin_func: func name %s was already defined differently in the " - "module", - name); + MIR_get_error_func ( + ctx) (MIR_repeated_decl_error, + "_MIR_builtin_func: func name %s was already defined differently in the " + "module", + name); } else { curr_module = module; item = new_export_import_forward (ctx, name, MIR_import_item, "import", FALSE); @@ -3447,10 +3544,12 @@ MIR_item_t _MIR_builtin_func (MIR_context_t ctx, MIR_module_t module, const char item->ref_def = ref_item; curr_module = saved_module; } + if (mir_mutex_unlock (&ctx_mutex)) parallel_error (ctx, "error in mutex unlock"); return item; } /* New Page */ +/* This page is for dealing with generated machine code */ #ifndef _WIN32 #include @@ -3501,14 +3600,16 @@ typedef struct code_holder code_holder_t; DEF_VARR (code_holder_t); struct machine_code_ctx { +#if MIR_PARALLEL_GEN + mir_mutex_t code_mutex; +#endif VARR (code_holder_t) * code_holders; size_t page_size; - VARR (uint8_t) * machine_insns; }; +#define code_mutex ctx->machine_code_ctx->code_mutex #define code_holders ctx->machine_code_ctx->code_holders #define page_size ctx->machine_code_ctx->page_size -#define machine_insns ctx->machine_code_ctx->machine_insns static code_holder_t *get_last_code_holder (MIR_context_t ctx, size_t size) { uint8_t *mem; @@ -3553,11 +3654,16 @@ static uint8_t *add_code (MIR_context_t ctx, code_holder_t *ch_ptr, const uint8_ return mem; } -uint8_t *_MIR_publish_code (MIR_context_t ctx, const uint8_t *code, size_t code_len) { +uint8_t *_MIR_publish_code (MIR_context_t ctx, const uint8_t *code, + size_t code_len) { /* thread safe */ code_holder_t *ch_ptr; + uint8_t *res = NULL; - if ((ch_ptr = get_last_code_holder (ctx, code_len)) == NULL) return NULL; - return add_code (ctx, ch_ptr, code, code_len); + if (mir_mutex_lock (&code_mutex)) parallel_error (ctx, "error in mutex lock"); + if ((ch_ptr = get_last_code_holder (ctx, code_len)) != NULL) + res = add_code (ctx, ch_ptr, code, code_len); + if (mir_mutex_unlock (&code_mutex)) parallel_error (ctx, "error in mutex unlock"); + return res; } uint8_t *_MIR_get_new_code_addr (MIR_context_t ctx, size_t size) { @@ -3569,25 +3675,29 @@ uint8_t *_MIR_get_new_code_addr (MIR_context_t ctx, size_t size) { uint8_t *_MIR_publish_code_by_addr (MIR_context_t ctx, void *addr, const uint8_t *code, size_t code_len) { code_holder_t *ch_ptr = get_last_code_holder (ctx, 0); + uint8_t *res = NULL; - if (ch_ptr == NULL || ch_ptr->free != addr || ch_ptr->free + code_len >= ch_ptr->bound) - return NULL; - return add_code (ctx, ch_ptr, code, code_len); + if (ch_ptr != NULL && ch_ptr->free == addr && ch_ptr->free + code_len < ch_ptr->bound) + res = add_code (ctx, ch_ptr, code, code_len); + return res; } -void _MIR_change_code (MIR_context_t ctx, uint8_t *addr, const uint8_t *code, size_t code_len) { +void _MIR_change_code (MIR_context_t ctx, uint8_t *addr, const uint8_t *code, + size_t code_len) { /* thread safe */ size_t len, start; start = (size_t) addr / page_size * page_size; len = (size_t) addr + code_len - start; + if (mir_mutex_lock (&code_mutex)) parallel_error (ctx, "error in mutex lock"); mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC); memcpy (addr, code, code_len); mem_protect ((uint8_t *) start, len, PROT_READ_EXEC); _MIR_flush_code_cache (addr, addr + code_len); + if (mir_mutex_unlock (&code_mutex)) parallel_error (ctx, "error in mutex unlock"); } void _MIR_update_code_arr (MIR_context_t ctx, uint8_t *base, size_t nloc, - const MIR_code_reloc_t *relocs) { + const MIR_code_reloc_t *relocs) { /* thread safe */ size_t i, len, start, max_offset = 0; mir_assert (relocs != NULL); @@ -3595,13 +3705,15 @@ void _MIR_update_code_arr (MIR_context_t ctx, uint8_t *base, size_t nloc, if (max_offset < relocs[i].offset) max_offset = relocs[i].offset; start = (size_t) base / page_size * page_size; len = (size_t) base + max_offset + sizeof (void *) - start; + if (mir_mutex_lock (&code_mutex)) parallel_error (ctx, "error in mutex lock"); mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC); for (i = 0; i < nloc; i++) memcpy (base + relocs[i].offset, &relocs[i].value, sizeof (void *)); mem_protect ((uint8_t *) start, len, PROT_READ_EXEC); _MIR_flush_code_cache (base, base + max_offset + sizeof (void *)); + if (mir_mutex_unlock (&code_mutex)) parallel_error (ctx, "error in mutex unlock"); } -void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) { +void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) { /* thread safe */ size_t start, len, offset, max_offset = 0; void *value; va_list args; @@ -3615,8 +3727,9 @@ void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) { va_end (args); start = (size_t) base / page_size * page_size; len = (size_t) base + max_offset + sizeof (void *) - start; - mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC); va_start (args, nloc); + if (mir_mutex_lock (&code_mutex)) parallel_error (ctx, "error in mutex lock"); + mem_protect ((uint8_t *) start, len, PROT_WRITE_EXEC); for (size_t i = 0; i < nloc; i++) { offset = va_arg (args, size_t); value = va_arg (args, void *); @@ -3624,24 +3737,25 @@ void _MIR_update_code (MIR_context_t ctx, uint8_t *base, size_t nloc, ...) { } mem_protect ((uint8_t *) start, len, PROT_READ_EXEC); _MIR_flush_code_cache (base, base + max_offset + sizeof (void *)); + if (mir_mutex_unlock (&code_mutex)) parallel_error (ctx, "error in mutex unlock"); va_end (args); } static void code_init (MIR_context_t ctx) { if ((ctx->machine_code_ctx = malloc (sizeof (struct machine_code_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); page_size = mem_page_size (); VARR_CREATE (code_holder_t, code_holders, 128); - VARR_CREATE (uint8_t, machine_insns, 1024); + if (mir_mutex_init (&code_mutex, NULL)) parallel_error (ctx, "error in mutex init"); } static void code_finish (MIR_context_t ctx) { + if (mir_mutex_destroy (&code_mutex)) parallel_error (ctx, "error in mutex destroy"); while (VARR_LENGTH (code_holder_t, code_holders) != 0) { code_holder_t ch = VARR_POP (code_holder_t, code_holders); mem_unmap (ch.start, ch.bound - ch.start); } VARR_DESTROY (code_holder_t, code_holders); - VARR_DESTROY (uint8_t, machine_insns); free (ctx->machine_code_ctx); ctx->machine_code_ctx = NULL; } @@ -3707,6 +3821,9 @@ struct io_ctx { int (*io_writer) (MIR_context_t, uint8_t); int (*io_reader) (MIR_context_t); struct reduce_data *io_reduce_data; + VARR (MIR_var_t) * proto_vars; + VARR (MIR_type_t) * proto_types; + VARR (MIR_op_t) * read_insn_ops; VARR (string_t) * output_strings; HTAB (string_t) * output_string_tab; VARR (MIR_str_t) * bin_strings; @@ -3720,6 +3837,9 @@ struct io_ctx { #define io_writer ctx->io_ctx->io_writer #define io_reader ctx->io_ctx->io_reader #define io_reduce_data ctx->io_ctx->io_reduce_data +#define proto_vars ctx->io_ctx->proto_vars +#define proto_types ctx->io_ctx->proto_types +#define read_insn_ops ctx->io_ctx->read_insn_ops #define output_strings ctx->io_ctx->output_strings #define output_string_tab ctx->io_ctx->output_string_tab #define bin_strings ctx->io_ctx->bin_strings @@ -3968,7 +4088,8 @@ static size_t write_insn (MIR_context_t ctx, writer_func_t writer, MIR_func_t fu size_t len; if (code == MIR_UNSPEC || code == MIR_PHI) - (*error_func) (MIR_binary_io_error, "UNSPEC or PHI is not portable and can not be output"); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "UNSPEC or PHI is not portable and can not be output"); if (code == MIR_LABEL) return write_lab (ctx, writer, insn); nops = MIR_insn_nops (ctx, insn); len = write_uint (ctx, writer, code); @@ -4149,7 +4270,7 @@ void MIR_write_module_with_func (MIR_context_t ctx, int (*const writer) (MIR_con io_writer = writer; #ifndef MIR_NO_BIN_COMPRESSION if ((io_reduce_data = reduce_encode_start (reduce_writer, ctx)) == NULL) - (*error_func) (MIR_binary_io_error, "can not alloc data for MIR binary compression"); + MIR_get_error_func (ctx) (MIR_binary_io_error, "can not alloc data for MIR binary compression"); #endif output_insns_len = output_labs_len = 0; output_regs_len = output_mem_len = output_int_len = output_float_len = 0; @@ -4179,7 +4300,7 @@ void MIR_write_module_with_func (MIR_context_t ctx, int (*const writer) (MIR_con string_finish (&output_strings, &output_string_tab); #ifndef MIR_NO_BIN_COMPRESSION if (!reduce_encode_finish (io_reduce_data)) - (*error_func) (MIR_binary_io_error, "error in writing MIR binary"); + MIR_get_error_func (ctx) (MIR_binary_io_error, "error in writing MIR binary"); #endif } @@ -4205,7 +4326,7 @@ static int get_byte (MIR_context_t ctx) { int c = reduce_decode_get (io_reduce_data); #endif - if (c == EOF) (*error_func) (MIR_binary_io_error, "unfinished binary MIR"); + if (c == EOF) MIR_get_error_func (ctx) (MIR_binary_io_error, "unfinished binary MIR"); return c; } @@ -4261,7 +4382,7 @@ static long double get_ldouble (MIR_context_t ctx) { static MIR_str_t to_str (MIR_context_t ctx, uint64_t str_num) { if (str_num >= VARR_LENGTH (MIR_str_t, bin_strings)) - (*error_func) (MIR_binary_io_error, "wrong string num %lu", str_num); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong string num %lu", str_num); return VARR_GET (MIR_str_t, bin_strings, str_num); } @@ -4297,7 +4418,7 @@ static MIR_label_t to_lab (MIR_context_t ctx, uint64_t lab_num) { static int64_t read_int (MIR_context_t ctx, const char *err_msg) { int c = get_byte (ctx); - if (TAG_I1 > c || c > TAG_I8) (*error_func) (MIR_binary_io_error, err_msg); + if (TAG_I1 > c || c > TAG_I8) MIR_get_error_func (ctx) (MIR_binary_io_error, err_msg); return get_int (ctx, c - TAG_I1 + 1); } @@ -4305,7 +4426,7 @@ static uint64_t read_uint (MIR_context_t ctx, const char *err_msg) { int c = get_byte (ctx); if (c & U0_FLAG) return c & U0_MASK; - if (TAG_U1 > c || c > TAG_U8) (*error_func) (MIR_binary_io_error, err_msg); + if (TAG_U1 > c || c > TAG_U8) MIR_get_error_func (ctx) (MIR_binary_io_error, err_msg); return get_uint (ctx, c - TAG_U1 + 1); } @@ -4324,7 +4445,7 @@ static void read_all_strings (MIR_context_t ctx, uint64_t nstr) { } str.s = VARR_ADDR (char, temp_string); str.len = len; - str = string_store (ctx, &strings, &string_tab, str).str; + str = get_ctx_string (ctx, str).str; VARR_PUSH (MIR_str_t, bin_strings, str); } } @@ -4334,7 +4455,7 @@ static MIR_type_t tag_type (bin_tag_t tag) { return (MIR_type_t) (tag - TAG_TI8) static MIR_type_t read_type (MIR_context_t ctx, const char *err_msg) { int c = get_byte (ctx); - if (TAG_TI8 > c || c > TAG_TRBLOCK) (*error_func) (MIR_binary_io_error, err_msg); + if (TAG_TI8 > c || c > TAG_TRBLOCK) MIR_get_error_func (ctx) (MIR_binary_io_error, err_msg); return tag_type (c); } @@ -4342,9 +4463,9 @@ static const char *read_name (MIR_context_t ctx, MIR_module_t module, const char int c = get_byte (ctx); const char *s; - if (TAG_NAME1 > c || c > TAG_NAME4) (*error_func) (MIR_binary_io_error, err_msg); + if (TAG_NAME1 > c || c > TAG_NAME4) MIR_get_error_func (ctx) (MIR_binary_io_error, err_msg); s = to_str (ctx, get_uint (ctx, c - TAG_NAME1 + 1)).s; - process_reserved_name (s, TEMP_ITEM_NAME_PREFIX, &module->last_temp_item_num); + if (module != NULL) process_reserved_name (s, TEMP_ITEM_NAME_PREFIX, &module->last_temp_item_num); return s; } @@ -4392,7 +4513,7 @@ static bin_tag_t read_token (MIR_context_t ctx, token_attr_t *attr) { REP6 (TAG_CASE, TF, TD, TP, TV, TBLOCK, TRBLOCK) attr->t = (MIR_type_t) (c - TAG_TI8) + MIR_T_I8; break; - default: (*error_func) (MIR_binary_io_error, "wrong tag %d", c); + default: MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong tag %d", c); } return c; } @@ -4403,7 +4524,7 @@ static MIR_disp_t read_disp (MIR_context_t ctx) { tag = read_token (ctx, &attr); if (TAG_I1 > tag || tag > TAG_I8) - (*error_func) (MIR_binary_io_error, "memory disp has wrong tag %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "memory disp has wrong tag %d", tag); return attr.i; } @@ -4413,7 +4534,7 @@ static MIR_reg_t read_reg (MIR_context_t ctx, MIR_item_t func) { tag = read_token (ctx, &attr); if (TAG_REG1 > tag || tag > TAG_REG4) - (*error_func) (MIR_binary_io_error, "register has wrong tag %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "register has wrong tag %d", tag); return to_reg (ctx, attr.u, func); } @@ -4447,9 +4568,9 @@ static int read_operand (MIR_context_t ctx, MIR_op_t *op, MIR_item_t func) { break; REP4 (TAG_CASE, NAME1, NAME2, NAME3, NAME4) { const char *name = to_str (ctx, attr.u).s; - MIR_item_t item = find_item (ctx, name, func->module); + MIR_item_t item = item_tab_find (ctx, name, func->module); - if (item == NULL) (*error_func) (MIR_binary_io_error, "not found item %s", name); + if (item == NULL) MIR_get_error_func (ctx) (MIR_binary_io_error, "not found item %s", name); *op = MIR_new_ref_op (ctx, item); break; } @@ -4493,23 +4614,23 @@ static int func_proto_read (MIR_context_t ctx, MIR_module_t module, uint64_t *nr int vararg_p = read_uint (ctx, "wrong vararg flag") != 0; uint64_t i, nres = read_uint (ctx, "wrong func nres"); - VARR_TRUNC (MIR_type_t, temp_types, 0); + VARR_TRUNC (MIR_type_t, proto_types, 0); for (i = 0; i < nres; i++) { tag = read_token (ctx, &attr); if (TAG_TI8 > tag || tag > TAG_TRBLOCK) - (*error_func) (MIR_binary_io_error, "wrong prototype result type tag %d", tag); - VARR_PUSH (MIR_type_t, temp_types, tag_type (tag)); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong prototype result type tag %d", tag); + VARR_PUSH (MIR_type_t, proto_types, tag_type (tag)); } - VARR_TRUNC (MIR_var_t, temp_vars, 0); + VARR_TRUNC (MIR_var_t, proto_vars, 0); for (;;) { tag = read_token (ctx, &attr); if (tag == TAG_EOI) break; if (TAG_TI8 > tag || tag > TAG_TRBLOCK) - (*error_func) (MIR_binary_io_error, "wrong prototype arg type tag %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong prototype arg type tag %d", tag); var.type = tag_type (tag); var.name = read_name (ctx, module, "wrong arg name"); if (MIR_blk_type_p (var.type)) var.size = read_uint (ctx, "wrong block arg size"); - VARR_PUSH (MIR_var_t, temp_vars, var); + VARR_PUSH (MIR_var_t, proto_vars, var); } *nres_ptr = nres; return vararg_p; @@ -4542,12 +4663,14 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) io_reader = reader; #ifndef MIR_NO_BIN_COMPRESSION if ((io_reduce_data = reduce_decode_start (reduce_reader, ctx)) == NULL) - (*error_func) (MIR_binary_io_error, "can not alloc data for MIR binary decompression"); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "can not alloc data for MIR binary decompression"); #endif version = read_uint (ctx, "wrong header"); if (version > CURR_BIN_VERSION) - (*error_func) (MIR_binary_io_error, "can not read version %d MIR binary: expected %d or less", - version, CURR_BIN_VERSION); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "can not read version %d MIR binary: expected %d or less", version, + CURR_BIN_VERSION); nstr = read_uint (ctx, "wrong header"); read_all_strings (ctx, nstr); module = NULL; @@ -4559,95 +4682,102 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) VARR_PUSH (uint64_t, insn_label_string_nums, attr.u); tag = read_token (ctx, &attr); } - VARR_TRUNC (MIR_op_t, temp_insn_ops, 0); + VARR_TRUNC (MIR_op_t, read_insn_ops, 0); if (TAG_NAME1 <= tag && tag <= TAG_NAME4) { name = to_str (ctx, attr.u).s; if (strcmp (name, "module") == 0) { name = read_name (ctx, module, "wrong module name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "insn label before module %s", name); - if (module != NULL) (*error_func) (MIR_binary_io_error, "nested module %s", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "insn label before module %s", name); + if (module != NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "nested module %s", name); module = MIR_new_module (ctx, name); } else if (strcmp (name, "endmodule") == 0) { if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "endmodule should have no labels"); - if (module == NULL) (*error_func) (MIR_binary_io_error, "endmodule without module"); + MIR_get_error_func (ctx) (MIR_binary_io_error, "endmodule should have no labels"); + if (module == NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "endmodule without module"); MIR_finish_module (ctx); module = NULL; } else if (strcmp (name, "proto") == 0) { name = read_name (ctx, module, "wrong prototype name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "insn label before proto %s", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "insn label before proto %s", name); if (module == NULL) - (*error_func) (MIR_binary_io_error, "prototype %s outside module", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "prototype %s outside module", name); if (func_proto_read (ctx, module, &nres)) - MIR_new_vararg_proto_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), - VARR_ADDR (MIR_var_t, temp_vars)); + MIR_new_vararg_proto_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, proto_types), + VARR_LENGTH (MIR_var_t, proto_vars), + VARR_ADDR (MIR_var_t, proto_vars)); else - MIR_new_proto_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), VARR_ADDR (MIR_var_t, temp_vars)); + MIR_new_proto_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, proto_types), + VARR_LENGTH (MIR_var_t, proto_vars), + VARR_ADDR (MIR_var_t, proto_vars)); } else if (strcmp (name, "func") == 0) { name = read_name (ctx, module, "wrong func name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "insn label before func %s", name); - if (func != NULL) (*error_func) (MIR_binary_io_error, "nested func %s", name); - if (module == NULL) (*error_func) (MIR_binary_io_error, "func %s outside module", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "insn label before func %s", name); + if (func != NULL) MIR_get_error_func (ctx) (MIR_binary_io_error, "nested func %s", name); + if (module == NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "func %s outside module", name); if (func_proto_read (ctx, module, &nres)) - func = MIR_new_vararg_func_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), - VARR_ADDR (MIR_var_t, temp_vars)); + func = MIR_new_vararg_func_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, proto_types), + VARR_LENGTH (MIR_var_t, proto_vars), + VARR_ADDR (MIR_var_t, proto_vars)); else - func = MIR_new_func_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), - VARR_ADDR (MIR_var_t, temp_vars)); + func = MIR_new_func_arr (ctx, name, nres, VARR_ADDR (MIR_type_t, proto_types), + VARR_LENGTH (MIR_var_t, proto_vars), + VARR_ADDR (MIR_var_t, proto_vars)); VARR_TRUNC (MIR_label_t, func_labels, 0); } else if (strcmp (name, "endfunc") == 0) { if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "endfunc should have no labels"); - if (func == NULL) (*error_func) (MIR_binary_io_error, "endfunc without func"); + MIR_get_error_func (ctx) (MIR_binary_io_error, "endfunc should have no labels"); + if (func == NULL) MIR_get_error_func (ctx) (MIR_binary_io_error, "endfunc without func"); MIR_finish_func (ctx); func = NULL; } else if (strcmp (name, "export") == 0) { name = read_name (ctx, module, "wrong export name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "export %s should have no labels", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "export %s should have no labels", name); MIR_new_export (ctx, name); } else if (strcmp (name, "import") == 0) { name = read_name (ctx, module, "wrong import name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "import %s should have no labels", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "import %s should have no labels", name); MIR_new_import (ctx, name); } else if (strcmp (name, "forward") == 0) { name = read_name (ctx, module, "wrong forward name"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "forward %s should have no labels", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "forward %s should have no labels", name); MIR_new_forward (ctx, name); } else if (strcmp (name, "nbss") == 0 || strcmp (name, "bss") == 0) { name = strcmp (name, "nbss") == 0 ? read_name (ctx, module, "wrong bss name") : NULL; if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "bss %s should have no labels", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "bss %s should have no labels", + name == NULL ? "" : name); u = read_uint (ctx, "wrong bss len"); MIR_new_bss (ctx, name, u); } else if (strcmp (name, "nref") == 0 || strcmp (name, "ref") == 0) { name = strcmp (name, "nref") == 0 ? read_name (ctx, module, "wrong ref data name") : NULL; if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "ref data %s should have no labels", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "ref data %s should have no labels", + name == NULL ? "" : name); item_name = read_name (ctx, module, "wrong ref data item name"); - if ((item = find_item (ctx, item_name, module)) == NULL) - (*error_func) (MIR_binary_io_error, "ref data refers to non-existing item %s", item_name); + if ((item = item_tab_find (ctx, item_name, module)) == NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "ref data refers to non-existing item %s", + item_name); i = read_int (ctx, "wrong ref disp"); MIR_new_ref_data (ctx, name, item, i); } else if (strcmp (name, "nexpr") == 0 || strcmp (name, "expr") == 0) { name = strcmp (name, "nexpr") == 0 ? read_name (ctx, module, "wrong expr name") : NULL; if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "expr %s should have no labels", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "expr %s should have no labels", + name == NULL ? "" : name); item_name = read_name (ctx, module, "wrong expr func name"); - if ((item = find_item (ctx, item_name, module)) == NULL || item->item_type != MIR_func_item) - (*error_func) (MIR_binary_io_error, "expr refers to non-function %s", item_name); + if ((item = item_tab_find (ctx, item_name, module)) == NULL + || item->item_type != MIR_func_item) + MIR_get_error_func (ctx) (MIR_binary_io_error, "expr refers to non-function %s", + item_name); MIR_new_expr_data (ctx, name, item); } else if (strcmp (name, "ndata") == 0 || strcmp (name, "data") == 0) { MIR_type_t type; @@ -4665,11 +4795,11 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) name = strcmp (name, "ndata") == 0 ? read_name (ctx, module, "wrong data name") : NULL; if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "data %s should have no labels", - name == NULL ? "" : name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "data %s should have no labels", + name == NULL ? "" : name); tag = read_token (ctx, &attr); if (TAG_TI8 > tag || tag > TAG_TRBLOCK) - (*error_func) (MIR_binary_io_error, "wrong data type tag %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong data type tag %d", tag); type = tag_type (tag); VARR_TRUNC (uint8_t, temp_data, 0); for (nel = 0;; nel++) { @@ -4703,8 +4833,9 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) push_data (ctx, (uint8_t *) &v.i64, sizeof (uint64_t)); break; default: - (*error_func) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "data type %s does not correspond value type", + type_str (type)); } break; case TAG_I1: @@ -4733,57 +4864,62 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) push_data (ctx, (uint8_t *) &v.i64, sizeof (int64_t)); break; default: - (*error_func) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "data type %s does not correspond value type", + type_str (type)); } break; case TAG_F: if (type != MIR_T_F) - (*error_func) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "data type %s does not correspond value type", + type_str (type)); push_data (ctx, (uint8_t *) &attr.f, sizeof (float)); break; case TAG_D: if (type != MIR_T_D) - (*error_func) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "data type %s does not correspond value type", + type_str (type)); push_data (ctx, (uint8_t *) &attr.d, sizeof (double)); break; case TAG_LD: if (type != MIR_T_LD) - (*error_func) (MIR_binary_io_error, "data type %s does not correspond value type", - type_str (type)); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "data type %s does not correspond value type", + type_str (type)); push_data (ctx, (uint8_t *) &attr.ld, sizeof (long double)); break; /* ??? ptr */ - default: (*error_func) (MIR_binary_io_error, "wrong data value tag %d", tag); + default: MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong data value tag %d", tag); } } MIR_new_data (ctx, name, type, VARR_LENGTH (uint8_t, temp_data) / _MIR_type_size (ctx, type), VARR_ADDR (uint8_t, temp_data)); } else if (strcmp (name, "local") == 0) { - if (func == NULL) (*error_func) (MIR_binary_io_error, "local outside func"); + if (func == NULL) MIR_get_error_func (ctx) (MIR_binary_io_error, "local outside func"); if (VARR_LENGTH (uint64_t, insn_label_string_nums) != 0) - (*error_func) (MIR_binary_io_error, "local should have no labels"); + MIR_get_error_func (ctx) (MIR_binary_io_error, "local should have no labels"); for (;;) { tag = read_token (ctx, &attr); if (tag == TAG_EOI) break; if (TAG_TI8 > tag || tag > TAG_TRBLOCK) - (*error_func) (MIR_binary_io_error, "wrong local var type tag %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong local var type tag %d", tag); MIR_new_func_reg (ctx, func->u.func, tag_type (tag), read_name (ctx, module, "wrong local var name")); } } else { - (*error_func) (MIR_binary_io_error, "unknown insn name %s", name); + MIR_get_error_func (ctx) (MIR_binary_io_error, "unknown insn name %s", name); } } else if (TAG_U0 <= tag && tag <= TAG_U8) { /* insn code */ MIR_insn_code_t insn_code = attr.u; if (insn_code >= MIR_LABEL) - (*error_func) (MIR_binary_io_error, "wrong insn code %d", insn_code); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong insn code %d", insn_code); if (insn_code == MIR_UNSPEC || insn_code == MIR_PHI) - (*error_func) (MIR_binary_io_error, "UNSPEC or PHI is not portable and can not be read"); + MIR_get_error_func (ctx) (MIR_binary_io_error, + "UNSPEC or PHI is not portable and can not be read"); for (uint64_t i = 0; i < VARR_LENGTH (uint64_t, insn_label_string_nums); i++) { lab = to_lab (ctx, VARR_GET (uint64_t, insn_label_string_nums, i)); MIR_append_insn (ctx, func, lab); @@ -4792,21 +4928,24 @@ void MIR_read_with_func (MIR_context_t ctx, int (*const reader) (MIR_context_t)) mir_assert (nop != 0 || MIR_call_code_p (insn_code) || insn_code == MIR_RET || insn_code == MIR_SWITCH); for (n = 0; (nop == 0 || n < nop) && read_operand (ctx, &op, func); n++) - VARR_PUSH (MIR_op_t, temp_insn_ops, op); + VARR_PUSH (MIR_op_t, read_insn_ops, op); if (nop != 0 && n < nop) - (*error_func) (MIR_binary_io_error, "wrong number of operands of insn %s", - insn_name (insn_code)); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong number of operands of insn %s", + insn_name (insn_code)); MIR_append_insn (ctx, func, - MIR_new_insn_arr (ctx, insn_code, n, VARR_ADDR (MIR_op_t, temp_insn_ops))); + MIR_new_insn_arr (ctx, insn_code, n, VARR_ADDR (MIR_op_t, read_insn_ops))); } else if (tag == TAG_EOFILE) { break; } else { - (*error_func) (MIR_binary_io_error, "wrong token %d", tag); + MIR_get_error_func (ctx) (MIR_binary_io_error, "wrong token %d", tag); } } - if (func != NULL) (*error_func) (MIR_binary_io_error, "unfinished func %s", func->u.func->name); - if (module != NULL) (*error_func) (MIR_binary_io_error, "unfinished module %s", module->name); - if (reader (ctx) != EOF) (*error_func) (MIR_binary_io_error, "garbage at the end of file"); + if (func != NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "unfinished func %s", func->u.func->name); + if (module != NULL) + MIR_get_error_func (ctx) (MIR_binary_io_error, "unfinished module %s", module->name); + if (reader (ctx) != EOF) + MIR_get_error_func (ctx) (MIR_binary_io_error, "garbage at the end of file"); #ifndef MIR_NO_BIN_COMPRESSION reduce_decode_finish (io_reduce_data); #endif @@ -4821,7 +4960,10 @@ void MIR_read (MIR_context_t ctx, FILE *f) { static void io_init (MIR_context_t ctx) { if ((ctx->io_ctx = malloc (sizeof (struct io_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); + VARR_CREATE (MIR_var_t, proto_vars, 0); + VARR_CREATE (MIR_type_t, proto_types, 0); + VARR_CREATE (MIR_op_t, read_insn_ops, 0); VARR_CREATE (MIR_str_t, bin_strings, 512); VARR_CREATE (uint64_t, insn_label_string_nums, 64); VARR_CREATE (MIR_label_t, func_labels, 512); @@ -4831,6 +4973,9 @@ static void io_finish (MIR_context_t ctx) { VARR_DESTROY (MIR_label_t, func_labels); VARR_DESTROY (uint64_t, insn_label_string_nums); VARR_DESTROY (MIR_str_t, bin_strings); + VARR_DESTROY (MIR_op_t, read_insn_ops); + VARR_DESTROY (MIR_var_t, proto_vars); + VARR_DESTROY (MIR_type_t, proto_types); free (ctx->io_ctx); ctx->io_ctx = NULL; } @@ -4895,6 +5040,9 @@ DEF_HTAB (label_desc_t); struct scan_ctx { jmp_buf error_jmp_buf; VARR (char) * error_msg_buf; + VARR (MIR_var_t) * scan_vars; + VARR (MIR_type_t) * scan_types; + VARR (MIR_op_t) * scan_insn_ops; size_t curr_lno; HTAB (insn_name_t) * insn_name_tab; const char *input_string; @@ -4905,6 +5053,9 @@ struct scan_ctx { #define error_jmp_buf ctx->scan_ctx->error_jmp_buf #define error_msg_buf ctx->scan_ctx->error_msg_buf +#define scan_vars ctx->scan_ctx->scan_vars +#define scan_types ctx->scan_ctx->scan_types +#define scan_insn_ops ctx->scan_ctx->scan_insn_ops #define curr_lno ctx->scan_ctx->curr_lno #define insn_name_tab ctx->scan_ctx->insn_name_tab #define input_string ctx->scan_ctx->input_string @@ -5195,16 +5346,16 @@ static MIR_label_t create_label_desc (MIR_context_t ctx, const char *name) { } static int func_reg_p (MIR_context_t ctx, MIR_func_t func, const char *name) { + func_regs_t func_regs = func->internal; size_t rdn, tab_rdn; reg_desc_t rd; int res; - rd.name_num = string_store (ctx, &strings, &string_tab, (MIR_str_t){strlen (name) + 1, name}).num; - rd.func = func; - rdn = VARR_LENGTH (reg_desc_t, reg_descs); - VARR_PUSH (reg_desc_t, reg_descs, rd); - res = HTAB_DO (size_t, namenum2rdn_tab, rdn, HTAB_FIND, tab_rdn); - VARR_POP (reg_desc_t, reg_descs); + rd.name = (char *) name; + rdn = VARR_LENGTH (reg_desc_t, func_regs->reg_descs); + VARR_PUSH (reg_desc_t, func_regs->reg_descs, rd); + res = HTAB_DO (size_t, func_regs->name2rdn_tab, rdn, HTAB_FIND, tab_rdn); + VARR_POP (reg_desc_t, func_regs->reg_descs); return res; } @@ -5212,14 +5363,14 @@ static void read_func_proto (MIR_context_t ctx, size_t nops, MIR_op_t *ops) { MIR_var_t var; size_t i; - VARR_TRUNC (MIR_type_t, temp_types, 0); + VARR_TRUNC (MIR_type_t, scan_types, 0); for (i = 0; i < nops; i++) { var.name = (const char *) ops[i].u.mem.disp; if ((var.name = (const char *) ops[i].u.mem.disp) != NULL) break; var.type = ops[i].u.mem.type; - VARR_PUSH (MIR_type_t, temp_types, var.type); + VARR_PUSH (MIR_type_t, scan_types, var.type); } - VARR_TRUNC (MIR_var_t, temp_vars, 0); + VARR_TRUNC (MIR_var_t, scan_vars, 0); for (; i < nops; i++) { if (ops[i].mode != MIR_OP_MEM) scan_error (ctx, "wrong prototype/func arg"); var.type = ops[i].u.mem.type; @@ -5227,7 +5378,7 @@ static void read_func_proto (MIR_context_t ctx, size_t nops, MIR_op_t *ops) { if (var.name == NULL) scan_error (ctx, "all func/prototype args should have form type:name or (r)blk:size(name)"); if (MIR_blk_type_p (var.type)) var.size = ops[i].u.mem.base; - VARR_PUSH (MIR_var_t, temp_vars, var); + VARR_PUSH (MIR_var_t, scan_vars, var); } } @@ -5376,7 +5527,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { if (func != NULL) MIR_append_insn (ctx, func, label); } } - VARR_TRUNC (MIR_op_t, temp_insn_ops, 0); + VARR_TRUNC (MIR_op_t, scan_insn_ops, 0); dots_p = FALSE; for (;;) { /* ops */ if (t.code == TC_NL || t.code == TC_SEMICOL) { @@ -5405,14 +5556,14 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { push_op_p = FALSE; } else if (!module_p && !end_module_p && !proto_p && !func_p && !end_func_p && !local_p && ((MIR_branch_code_p (insn_code) - && VARR_LENGTH (MIR_op_t, temp_insn_ops) == 0) + && VARR_LENGTH (MIR_op_t, scan_insn_ops) == 0) || (insn_code == MIR_SWITCH - && VARR_LENGTH (MIR_op_t, temp_insn_ops) > 0))) { + && VARR_LENGTH (MIR_op_t, scan_insn_ops) > 0))) { op = MIR_new_label_op (ctx, create_label_desc (ctx, name)); } else if (!expr_p && !ref_p && func_reg_p (ctx, func->u.func, name)) { op.mode = MIR_OP_REG; op.u.reg = MIR_reg (ctx, name, func->u.func); - } else if ((item = find_item (ctx, name, module)) != NULL) { + } else if ((item = item_tab_find (ctx, name, module)) != NULL) { op = MIR_new_ref_op (ctx, item); } else { scan_error (ctx, "undeclared name %s", name); @@ -5508,7 +5659,7 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { default: break; } if (dots_p) break; - if (push_op_p) VARR_PUSH (MIR_op_t, temp_insn_ops, op); + if (push_op_p) VARR_PUSH (MIR_op_t, scan_insn_ops, op); if (read_p) scan_token (ctx, &t, get_string_char, unget_string_char); if (t.code != TC_COMMA) break; scan_token (ctx, &t, get_string_char, unget_string_char); @@ -5517,19 +5668,19 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { scan_error (ctx, "wrong insn end"); if (module_p) { if (module != NULL) scan_error (ctx, "nested module"); - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 0) scan_error (ctx, "module should have no params"); module = MIR_new_module (ctx, VARR_GET (label_name_t, label_names, 0)); } else if (end_module_p) { if (module == NULL) scan_error (ctx, "standalone endmodule"); - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 0) scan_error (ctx, "endmodule should have no params"); MIR_finish_module (ctx); module = NULL; } else if (bss_p) { - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 1) scan_error (ctx, "bss should have one operand"); - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); if (op_addr[0].mode != MIR_OP_INT || op_addr[0].u.i < 0) scan_error (ctx, "wrong bss operand type or value"); name @@ -5537,9 +5688,9 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { : VARR_GET (label_name_t, label_names, 0)); MIR_new_bss (ctx, name, op_addr[0].u.i); } else if (ref_p) { - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 2) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 2) scan_error (ctx, "ref should have two operands"); - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); if (op_addr[0].mode != MIR_OP_REF) scan_error (ctx, "wrong ref operand"); if (op_addr[1].mode != MIR_OP_INT) scan_error (ctx, "wrong ref disp operand"); name @@ -5547,9 +5698,9 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { : VARR_GET (label_name_t, label_names, 0)); MIR_new_ref_data (ctx, name, op_addr[0].u.ref, op_addr[1].u.i); } else if (expr_p) { - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 1) scan_error (ctx, "expr should have one operand"); - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); if (op_addr[0].mode != MIR_OP_REF || op_addr[0].u.ref->item_type != MIR_func_item) scan_error (ctx, "wrong expr operand"); name @@ -5557,9 +5708,9 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { : VARR_GET (label_name_t, label_names, 0)); MIR_new_expr_data (ctx, name, op_addr[0].u.ref); } else if (string_p) { - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 1) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 1) scan_error (ctx, "string should have one operand"); - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); if (op_addr[0].mode != MIR_OP_STR) scan_error (ctx, "wrong string data operand type"); name = (VARR_LENGTH (label_name_t, label_names) == 0 ? NULL @@ -5567,47 +5718,47 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { MIR_new_string_data (ctx, name, op_addr[0].u.str); } else if (proto_p) { if (module == NULL) scan_error (ctx, "prototype outside module"); - read_func_proto (ctx, VARR_LENGTH (MIR_op_t, temp_insn_ops), - VARR_ADDR (MIR_op_t, temp_insn_ops)); + read_func_proto (ctx, VARR_LENGTH (MIR_op_t, scan_insn_ops), + VARR_ADDR (MIR_op_t, scan_insn_ops)); if (dots_p) MIR_new_vararg_proto_arr (ctx, VARR_GET (label_name_t, label_names, 0), - VARR_LENGTH (MIR_type_t, temp_types), - VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), - VARR_ADDR (MIR_var_t, temp_vars)); + VARR_LENGTH (MIR_type_t, scan_types), + VARR_ADDR (MIR_type_t, scan_types), + VARR_LENGTH (MIR_var_t, scan_vars), + VARR_ADDR (MIR_var_t, scan_vars)); else MIR_new_proto_arr (ctx, VARR_GET (label_name_t, label_names, 0), - VARR_LENGTH (MIR_type_t, temp_types), VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), VARR_ADDR (MIR_var_t, temp_vars)); + VARR_LENGTH (MIR_type_t, scan_types), VARR_ADDR (MIR_type_t, scan_types), + VARR_LENGTH (MIR_var_t, scan_vars), VARR_ADDR (MIR_var_t, scan_vars)); } else if (func_p) { if (module == NULL) scan_error (ctx, "func outside module"); if (func != NULL) scan_error (ctx, "nested func"); - read_func_proto (ctx, VARR_LENGTH (MIR_op_t, temp_insn_ops), - VARR_ADDR (MIR_op_t, temp_insn_ops)); + read_func_proto (ctx, VARR_LENGTH (MIR_op_t, scan_insn_ops), + VARR_ADDR (MIR_op_t, scan_insn_ops)); if (dots_p) func = MIR_new_vararg_func_arr (ctx, VARR_GET (label_name_t, label_names, 0), - VARR_LENGTH (MIR_type_t, temp_types), - VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), - VARR_ADDR (MIR_var_t, temp_vars)); + VARR_LENGTH (MIR_type_t, scan_types), + VARR_ADDR (MIR_type_t, scan_types), + VARR_LENGTH (MIR_var_t, scan_vars), + VARR_ADDR (MIR_var_t, scan_vars)); else func = MIR_new_func_arr (ctx, VARR_GET (label_name_t, label_names, 0), - VARR_LENGTH (MIR_type_t, temp_types), - VARR_ADDR (MIR_type_t, temp_types), - VARR_LENGTH (MIR_var_t, temp_vars), VARR_ADDR (MIR_var_t, temp_vars)); + VARR_LENGTH (MIR_type_t, scan_types), + VARR_ADDR (MIR_type_t, scan_types), + VARR_LENGTH (MIR_var_t, scan_vars), VARR_ADDR (MIR_var_t, scan_vars)); HTAB_CLEAR (label_desc_t, label_desc_tab); } else if (end_func_p) { if (func == NULL) scan_error (ctx, "standalone endfunc"); - if (VARR_LENGTH (MIR_op_t, temp_insn_ops) != 0) + if (VARR_LENGTH (MIR_op_t, scan_insn_ops) != 0) scan_error (ctx, "endfunc should have no params"); func = NULL; MIR_finish_func (ctx); } else if (export_p || import_p || forward_p) { /* we already created items, now do nothing: */ - mir_assert (VARR_LENGTH (MIR_op_t, temp_insn_ops) == 0); + mir_assert (VARR_LENGTH (MIR_op_t, scan_insn_ops) == 0); } else if (local_p) { - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); - n = VARR_LENGTH (MIR_op_t, temp_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); + n = VARR_LENGTH (MIR_op_t, scan_insn_ops); for (i = 0; i < n; i++) { if (op_addr[i].mode != MIR_OP_MEM || (const char *) op_addr[i].u.mem.disp == NULL) scan_error (ctx, "wrong local var"); @@ -5626,8 +5777,8 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { int64_t i64; } v; - n = VARR_LENGTH (MIR_op_t, temp_insn_ops); - op_addr = VARR_ADDR (MIR_op_t, temp_insn_ops); + n = VARR_LENGTH (MIR_op_t, scan_insn_ops); + op_addr = VARR_ADDR (MIR_op_t, scan_insn_ops); VARR_TRUNC (uint8_t, temp_data, 0); for (i = 0; i < n; i++) { if (op_addr[i].mode != type2mode (data_type)) @@ -5681,15 +5832,15 @@ void MIR_scan_string (MIR_context_t ctx, const char *str) { VARR_LENGTH (uint8_t, temp_data) / _MIR_type_size (ctx, data_type), VARR_ADDR (uint8_t, temp_data)); } else { - insn = MIR_new_insn_arr (ctx, insn_code, VARR_LENGTH (MIR_op_t, temp_insn_ops), - VARR_ADDR (MIR_op_t, temp_insn_ops)); + insn = MIR_new_insn_arr (ctx, insn_code, VARR_LENGTH (MIR_op_t, scan_insn_ops), + VARR_ADDR (MIR_op_t, scan_insn_ops)); 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 (VARR_LENGTH (char, error_msg_buf) != 0) - (*error_func) (MIR_syntax_error, VARR_ADDR (char, error_msg_buf)); + MIR_get_error_func (ctx) (MIR_syntax_error, VARR_ADDR (char, error_msg_buf)); } static void scan_init (MIR_context_t ctx) { @@ -5697,8 +5848,11 @@ static void scan_init (MIR_context_t ctx) { size_t i; if ((ctx->scan_ctx = malloc (sizeof (struct scan_ctx))) == NULL) - (*error_func) (MIR_alloc_error, "Not enough memory for ctx"); + MIR_get_error_func (ctx) (MIR_alloc_error, "Not enough memory for ctx"); VARR_CREATE (char, error_msg_buf, 0); + VARR_CREATE (MIR_var_t, scan_vars, 0); + VARR_CREATE (MIR_type_t, scan_types, 0); + VARR_CREATE (MIR_op_t, scan_insn_ops, 0); VARR_CREATE (label_name_t, label_names, 0); HTAB_CREATE (label_desc_t, label_desc_tab, 100, label_hash, label_eq, NULL); HTAB_CREATE (insn_name_t, insn_name_tab, MIR_INSN_BOUND, insn_name_hash, insn_name_eq, NULL); @@ -5711,6 +5865,9 @@ static void scan_init (MIR_context_t ctx) { static void scan_finish (MIR_context_t ctx) { VARR_DESTROY (char, error_msg_buf); + VARR_DESTROY (MIR_var_t, scan_vars); + VARR_DESTROY (MIR_type_t, scan_types); + VARR_DESTROY (MIR_op_t, scan_insn_ops); VARR_DESTROY (label_name_t, label_names); HTAB_DESTROY (label_desc_t, label_desc_tab); HTAB_DESTROY (insn_name_t, insn_name_tab); diff --git a/mir/mir.h b/mir/mir.h index 88fcd36..4f13985 100644 --- a/mir/mir.h +++ b/mir/mir.h @@ -31,6 +31,15 @@ static inline int mir_assert (int cond) { return 0 && cond; } #define MIR_NO_SCAN 0 #endif +#ifndef MIR_PARALLEL_GEN +#define MIR_PARALLEL_GEN 0 +#endif + +#if MIR_PARALLEL_GEN && defined(_WIN64) /* TODO: Win64 thread primitives ??? */ +#undef MIR_PARALLEL_GEN +#define MIR_PARALLEL_GEN 0 +#endif + #ifdef __GNUC__ #define MIR_UNUSED __attribute__ ((unused)) #else @@ -53,7 +62,7 @@ typedef enum MIR_error_type { REP4 (ERR_EL, func, vararg_func, nested_func, wrong_param_value), REP5 (ERR_EL, reserved_name, import_export, undeclared_func_reg, repeated_decl, reg_type), REP6 (ERR_EL, wrong_type, unique_reg, undeclared_op_ref, ops_num, call_op, unspec_op), - REP4 (ERR_EL, ret, op_mode, out_op, invalid_insn) + REP6 (ERR_EL, ret, op_mode, out_op, invalid_insn, ctx_change, parallel) } MIR_error_type_t; #ifdef __GNUC__ @@ -65,6 +74,28 @@ typedef enum MIR_error_type { typedef void MIR_NO_RETURN (*MIR_error_func_t) (MIR_error_type_t error_type, const char *format, ...); +#if MIR_PARALLEL_GEN +#include +typedef pthread_mutex_t mir_mutex_t; +typedef pthread_cond_t mir_cond_t; +#define mir_thread_create(m, attr, f, arg) pthread_create (m, attr, f, arg) +#define mir_thread_join(t, r) pthread_join (t, r) +#define mir_mutex_init(m, a) pthread_mutex_init (m, a) +#define mir_mutex_destroy(m) pthread_mutex_destroy (m) +#define mir_mutex_lock(m) pthread_mutex_lock (m) +#define mir_mutex_unlock(m) pthread_mutex_unlock (m) +#define mir_cond_init(m, a) pthread_cond_init (m, a) +#define mir_cond_destroy(m) pthread_cond_destroy (m) +#define mir_cond_wait(c, m) pthread_cond_wait (c, m) +#define mir_cond_signal(c) pthread_cond_signal (c) +#define mir_cond_broadcast(c) pthread_cond_broadcast (c) +#else +#define mir_mutex_init(m, a) 0 +#define mir_mutex_destroy(m) 0 +#define mir_mutex_lock(m) 0 +#define mir_mutex_unlock(m) 0 +#endif + #define INSN_EL(i) MIR_##i /* The most MIR insns have destination operand and one or two source @@ -279,6 +310,7 @@ typedef struct MIR_func { VARR (MIR_var_t) * vars; /* args and locals but temps */ void *machine_code; /* address of generated machine code or NULL */ void *call_addr; /* address to call the function, it can be the same as machine_code */ + void *internal; /* internal data structure */ } * MIR_func_t; typedef struct MIR_proto { @@ -493,6 +525,8 @@ extern void MIR_insert_insn_before (MIR_context_t ctx, MIR_item_t func, MIR_insn MIR_insn_t insn); extern void MIR_remove_insn (MIR_context_t ctx, MIR_item_t func, MIR_insn_t insn); +extern void MIR_change_module_ctx (MIR_context_t old_ctx, MIR_module_t m, MIR_context_t new_ctx); + extern MIR_insn_code_t MIR_reverse_branch_code (MIR_insn_code_t code); extern const char *MIR_type_str (MIR_context_t ctx, MIR_type_t tp); diff --git a/src/ravi_mirjit.c b/src/ravi_mirjit.c index 36c1b03..75b729e 100644 --- a/src/ravi_mirjit.c +++ b/src/ravi_mirjit.c @@ -412,13 +412,12 @@ void *mir_get_func(MIR_context_t ctx, MIR_module_t module, const char *func_name fprintf(stderr, "Error: Compiled function %s not found\n", func_name); exit(1); } - return MIR_gen (ctx, main_func); + return MIR_gen (ctx, 0, main_func); } void mir_prepare(MIR_context_t ctx, int optlevel) { c2mir_init(ctx); - MIR_gen_init (ctx); - MIR_gen_set_optimize_level(ctx, optlevel); + MIR_gen_init (ctx, optlevel); } void mir_cleanup(MIR_context_t ctx) {