📄 loop.c
字号:
pushlevel (0); /* this happens only in pass 2 */ declare_temps (); clear_last_expr (); push_momentary (); expand_start_bindings (0);}voidnonvalue_end_loop_scope (){ expand_end_bindings (getdecls (), kept_level_p (), 0); pop_momentary (); poplevel (kept_level_p (), 1, 0);}/* 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 (loopstack->iter_list == NULL) loopstack->iter_list = ip; else { ITERATOR *temp = loopstack->iter_list; while (temp->next != NULL) temp = temp->next; temp->next = ip; } ip->user_var = user_var; ip->start_exp = start_exp; ip->step_exp = step_exp; ip->end_exp = end_exp; 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->stepin_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_TYPE (start_exp) == NULL_TREE) { if (TREE_CODE (start_exp) == CONSTRUCTOR) error ("modeless tuple not allowed in this context"); else error ("IN expression does not have a mode"); return; } if (TREE_CODE (TREE_TYPE (start_exp)) == SET_TYPE) { if (CH_BOOLS_TYPE_P (TREE_TYPE (start_exp))) { sorry ("location enumeration for BOOLS"); return; } ip->itype = DO_POWERSET; } else if (discrete_type_p (TREE_TYPE (ip->start_exp))) { /* range enumeration */ tree type = TREE_TYPE (ip->start_exp); /* save the original type for later use in determine to do a rangecheck or not */ ip->stepin_type = type; ip->itype = DO_STEP; if (ip->down_flag) { ip->start_exp = build_chill_upper (type); ip->end_exp = build_chill_lower (type); } else { ip->start_exp = build_chill_lower (type); ip->end_exp = build_chill_upper (type); } } else if (TREE_CODE (TREE_TYPE (ip->start_exp)) == ARRAY_TYPE) { if (TYPE_PACKED (TREE_TYPE (ip->start_exp))) { sorry ("location enumeration for bit-packed arrays"); return; } 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 ip->itype = DO_STEP; if (ip->itype == DO_STEP) { struct ch_class class; if (ip->step_exp == NULL_TREE) ip->step_exp = integer_one_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 (ip->end_exp) == ERROR_MARK) 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; } if (! discrete_type_p (TREE_TYPE (ip->end_exp))) { error ("TO expr must have discrete mode"); return; } if (! CH_COMPATIBLE_CLASSES (ip->start_exp, ip->end_exp)) { error ("start expr and TO expr must be compatible"); return; } if (step_exp != NULL_TREE) { if (TREE_CODE (step_exp) == ERROR_MARK) return; if (! discrete_type_p (TREE_TYPE (step_exp))) { error ("BY expr must have discrete mode"); return; } if (! CH_COMPATIBLE_CLASSES (ip->start_exp, step_exp)) { error ("start expr and BY expr must be compatible"); return; } } if (! flag_local_loop_counter) { /* In this case, it's a previously-declared VAR_DECL node. */ tree id_node = ip->user_var; if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE) ip->user_var = lookup_name (ip->user_var); /* Chill 1984 allows the name to be a defining occurrence, but does not require it. */ if (ip->user_var == NULL_TREE) { warning ("loop identifier undeclared"); ip->user_var = id_node; /* We declare a local name below. */ } else { if (TREE_CODE (TREE_TYPE (ip->user_var)) == REFERENCE_TYPE) ip->user_var = convert_from_reference (ip->user_var); if (! CH_COMPATIBLE_CLASSES (ip->start_exp, ip->user_var)) { error ("loop variable incompatible with start expression"); return; } class = chill_expr_class (ip->user_var); } } /* Otherwise, declare a new name. */ if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE) { class = CH_RESULTING_CLASS (chill_expr_class (ip->start_exp), chill_expr_class (ip->end_exp)); if (step_exp) class = CH_RESULTING_CLASS (class, chill_expr_class (step_exp)); /* Integer literals noramally have type 'long long' (see convert_integer in lex.c). That is usually overkill. */ if (class.kind == CH_DERIVED_CLASS && class.mode == long_long_integer_type_node && int_fits_type_p (ip->start_exp, integer_type_node) && int_fits_type_p (ip->end_exp, integer_type_node)) class.mode = integer_type_node; } 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_to_class (class, ip->start_exp); ip->end_exp = convert_to_class (class, ip->end_exp); ip->step_exp = convert_to_class (class, 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->error_flag = 0; /* no errors! */}voidbuild_loop_start (start_label) tree start_label;{ ITERATOR *firstp = loopstack->iter_list; if (firstp->error_flag) return; maybe_skip_loop (); if (initialize_iter_var ()) return; /* use the label as an 'exit' label, 'goto' needs another sort of label */ expand_start_loop (start_label != NULL_TREE);}/* * Called after the last action of the loop body * has been parsed. */voidbuild_loop_end (){ ITERATOR *ip = loopstack->iter_list; emit_line_note (input_filename, lineno); if (ip->error_flag) return; if (bottom_loop_end_check ()) return; if (increment_temps ()) return; 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; } }}/* * Reserve space for any loop-control temporaries, initialize them */static intdeclare_temps (){ ITERATOR *firstp = loopstack->iter_list, *ip; tree start_ptr; for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: break; case DO_STEP: ip->iter_type = type_for_size (TYPE_PRECISION (TREE_TYPE (ip->start_exp)), 1); /* create, initialize temporaries if expressions aren't constant */ ip->start_temp = maybe_make_for_temp (ip->start_exp, "for_start", TREE_TYPE (ip->start_exp)); ip->end_temp = maybe_make_for_temp (ip->end_exp, "for_end", TREE_TYPE (ip->end_exp)); /* this is just the step-expression */ ip->step_temp = maybe_make_for_temp (ip->step_exp, "for_step", TREE_TYPE (ip->step_exp)); if (TREE_CODE (ip->user_var) == IDENTIFIER_NODE) { /* (re-)declare the user's iteration variable in the loop's scope. */ tree id_node = ip->user_var; ip->user_var = decl_temp1 (id_node, TREE_TYPE (ip->start_exp), 0, NULL_TREE, 0, 0); CH_DERIVED_FLAG (ip->user_var) = CH_DERIVED_FLAG (ip->start_exp); pushdecl (ip->user_var); } ip->iter_var = decl_temp1 (get_unique_identifier ("iter_var"), ip->iter_type, 0, NULL_TREE, 0, 0); break; case DO_POWERSET: /* the user's powerset-expression */ ip->powerset_temp = save_expr (ip->start_exp); mark_addressable (ip->powerset_temp); ip->iter_type = integer_type_node; ip->iter_var = decl_temp1 (get_unique_identifier ("iter_var"), ip->iter_type, 0, !ip->down_flag ? integer_zero_node : powersetlen (ip->powerset_temp), 0, 0); 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, TYPE_DOMAIN (TREE_TYPE (ip->start_exp)), 0, NULL_TREE, 0, 0); pushdecl (ip->user_var); } else { /* in this case, it's a previously-declared VAR_DECL node */ ip->user_var = lookup_name (ip->user_var); } 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; /* 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, build1 (INDIRECT_REF, ip->base_type, ip->loc_ptr_temp)); /* FIXME: see stor_layout */ ip->step_temp = size_in_bytes (ip->base_type); temp = TYPE_DOMAIN (array_type); /* pointer to first array entry to look at */ start_ptr = build1 (ADDR_EXPR, ptr_type, ip->start_exp); mark_addressable (ip->start_exp); ip->start_temp = ip->down_flag ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -