📄 nloop.c
字号:
return; expand_end_bindings (getdecls (), kept_level_p (), 0); pop_momentary ();}/* The iterator structure records all aspects of a * 'FOR i := start [DOWN] TO end' clause or * 'FOR i IN modename' or 'FOR i IN powerset' clause. * It's saved on the iter_list of the current LOOP. */voidbuild_loop_iterator (user_var, start_exp, step_exp, end_exp, down_flag, in_flag, ever_flag) tree user_var, start_exp, step_exp, end_exp; int down_flag, in_flag, ever_flag;{ ITERATOR *ip = (ITERATOR *)xmalloc (sizeof (ITERATOR)); /* chain this iterator onto the current loop */ if (loop_stack->iter_list == NULL) loop_stack->iter_list = ip; else { ITERATOR *temp = loop_stack->iter_list; while (temp->next != NULL) temp = temp->next; temp->next = ip; } ip->itype = DO_UNUSED; ip->user_var = user_var; ip->start_exp = start_exp; ip->step_exp = step_exp; ip->end_exp = end_exp; ip->condition = NULL_TREE; ip->start_temp = NULL_TREE; ip->end_temp = NULL_TREE; ip->step_temp = NULL_TREE; ip->down_flag = down_flag; ip->powerset_temp = NULL_TREE; ip->iter_var = NULL_TREE; ip->iter_type = NULL_TREE; ip->loc_ptr_temp = NULL_TREE; ip->error_flag = 1; /* assume error will be found */ ip->next = (ITERATOR *)0; if (ever_flag) ip->itype = DO_FOREVER; else if (in_flag && start_exp != NULL_TREE) { if (TREE_CODE (start_exp) == ERROR_MARK) return; if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE) ip->itype = DO_POWERSET; else if (discrete_type_p (TREE_TYPE (ip->start_exp))) ip->itype = DO_RANGE; else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE) ip->itype = DO_LOC; else if (chill_varying_type_p (TREE_TYPE (ip->start_exp))) ip->itype = DO_LOC_VARYING; else { error ("Loop's IN expression is not a composite object"); return; } } else if (start_exp == NULL_TREE && end_exp == NULL_TREE && step_exp == NULL_TREE && !down_flag) ip->itype = DO_OD; else { /* FIXME: Move this to the lexer? */#define CST_FITS_INT(NODE) (TREE_CODE(NODE) == INTEGER_CST &&\ int_fits_type_p (NODE, integer_type_node)) tree max_prec_type = integer_type_node; if (! discrete_type_p (TREE_TYPE (ip->start_exp))) { error ("start expr must have discrete mode"); return; } if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ENUMERAL_TYPE && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->start_exp))) { error ("DO FOR start expression is a numbered SET"); return; } if (TREE_CODE (TREE_TYPE (ip->end_exp)) == ENUMERAL_TYPE && CH_ENUM_IS_NUMBERED (TREE_TYPE (ip->end_exp))) { error ("TO expression is a numbered SET"); return; } /* Convert all three expressions to a common precision, which is the largest precision they exhibit, but INTEGER_CST nodes are built in the lexer as long_integer_type nodes. We'll treat convert them to integer_type_nodes if possible, for faster loop times. */ if (TYPE_PRECISION (max_prec_type) < TYPE_PRECISION (TREE_TYPE (ip->start_exp)) && !CST_FITS_INT (ip->start_exp)) max_prec_type = TREE_TYPE (ip->start_exp); if (! discrete_type_p (TREE_TYPE (ip->end_exp))) { error ("TO expr must have discrete mode"); return; } if (! CH_COMPATIBLE (ip->start_exp, TREE_TYPE (ip->end_exp))) { error ("start expr and TO expr must be compatible"); return; } if (TYPE_PRECISION (max_prec_type) < TYPE_PRECISION (TREE_TYPE (ip->end_exp)) && !CST_FITS_INT (ip->end_exp)) max_prec_type = TREE_TYPE (ip->end_exp); if (ip->step_exp != NULL_TREE) { /* assure that default 'BY 1' gets a useful type */ if (ip->step_exp == integer_one_node) ip->step_exp = convert (TREE_TYPE (ip->start_exp), ip->step_exp); if (! discrete_type_p (TREE_TYPE (ip->step_exp))) { error ("BY expr must have discrete mode"); return; } if (! CH_COMPATIBLE (ip->start_exp, TREE_TYPE (ip->step_exp))) { error ("start expr and BY expr must be compatible"); return; } if (TYPE_PRECISION (max_prec_type) < TYPE_PRECISION (TREE_TYPE (ip->step_exp)) && !CST_FITS_INT (ip->step_exp)) max_prec_type = TREE_TYPE (ip->step_exp); } if (TREE_CODE (ip->start_exp) == INTEGER_CST && TREE_CODE (ip->end_exp) == INTEGER_CST && compare_int_csts (ip->down_flag ? LT_EXPR : GT_EXPR, ip->start_exp, ip->end_exp)) warning ("body of DO FOR will never execute"); ip->start_exp = convert (max_prec_type, ip->start_exp); ip->end_exp = convert (max_prec_type, ip->end_exp); if (ip->step_exp != NULL_TREE) { ip->step_exp = convert (max_prec_type, ip->step_exp); if (TREE_CODE (ip->step_exp) != INTEGER_CST) { /* generate runtime check for negative BY expr */ ip->step_exp = check_range (ip->step_exp, ip->step_exp, integer_zero_node, NULL_TREE); } else if (compare_int_csts (LE_EXPR, ip->step_exp, integer_zero_node)) { error ("BY expression is negative or zero"); return; } } ip->itype = DO_STEP; } ip->error_flag = 0; /* no errors! */}voidbuild_loop_start (while_control, start_label) tree while_control, start_label;{ ITERATOR *firstp = loop_stack->iter_list; firstp->condition = while_control; if (firstp->error_flag) return; /* We didn't know at begin_loop_scope time about the condition; adjust iterator type now. */ if (firstp->itype == DO_OD && firstp->condition) firstp->itype = DO_WHILE; if (initialize_iter_var ()) return; if (maybe_skip_loop ()) return; /* use the label as an 'exit' label, 'goto' needs another sort of label */ expand_start_loop (start_label != NULL_TREE); if (top_loop_end_check ()) return; emit_line_note (input_filename, lineno); }/* * Called after the last action of the loop body * has been parsed. */voidbuild_loop_end (){ ITERATOR *ip = loop_stack->iter_list; emit_line_note (input_filename, lineno); if (ip->error_flag) return; if (bottom_loop_end_check ()) return; if (increment_temps ()) return; if (ip->itype != DO_OD) { expand_end_loop (); for (; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_LOC_VARYING: case DO_STEP: expand_end_cond (); break; default: break; } } }}/* * The rest of the routines in this file are called from * the above three routines. */static intclassify_loop (){ ITERATOR *firstp = loop_stack->iter_list, *ip; firstp->error_flag = 0; if (firstp->itype == DO_UNUSED || firstp->itype == DO_OD) { /* if we have just DO .. OD, do nothing - this is just a BEGIN .. END without creating a new scope, and no looping */ if (firstp->condition != NULL_TREE) firstp->itype = DO_WHILE; else firstp->itype = DO_OD; } /* Issue a warning if the any loop counter is mentioned more than once in the iterator list. */ for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: case DO_WHILE: break; case DO_STEP: case DO_RANGE: case DO_POWERSET: case DO_LOC: case DO_LOC_VARYING: /* FIXME: check for name uniqueness */ break; default: ; } } return firstp->error_flag;}/* * Reserve space for any loop-control temporaries, initialize them */static intdeclare_temps (){ ITERATOR *firstp = loop_stack->iter_list, *ip; tree start_ptr; for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: case DO_WHILE: break; case DO_STEP: ip->iter_type = chill_unsigned_type (TREE_TYPE (ip->start_exp)); /* create, initialize temporaries if expressions aren't constant */ ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start", ip->iter_type); ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end", ip->iter_type); /* this is just the step-expression */ ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step", ip->iter_type); goto do_step_range; case DO_RANGE: ip->iter_type = chill_unsigned_type_node; ip->start_temp = (ip->down_flag ? build_chill_upper : build_chill_lower)(TREE_TYPE (ip->start_exp)); ip->end_temp = (ip->down_flag ? build_chill_lower : build_chill_upper)(TREE_TYPE (ip->start_exp)); ip->step_temp = integer_one_node; do_step_range: if (flag_local_loop_counter) { /* (re-)declare the user's iteration variable in the loop's scope. */ tree id_node = ip->user_var; IDENTIFIER_LOCAL_VALUE (id_node) = ip->user_var = decl_temp1 (id_node, ip->iter_type, 0, NULL_TREE, 0, 0); } else { /* in this case, it's a previously-declared VAR_DECL node, checked in build_loop_iterator. */ if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE) ip->user_var = lookup_name (ip->user_var); if (ip->user_var == NULL_TREE) { error ("loop identifier undeclared"); ip->error_flag = 1; return 1; } } ip->iter_var = decl_temp1 (get_unique_identifier ("iter_var"), ip->iter_type, 0, NULL_TREE, 0, 0); break; case DO_POWERSET: ip->iter_type = chill_unsigned_type ( TYPE_DOMAIN (TREE_TYPE (ip->start_exp))); if (flag_local_loop_counter) { /* declare the user's iteration variable in the loop's scope. */ /* in this case, it's just an IDENTIFIER_NODE */ ip->user_var = decl_temp1 (ip->user_var, ip->iter_type, 0, NULL_TREE, 0, 0); } else { /* in this case, it's a previously-declared VAR_DECL node */ ip->user_var = lookup_name (ip->user_var); } /* the user's powerset-expression, evaluated and saved in a temp */ ip->powerset_temp = maybe_make_for_temp (ip->start_exp, "for_set", TREE_TYPE (ip->start_exp)); mark_addressable (ip->powerset_temp); break; case DO_LOC: case DO_LOC_VARYING: ip->iter_type = chill_unsigned_type_node; /* create the counter temp */ ip->iter_var = build_temporary_variable ("iter_var", ip->iter_type); if (!CH_LOCATION_P (ip->start_exp)) ip->start_exp = decl_temp1 (get_unique_identifier ("iter_loc"), TREE_TYPE (ip->start_exp), 0, ip->start_exp, 0, 0); if (ip->itype == DO_LOC) { tree array_type = TREE_TYPE (ip->start_exp); tree ptr_type; tree temp; if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE) { error ("Can't iterate through array of BOOL"); ip->error_flag = 1; return ip->error_flag; } /* FIXME: check for array type in ip->start_exp */ /* create pointer temporary */ ip->base_type = TREE_TYPE (array_type); ptr_type = build_pointer_type (ip->base_type); ip->loc_ptr_temp = build_temporary_variable ("loc_ptr_tmp", ptr_type); /* declare the user's iteration variable in the loop's scope, as an expression, to be passed to build_component_ref later */ save_expr_under_name (ip->user_var,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -