📄 loop.c
字号:
fold (build (PLUS_EXPR, ptr_type, start_ptr, fold (build (MULT_EXPR, integer_type_node, ip->step_temp, fold (build (MINUS_EXPR, integer_type_node, TYPE_MAX_VALUE (temp), TYPE_MIN_VALUE (temp))))))) : start_ptr; } else { tree array_length = convert (integer_type_node, build_component_ref (ip->start_exp, var_length_id)); tree array_type = TREE_TYPE (TREE_CHAIN ( TYPE_FIELDS (TREE_TYPE (ip->start_exp)))); tree array_data_ptr = build_component_ref (ip->start_exp, var_data_id); tree ptr_type; if (TREE_CODE (TREE_TYPE (array_type)) == BOOLEAN_TYPE) { error ("Can't iterate through array of BOOL"); firstp->error_flag = 1; return firstp->error_flag; } /* 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_temp", 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); /* pointer to first array entry to look at */ start_ptr = build1 (ADDR_EXPR, ptr_type, array_data_ptr); mark_addressable (array_data_ptr); ip->start_temp = ip->down_flag ? fold (build (PLUS_EXPR, ptr_type, start_ptr, fold (build (MULT_EXPR, integer_type_node, ip->step_temp, fold (build (MINUS_EXPR, integer_type_node, array_length, integer_one_node)))))) : start_ptr; } default: ; } } return firstp->error_flag;}/* * Initialize the hidden iteration-control variables, * and the user's explicit loop variable. */static intinitialize_iter_var (){ ITERATOR *firstp = loopstack->iter_list, *ip; for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { tree array_type, array_length; case DO_FOREVER: break; case DO_STEP: { tree count; count = build (MINUS_EXPR, ip->iter_type, convert (ip->iter_type, ip->down_flag ? ip->start_temp : ip->end_temp), convert (ip->iter_type, ip->down_flag ? ip->end_temp : ip->start_temp)); count = fold (build (TRUNC_DIV_EXPR, ip->iter_type, fold (count), ip->step_temp)); /* The count in this case is actually one less than the number of iterations, to avoid overflow problems if we iterate *all* the values of iter_type. */ /* initialize the loop's hidden counter variable */ expand_expr_stmt ( build_chill_modify_expr (ip->iter_var, count)); /* initialize user's variable */ expand_expr_stmt ( build_chill_modify_expr (ip->user_var, ip->start_temp)); } break; case DO_POWERSET: break; case DO_LOC: array_type = TREE_TYPE (ip->start_exp); array_length = fold (build (TRUNC_DIV_EXPR, integer_type_node, size_in_bytes (array_type), size_in_bytes (TREE_TYPE (array_type)))); goto do_loc_common; case DO_LOC_VARYING: array_length = convert (integer_type_node, build_component_ref (ip->start_exp, var_length_id)); do_loc_common: expand_expr_stmt (build_chill_modify_expr (ip->iter_var, array_length)); expand_expr_stmt ( build_chill_modify_expr (ip->loc_ptr_temp, ip->start_temp)); break; default: ; } } return firstp->error_flag;}/* Generate code to skip the whole loop, if start expression not * <= end expression (or >= for DOWN loops). This comparison must * *NOT* be done in unsigned mode, or it will fail. * Also, skip processing an empty VARYING array. */static voidmaybe_skip_loop (){ ITERATOR *firstp = loopstack->iter_list, *ip; for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_STEP: expand_start_cond ( build_compare_discrete_expr (ip->down_flag ? GE_EXPR : LE_EXPR, ip->start_temp, ip->end_temp), 0); break; case DO_LOC_VARYING: { tree array_length = convert (integer_type_node, build_component_ref (ip->start_exp, var_length_id)); expand_start_cond ( build (NE_EXPR, TREE_TYPE (array_length), array_length, integer_zero_node), 0); break; } default: break; } }} /* * Check at the top of the loop for a termination */voidtop_loop_end_check (condition) tree condition;{ ITERATOR *ip; for (ip = loopstack->iter_list; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: case DO_STEP: break; case DO_POWERSET: { tree temp1; char *func_name; tree user_type = TREE_TYPE (ip->user_var); if (ip->down_flag) func_name = "__flsetclrpowerset"; else func_name = "__ffsetclrpowerset"; temp1 = lookup_name (get_identifier (func_name)); if (ip->down_flag) temp1 = build_chill_function_call (temp1, tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp), tree_cons (NULL_TREE, ip->iter_var, tree_cons (NULL_TREE, integer_zero_node, NULL_TREE)))); else temp1 = build_chill_function_call (temp1, tree_cons (NULL_TREE, force_addr_of (ip->powerset_temp), tree_cons (NULL_TREE, powersetlen (ip->powerset_temp), tree_cons (NULL_TREE, ip->iter_var, NULL_TREE)))); expand_assignment (ip->iter_var, temp1, 0, 0); expand_exit_loop_if_false (0, build (GE_EXPR, boolean_type_node, ip->iter_var, integer_zero_node)); temp1 = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (ip->powerset_temp))); expand_assignment (ip->user_var, build (PLUS_EXPR, user_type, convert (user_type, ip->iter_var), convert (user_type, temp1)), 0, 0); } break; case DO_LOC: case DO_LOC_VARYING: break; default: ; } } emit_line_note (input_filename, lineno); /* now, exit the loop if the condition isn't TRUE. */ if (condition) expand_exit_loop_if_false (0, truthvalue_conversion (condition));}/* * Check generated temporaries for loop's end */static intbottom_loop_end_check (){ ITERATOR *firstp = loopstack->iter_list, *ip; emit_line_note (input_filename, lineno); /* now, generate code to check each loop counter for termination */ for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: break; case DO_STEP: /* exit if it's zero */ expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node, ip->iter_var, integer_zero_node)); /* decrement iteration counter by one */ chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node); break; case DO_LOC: case DO_LOC_VARYING: /* decrement iteration counter by one */ chill_expand_assignment (ip->iter_var, MINUS_EXPR, integer_one_node); /* exit if it's zero */ expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node, ip->iter_var, integer_zero_node)); break; case DO_POWERSET: break; default: ; } } return firstp->error_flag;}/* * increment the loop-control variables. */static intincrement_temps (){ ITERATOR *firstp = loopstack->iter_list, *ip; for (ip = firstp; ip != NULL; ip = ip->next) { switch (ip->itype) { case DO_FOREVER: break; case DO_STEP: { tree delta = fold (build (ip->down_flag ? MINUS_EXPR : PLUS_EXPR, TREE_TYPE (ip->user_var), ip->user_var, ip->step_temp)); expand_expr_stmt ( build_chill_modify_expr (ip->user_var, delta)); } break; case DO_LOC: case DO_LOC_VARYING: /* This statement uses the C semantics, so that the pointer is actually incremented by the length of the object pointed to. */ { enum tree_code op = ip->down_flag ? MINUS_EXPR : PLUS_EXPR; tree el_type = TREE_TYPE (TREE_TYPE (ip->loc_ptr_temp)); chill_expand_assignment (ip->loc_ptr_temp, NOP_EXPR, build (op, TREE_TYPE (ip->loc_ptr_temp), ip->loc_ptr_temp, size_in_bytes (el_type))); } break; case DO_POWERSET: if (!ip->down_flag) expand_assignment (ip->iter_var, build (PLUS_EXPR, ip->iter_type, ip->iter_var, integer_one_node), 0, 0); break; default: ; } } return firstp->error_flag;}/* * Generate a (temporary) unique identifier_node of * the form "__tmp_%s_%d" */treeget_unique_identifier (lead) char *lead;{ char idbuf [256]; static int idcount = 0; sprintf (idbuf, "__tmp_%s_%d", lead ? lead : "", idcount++); return get_identifier (idbuf);}/* * build a temporary variable, given its NAME and TYPE. * The name will have a number appended to assure uniqueness. * return its DECL node. */static treebuild_temporary_variable (name, type) char *name; tree type;{ return decl_temp1 (get_unique_identifier (name), type, 0, NULL_TREE, 0, 0);}/* * If the given expression isn't a constant, build a temp for it * and evaluate the expression into the temp. Return the tree * representing either the original constant expression or the * temp which now contains the expression's value. */static treemaybe_make_for_temp (exp, temp_name, exp_type) tree exp; char *temp_name; tree exp_type;{ tree result = exp; if (exp != NULL_TREE) { /* if exp isn't constant, create a temporary for its value */ if (TREE_CONSTANT (exp)) { /* FIXME: assure that TREE_TYPE (result) == ip->exp_type */ result = convert (exp_type, exp); } else { /* build temp, assign the value */ result = decl_temp1 (get_unique_identifier (temp_name), exp_type, 0, exp, 0, 0); } } return result;}#if 0/* * Adapt the C unsigned_type function to CHILL - we need to * account for any CHILL-specific integer types here. So far, * the 16-bit integer type is the only one. */static treechill_unsigned_type (type) tree type;{ extern tree chill_unsigned_type_node; tree type1 = TYPE_MAIN_VARIANT (type); if (type1 == chill_integer_type_node) return chill_unsigned_type_node; else return unsigned_type (type);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -