diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 0990f390d..4d0c41cbc 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -381,10 +381,12 @@ etype_t extract_type (expr_t *e); ex_listitem_t *new_listitem (expr_t *e); int list_count (ex_list_t *list) __attribute__((pure)); void list_scatter (ex_list_t *list, expr_t **exprs); +void list_scatter_rev (ex_list_t *list, expr_t **exprs); void list_gather (ex_list_t *dst, expr_t **exprs, int count); expr_t *new_list_expr (expr_t *first); expr_t *list_append_expr (expr_t *list, expr_t *expr); expr_t *list_prepend_expr (expr_t *list, expr_t *expr); +expr_t *list_append_list (expr_t *list, ex_list_t *append); expr_t *list_prepend_list (expr_t *list, ex_list_t *prepend); /** Create a new expression node. @@ -843,7 +845,6 @@ expr_t *convert_name (expr_t *e)__attribute__((warn_unused_result)); expr_t *append_expr (expr_t *block, expr_t *e); expr_t *prepend_expr (expr_t *block, expr_t *e); -expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); void dump_dot_expr (void *e, const char *filename); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index deb17d471..22ab94eaf 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1637,6 +1637,7 @@ class_finish_module (void) init_sym = function_symbol (init_sym, 0, 1); module_expr = address_expr (new_symbol_expr (module_sym), 0); + module_expr = new_list_expr (module_expr); init_expr = new_block_expr (); append_expr (init_expr, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c6b26fd03..d703c415b 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -204,7 +204,8 @@ get_type (expr_t *e) return e->multivec.type; case ex_list: if (e->list.head) { - return get_type ((*e->list.tail)->expr); + auto last = (ex_listitem_t *) e->list.tail; + return get_type (last->expr); } return 0; case ex_count: @@ -296,6 +297,14 @@ list_prepend_expr (expr_t *list, expr_t *expr) return list; } +expr_t * +list_append_list (expr_t *list, ex_list_t *append) +{ + *list->list.tail = append->head; + list->list.tail = append->tail; + return list; +} + expr_t * list_prepend_list (expr_t *list, ex_list_t *prepend) { @@ -338,6 +347,15 @@ list_scatter (ex_list_t *list, expr_t **exprs) } } +void +list_scatter_rev (ex_list_t *list, expr_t **exprs) +{ + int count = list_count (list); + for (auto li = list->head; li; li = li->next) { + exprs[--count] = li->expr; + } +} + void list_gather (ex_list_t *list, expr_t **exprs, int count) { @@ -2216,29 +2234,29 @@ vararg_integer (expr_t *e) expr_t * build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) { - expr_t *e; - expr_t *p; - int arg_count = 0, param_count = 0; - int i; - expr_t *args = 0, **a = &args; - int arg_expr_count = 0; - int emit_args = 0; + int param_count = 0; expr_t *assign; expr_t *call; expr_t *err = 0; - for (e = params; e; e = e->next) { - if (e->type == ex_error) + int arg_count = params ? list_count (¶ms->list) :0; + expr_t *arguments[arg_count]; + if (params) { + list_scatter_rev (¶ms->list, arguments); + } + + for (int i = 0; i < arg_count; i++) { + auto e = arguments[i]; + if (e->type == ex_error) { return e; - arg_count++; + } } if (options.code.progsversion < PROG_VERSION && arg_count > PR_MAX_PARAMS) { return error (fexpr, "more than %d parameters", PR_MAX_PARAMS); } - type_t *arg_types[arg_count]; - expr_t *arg_exprs[arg_count][2]; + if (ftype->t.func.num_params < -1) { if (-arg_count > ftype->t.func.num_params + 1) { if (!options.traditional) @@ -2258,11 +2276,11 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } param_count = ftype->t.func.num_params; } - if (ftype->t.func.num_params < 0) { - emit_args = !ftype->t.func.no_va_list; - } + + type_t *arg_types[arg_count]; // params is reversed (a, b, c) -> c, b, a - for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { + for (int i = 0; i < arg_count; i++) { + auto e = arguments[i]; type_t *t; if (e->type == ex_compound) { @@ -2324,21 +2342,29 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } vararg_integer (e); } - arg_types[arg_count - 1 - i] = t; + arg_types[i] = t; } - if (err) + if (err) { return err; + } + bool emit_args = false; + if (ftype->t.func.num_params < 0) { + emit_args = !ftype->t.func.no_va_list; + } call = expr_file_line (new_block_expr (), fexpr); call->block.is_call = 1; + int arg_expr_count = 0; + expr_t *arg_exprs[arg_count][2]; + expr_t *args = new_list_expr (0); // args is built in reverse order so it matches params - for (p = params, i = 0; p; p = p->next, i++) { - if (emit_args && arg_count - i == param_count) { - emit_args = 0; - *a = new_args_expr (); - a = &(*a)->next; + for (int i = 0; i < arg_count; i++) { + if (emit_args && i == param_count) { + list_prepend_expr (args, new_args_expr ()); + emit_args = false; } - expr_t *e = p; + + auto e = arguments[i]; if (e->type == ex_compound) { e = expr_file_line (initialized_temp_expr (arg_types[i], e), e); } @@ -2348,32 +2374,34 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (has_function_call (e)) { expr_t *cast = cast_expr (arg_types[i], e); expr_t *tmp = new_temp_def_expr (arg_types[i]); - *a = expr_file_line (tmp, e); + tmp = expr_file_line (tmp, e); + list_prepend_expr (args, tmp); + arg_exprs[arg_expr_count][0] = expr_file_line (cast, e); - arg_exprs[arg_expr_count][1] = *a; + arg_exprs[arg_expr_count][1] = tmp; arg_expr_count++; } else { - *a = expr_file_line (cast_expr (arg_types[i], e), e); + e = expr_file_line (cast_expr (arg_types[i], e), e); + list_prepend_expr (args, e); } - a = &(*a)->next; } if (emit_args) { - emit_args = 0; - *a = new_args_expr (); - a = &(*a)->next; + emit_args = false; + list_prepend_expr (args, new_args_expr ()); } - for (i = 0; i < arg_expr_count - 1; i++) { + for (int i = 0; i < arg_expr_count - 1; i++) { assign = assign_expr (arg_exprs[i][1], arg_exprs[i][0]); append_expr (call, expr_file_line (assign, arg_exprs[i][0])); } if (arg_expr_count) { - e = assign_expr (arg_exprs[arg_expr_count - 1][1], - arg_exprs[arg_expr_count - 1][0]); + auto e = assign_expr (arg_exprs[arg_expr_count - 1][1], + arg_exprs[arg_expr_count - 1][0]); e = expr_file_line (e, arg_exprs[arg_expr_count - 1][0]); append_expr (call, e); } - e = expr_file_line (call_expr (fexpr, args, ftype->t.func.type), fexpr); - call->block.result = e; + type_t *ret_type = ftype->t.func.type; + call->block.result = expr_file_line (call_expr (fexpr, args, ret_type), + fexpr); return call; } @@ -3153,17 +3181,3 @@ sizeof_expr (expr_t *expr, struct type_s *type) } return expr; } - -expr_t * -reverse_expr_list (expr_t *e) -{ - expr_t *r = 0; - - while (e) { - expr_t *t = e->next; - e->next = r; - r = e; - e = t; - } - return r; -} diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index cbb04bea3..eb589cc2b 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -180,7 +180,6 @@ super_expr (class_type_t *class_type) expr_t * message_expr (expr_t *receiver, keywordarg_t *message) { - expr_t *args = 0, **a = &args; expr_t *selector = selector_expr (message); expr_t *call; keywordarg_t *m; @@ -226,16 +225,15 @@ message_expr (expr_t *receiver, keywordarg_t *message) if (method) return_type = method->type->t.func.type; + expr_t *args = expr_file_line (new_list_expr (0), receiver); for (m = message; m; m = m->next) { - *a = m->expr; - while ((*a)) { - expr_file_line (selector, *a); - a = &(*a)->next; + if (m->expr && m->expr->list.head) { + list_append_list (args, &m->expr->list); + expr_file_line (selector, m->expr); } } - *a = selector; - a = &(*a)->next; - *a = receiver; + list_append_expr (args, selector); + list_append_expr (args, receiver); send_msg = expr_file_line (send_message (super), receiver); if (method) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index edb474d73..f4df88972 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -349,30 +349,32 @@ func_compare (const void *a, const void *b) expr_t * find_function (expr_t *fexpr, expr_t *params) { - expr_t *e; int i, j, func_count, parm_count, reported = 0; overloaded_function_t *f, dummy, *best = 0; - type_t type; + type_t type = {}; void **funcs, *dummy_p = &dummy; if (fexpr->type != ex_symbol) return fexpr; - memset (&type, 0, sizeof (type)); type.type = ev_func; - - for (e = params; e; e = e->next) { - if (e->type == ex_error) - return e; - type.t.func.num_params++; + type.t.func.num_params = params ? list_count (¶ms->list) : 0; + expr_t *args[type.t.func.num_params]; + if (params) { + list_scatter_rev (¶ms->list, args); } - i = type.t.func.num_params * sizeof (type_t); - type.t.func.param_types = alloca(i); - memset (type.t.func.param_types, 0, i); - for (i = 0, e = params; e; i++, e = e->next) { - type.t.func.param_types[type.t.func.num_params - 1 - i] = get_type (e); - if (e->type == ex_error) + + for (int i = 0; i < type.t.func.num_params; i++) { + auto e = args[i]; + if (e->type == ex_error) { return e; + } + } + type_t *arg_types[type.t.func.num_params]; + type.t.func.param_types = arg_types; + for (int i = 0; i < type.t.func.num_params; i++) { + auto e = args[i]; + type.t.func.param_types[i] = get_type (e); } funcs = Hash_FindList (function_map, fexpr->symbol->name); if (!funcs) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 89d30895c..921e930e2 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -703,32 +703,26 @@ clear_selectors (void) expr_t * method_check_params (method_t *method, expr_t *args) { - int i, count, param_count; - expr_t *a, **arg_list, *err = 0; + int i, param_count; + expr_t *err = 0; type_t *mtype = method->type; if (mtype->t.func.num_params == -1) return 0; - for (count = 0, a = args; a; a = a->next) - count++; - - if (count > PR_MAX_PARAMS) - return error (args, "more than %d parameters", PR_MAX_PARAMS); - if (mtype->t.func.num_params >= 0) param_count = mtype->t.func.num_params; else param_count = -mtype->t.func.num_params - 1; + int count = list_count (&args->list); if (count < param_count) return error (args, "too few arguments"); if (mtype->t.func.num_params >= 0 && count > mtype->t.func.num_params) return error (args, "too many arguments"); - arg_list = malloc (count * sizeof (expr_t *)); - for (i = count - 1, a = args; a; a = a->next) - arg_list[i--] = a; + expr_t *arg_list[count]; + list_scatter_rev (&args->list, arg_list); for (i = 2; i < count; i++) { expr_t *e = arg_list[i]; type_t *arg_type = mtype->t.func.param_types[i]; @@ -752,6 +746,5 @@ method_check_params (method_t *method, expr_t *args) vararg_integer (e); } } - free (arg_list); return err; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a36606c4f..86c399027 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1799,12 +1799,8 @@ opt_arg_list ; arg_list - : arg_expr - | arg_list ',' arg_expr - { - $3->next = $1; - $$ = $3; - } + : arg_expr { $$ = new_list_expr ($1); } + | arg_list ',' arg_expr { $$ = list_prepend_expr ($1, $3); } ; arg_expr diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index e6f78fe3b..6afa6c82b 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -458,12 +458,8 @@ procedure_statement ; expression_list - : expression - | expression_list ',' expression - { - $$ = $3; - $$->next = $1; - } + : expression { $$ = new_list_expr ($1); } + | expression_list ',' expression { $$ = list_prepend_expr ($1, $3); } ; unary_expr diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 52f873630..d8ed76686 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1068,7 +1068,6 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) { expr_t *func = call->branch.target; expr_t *args = call->branch.args; - expr_t *a; expr_t *param; operand_t *arguments[2] = {0, 0}; int count = 0; @@ -1079,7 +1078,8 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) operand_t *use = 0; // function arguments are in reverse order - for (a = args; a; a = a->next) { + for (auto li = args->list.head; li; li = li->next) { + auto a = li->expr; if (a->type == ex_args) { // v6p uses callN and pr_argc continue; @@ -1087,7 +1087,8 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) count++; } ind = count; - for (a = args; a; a = a->next) { + for (auto li = args->list.head; li; li = li->next) { + auto a = li->expr; if (a->type == ex_args) { // v6p uses callN and pr_argc continue; @@ -1157,7 +1158,6 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } defspace_t *arg_space = current_func->arguments; expr_t *func = call->branch.target; - expr_t **args = 0; expr_t *args_va_list = 0; // .args (...) parameter expr_t *args_params = 0; // first arg in ... operand_t *use = 0; @@ -1166,17 +1166,9 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) defspace_reset (arg_space); - int num_args = 0; - for (expr_t *a = call->branch.args; a; a = a->next) { - num_args++; - } - if (num_args) { - int i = num_args; - args = alloca (num_args * sizeof (expr_t *)); - for (expr_t *a = call->branch.args; a; a = a->next) { - args[--i] = a; - } - } + int num_args = list_count (&call->branch.args->list); + expr_t *args[num_args]; + list_scatter_rev (&call->branch.args->list, args); int arg_num = 0; for (int i = 0; i < num_args; i++) { expr_t *a = args[i]; @@ -2590,12 +2582,15 @@ search_for_super_dealloc (sblock_t *sblock) } // function arguments are in reverse order, and the selector // is the second argument (or second last in the list) - expr_t *arg; - for (arg = st->expr->branch.args; - arg && arg->next && arg->next->next; arg = arg->next) { + expr_t *arg = 0; + auto arguments = st->expr->branch.args; + for (auto li = arguments->list.head; li; li = li->next) { + if (li->next && !li->next->next) { + arg = li->expr; + } } - if (arg && arg->next && is_selector (arg)) { - selector_t *sel = get_selector (st->expr->branch.args); + if (arg && is_selector (arg)) { + selector_t *sel = get_selector (arg); if (sel && strcmp (sel->name, "dealloc") == 0) { op = pseudo_operand (super_dealloc, st->expr); statement_add_def (st, op);