类似的,第五个循环把 present_set 模式的 decl 与对应的 define_cpu_unit 模式的 decls 。这个处理与第四个循环所做的相似(参考 DEFINE_INSN_RESERVATION模式的概览 )。
process_decls (continued)
2992 /* Check presence set declarations and form presence sets. */
2993 for (i = 0; i < description ->decls_num; i++)
2994 {
2995 decl = description ->decls [i];
2996 if (decl->mode == dm_presence)
2997 {
2998 unit_set_el_t unit_set_el_list;
2999 pattern_set_el_t pattern_set_el_list;
3000
3001 unit_set_el_list
3002 = process_presence_absence_names
3003 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
3004 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3005 pattern_set_el_list
3006 = process_presence_absence_patterns
3007 (DECL_PRESENCE (decl)->patterns,
3008 DECL_PRESENCE (decl)->patterns_num,
3009 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3010 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3011 decl->pos, TRUE,
3012 DECL_PRESENCE (decl)->final_p);
3013 }
3014 }
然后第六个循环把 absent_set 模式的 decl 与 define_cpu_unit 模式的 decl 绑定起来。这个处理与上个循环的处理相似 ( 参见 DEFINE_INSN_RESERVATION 模式的概览 ) 。
process_decls (continued)
3016 /* Check absence set declarations and form absence sets. */
3017 for (i = 0; i < description ->decls_num; i++)
3018 {
3019 decl = description ->decls [i];
3020 if (decl->mode == dm_absence)
3021 {
3022 unit_set_el_t unit_set_el_list;
3023 pattern_set_el_t pattern_set_el_list;
3024
3025 unit_set_el_list
3026 = process_presence_absence_names
3027 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
3028 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3029 pattern_set_el_list
3030 = process_presence_absence_patterns
3031 (DECL_ABSENCE (decl)->patterns,
3032 DECL_ABSENCE (decl)->patterns_num,
3033 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3034 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3035 decl->pos, FALSE,
3036 DECL_ABSENCE (decl)->final_p);
3037 }
3038 }
3039 }
在 3023 行的 pattern_set_el_t 被 typedef 为以下 pattern_set_el 的指针类型 , 这个结构体将构成一个链表。因为这些模式的第二个操作数是一个列表 , 而其中的每个元素又是由空格分隔的功能单元列表 , 所以在 1056 行的 unit_decls 被声明为 unit_decl** 。
1051 struct pattern_set_el
1052 {
1053 /* The number of units in unit_decls. */
1054 int units_num;
1055 /* The units forming the pattern. */
1056 struct unit_decl **unit_decls;
1057 pattern_set_el_t next_pattern_set_el;
1058 };
在 读入 EXCLUSION_SET模式 一节,我们知道参数 names 是记录模式第一个操作数的数组,这里通过 process_presence_absence_names 从这个数组构建出一个 unit_set_el_t 链表,绑定了对应功能单元的 decl 。
2546 static unit_set_el_t
2547 process_presence_absence_names (char **names, int num,
2548 pos_t req_pos ATTRIBUTE_UNUSED,
2549 int presence_p, int final_p)
2550 {
2551 unit_set_el_t el_list;
2552 unit_set_el_t last_el;
2553 unit_set_el_t new_el;
2554 decl_t decl_in_table;
2555 int i;
2556
2557 el_list = NULL;
2558 last_el = NULL;
2559 for (i = 0; i < num; i++)
2560 {
2561 decl_in_table = find_decl (names [i]);
2562 if (decl_in_table == NULL)
2563 error ((presence_p
2564 ? (final_p
2565 ? "unit `%s' in final presence set is not declared"
2566 : "unit `%s' in presence set is not declared")
2567 : (final_p
2568 ? "unit `%s' in final absence set is not declared"
2569 : "unit `%s' in absence set is not declared")), names [i]);
2570 else if (decl_in_table->mode != dm_unit)
2571 error ((presence_p
2572 ? (final_p
2573 ? "`%s' in final presence set is not unit"
2574 : "`%s' in presence set is not unit")
2575 : (final_p
2576 ? "`%s' in final absence set is not unit"
2577 : "`%s' in absence set is not unit")), names [i]);
2578 else
2579 {
2580 new_el = create_node (sizeof (struct unit_set_el));
2581 new_el->unit_decl = DECL_UNIT (decl_in_table);
2582 new_el->next_unit_set_el = NULL;
2583 if (last_el == NULL)
2584 el_list = last_el = new_el;
2585 else
2586 {
2587 last_el->next_unit_set_el = new_el;
2588 last_el = last_el->next_unit_set_el;
2589 }
2590 }
2591 }
2592 return el_list;
2593 }
类似的,参数 patterns 则是记录模式第二个操作数的数组,这里面也只有代表模式名的字符串,需要通过 process_presence_absence_patterns 来绑定对应的功能单元的 decl 。
2598 static pattern_set_el_t
2599 process_presence_absence_patterns (char ***patterns, int num,
2600 pos_t req_pos ATTRIBUTE_UNUSED,
2601 int presence_p, int final_p)
2602 {
2603 pattern_set_el_t el_list;
2604 pattern_set_el_t last_el;
2605 pattern_set_el_t new_el;
2606 decl_t decl_in_table;
2607 int i, j;
2608
2609 el_list = NULL;
2610 last_el = NULL;
2611 for (i = 0; i < num; i++)
2612 {
2613 for (j = 0; patterns [i] [j] != NULL; j++)
2614 ;
2615 new_el = create_node (sizeof (struct pattern_set_el)
2616 + sizeof (struct unit_decl *) * j);
2617 new_el->unit_decls
2618 = (struct unit_decl **) ((char *) new_el
2619 + sizeof (struct pattern_set_el));
2620 new_el->next_pattern_set_el = NULL;
2621 if (last_el == NULL)
2622 el_list = last_el = new_el;
2623 else
2624 {
2625 last_el->next_pattern_set_el = new_el;
2626 last_el = last_el->next_pattern_set_el;
2627 }
2628 new_el->units_num = 0;
2629 for (j = 0; patterns [i] [j] != NULL; j++)
2630 {
2631 decl_in_table = find_decl (patterns [i] [j]);
2632 if (decl_in_table == NULL)
2633 error ((presence_p
2634 ? (final_p
2635 ? "unit `%s' in final presence set is not declared"
2636 : "unit `%s' in presence set is not declared")
2637 : (final_p
2638 ? "unit `%s' in final absence set is not declared"
2639 : "unit `%s' in absence set is not declared")),
2640 patterns [i] [j]);
2641 else if (decl_in_table->mode != dm_unit)
2642 error ((presence_p
2643 ? (final_p
2644 ? "`%s' in final presence set is not unit"
2645 : "`%s' in presence set is not unit")
2646 : (final_p
2647 ? "`%s' in final absence set is not unit"
2648 : "`%s' in absence set is not unit")),
2649 patterns [i] [j]);
2650 else
2651 {
2652 new_el->unit_decls [new_el->units_num]
2653 = DECL_UNIT (decl_in_table);
2654 new_el->units_num++;
2655 }
2656 }
2657 }
2658 return el_list;
2659 }
注意 pattern_set_el 结构体中 unit_decls 域所需的内存也在 2618 行一起分配了。因为每个这样的模式只是管中窥豹,要把这些局部视角组合起来,才能看到这个功能单元整体的约束情况。因此需要 add_presence_absence 来整合这些信息。
2669 static void
2670 add_presence_absence ( unit_set_el_t dest_list,
2671 pattern_set_el_t pattern_list,
2672 pos_t req_pos ATTRIBUTE_UNUSED,
2673 int presence_p, int final_p)
2674 {
2675 unit_set_el_t dst;
2676 pattern_set_el_t pat;
2677 struct unit_decl *unit;
2678 unit_set_el_t curr_excl_el;
2679 pattern_set_el_t curr_pat_el;
2680 pattern_set_el_t prev_el;
2681 pattern_set_el_t copy;
2682 int i;
2683 int no_error_flag;
2684
2685 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2686 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2687 {
2688 for (i = 0; i < pat->units_num; i++)
2689 {
2690 unit = pat->unit_decls [i];
2691 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2692 {
2693 error ("unit `%s' requires own absence", unit->name);
2694 continue ;
2695 }
2696 if (dst->unit_decl->automaton_name != NULL
2697 && unit->automaton_name != NULL
2698 && strcmp (dst->unit_decl->automaton_name,
2699 unit->automaton_name) != 0)
2700 {
2701 error ((presence_p
2702 ? (final_p
2703 ? "units `%s' and `%s' in final presence set belong to different automata"
2704 : "units `%s' and `%s' in presence set belong to different automata")
2705 : (final_p
2706 ? "units `%s' and `%s' in final absence set belong to different automata"
2707 : "units `%s' and `%s' in absence set belong to different automata")),
2708 unit->name, dst->unit_decl->name);
2709 continue ;
2710 }
2711 no_error_flag = 1;
2712 if (presence_p)
2713 for (curr_excl_el = dst->unit_decl->excl_list;
2714 curr_excl_el != NULL;
2715 curr_excl_el = curr_excl_el->next_unit_set_el)
2716 {
2717 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2718 {
2719 if (!w_flag )
2720 {
2721 error ("unit `%s' excludes and requires presence of `%s'",
2722 dst->unit_decl->name, unit->name);
2723 no_error_flag = 0;
2724 }
2725 else
2726 warning
2727 ("unit `%s' excludes and requires presence of `%s'",
2728 dst->unit_decl->name, unit->name);
2729 }
2730 }
2731 else if (pat->units_num == 1)
2732 for (curr_pat_el = dst->unit_decl->presence_list;
2733 curr_pat_el != NULL;
2734 curr_pat_el = curr_pat_el->next_pattern_set_el)
2735 if (curr_pat_el->units_num == 1
2736 && unit == curr_pat_el->unit_decls [0])
2737 {
2738 if (!w_flag )
2739 {
2740 error
2741 ("unit `%s' requires absence and presence of `%s'",
2742 dst->unit_decl->name, unit->name);
2743 no_error_flag = 0;
2744 }
2745 else
2746 warning
2747 ("unit `%s' requires absence and presence of `%s'",
2748 dst->unit_decl->name, unit->name);
2749 }
2750 if (no_error_flag)
2751 {
2752 for (prev_el = (presence_p
2753 ? (final_p
2754 ? dst->unit_decl->final_presence_list
2755 : dst->unit_decl->final_presence_list)
2756 : (final_p
2757 ? dst->unit_decl->final_absence_list
2758 : dst->unit_decl->absence_list));
2759 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2760 prev_el = prev_el->next_pattern_set_el)
2761 ;
2762 copy = copy_node (pat, sizeof (*pat));
2763 copy->next_pattern_set_el = NULL;
2764 if (prev_el == NULL)
2765 {
2766 if (presence_p)
2767 {
2768 if (final_p)
2769 dst->unit_decl->final_presence_list = copy;
2770 else
2771 dst->unit_decl->presence_list = copy;
2772 }
2773 else if (final_p)
2774 dst->unit_decl->final_absence_list = copy;
2775 else
2776 dst->unit_decl->absence_list = copy;
2777 }
2778 else
2779 prev_el->next_pattern_set_el = copy;
2780 }
2781 }
2782 }
2783 }
看到在 2713 行的“ dst->unit_decl->excl_list ”是在上一节准备的。注意上面 presence 及 absence 约束之间的矛盾,只要不会导致致命的错误,是不加处理的,因为由此生成的自动机是可以识别及避开这些矛盾的。
注意到所有的 decl 仍旧保留在 decls 数组中。上述的循环只是把相关的 decl 绑定在一起。之后 check_automaton_usage 检查是否有未被使用的自动机——即没有绑定 CPU 单元(参考 处理 decl的第二个循环 – DECL_UNIT , 2875 行)。
3044 static void
3045 check_automaton_usage (void) in genautomata.c
3046 {
3047 decl_t decl;
3048 int i;
3049
3050 for (i = 0; i < description ->decls_num; i++)
3051 {
3052 decl = description ->decls [i];
3053 if (decl->mode == dm_automaton
3054 && !DECL_AUTOMATON (decl)->automaton_is_used)
3055 {
3056 if (!w_flag )
3057 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
3058 else
3059 warning ("automaton `%s' is not used",
3060 DECL_AUTOMATON (decl)->name);
3061 }
3062 }
3063 }
我们已经看过, define_insn_reservation 的 decl 的 regexp 部分描述了在 CPU 周期中,指令所使用的 CPU 单元。 process_regexp_decls 把所有感兴趣的单元的 decl 放入哈希表 decl_table 中,并在 define_reservation 及 define_insn_reserv 里绑定对应单元的 decl 。
3125 static void
3126 process_regexp_decls (void) in genautomata.c
3127 {
3128 decl_t decl;
3129 int i;
3130
3131 for (i = 0; i < description ->decls_num; i++)
3132 {
3133 decl = description ->decls [i];
3134 if (decl->mode == dm_reserv)
3135 DECL_RESERV (decl)->regexp
3136 = process_regexp (DECL_RESERV (decl)->regexp);
3137 else if (decl->mode == dm_insn_reserv)
3138 DECL_INSN_RESERV (decl)->regexp
3139 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3140 }
3141 }
regexp 部分的生成参考 读入 DEFINE_RESERVATION模式 一节。在机器描述文件里,模式 DEFINE_RESERVATION ,在使用处,与普通的单元无二无别,在构建入 regexp 时,它将给定为 rm_unit 类型。不过,对应单元的 decl 可以明白告知,因此在 3088 行要进行检查,并更新之。
3070 static regexp_t
3071 process_regexp (regexp_t regexp) in genautomata.c
3072 {
3073 decl_t decl_in_table;
3074 regexp_t new_regexp;
3075 int i;
3076
3077 if (regexp->mode == rm_unit)
3078 {
3079 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
3080 if (decl_in_table == NULL)
3081 error ("undeclared unit or reservation `%s'",
3082 REGEXP_UNIT (regexp)->name);
3083 else if (decl_in_table->mode == dm_unit)
3084 {
3085 DECL_UNIT (decl_in_table)->unit_is_used = 1;
3086 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
3087 }
3088 else if (decl_in_table->mode == dm_reserv)
3089 {
3090 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
3091 new_regexp = create_node (sizeof (struct regexp));
3092 new_regexp->mode = rm_reserv;
3093 new_regexp->pos = regexp->pos;
3094 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
3095 REGEXP_RESERV (new_regexp)->reserv_decl
3096 = DECL_RESERV (decl_in_table);
3097 regexp = new_regexp;
3098 }
3099 else
3100 abort ();
3101 }
3102 else if (regexp->mode == rm_sequence)
3103 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3104 REGEXP_SEQUENCE (regexp)->regexps [i]
3105 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
3106 else if (regexp->mode == rm_allof)
3107 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3108 REGEXP_ALLOF (regexp)->regexps [i]
3109 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
3110 else if (regexp->mode == rm_oneof)
3111 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3112 REGEXP_ONEOF (regexp)->regexps [i]
3113 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
3114 else if (regexp->mode == rm_repeat)
3115 REGEXP_REPEAT (regexp)->regexp
3116 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
3117 else if (regexp->mode != rm_nothing)
3118 abort ();
3119 return regexp;
3120 }
最后,我们可以得到以下的数据结构。
图 70 : DEFINE_INSN_RESERVATION 模式的 decl 的例子
接下来, check_usage 检查是否存在未被引用的 CPU 单元。
3147 static void
3148 check_usage (void) in genautomata.c
3149 {
3150 decl_t decl;
3151 int i;
3152
3153 for (i = 0; i < description ->decls_num; i++)
3154 {
3155 decl = description ->decls [i];
3156 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3157 {
3158 if (!w_flag )
3159 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3160 else
3161 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3162 }
3163 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3164 {
3165 if (!w_flag )
3166 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3167 else
3168 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3169 }
3170 }
3171 }
引入 define_reservation 带来了在这类模式中循环引用的危险性。这种错误是致命的,因此我们需要在这里检查这个情况。
3239 static void
3240 check_loops_in_regexps (void) in genautomata.c
3241 {
3242 decl_t decl;
3243 int i;
3244
3245 for (i = 0; i < description ->decls_num; i++)
3246 {
3247 decl = description ->decls [i];
3248 if (decl->mode == dm_reserv)
3249 DECL_RESERV (decl)->loop_pass_num = 0;
3250 }
3251 for (i = 0; i < description ->decls_num; i++)
3252 {
3253 decl = description ->decls [i];
3254 curr_loop_pass_num = i;
3255
3256 if (decl->mode == dm_reserv)
3257 {
3258 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num ;
3259 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3260 {
3261 if (DECL_RESERV (decl)->regexp == NULL)
3262 abort ();
3263 error ("cycle in definition of reservation `%s'",
3264 DECL_RESERV (decl)->name);
3265 }
3266 }
3267 }
3268 }
在 process_regexp 里, define_reservation 仅展开一次。如果存在 define_reservation 模式 A 及 B ,它们相互引用。由 process_regexp ,我们将得到如下的展开形式( à 表示引用, ßß 表示展开到所引用部分):
a à A à B ßß A (decl_reserv)
b à B à A ßß B (decl_reserv)
这是我们必须要防止的情形。在 check_loops_in_regexps 里,首先把所有 define_reservation 模式的 loop_pass_num 重置为 0 。在 3251 行的 FOR 循环里,相互引用的 define_reservation 模式必有一个首先得到处理,此时它所引用的 define_reservation 模式的 loop_pass_num 仍然为 0 ,将进入 3198 行的 ELSE 块,对这个模式进行处理。因为 start_decl 总是第一个模式, 3191 行条件满足,查出了循环引用。而 3194 行的条件则是允许对 define_reservation 模式的多次非循环的引用。
3180 static int
3181 loop_in_regexp (regexp_t regexp, decl_t start_decl) in genautomata.c
3182 {
3183 int i;
3184
3185 if (regexp == NULL)
3186 return 0;
3187 if (regexp->mode == rm_unit)
3188 return 0;
3189 else if (regexp->mode == rm_reserv)
3190 {
3191 if (start_decl->mode == dm_reserv
3192 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3193 return 1;
3194 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3195 == curr_loop_pass_num )
3196 /* declaration has been processed. */
3197 return 0;
3198 else
3199 {
3200 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3201 = curr_loop_pass_num ;
3202 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3203 start_decl);
3204 }
3205 }
3206 else if (regexp->mode == rm_sequence)
3207 {
3208 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3209 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3210 return 1;
3211 return 0;
3212 }
3213 else if (regexp->mode == rm_allof)
3214 {
3215 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3216 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3217 return 1;
3218 return 0;
3219 }
3220 else if (regexp->mode == rm_oneof)
3221 {
3222 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3223 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3224 return 1;
3225 return 0;
3226 }
3227 else if (regexp->mode == rm_repeat)
3228 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3229 else
3230 {
3231 if (regexp->mode != rm_nothing)
3232 abort ();
3233 return 0;
3234 }
3235 }
接着,在 check_all_description 中, evaluate_max_reserv_cycles 被调用,其中的全局变量 description 将记录在 define_insn_reservation 模式中出现的最大周期数。
3362 static void
3363 evaluate_max_reserv_cycles (void) in genautomata.c
3364 {
3365 int max_insn_cycles_num;
3366 int min_insn_cycles_num;
3367 decl_t decl;
3368 int i;
3369
3370 description ->max_insn_reserv_cycles = 0;
3371 for (i = 0; i < description ->decls_num; i++)
3372 {
3373 decl = description ->decls [i];
3374 if (decl->mode == dm_insn_reserv)
3375 {
3376 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3377 &max_insn_cycles_num, &min_insn_cycles_num);
3378 if (description ->max_insn_reserv_cycles < max_insn_cycles_num)
3379 description ->max_insn_reserv_cycles = max_insn_cycles_num;
3380 }
3381 }
3382 description ->max_insn_reserv_cycles++;
3383 }
我们需要最大及最小周期数,因为在下面,将构建一个位图并与每个状态关联来显示资源的分配(使用)。这个位图的大小由功能单元数乘以(最大周期数 - 最小周期数)来确定。
process_regexp_cycles 递归进入 regexp ,并相应地设置 unit_decl 的 max_occ_cycle_num 及 min_occ_cycle_num 域。
3272 static void
3273 process_regexp_cycles (regexp_t regexp, int max_start_cycle, in genautomata.c
3274 int min_start_cycle, int *max_finish_cycle,
3275 int *min_finish_cycle)
3276 {
3277 int i;
3278
3279 if (regexp->mode == rm_unit)
3280 {
3281 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
3282 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
3283 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
3284 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
3285 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
3286 *max_finish_cycle = max_start_cycle;
3287 *min_finish_cycle = min_start_cycle;
3288 }
3289 else if (regexp->mode == rm_reserv)
3290 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3291 max_start_cycle, min_start_cycle,
3292 max_finish_cycle, min_finish_cycle);
3293 else if (regexp->mode == rm_repeat)
3294 {
3295 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3296 {
3297 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3298 max_start_cycle, min_start_cycle,
3299 max_finish_cycle, min_finish_cycle);
3300 max_start_cycle = *max_finish_cycle + 1;
3301 min_start_cycle = *min_finish_cycle + 1;
3302 }
3303 }
3304 else if (regexp->mode == rm_sequence)
3305 {
3306 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3307 {
3308 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3309 max_start_cycle, min_start_cycle,
3310 max_finish_cycle, min_finish_cycle);
3311 max_start_cycle = *max_finish_cycle + 1;
3312 min_start_cycle = *min_finish_cycle + 1;
3313 }
3314 }
3315 else if (regexp->mode == rm_allof)
3316 {
3317 int max_cycle = 0;
3318 int min_cycle = 0;
3319
3320 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3321 {
3322 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3323 max_start_cycle, min_start_cycle,
3324 max_finish_cycle, min_finish_cycle);
3325 if (max_cycle < *max_finish_cycle)
3326 max_cycle = *max_finish_cycle;
3327 if (i == 0 || min_cycle > *min_finish_cycle)
3328 min_cycle = *min_finish_cycle;
3329 }
3330 *max_finish_cycle = max_cycle;
3331 *min_finish_cycle = min_cycle;
3332 }
3333 else if (regexp->mode == rm_oneof)
3334 {
3335 int max_cycle = 0;
3336 int min_cycle = 0;
3337
3338 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3339 {
3340 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3341 max_start_cycle, min_start_cycle,
3342 max_finish_cycle, min_finish_cycle);
3343 if (max_cycle < *max_finish_cycle)
3344 max_cycle = *max_finish_cycle;
3345 if (i == 0 || min_cycle > *min_finish_cycle)
3346 min_cycle = *min_finish_cycle;
3347 }
3348 *max_finish_cycle = max_cycle;
3349 *min_finish_cycle = min_cycle;
3350 }
3351 else
3352 {
3353 if (regexp->mode != rm_nothing)
3354 abort ();
3355 *max_finish_cycle = max_start_cycle;
3356 *min_finish_cycle = min_start_cycle;
3357 }
3358 }