#include "bconfig.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "obstack.h"
#include "errors.h"
#include "gensupport.h"
#include <math.h>
#include "hashtab.h"
#include "vec.h"
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
typedef int pos_t;
typedef unsigned HOST_WIDE_INT set_el_t;
typedef set_el_t *reserv_sets_t;
struct ticker
{
int modified_creation_time;
int incremented_off_time;
};
typedef struct ticker ticker_t;
typedef HOST_WIDE_INT vect_el_t;
struct unit_decl;
struct bypass_decl;
struct result_decl;
struct automaton_decl;
struct unit_pattern_rel_decl;
struct reserv_decl;
struct insn_reserv_decl;
struct decl;
struct unit_regexp;
struct result_regexp;
struct reserv_regexp;
struct nothing_regexp;
struct sequence_regexp;
struct repeat_regexp;
struct allof_regexp;
struct oneof_regexp;
struct regexp;
struct description;
struct unit_set_el;
struct pattern_set_el;
struct pattern_reserv;
struct state;
struct alt_state;
struct arc;
struct ainsn;
struct automaton;
struct state_ainsn_table;
typedef struct unit_decl *unit_decl_t;
typedef struct decl *decl_t;
typedef struct regexp *regexp_t;
typedef struct unit_set_el *unit_set_el_t;
typedef struct pattern_set_el *pattern_set_el_t;
typedef struct pattern_reserv *pattern_reserv_t;
typedef struct alt_state *alt_state_t;
typedef struct state *state_t;
typedef struct arc *arc_t;
typedef struct ainsn *ainsn_t;
typedef struct automaton *automaton_t;
typedef struct automata_list_el *automata_list_el_t;
typedef struct state_ainsn_table *state_ainsn_table_t;
static pos_t no_pos = 0;
static struct obstack irp;
DEF_VEC_P(alt_state_t);
DEF_VEC_ALLOC_P(alt_state_t,heap);
DEF_VEC_P(ainsn_t);
DEF_VEC_ALLOC_P(ainsn_t,heap);
DEF_VEC_P(state_t);
DEF_VEC_ALLOC_P(state_t,heap);
DEF_VEC_P(decl_t);
DEF_VEC_ALLOC_P(decl_t,heap);
DEF_VEC_P(reserv_sets_t);
DEF_VEC_ALLOC_P(reserv_sets_t,heap);
DEF_VEC_I(vect_el_t);
DEF_VEC_ALLOC_I(vect_el_t, heap);
typedef VEC(vect_el_t,heap) *vla_hwint_t;
static regexp_t gen_regexp_sequence (const char *);
static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
reserv_sets_t);
static reserv_sets_t get_excl_set (reserv_sets_t);
static int check_presence_pattern_sets (reserv_sets_t,
reserv_sets_t, int);
static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
int);
static arc_t first_out_arc (state_t);
static arc_t next_out_arc (arc_t);
#define NO_MINIMIZATION_OPTION "-no-minimization"
#define TIME_OPTION "-time"
#define V_OPTION "-v"
#define W_OPTION "-w"
#define NDFA_OPTION "-ndfa"
#define PROGRESS_OPTION "-progress"
static int ndfa_flag;
static int no_minimization_flag;
static int split_argument;
static int time_flag;
static int v_flag;
static int progress_flag;
static int w_flag;
static FILE *output_file;
static FILE *output_description_file;
static char *output_description_file_name;
static struct description *description;
enum decl_mode
{
dm_unit,
dm_bypass,
dm_automaton,
dm_excl,
dm_presence,
dm_absence,
dm_reserv,
dm_insn_reserv
};
struct unit_decl
{
const char *name;
const char *automaton_name;
char query_p;
char unit_is_used;
int unit_num;
struct automaton_decl *automaton_decl;
int max_occ_cycle_num;
int min_occ_cycle_num;
unit_set_el_t excl_list;
pattern_set_el_t presence_list;
pattern_set_el_t final_presence_list;
pattern_set_el_t absence_list;
pattern_set_el_t final_absence_list;
int query_num;
int last_distribution_check_cycle;
int corresponding_automaton_num;
char in_set_p;
};
struct bypass_decl
{
int latency;
const char *out_insn_name;
const char *in_insn_name;
const char *bypass_guard_name;
struct insn_reserv_decl *out_insn_reserv;
struct insn_reserv_decl *in_insn_reserv;
struct bypass_decl *next;
};
struct automaton_decl
{
const char *name;
char automaton_is_used;
automaton_t corresponding_automaton;
};
struct excl_rel_decl
{
int all_names_num;
int first_list_length;
char *names [1];
};
struct unit_pattern_rel_decl
{
int final_p;
int names_num;
int patterns_num;
char **names;
char ***patterns;
};
struct reserv_decl
{
const char *name;
regexp_t regexp;
char reserv_is_used;
int loop_pass_num;
};
struct insn_reserv_decl
{
rtx condexp;
int default_latency;
regexp_t regexp;
const char *name;
int insn_num;
struct bypass_decl *bypass_list;
regexp_t transformed_regexp;
arc_t arcs_marked_by_insn;
int equiv_class_num;
automata_list_el_t important_automata_list;
int processed_p;
};
struct decl
{
enum decl_mode mode;
pos_t pos;
union
{
struct unit_decl unit;
struct bypass_decl bypass;
struct automaton_decl automaton;
struct excl_rel_decl excl;
struct unit_pattern_rel_decl presence;
struct unit_pattern_rel_decl absence;
struct reserv_decl reserv;
struct insn_reserv_decl insn_reserv;
} decl;
};
enum regexp_mode
{
rm_unit,
rm_reserv,
rm_nothing,
rm_sequence,
rm_repeat,
rm_allof,
rm_oneof
};
struct unit_regexp
{
const char *name;
unit_decl_t unit_decl;
};
struct reserv_regexp
{
const char *name;
struct reserv_decl *reserv_decl;
};
struct nothing_regexp
{
char unused;
};
struct sequence_regexp
{
int regexps_num;
regexp_t regexps [1];
};
struct repeat_regexp
{
int repeat_num;
regexp_t regexp;
};
struct allof_regexp
{
int regexps_num;
regexp_t regexps [1];
};
struct oneof_regexp
{
int regexps_num;
regexp_t regexps [1];
};
struct regexp
{
enum regexp_mode mode;
pos_t pos;
union
{
struct unit_regexp unit;
struct reserv_regexp reserv;
struct nothing_regexp nothing;
struct sequence_regexp sequence;
struct repeat_regexp repeat;
struct allof_regexp allof;
struct oneof_regexp oneof;
} regexp;
};
struct description
{
int decls_num;
int units_num;
int query_units_num;
int insns_num;
int max_insn_reserv_cycles;
automaton_t first_automaton;
decl_t decls [1];
};
struct unit_set_el
{
unit_decl_t unit_decl;
unit_set_el_t next_unit_set_el;
};
struct pattern_set_el
{
int units_num;
struct unit_decl **unit_decls;
pattern_set_el_t next_pattern_set_el;
};
struct pattern_reserv
{
reserv_sets_t reserv;
pattern_reserv_t next_pattern_reserv;
};
struct state
{
int new_cycle_p;
reserv_sets_t reservs;
int unique_num;
automaton_t automaton;
arc_t first_out_arc;
unsigned int num_out_arcs;
char it_was_placed_in_stack_for_NDFA_forming;
char it_was_placed_in_stack_for_DFA_forming;
alt_state_t component_states;
int pass_num;
state_t next_equiv_class_state;
int equiv_class_num_1, equiv_class_num_2;
state_t equiv_class_state;
unsigned int *presence_signature;
int order_state_num;
int state_pass_num;
int min_insn_issue_delay;
int longest_path_length;
};
#define UNDEFINED_LONGEST_PATH_LENGTH -1
struct arc
{
state_t to_state;
ainsn_t insn;
arc_t next_out_arc;
arc_t next_arc_marked_by_insn;
};
struct alt_state
{
state_t state;
alt_state_t next_alt_state;
alt_state_t next_sorted_alt_state;
};
struct ainsn
{
struct insn_reserv_decl *insn_reserv_decl;
ainsn_t next_ainsn;
alt_state_t alt_states;
alt_state_t sorted_alt_states;
ainsn_t next_same_reservs_insn;
char first_insn_with_same_reservs;
char arc_exists_p;
ainsn_t next_equiv_class_insn;
char first_ainsn_with_given_equivalence_num;
int insn_equiv_class_num;
int important_p;
};
struct automaton
{
ainsn_t ainsn_list;
struct automaton_decl *corresponding_automaton_decl;
automaton_t next_automaton;
state_t start_state;
int insn_equiv_classes_num;
int achieved_states_num;
int automaton_order_num;
int NDFA_states_num, DFA_states_num;
int minimal_DFA_states_num;
int NDFA_arcs_num, DFA_arcs_num;
int minimal_DFA_arcs_num;
state_ainsn_table_t trans_table;
int max_min_delay;
int min_issue_delay_table_compression_factor;
int locked_states;
};
struct automata_list_el
{
automaton_t automaton;
automata_list_el_t next_automata_list_el;
};
struct state_ainsn_table
{
automaton_t automaton;
vla_hwint_t comb_vect;
vla_hwint_t check_vect;
vla_hwint_t base_vect;
vla_hwint_t full_vect;
int min_comb_vect_el_value, max_comb_vect_el_value;
int min_base_vect_el_value, max_base_vect_el_value;
};
#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
#define DECL_UNIT(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_unit) \
decl_mode_check_failed (_decl->mode, "dm_unit", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.unit; }))
#define DECL_BYPASS(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_bypass) \
decl_mode_check_failed (_decl->mode, "dm_bypass", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.bypass; }))
#define DECL_AUTOMATON(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_automaton) \
decl_mode_check_failed (_decl->mode, "dm_automaton", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.automaton; }))
#define DECL_EXCL(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_excl) \
decl_mode_check_failed (_decl->mode, "dm_excl", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.excl; }))
#define DECL_PRESENCE(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_presence) \
decl_mode_check_failed (_decl->mode, "dm_presence", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.presence; }))
#define DECL_ABSENCE(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_absence) \
decl_mode_check_failed (_decl->mode, "dm_absence", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.absence; }))
#define DECL_RESERV(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_reserv) \
decl_mode_check_failed (_decl->mode, "dm_reserv", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.reserv; }))
#define DECL_INSN_RESERV(d) __extension__ \
(({ struct decl *const _decl = (d); \
if (_decl->mode != dm_insn_reserv) \
decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
__FILE__, __LINE__, __FUNCTION__); \
&(_decl)->decl.insn_reserv; }))
static const char *decl_name (enum decl_mode);
static void decl_mode_check_failed (enum decl_mode, const char *,
const char *, int, const char *)
ATTRIBUTE_NORETURN;
static const char *
decl_name (enum decl_mode mode)
{
static char str [100];
if (mode == dm_unit)
return "dm_unit";
else if (mode == dm_bypass)
return "dm_bypass";
else if (mode == dm_automaton)
return "dm_automaton";
else if (mode == dm_excl)
return "dm_excl";
else if (mode == dm_presence)
return "dm_presence";
else if (mode == dm_absence)
return "dm_absence";
else if (mode == dm_reserv)
return "dm_reserv";
else if (mode == dm_insn_reserv)
return "dm_insn_reserv";
else
sprintf (str, "unknown (%d)", (int) mode);
return str;
}
static void
decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
const char *file, int line, const char *func)
{
fprintf
(stderr,
"\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
file, line, func, expected_mode_str, decl_name (mode));
exit (1);
}
#define REGEXP_UNIT(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_unit) \
regexp_mode_check_failed (_regexp->mode, "rm_unit", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.unit; }))
#define REGEXP_RESERV(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_reserv) \
regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.reserv; }))
#define REGEXP_SEQUENCE(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_sequence) \
regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.sequence; }))
#define REGEXP_REPEAT(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_repeat) \
regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.repeat; }))
#define REGEXP_ALLOF(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_allof) \
regexp_mode_check_failed (_regexp->mode, "rm_allof", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.allof; }))
#define REGEXP_ONEOF(r) __extension__ \
(({ struct regexp *const _regexp = (r); \
if (_regexp->mode != rm_oneof) \
regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
__FILE__, __LINE__, __FUNCTION__); \
&(_regexp)->regexp.oneof; }))
static const char *regexp_name (enum regexp_mode);
static void regexp_mode_check_failed (enum regexp_mode, const char *,
const char *, int,
const char *) ATTRIBUTE_NORETURN;
static const char *
regexp_name (enum regexp_mode mode)
{
switch (mode)
{
case rm_unit:
return "rm_unit";
case rm_reserv:
return "rm_reserv";
case rm_nothing:
return "rm_nothing";
case rm_sequence:
return "rm_sequence";
case rm_repeat:
return "rm_repeat";
case rm_allof:
return "rm_allof";
case rm_oneof:
return "rm_oneof";
default:
gcc_unreachable ();
}
}
static void
regexp_mode_check_failed (enum regexp_mode mode,
const char *expected_mode_str,
const char *file, int line, const char *func)
{
fprintf
(stderr,
"\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
file, line, func, expected_mode_str, regexp_name (mode));
exit (1);
}
#else
#define DECL_UNIT(d) (&(d)->decl.unit)
#define DECL_BYPASS(d) (&(d)->decl.bypass)
#define DECL_AUTOMATON(d) (&(d)->decl.automaton)
#define DECL_EXCL(d) (&(d)->decl.excl)
#define DECL_PRESENCE(d) (&(d)->decl.presence)
#define DECL_ABSENCE(d) (&(d)->decl.absence)
#define DECL_RESERV(d) (&(d)->decl.reserv)
#define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
#define REGEXP_UNIT(r) (&(r)->regexp.unit)
#define REGEXP_RESERV(r) (&(r)->regexp.reserv)
#define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
#define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
#define REGEXP_ALLOF(r) (&(r)->regexp.allof)
#define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
#endif
static void *
create_node (size_t size)
{
void *result;
obstack_blank (&irp, size);
result = obstack_base (&irp);
obstack_finish (&irp);
memset (result, 0, size);
return result;
}
static void *
copy_node (const void *from, size_t size)
{
void *const result = create_node (size);
memcpy (result, from, size);
return result;
}
static const char *
check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
{
const char *str;
for (str = name; *str != '\0'; str++)
if (*str == '\"')
error ("Name `%s' contains quotes", name);
return name;
}
static VEC(decl_t,heap) *decls;
static char *
next_sep_el (const char **pstr, int sep, int par_flag)
{
char *out_str;
const char *p;
int pars_num;
int n_spaces;
while (ISSPACE ((int) **pstr))
(*pstr)++;
if (**pstr == '\0')
return NULL;
n_spaces = 0;
for (pars_num = 0, p = *pstr; *p != '\0'; p++)
{
if (par_flag && *p == '(')
pars_num++;
else if (par_flag && *p == ')')
pars_num--;
else if (pars_num == 0 && *p == sep)
break;
if (pars_num == 0 && ISSPACE ((int) *p))
n_spaces++;
else
{
for (; n_spaces != 0; n_spaces--)
obstack_1grow (&irp, p [-n_spaces]);
obstack_1grow (&irp, *p);
}
}
obstack_1grow (&irp, '\0');
out_str = obstack_base (&irp);
obstack_finish (&irp);
*pstr = p;
if (**pstr == sep)
(*pstr)++;
return out_str;
}
static int
n_sep_els (const char *s, int sep, int par_flag)
{
int n;
int pars_num;
if (*s == '\0')
return 0;
for (pars_num = 0, n = 1; *s; s++)
if (par_flag && *s == '(')
pars_num++;
else if (par_flag && *s == ')')
pars_num--;
else if (pars_num == 0 && *s == sep)
n++;
return (pars_num != 0 ? -1 : n);
}
static char **
get_str_vect (const char *str, int *els_num, int sep, int paren_p)
{
int i;
char **vect;
const char **pstr;
char *trail;
*els_num = n_sep_els (str, sep, paren_p);
if (*els_num <= 0)
return NULL;
obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
vect = (char **) obstack_base (&irp);
obstack_finish (&irp);
pstr = &str;
for (i = 0; i < *els_num; i++)
vect [i] = next_sep_el (pstr, sep, paren_p);
trail = next_sep_el (pstr, sep, paren_p);
gcc_assert (!trail);
vect [i] = NULL;
return vect;
}
static void
gen_cpu_unit (rtx def)
{
decl_t decl;
char **str_cpu_units;
int vect_length;
int i;
str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
if (str_cpu_units == NULL)
fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
for (i = 0; i < vect_length; i++)
{
decl = create_node (sizeof (struct decl));
decl->mode = dm_unit;
decl->pos = 0;
DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
DECL_UNIT (decl)->query_p = 0;
DECL_UNIT (decl)->min_occ_cycle_num = -1;
DECL_UNIT (decl)->in_set_p = 0;
VEC_safe_push (decl_t,heap, decls, decl);
}
}
static void
gen_query_cpu_unit (rtx def)
{
decl_t decl;
char **str_cpu_units;
int vect_length;
int i;
str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
FALSE);
if (str_cpu_units == NULL)
fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
for (i = 0; i < vect_length; i++)
{
decl = create_node (sizeof (struct decl));
decl->mode = dm_unit;
decl->pos = 0;
DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
DECL_UNIT (decl)->query_p = 1;
VEC_safe_push (decl_t,heap, decls, decl);
}
}
static void
gen_bypass (rtx def)
{
decl_t decl;
char **out_insns;
int out_length;
char **in_insns;
int in_length;
int i, j;
out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
if (out_insns == NULL)
fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
if (in_insns == NULL)
fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
for (i = 0; i < out_length; i++)
for (j = 0; j < in_length; j++)
{
decl = create_node (sizeof (struct decl));
decl->mode = dm_bypass;
decl->pos = 0;
DECL_BYPASS (decl)->latency = XINT (def, 0);
DECL_BYPASS (decl)->out_insn_name = out_insns [i];
DECL_BYPASS (decl)->in_insn_name = in_insns [j];
DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
VEC_safe_push (decl_t,heap, decls, decl);
}
}
static void
gen_excl_set (rtx def)
{
decl_t decl;
char **first_str_cpu_units;
char **second_str_cpu_units;
int first_vect_length;
int length;
int i;
first_str_cpu_units
= get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
if (first_str_cpu_units == NULL)
fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
FALSE);
if (second_str_cpu_units == NULL)
fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
length += first_vect_length;
decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
decl->mode = dm_excl;
decl->pos = 0;
DECL_EXCL (decl)->all_names_num = length;
DECL_EXCL (decl)->first_list_length = first_vect_length;
for (i = 0; i < length; i++)
if (i < first_vect_length)
DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
else
DECL_EXCL (decl)->names [i]
= second_str_cpu_units [i - first_vect_length];
VEC_safe_push (decl_t,heap, decls, decl);
}
static void
gen_presence_absence_set (rtx def, int presence_p, int final_p)
{
decl_t decl;
char **str_cpu_units;
char **str_pattern_lists;
char ***str_patterns;
int cpu_units_length;
int length;
int patterns_length;
int i;
str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
FALSE);
if (str_cpu_units == NULL)
fatal ((presence_p
? (final_p
? "invalid first string `%s' in final_presence_set"
: "invalid first string `%s' in presence_set")
: (final_p
? "invalid first string `%s' in final_absence_set"
: "invalid first string `%s' in absence_set")),
XSTR (def, 0));
str_pattern_lists = get_str_vect (XSTR (def, 1),
&patterns_length, ',', FALSE);
if (str_pattern_lists == NULL)
fatal ((presence_p
? (final_p
? "invalid second string `%s' in final_presence_set"
: "invalid second string `%s' in presence_set")
: (final_p
? "invalid second string `%s' in final_absence_set"
: "invalid second string `%s' in absence_set")), XSTR (def, 1));
str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
for (i = 0; i < patterns_length; i++)
{
str_patterns [i] = get_str_vect (str_pattern_lists [i],
&length, ' ', FALSE);
gcc_assert (str_patterns [i]);
}
decl = create_node (sizeof (struct decl));
decl->pos = 0;
if (presence_p)
{
decl->mode = dm_presence;
DECL_PRESENCE (decl)->names_num = cpu_units_length;
DECL_PRESENCE (decl)->names = str_cpu_units;
DECL_PRESENCE (decl)->patterns = str_patterns;
DECL_PRESENCE (decl)->patterns_num = patterns_length;
DECL_PRESENCE (decl)->final_p = final_p;
}
else
{
decl->mode = dm_absence;
DECL_ABSENCE (decl)->names_num = cpu_units_length;
DECL_ABSENCE (decl)->names = str_cpu_units;
DECL_ABSENCE (decl)->patterns = str_patterns;
DECL_ABSENCE (decl)->patterns_num = patterns_length;
DECL_ABSENCE (decl)->final_p = final_p;
}
VEC_safe_push (decl_t,heap, decls, decl);
}
static void
gen_presence_set (rtx def)
{
gen_presence_absence_set (def, TRUE, FALSE);
}
static void
gen_final_presence_set (rtx def)
{
gen_presence_absence_set (def, TRUE, TRUE);
}
static void
gen_absence_set (rtx def)
{
gen_presence_absence_set (def, FALSE, FALSE);
}
static void
gen_final_absence_set (rtx def)
{
gen_presence_absence_set (def, FALSE, TRUE);
}
static void
gen_automaton (rtx def)
{
decl_t decl;
char **str_automata;
int vect_length;
int i;
str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
if (str_automata == NULL)
fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
for (i = 0; i < vect_length; i++)
{
decl = create_node (sizeof (struct decl));
decl->mode = dm_automaton;
decl->pos = 0;
DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
VEC_safe_push (decl_t,heap, decls, decl);
}
}
static void
gen_automata_option (rtx def)
{
if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
no_minimization_flag = 1;
else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
time_flag = 1;
else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
v_flag = 1;
else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
w_flag = 1;
else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
ndfa_flag = 1;
else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
progress_flag = 1;
else
fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
}
#define NOTHING_NAME "nothing"
static const char *reserv_str;
static regexp_t
gen_regexp_el (const char *str)
{
regexp_t regexp;
char *dstr;
int len;
if (*str == '(')
{
len = strlen (str);
if (str [len - 1] != ')')
fatal ("garbage after ) in reservation `%s'", reserv_str);
dstr = alloca (len - 1);
memcpy (dstr, str + 1, len - 2);
dstr [len-2] = '\0';
regexp = gen_regexp_sequence (dstr);
}
else if (strcmp (str, NOTHING_NAME) == 0)
{
regexp = create_node (sizeof (struct decl));
regexp->mode = rm_nothing;
}
else
{
regexp = create_node (sizeof (struct decl));
regexp->mode = rm_unit;
REGEXP_UNIT (regexp)->name = str;
}
return regexp;
}
static regexp_t
gen_regexp_repeat (const char *str)
{
regexp_t regexp;
regexp_t repeat;
char **repeat_vect;
int els_num;
int i;
repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
if (repeat_vect == NULL)
fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
if (els_num > 1)
{
regexp = gen_regexp_el (repeat_vect [0]);
for (i = 1; i < els_num; i++)
{
repeat = create_node (sizeof (struct regexp));
repeat->mode = rm_repeat;
REGEXP_REPEAT (repeat)->regexp = regexp;
REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
fatal ("repetition `%s' <= 1 in reservation `%s'",
str, reserv_str);
regexp = repeat;
}
return regexp;
}
else
return gen_regexp_el (str);
}
static regexp_t
gen_regexp_allof (const char *str)
{
regexp_t allof;
char **allof_vect;
int els_num;
int i;
allof_vect = get_str_vect (str, &els_num, '+', TRUE);
if (allof_vect == NULL)
fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
if (els_num > 1)
{
allof = create_node (sizeof (struct regexp)
+ sizeof (regexp_t) * (els_num - 1));
allof->mode = rm_allof;
REGEXP_ALLOF (allof)->regexps_num = els_num;
for (i = 0; i < els_num; i++)
REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
return allof;
}
else
return gen_regexp_repeat (str);
}
static regexp_t
gen_regexp_oneof (const char *str)
{
regexp_t oneof;
char **oneof_vect;
int els_num;
int i;
oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
if (oneof_vect == NULL)
fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
if (els_num > 1)
{
oneof = create_node (sizeof (struct regexp)
+ sizeof (regexp_t) * (els_num - 1));
oneof->mode = rm_oneof;
REGEXP_ONEOF (oneof)->regexps_num = els_num;
for (i = 0; i < els_num; i++)
REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
return oneof;
}
else
return gen_regexp_allof (str);
}
static regexp_t
gen_regexp_sequence (const char *str)
{
regexp_t sequence;
char **sequence_vect;
int els_num;
int i;
sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
if (els_num > 1)
{
sequence = create_node (sizeof (struct regexp)
+ sizeof (regexp_t) * (els_num - 1));
sequence->mode = rm_sequence;
REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
for (i = 0; i < els_num; i++)
REGEXP_SEQUENCE (sequence)->regexps [i]
= gen_regexp_oneof (sequence_vect [i]);
return sequence;
}
else
return gen_regexp_oneof (str);
}
static regexp_t
gen_regexp (const char *str)
{
reserv_str = str;
return gen_regexp_sequence (str);;
}
static void
gen_reserv (rtx def)
{
decl_t decl;
decl = create_node (sizeof (struct decl));
decl->mode = dm_reserv;
decl->pos = 0;
DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
VEC_safe_push (decl_t,heap, decls, decl);
}
static void
gen_insn_reserv (rtx def)
{
decl_t decl;
decl = create_node (sizeof (struct decl));
decl->mode = dm_insn_reserv;
decl->pos = 0;
DECL_INSN_RESERV (decl)->name
= check_name (XSTR (def, 0), decl->pos);
DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
VEC_safe_push (decl_t,heap, decls, decl);
}
static unsigned
string_hash (const char *string)
{
unsigned result, i;
for (result = i = 0;*string++ != '\0'; i++)
result += ((unsigned char) *string << (i % CHAR_BIT));
return result;
}
static hashval_t
automaton_decl_hash (const void *automaton_decl)
{
const decl_t decl = (decl_t) automaton_decl;
gcc_assert (decl->mode != dm_automaton
|| DECL_AUTOMATON (decl)->name);
return string_hash (DECL_AUTOMATON (decl)->name);
}
static int
automaton_decl_eq_p (const void* automaton_decl_1,
const void* automaton_decl_2)
{
const decl_t decl1 = (decl_t) automaton_decl_1;
const decl_t decl2 = (decl_t) automaton_decl_2;
gcc_assert (decl1->mode == dm_automaton
&& DECL_AUTOMATON (decl1)->name
&& decl2->mode == dm_automaton
&& DECL_AUTOMATON (decl2)->name);
return strcmp (DECL_AUTOMATON (decl1)->name,
DECL_AUTOMATON (decl2)->name) == 0;
}
static htab_t automaton_decl_table;
static decl_t
insert_automaton_decl (decl_t automaton_decl)
{
void **entry_ptr;
entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
if (*entry_ptr == NULL)
*entry_ptr = (void *) automaton_decl;
return (decl_t) *entry_ptr;
}
static struct decl work_automaton_decl;
static decl_t
find_automaton_decl (const char *name)
{
void *entry;
work_automaton_decl.mode = dm_automaton;
DECL_AUTOMATON (&work_automaton_decl)->name = name;
entry = htab_find (automaton_decl_table, &work_automaton_decl);
return (decl_t) entry;
}
static void
initiate_automaton_decl_table (void)
{
work_automaton_decl.mode = dm_automaton;
automaton_decl_table = htab_create (10, automaton_decl_hash,
automaton_decl_eq_p, (htab_del) 0);
}
static void
finish_automaton_decl_table (void)
{
htab_delete (automaton_decl_table);
}
static hashval_t
insn_decl_hash (const void *insn_decl)
{
const decl_t decl = (decl_t) insn_decl;
gcc_assert (decl->mode == dm_insn_reserv
&& DECL_INSN_RESERV (decl)->name);
return string_hash (DECL_INSN_RESERV (decl)->name);
}
static int
insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
{
const decl_t decl1 = (decl_t) insn_decl_1;
const decl_t decl2 = (decl_t) insn_decl_2;
gcc_assert (decl1->mode == dm_insn_reserv
&& DECL_INSN_RESERV (decl1)->name
&& decl2->mode == dm_insn_reserv
&& DECL_INSN_RESERV (decl2)->name);
return strcmp (DECL_INSN_RESERV (decl1)->name,
DECL_INSN_RESERV (decl2)->name) == 0;
}
static htab_t insn_decl_table;
static decl_t
insert_insn_decl (decl_t insn_decl)
{
void **entry_ptr;
entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
if (*entry_ptr == NULL)
*entry_ptr = (void *) insn_decl;
return (decl_t) *entry_ptr;
}
static struct decl work_insn_decl;
static decl_t
find_insn_decl (const char *name)
{
void *entry;
work_insn_decl.mode = dm_insn_reserv;
DECL_INSN_RESERV (&work_insn_decl)->name = name;
entry = htab_find (insn_decl_table, &work_insn_decl);
return (decl_t) entry;
}
static void
initiate_insn_decl_table (void)
{
work_insn_decl.mode = dm_insn_reserv;
insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
(htab_del) 0);
}
static void
finish_insn_decl_table (void)
{
htab_delete (insn_decl_table);
}
static hashval_t
decl_hash (const void *decl)
{
const decl_t d = (const decl_t) decl;
gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
|| (d->mode == dm_reserv && DECL_RESERV (d)->name));
return string_hash (d->mode == dm_unit
? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
}
static int
decl_eq_p (const void *decl_1, const void *decl_2)
{
const decl_t d1 = (const decl_t) decl_1;
const decl_t d2 = (const decl_t) decl_2;
gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
|| (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
|| (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
return strcmp ((d1->mode == dm_unit
? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
(d2->mode == dm_unit
? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
}
static htab_t decl_table;
static decl_t
insert_decl (decl_t decl)
{
void **entry_ptr;
entry_ptr = htab_find_slot (decl_table, decl, 1);
if (*entry_ptr == NULL)
*entry_ptr = (void *) decl;
return (decl_t) *entry_ptr;
}
static struct decl work_decl;
static decl_t
find_decl (const char *name)
{
void *entry;
work_decl.mode = dm_unit;
DECL_UNIT (&work_decl)->name = name;
entry = htab_find (decl_table, &work_decl);
return (decl_t) entry;
}
static void
initiate_decl_table (void)
{
work_decl.mode = dm_unit;
decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
}
static void
finish_decl_table (void)
{
htab_delete (decl_table);
}
static unit_set_el_t
process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
{
unit_set_el_t el_list;
unit_set_el_t last_el;
unit_set_el_t new_el;
decl_t decl_in_table;
int i;
el_list = NULL;
last_el = NULL;
for (i = 0; i < num; i++)
{
decl_in_table = find_decl (names [i]);
if (decl_in_table == NULL)
error ("unit `%s' in exclusion is not declared", names [i]);
else if (decl_in_table->mode != dm_unit)
error ("`%s' in exclusion is not unit", names [i]);
else
{
new_el = create_node (sizeof (struct unit_set_el));
new_el->unit_decl = DECL_UNIT (decl_in_table);
new_el->next_unit_set_el = NULL;
if (last_el == NULL)
el_list = last_el = new_el;
else
{
last_el->next_unit_set_el = new_el;
last_el = last_el->next_unit_set_el;
}
}
}
return el_list;
}
static void
add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
pos_t excl_pos ATTRIBUTE_UNUSED)
{
unit_set_el_t dst;
unit_set_el_t src;
unit_set_el_t curr_el;
unit_set_el_t prev_el;
unit_set_el_t copy;
for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
for (src = source_list; src != NULL; src = src->next_unit_set_el)
{
if (dst->unit_decl == src->unit_decl)
{
error ("unit `%s' excludes itself", src->unit_decl->name);
continue;
}
if (dst->unit_decl->automaton_name != NULL
&& src->unit_decl->automaton_name != NULL
&& strcmp (dst->unit_decl->automaton_name,
src->unit_decl->automaton_name) != 0)
{
error ("units `%s' and `%s' in exclusion set belong to different automata",
src->unit_decl->name, dst->unit_decl->name);
continue;
}
for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
curr_el != NULL;
prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
if (curr_el->unit_decl == src->unit_decl)
break;
if (curr_el == NULL)
{
copy = copy_node (src, sizeof (*src));
copy->next_unit_set_el = NULL;
if (prev_el == NULL)
dst->unit_decl->excl_list = copy;
else
prev_el->next_unit_set_el = copy;
}
}
}
static unit_set_el_t
process_presence_absence_names (char **names, int num,
pos_t req_pos ATTRIBUTE_UNUSED,
int presence_p, int final_p)
{
unit_set_el_t el_list;
unit_set_el_t last_el;
unit_set_el_t new_el;
decl_t decl_in_table;
int i;
el_list = NULL;
last_el = NULL;
for (i = 0; i < num; i++)
{
decl_in_table = find_decl (names [i]);
if (decl_in_table == NULL)
error ((presence_p
? (final_p
? "unit `%s' in final presence set is not declared"
: "unit `%s' in presence set is not declared")
: (final_p
? "unit `%s' in final absence set is not declared"
: "unit `%s' in absence set is not declared")), names [i]);
else if (decl_in_table->mode != dm_unit)
error ((presence_p
? (final_p
? "`%s' in final presence set is not unit"
: "`%s' in presence set is not unit")
: (final_p
? "`%s' in final absence set is not unit"
: "`%s' in absence set is not unit")), names [i]);
else
{
new_el = create_node (sizeof (struct unit_set_el));
new_el->unit_decl = DECL_UNIT (decl_in_table);
new_el->next_unit_set_el = NULL;
if (last_el == NULL)
el_list = last_el = new_el;
else
{
last_el->next_unit_set_el = new_el;
last_el = last_el->next_unit_set_el;
}
}
}
return el_list;
}
static pattern_set_el_t
process_presence_absence_patterns (char ***patterns, int num,
pos_t req_pos ATTRIBUTE_UNUSED,
int presence_p, int final_p)
{
pattern_set_el_t el_list;
pattern_set_el_t last_el;
pattern_set_el_t new_el;
decl_t decl_in_table;
int i, j;
el_list = NULL;
last_el = NULL;
for (i = 0; i < num; i++)
{
for (j = 0; patterns [i] [j] != NULL; j++)
;
new_el = create_node (sizeof (struct pattern_set_el)
+ sizeof (struct unit_decl *) * j);
new_el->unit_decls
= (struct unit_decl **) ((char *) new_el
+ sizeof (struct pattern_set_el));
new_el->next_pattern_set_el = NULL;
if (last_el == NULL)
el_list = last_el = new_el;
else
{
last_el->next_pattern_set_el = new_el;
last_el = last_el->next_pattern_set_el;
}
new_el->units_num = 0;
for (j = 0; patterns [i] [j] != NULL; j++)
{
decl_in_table = find_decl (patterns [i] [j]);
if (decl_in_table == NULL)
error ((presence_p
? (final_p
? "unit `%s' in final presence set is not declared"
: "unit `%s' in presence set is not declared")
: (final_p
? "unit `%s' in final absence set is not declared"
: "unit `%s' in absence set is not declared")),
patterns [i] [j]);
else if (decl_in_table->mode != dm_unit)
error ((presence_p
? (final_p
? "`%s' in final presence set is not unit"
: "`%s' in presence set is not unit")
: (final_p
? "`%s' in final absence set is not unit"
: "`%s' in absence set is not unit")),
patterns [i] [j]);
else
{
new_el->unit_decls [new_el->units_num]
= DECL_UNIT (decl_in_table);
new_el->units_num++;
}
}
}
return el_list;
}
static void
add_presence_absence (unit_set_el_t dest_list,
pattern_set_el_t pattern_list,
pos_t req_pos ATTRIBUTE_UNUSED,
int presence_p, int final_p)
{
unit_set_el_t dst;
pattern_set_el_t pat;
struct unit_decl *unit;
unit_set_el_t curr_excl_el;
pattern_set_el_t curr_pat_el;
pattern_set_el_t prev_el;
pattern_set_el_t copy;
int i;
int no_error_flag;
for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
{
for (i = 0; i < pat->units_num; i++)
{
unit = pat->unit_decls [i];
if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
{
error ("unit `%s' requires own absence", unit->name);
continue;
}
if (dst->unit_decl->automaton_name != NULL
&& unit->automaton_name != NULL
&& strcmp (dst->unit_decl->automaton_name,
unit->automaton_name) != 0)
{
error ((presence_p
? (final_p
? "units `%s' and `%s' in final presence set belong to different automata"
: "units `%s' and `%s' in presence set belong to different automata")
: (final_p
? "units `%s' and `%s' in final absence set belong to different automata"
: "units `%s' and `%s' in absence set belong to different automata")),
unit->name, dst->unit_decl->name);
continue;
}
no_error_flag = 1;
if (presence_p)
for (curr_excl_el = dst->unit_decl->excl_list;
curr_excl_el != NULL;
curr_excl_el = curr_excl_el->next_unit_set_el)
{
if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
{
if (!w_flag)
{
error ("unit `%s' excludes and requires presence of `%s'",
dst->unit_decl->name, unit->name);
no_error_flag = 0;
}
else
warning
(0, "unit `%s' excludes and requires presence of `%s'",
dst->unit_decl->name, unit->name);
}
}
else if (pat->units_num == 1)
for (curr_pat_el = dst->unit_decl->presence_list;
curr_pat_el != NULL;
curr_pat_el = curr_pat_el->next_pattern_set_el)
if (curr_pat_el->units_num == 1
&& unit == curr_pat_el->unit_decls [0])
{
if (!w_flag)
{
error
("unit `%s' requires absence and presence of `%s'",
dst->unit_decl->name, unit->name);
no_error_flag = 0;
}
else
warning
(0, "unit `%s' requires absence and presence of `%s'",
dst->unit_decl->name, unit->name);
}
if (no_error_flag)
{
for (prev_el = (presence_p
? (final_p
? dst->unit_decl->final_presence_list
: dst->unit_decl->final_presence_list)
: (final_p
? dst->unit_decl->final_absence_list
: dst->unit_decl->absence_list));
prev_el != NULL && prev_el->next_pattern_set_el != NULL;
prev_el = prev_el->next_pattern_set_el)
;
copy = copy_node (pat, sizeof (*pat));
copy->next_pattern_set_el = NULL;
if (prev_el == NULL)
{
if (presence_p)
{
if (final_p)
dst->unit_decl->final_presence_list = copy;
else
dst->unit_decl->presence_list = copy;
}
else if (final_p)
dst->unit_decl->final_absence_list = copy;
else
dst->unit_decl->absence_list = copy;
}
else
prev_el->next_pattern_set_el = copy;
}
}
}
}
static struct bypass_decl *
find_bypass (struct bypass_decl *bypass_list,
struct insn_reserv_decl *in_insn_reserv)
{
struct bypass_decl *bypass;
for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
if (bypass->in_insn_reserv == in_insn_reserv)
break;
return bypass;
}
static void
process_decls (void)
{
decl_t decl;
decl_t automaton_decl;
decl_t decl_in_table;
decl_t out_insn_reserv;
decl_t in_insn_reserv;
struct bypass_decl *bypass;
int automaton_presence;
int i;
automaton_presence = 0;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_automaton)
{
automaton_presence = 1;
decl_in_table = insert_automaton_decl (decl);
if (decl_in_table != decl)
{
if (!w_flag)
error ("repeated declaration of automaton `%s'",
DECL_AUTOMATON (decl)->name);
else
warning (0, "repeated declaration of automaton `%s'",
DECL_AUTOMATON (decl)->name);
}
}
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
{
if (DECL_INSN_RESERV (decl)->default_latency < 0)
error ("define_insn_reservation `%s' has negative latency time",
DECL_INSN_RESERV (decl)->name);
DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
description->insns_num++;
decl_in_table = insert_insn_decl (decl);
if (decl_in_table != decl)
error ("`%s' is already used as insn reservation name",
DECL_INSN_RESERV (decl)->name);
}
else if (decl->mode == dm_bypass)
{
if (DECL_BYPASS (decl)->latency < 0)
error ("define_bypass `%s - %s' has negative latency time",
DECL_BYPASS (decl)->out_insn_name,
DECL_BYPASS (decl)->in_insn_name);
}
else if (decl->mode == dm_unit || decl->mode == dm_reserv)
{
if (decl->mode == dm_unit)
{
DECL_UNIT (decl)->automaton_decl = NULL;
if (DECL_UNIT (decl)->automaton_name != NULL)
{
automaton_decl
= find_automaton_decl (DECL_UNIT (decl)->automaton_name);
if (automaton_decl == NULL)
error ("automaton `%s' is not declared",
DECL_UNIT (decl)->automaton_name);
else
{
DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
DECL_UNIT (decl)->automaton_decl
= DECL_AUTOMATON (automaton_decl);
}
}
else if (automaton_presence)
error ("define_unit `%s' without automaton when one defined",
DECL_UNIT (decl)->name);
DECL_UNIT (decl)->unit_num = description->units_num;
description->units_num++;
if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
{
error ("`%s' is declared as cpu unit", NOTHING_NAME);
continue;
}
decl_in_table = find_decl (DECL_UNIT (decl)->name);
}
else
{
if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
{
error ("`%s' is declared as cpu reservation", NOTHING_NAME);
continue;
}
decl_in_table = find_decl (DECL_RESERV (decl)->name);
}
if (decl_in_table == NULL)
decl_in_table = insert_decl (decl);
else
{
if (decl->mode == dm_unit)
error ("repeated declaration of unit `%s'",
DECL_UNIT (decl)->name);
else
error ("repeated declaration of reservation `%s'",
DECL_RESERV (decl)->name);
}
}
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_bypass)
{
out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
if (out_insn_reserv == NULL)
error ("there is no insn reservation `%s'",
DECL_BYPASS (decl)->out_insn_name);
else if (in_insn_reserv == NULL)
error ("there is no insn reservation `%s'",
DECL_BYPASS (decl)->in_insn_name);
else
{
DECL_BYPASS (decl)->out_insn_reserv
= DECL_INSN_RESERV (out_insn_reserv);
DECL_BYPASS (decl)->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv);
bypass
= find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
DECL_BYPASS (decl)->in_insn_reserv);
if (bypass != NULL)
{
if (DECL_BYPASS (decl)->latency == bypass->latency)
{
if (!w_flag)
error
("the same bypass `%s - %s' is already defined",
DECL_BYPASS (decl)->out_insn_name,
DECL_BYPASS (decl)->in_insn_name);
else
warning
(0, "the same bypass `%s - %s' is already defined",
DECL_BYPASS (decl)->out_insn_name,
DECL_BYPASS (decl)->in_insn_name);
}
else
error ("bypass `%s - %s' is already defined",
DECL_BYPASS (decl)->out_insn_name,
DECL_BYPASS (decl)->in_insn_name);
}
else
{
DECL_BYPASS (decl)->next
= DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
DECL_INSN_RESERV (out_insn_reserv)->bypass_list
= DECL_BYPASS (decl);
}
}
}
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_excl)
{
unit_set_el_t unit_set_el_list;
unit_set_el_t unit_set_el_list_2;
unit_set_el_list
= process_excls (DECL_EXCL (decl)->names,
DECL_EXCL (decl)->first_list_length, decl->pos);
unit_set_el_list_2
= process_excls (&DECL_EXCL (decl)->names
[DECL_EXCL (decl)->first_list_length],
DECL_EXCL (decl)->all_names_num
- DECL_EXCL (decl)->first_list_length,
decl->pos);
add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
}
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_presence)
{
unit_set_el_t unit_set_el_list;
pattern_set_el_t pattern_set_el_list;
unit_set_el_list
= process_presence_absence_names
(DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
pattern_set_el_list
= process_presence_absence_patterns
(DECL_PRESENCE (decl)->patterns,
DECL_PRESENCE (decl)->patterns_num,
decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
add_presence_absence (unit_set_el_list, pattern_set_el_list,
decl->pos, TRUE,
DECL_PRESENCE (decl)->final_p);
}
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_absence)
{
unit_set_el_t unit_set_el_list;
pattern_set_el_t pattern_set_el_list;
unit_set_el_list
= process_presence_absence_names
(DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
pattern_set_el_list
= process_presence_absence_patterns
(DECL_ABSENCE (decl)->patterns,
DECL_ABSENCE (decl)->patterns_num,
decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
add_presence_absence (unit_set_el_list, pattern_set_el_list,
decl->pos, FALSE,
DECL_ABSENCE (decl)->final_p);
}
}
}
static void
check_automaton_usage (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_automaton
&& !DECL_AUTOMATON (decl)->automaton_is_used)
{
if (!w_flag)
error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
else
warning (0, "automaton `%s' is not used",
DECL_AUTOMATON (decl)->name);
}
}
}
static regexp_t
process_regexp (regexp_t regexp)
{
decl_t decl_in_table;
regexp_t new_regexp;
int i;
switch (regexp->mode)
{
case rm_unit:
decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
if (decl_in_table == NULL)
error ("undeclared unit or reservation `%s'",
REGEXP_UNIT (regexp)->name);
else
switch (decl_in_table->mode)
{
case dm_unit:
DECL_UNIT (decl_in_table)->unit_is_used = 1;
REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
break;
case dm_reserv:
DECL_RESERV (decl_in_table)->reserv_is_used = 1;
new_regexp = create_node (sizeof (struct regexp));
new_regexp->mode = rm_reserv;
new_regexp->pos = regexp->pos;
REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
REGEXP_RESERV (new_regexp)->reserv_decl
= DECL_RESERV (decl_in_table);
regexp = new_regexp;
break;
default:
gcc_unreachable ();
}
break;
case rm_sequence:
for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
REGEXP_SEQUENCE (regexp)->regexps [i]
= process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
break;
case rm_allof:
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
REGEXP_ALLOF (regexp)->regexps [i]
= process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
break;
case rm_oneof:
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
REGEXP_ONEOF (regexp)->regexps [i]
= process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
break;
case rm_repeat:
REGEXP_REPEAT (regexp)->regexp
= process_regexp (REGEXP_REPEAT (regexp)->regexp);
break;
case rm_nothing:
break;
default:
gcc_unreachable ();
}
return regexp;
}
static void
process_regexp_decls (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_reserv)
DECL_RESERV (decl)->regexp
= process_regexp (DECL_RESERV (decl)->regexp);
else if (decl->mode == dm_insn_reserv)
DECL_INSN_RESERV (decl)->regexp
= process_regexp (DECL_INSN_RESERV (decl)->regexp);
}
}
static void
check_usage (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
{
if (!w_flag)
error ("unit `%s' is not used", DECL_UNIT (decl)->name);
else
warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
}
else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
{
if (!w_flag)
error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
else
warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
}
}
}
static int curr_loop_pass_num;
static int
loop_in_regexp (regexp_t regexp, decl_t start_decl)
{
int i;
if (regexp == NULL)
return 0;
switch (regexp->mode)
{
case rm_unit:
return 0;
case rm_reserv:
if (start_decl->mode == dm_reserv
&& REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
return 1;
else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
== curr_loop_pass_num)
return 0;
else
{
REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
= curr_loop_pass_num;
return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
start_decl);
}
case rm_sequence:
for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
return 1;
return 0;
case rm_allof:
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
return 1;
return 0;
case rm_oneof:
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
return 1;
return 0;
case rm_repeat:
return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
case rm_nothing:
return 0;
default:
gcc_unreachable ();
}
}
static void
check_loops_in_regexps (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_reserv)
DECL_RESERV (decl)->loop_pass_num = 0;
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
curr_loop_pass_num = i;
if (decl->mode == dm_reserv)
{
DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
{
gcc_assert (DECL_RESERV (decl)->regexp);
error ("cycle in definition of reservation `%s'",
DECL_RESERV (decl)->name);
}
}
}
}
static void
process_regexp_cycles (regexp_t regexp, int max_start_cycle,
int min_start_cycle, int *max_finish_cycle,
int *min_finish_cycle)
{
int i;
switch (regexp->mode)
{
case rm_unit:
if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
|| REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
*max_finish_cycle = max_start_cycle;
*min_finish_cycle = min_start_cycle;
break;
case rm_reserv:
process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
max_start_cycle, min_start_cycle,
max_finish_cycle, min_finish_cycle);
break;
case rm_repeat:
for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
{
process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
max_start_cycle, min_start_cycle,
max_finish_cycle, min_finish_cycle);
max_start_cycle = *max_finish_cycle + 1;
min_start_cycle = *min_finish_cycle + 1;
}
break;
case rm_sequence:
for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
{
process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
max_start_cycle, min_start_cycle,
max_finish_cycle, min_finish_cycle);
max_start_cycle = *max_finish_cycle + 1;
min_start_cycle = *min_finish_cycle + 1;
}
break;
case rm_allof:
{
int max_cycle = 0;
int min_cycle = 0;
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
{
process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
max_start_cycle, min_start_cycle,
max_finish_cycle, min_finish_cycle);
if (max_cycle < *max_finish_cycle)
max_cycle = *max_finish_cycle;
if (i == 0 || min_cycle > *min_finish_cycle)
min_cycle = *min_finish_cycle;
}
*max_finish_cycle = max_cycle;
*min_finish_cycle = min_cycle;
}
break;
case rm_oneof:
{
int max_cycle = 0;
int min_cycle = 0;
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
{
process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
max_start_cycle, min_start_cycle,
max_finish_cycle, min_finish_cycle);
if (max_cycle < *max_finish_cycle)
max_cycle = *max_finish_cycle;
if (i == 0 || min_cycle > *min_finish_cycle)
min_cycle = *min_finish_cycle;
}
*max_finish_cycle = max_cycle;
*min_finish_cycle = min_cycle;
}
break;
case rm_nothing:
*max_finish_cycle = max_start_cycle;
*min_finish_cycle = min_start_cycle;
break;
default:
gcc_unreachable ();
}
}
static void
evaluate_max_reserv_cycles (void)
{
int max_insn_cycles_num;
int min_insn_cycles_num;
decl_t decl;
int i;
description->max_insn_reserv_cycles = 0;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
{
process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
&max_insn_cycles_num, &min_insn_cycles_num);
if (description->max_insn_reserv_cycles < max_insn_cycles_num)
description->max_insn_reserv_cycles = max_insn_cycles_num;
}
}
description->max_insn_reserv_cycles++;
}
static void
check_all_description (void)
{
process_decls ();
check_automaton_usage ();
process_regexp_decls ();
check_usage ();
check_loops_in_regexps ();
if (!have_error)
evaluate_max_reserv_cycles ();
}
static ticker_t
create_ticker (void)
{
ticker_t ticker;
ticker.modified_creation_time = get_run_time ();
ticker.incremented_off_time = 0;
return ticker;
}
static void
ticker_off (ticker_t *ticker)
{
if (ticker->incremented_off_time == 0)
ticker->incremented_off_time = get_run_time () + 1;
}
static void
ticker_on (ticker_t *ticker)
{
if (ticker->incremented_off_time != 0)
{
ticker->modified_creation_time
+= get_run_time () - ticker->incremented_off_time + 1;
ticker->incremented_off_time = 0;
}
}
static int
active_time (ticker_t ticker)
{
if (ticker.incremented_off_time != 0)
return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
else
return get_run_time () - ticker.modified_creation_time;
}
static void
print_active_time (FILE *f, ticker_t ticker)
{
int msecs;
msecs = active_time (ticker);
fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
}
static int automata_num;
static ticker_t transform_time;
static ticker_t NDFA_time;
static ticker_t NDFA_to_DFA_time;
static ticker_t minimize_time;
static ticker_t equiv_time;
static ticker_t automaton_generation_time;
static ticker_t output_time;
static ticker_t check_time;
static ticker_t generation_time;
static ticker_t all_time;
static decl_t advance_cycle_insn_decl;
static void
add_advance_cycle_insn_decl (void)
{
advance_cycle_insn_decl = create_node (sizeof (struct decl));
advance_cycle_insn_decl->mode = dm_insn_reserv;
advance_cycle_insn_decl->pos = no_pos;
DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
= description->insns_num;
description->decls [description->decls_num] = advance_cycle_insn_decl;
description->decls_num++;
description->insns_num++;
}
static alt_state_t first_free_alt_state;
#ifndef NDEBUG
static int allocated_alt_states_num = 0;
#endif
static alt_state_t
get_free_alt_state (void)
{
alt_state_t result;
if (first_free_alt_state != NULL)
{
result = first_free_alt_state;
first_free_alt_state = first_free_alt_state->next_alt_state;
}
else
{
#ifndef NDEBUG
allocated_alt_states_num++;
#endif
result = create_node (sizeof (struct alt_state));
}
result->state = NULL;
result->next_alt_state = NULL;
result->next_sorted_alt_state = NULL;
return result;
}
static void
free_alt_state (alt_state_t alt_state)
{
if (alt_state == NULL)
return;
alt_state->next_alt_state = first_free_alt_state;
first_free_alt_state = alt_state;
}
static void
free_alt_states (alt_state_t alt_states_list)
{
alt_state_t curr_alt_state;
alt_state_t next_alt_state;
for (curr_alt_state = alt_states_list;
curr_alt_state != NULL;
curr_alt_state = next_alt_state)
{
next_alt_state = curr_alt_state->next_alt_state;
free_alt_state (curr_alt_state);
}
}
static int
alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
{
if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
== (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
return 0;
else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
< (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
return -1;
else
return 1;
}
static alt_state_t
uniq_sort_alt_states (alt_state_t alt_states_list)
{
alt_state_t curr_alt_state;
VEC(alt_state_t,heap) *alt_states;
size_t i;
size_t prev_unique_state_ind;
alt_state_t result;
if (alt_states_list == 0)
return 0;
if (alt_states_list->next_alt_state == 0)
return alt_states_list;
alt_states = VEC_alloc (alt_state_t,heap, 150);
for (curr_alt_state = alt_states_list;
curr_alt_state != NULL;
curr_alt_state = curr_alt_state->next_alt_state)
VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
qsort (VEC_address (alt_state_t, alt_states),
VEC_length (alt_state_t, alt_states),
sizeof (alt_state_t), alt_state_cmp);
prev_unique_state_ind = 0;
for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
!= VEC_index (alt_state_t, alt_states, i)->state)
{
prev_unique_state_ind++;
VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
VEC_index (alt_state_t, alt_states, i));
}
VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
= VEC_index (alt_state_t, alt_states, i);
VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
result = VEC_index (alt_state_t, alt_states, 0);
VEC_free (alt_state_t,heap, alt_states);
return result;
}
static int
alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
{
while (alt_states_1 != NULL && alt_states_2 != NULL
&& alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
{
alt_states_1 = alt_states_1->next_sorted_alt_state;
alt_states_2 = alt_states_2->next_sorted_alt_state;
}
return alt_states_1 == alt_states_2;
}
static void
initiate_alt_states (void)
{
first_free_alt_state = NULL;
}
static void
finish_alt_states (void)
{
}
#define SET_BIT(bitstring, bitno) \
(((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
#define CLEAR_BIT(bitstring, bitno) \
(((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
#define TEST_BIT(bitstring, bitno) \
(((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
static int max_cycles_num;
static int els_in_cycle_reserv;
static int els_in_reservs;
static unit_decl_t *units_array;
static reserv_sets_t temp_reserv;
static htab_t state_table;
static state_t first_free_state;
static int curr_unique_state_num;
#ifndef NDEBUG
static int allocated_states_num = 0;
#endif
static reserv_sets_t
alloc_empty_reserv_sets (void)
{
reserv_sets_t result;
obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
result = (reserv_sets_t) obstack_base (&irp);
obstack_finish (&irp);
memset (result, 0, els_in_reservs * sizeof (set_el_t));
return result;
}
static unsigned
reserv_sets_hash_value (reserv_sets_t reservs)
{
set_el_t hash_value;
unsigned result;
int reservs_num, i;
set_el_t *reserv_ptr;
hash_value = 0;
reservs_num = els_in_reservs;
reserv_ptr = reservs;
i = 0;
while (reservs_num != 0)
{
reservs_num--;
hash_value += ((*reserv_ptr >> i)
| (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
i++;
if (i == sizeof (set_el_t) * CHAR_BIT)
i = 0;
reserv_ptr++;
}
if (sizeof (set_el_t) <= sizeof (unsigned))
return hash_value;
result = 0;
for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
{
result += (unsigned) hash_value;
hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
}
return result;
}
static int
reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
{
int reservs_num;
set_el_t *reserv_ptr_1;
set_el_t *reserv_ptr_2;
gcc_assert (reservs_1 && reservs_2);
reservs_num = els_in_reservs;
reserv_ptr_1 = reservs_1;
reserv_ptr_2 = reservs_2;
while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
{
reservs_num--;
reserv_ptr_1++;
reserv_ptr_2++;
}
if (reservs_num == 0)
return 0;
else if (*reserv_ptr_1 < *reserv_ptr_2)
return -1;
else
return 1;
}
static int
reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
{
return reserv_sets_cmp (reservs_1, reservs_2) == 0;
}
static void
set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
{
gcc_assert (cycle_num < max_cycles_num);
SET_BIT (reservs, cycle_num * els_in_cycle_reserv
* sizeof (set_el_t) * CHAR_BIT + unit_num);
}
static int
test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
{
gcc_assert (cycle_num < max_cycles_num);
return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
* sizeof (set_el_t) * CHAR_BIT + unit_num);
}
static int
reserv_sets_are_intersected (reserv_sets_t operand_1,
reserv_sets_t operand_2)
{
set_el_t *el_ptr_1;
set_el_t *el_ptr_2;
set_el_t *cycle_ptr_1;
set_el_t *cycle_ptr_2;
gcc_assert (operand_1 && operand_2);
for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
el_ptr_1 < operand_1 + els_in_reservs;
el_ptr_1++, el_ptr_2++)
if (*el_ptr_1 & *el_ptr_2)
return 1;
reserv_sets_or (temp_reserv, operand_1, operand_2);
for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
cycle_ptr_1 < operand_1 + els_in_reservs;
cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
{
for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
el_ptr_1++, el_ptr_2++)
if (*el_ptr_1 & *el_ptr_2)
return 1;
if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
return 1;
if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
- operand_2),
cycle_ptr_2, TRUE))
return 1;
if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
return 1;
if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
cycle_ptr_2, TRUE))
return 1;
}
return 0;
}
static void
reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
{
int i;
gcc_assert (result && operand && result != operand);
for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
result [i - els_in_cycle_reserv] = operand [i];
}
static void
reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
reserv_sets_t operand_2)
{
set_el_t *el_ptr_1;
set_el_t *el_ptr_2;
set_el_t *result_set_el_ptr;
gcc_assert (result && operand_1 && operand_2);
for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
el_ptr_1 < operand_1 + els_in_reservs;
el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
*result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
}
static void
reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
reserv_sets_t operand_2)
{
set_el_t *el_ptr_1;
set_el_t *el_ptr_2;
set_el_t *result_set_el_ptr;
gcc_assert (result && operand_1 && operand_2);
for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
el_ptr_1 < operand_1 + els_in_reservs;
el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
*result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
}
static void
output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
int repetition_num)
{
int unit_num;
int reserved_units_num;
reserved_units_num = 0;
for (unit_num = 0; unit_num < description->units_num; unit_num++)
if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
* sizeof (set_el_t) * CHAR_BIT + unit_num))
reserved_units_num++;
gcc_assert (repetition_num > 0);
if (repetition_num != 1 && reserved_units_num > 1)
fprintf (f, "(");
reserved_units_num = 0;
for (unit_num = 0;
unit_num < description->units_num;
unit_num++)
if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
* sizeof (set_el_t) * CHAR_BIT + unit_num))
{
if (reserved_units_num != 0)
fprintf (f, "+");
reserved_units_num++;
fprintf (f, "%s", units_array [unit_num]->name);
}
if (reserved_units_num == 0)
fprintf (f, NOTHING_NAME);
gcc_assert (repetition_num > 0);
if (repetition_num != 1 && reserved_units_num > 1)
fprintf (f, ")");
if (repetition_num != 1)
fprintf (f, "*%d", repetition_num);
}
static void
output_reserv_sets (FILE *f, reserv_sets_t reservs)
{
int start_cycle = 0;
int cycle;
int repetition_num;
repetition_num = 0;
for (cycle = 0; cycle < max_cycles_num; cycle++)
if (repetition_num == 0)
{
repetition_num++;
start_cycle = cycle;
}
else if (memcmp
((char *) reservs + start_cycle * els_in_cycle_reserv
* sizeof (set_el_t),
(char *) reservs + cycle * els_in_cycle_reserv
* sizeof (set_el_t),
els_in_cycle_reserv * sizeof (set_el_t)) == 0)
repetition_num++;
else
{
if (start_cycle != 0)
fprintf (f, ", ");
output_cycle_reservs (f, reservs, start_cycle, repetition_num);
repetition_num = 1;
start_cycle = cycle;
}
if (start_cycle < max_cycles_num)
{
if (start_cycle != 0)
fprintf (f, ", ");
output_cycle_reservs (f, reservs, start_cycle, repetition_num);
}
}
static state_t
get_free_state (int with_reservs, automaton_t automaton)
{
state_t result;
gcc_assert (max_cycles_num > 0 && automaton);
if (first_free_state)
{
result = first_free_state;
first_free_state = result->next_equiv_class_state;
result->next_equiv_class_state = NULL;
result->automaton = automaton;
result->first_out_arc = NULL;
result->it_was_placed_in_stack_for_NDFA_forming = 0;
result->it_was_placed_in_stack_for_DFA_forming = 0;
result->component_states = NULL;
result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
}
else
{
#ifndef NDEBUG
allocated_states_num++;
#endif
result = create_node (sizeof (struct state));
result->automaton = automaton;
result->first_out_arc = NULL;
result->unique_num = curr_unique_state_num;
result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
curr_unique_state_num++;
}
if (with_reservs)
{
if (result->reservs == NULL)
result->reservs = alloc_empty_reserv_sets ();
else
memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
}
return result;
}
static void
free_state (state_t state)
{
free_alt_states (state->component_states);
state->next_equiv_class_state = first_free_state;
first_free_state = state;
}
static hashval_t
state_hash (const void *state)
{
unsigned int hash_value;
alt_state_t alt_state;
if (((state_t) state)->component_states == NULL)
hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
else
{
hash_value = 0;
for (alt_state = ((state_t) state)->component_states;
alt_state != NULL;
alt_state = alt_state->next_sorted_alt_state)
hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
| (hash_value << CHAR_BIT))
+ alt_state->state->unique_num);
}
hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
| (hash_value << CHAR_BIT))
+ ((state_t) state)->automaton->automaton_order_num);
return hash_value;
}
static int
state_eq_p (const void *state_1, const void *state_2)
{
alt_state_t alt_state_1;
alt_state_t alt_state_2;
if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
return 0;
else if (((state_t) state_1)->component_states == NULL
&& ((state_t) state_2)->component_states == NULL)
return reserv_sets_eq (((state_t) state_1)->reservs,
((state_t) state_2)->reservs);
else if (((state_t) state_1)->component_states != NULL
&& ((state_t) state_2)->component_states != NULL)
{
for (alt_state_1 = ((state_t) state_1)->component_states,
alt_state_2 = ((state_t) state_2)->component_states;
alt_state_1 != NULL && alt_state_2 != NULL;
alt_state_1 = alt_state_1->next_sorted_alt_state,
alt_state_2 = alt_state_2->next_sorted_alt_state)
if (alt_state_1->state != alt_state_2->state)
return 0;
return alt_state_1 == alt_state_2;
}
else
return 0;
}
static state_t
insert_state (state_t state)
{
void **entry_ptr;
entry_ptr = htab_find_slot (state_table, (void *) state, 1);
if (*entry_ptr == NULL)
*entry_ptr = (void *) state;
return (state_t) *entry_ptr;
}
static void
set_state_reserv (state_t state, int cycle_num, int unit_num)
{
set_unit_reserv (state->reservs, cycle_num, unit_num);
}
static int
intersected_state_reservs_p (state_t state1, state_t state2)
{
gcc_assert (state1->automaton == state2->automaton);
return reserv_sets_are_intersected (state1->reservs, state2->reservs);
}
static state_t
states_union (state_t state1, state_t state2, reserv_sets_t reservs)
{
state_t result;
state_t state_in_table;
gcc_assert (state1->automaton == state2->automaton);
result = get_free_state (1, state1->automaton);
reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
reserv_sets_and (result->reservs, result->reservs, reservs);
state_in_table = insert_state (result);
if (result != state_in_table)
{
free_state (result);
result = state_in_table;
}
return result;
}
static state_t
state_shift (state_t state, reserv_sets_t reservs)
{
state_t result;
state_t state_in_table;
result = get_free_state (1, state->automaton);
reserv_sets_shift (result->reservs, state->reservs);
reserv_sets_and (result->reservs, result->reservs, reservs);
state_in_table = insert_state (result);
if (result != state_in_table)
{
free_state (result);
result = state_in_table;
}
return result;
}
static void
initiate_states (void)
{
decl_t decl;
int i;
if (description->units_num)
units_array = XNEWVEC (unit_decl_t, description->units_num);
else
units_array = 0;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
}
max_cycles_num = description->max_insn_reserv_cycles;
els_in_cycle_reserv
= ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
/ (sizeof (set_el_t) * CHAR_BIT));
els_in_reservs = els_in_cycle_reserv * max_cycles_num;
curr_unique_state_num = 0;
initiate_alt_states ();
state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
temp_reserv = alloc_empty_reserv_sets ();
}
static void
finish_states (void)
{
free (units_array);
units_array = 0;
htab_delete (state_table);
first_free_state = NULL;
finish_alt_states ();
}
static arc_t first_free_arc;
#ifndef NDEBUG
static int allocated_arcs_num = 0;
#endif
static void
free_arc (arc_t arc)
{
arc->next_out_arc = first_free_arc;
first_free_arc = arc;
}
static void
remove_arc (state_t from_state, arc_t arc)
{
arc_t prev_arc;
arc_t curr_arc;
gcc_assert (arc);
for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
curr_arc != NULL;
prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
if (curr_arc == arc)
break;
gcc_assert (curr_arc);
if (prev_arc == NULL)
from_state->first_out_arc = arc->next_out_arc;
else
prev_arc->next_out_arc = arc->next_out_arc;
from_state->num_out_arcs--;
free_arc (arc);
}
static arc_t
find_arc (state_t from_state, state_t to_state, ainsn_t insn)
{
arc_t arc;
for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
if (arc->to_state == to_state && arc->insn == insn)
return arc;
return NULL;
}
static arc_t
add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
{
arc_t new_arc;
new_arc = find_arc (from_state, to_state, ainsn);
if (new_arc != NULL)
return new_arc;
if (first_free_arc == NULL)
{
#ifndef NDEBUG
allocated_arcs_num++;
#endif
new_arc = create_node (sizeof (struct arc));
new_arc->to_state = NULL;
new_arc->insn = NULL;
new_arc->next_out_arc = NULL;
}
else
{
new_arc = first_free_arc;
first_free_arc = first_free_arc->next_out_arc;
}
new_arc->to_state = to_state;
new_arc->insn = ainsn;
ainsn->arc_exists_p = 1;
new_arc->next_out_arc = from_state->first_out_arc;
from_state->first_out_arc = new_arc;
from_state->num_out_arcs++;
new_arc->next_arc_marked_by_insn = NULL;
return new_arc;
}
static arc_t
first_out_arc (state_t state)
{
return state->first_out_arc;
}
static arc_t
next_out_arc (arc_t arc)
{
return arc->next_out_arc;
}
static void
initiate_arcs (void)
{
first_free_arc = NULL;
}
static void
finish_arcs (void)
{
}
static automata_list_el_t first_free_automata_list_el;
static automata_list_el_t current_automata_list;
static htab_t automata_list_table;
static automata_list_el_t
get_free_automata_list_el (void)
{
automata_list_el_t result;
if (first_free_automata_list_el != NULL)
{
result = first_free_automata_list_el;
first_free_automata_list_el
= first_free_automata_list_el->next_automata_list_el;
}
else
result = create_node (sizeof (struct automata_list_el));
result->automaton = NULL;
result->next_automata_list_el = NULL;
return result;
}
static void
free_automata_list_el (automata_list_el_t automata_list_el)
{
if (automata_list_el == NULL)
return;
automata_list_el->next_automata_list_el = first_free_automata_list_el;
first_free_automata_list_el = automata_list_el;
}
static void
free_automata_list (automata_list_el_t automata_list)
{
automata_list_el_t curr_automata_list_el;
automata_list_el_t next_automata_list_el;
for (curr_automata_list_el = automata_list;
curr_automata_list_el != NULL;
curr_automata_list_el = next_automata_list_el)
{
next_automata_list_el = curr_automata_list_el->next_automata_list_el;
free_automata_list_el (curr_automata_list_el);
}
}
static hashval_t
automata_list_hash (const void *automata_list)
{
unsigned int hash_value;
automata_list_el_t curr_automata_list_el;
hash_value = 0;
for (curr_automata_list_el = (automata_list_el_t) automata_list;
curr_automata_list_el != NULL;
curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
| (hash_value << CHAR_BIT))
+ curr_automata_list_el->automaton->automaton_order_num);
return hash_value;
}
static int
automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
{
automata_list_el_t automata_list_el_1;
automata_list_el_t automata_list_el_2;
for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
automata_list_el_2 = (automata_list_el_t) automata_list_2;
automata_list_el_1 != NULL && automata_list_el_2 != NULL;
automata_list_el_1 = automata_list_el_1->next_automata_list_el,
automata_list_el_2 = automata_list_el_2->next_automata_list_el)
if (automata_list_el_1->automaton != automata_list_el_2->automaton)
return 0;
return automata_list_el_1 == automata_list_el_2;
}
static void
initiate_automata_lists (void)
{
first_free_automata_list_el = NULL;
automata_list_table = htab_create (1500, automata_list_hash,
automata_list_eq_p, (htab_del) 0);
}
static void
automata_list_start (void)
{
current_automata_list = NULL;
}
static void
automata_list_add (automaton_t automaton)
{
automata_list_el_t el;
el = get_free_automata_list_el ();
el->automaton = automaton;
el->next_automata_list_el = current_automata_list;
current_automata_list = el;
}
static automata_list_el_t
automata_list_finish (void)
{
void **entry_ptr;
if (current_automata_list == NULL)
return NULL;
entry_ptr = htab_find_slot (automata_list_table,
(void *) current_automata_list, 1);
if (*entry_ptr == NULL)
*entry_ptr = (void *) current_automata_list;
else
free_automata_list (current_automata_list);
current_automata_list = NULL;
return (automata_list_el_t) *entry_ptr;
}
static void
finish_automata_lists (void)
{
htab_delete (automata_list_table);
}
static reserv_sets_t excl_set;
static reserv_sets_t *unit_excl_set_table;
static void
initiate_excl_sets (void)
{
decl_t decl;
reserv_sets_t unit_excl_set;
unit_set_el_t el;
int i;
obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
excl_set = (reserv_sets_t) obstack_base (&irp);
obstack_finish (&irp);
obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
obstack_finish (&irp);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
{
obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
unit_excl_set = (reserv_sets_t) obstack_base (&irp);
obstack_finish (&irp);
memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
for (el = DECL_UNIT (decl)->excl_list;
el != NULL;
el = el->next_unit_set_el)
{
SET_BIT (unit_excl_set, el->unit_decl->unit_num);
el->unit_decl->in_set_p = TRUE;
}
unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
}
}
}
static reserv_sets_t
get_excl_set (reserv_sets_t in_set)
{
int excl_char_num;
int chars_num;
int i;
int start_unit_num;
int unit_num;
chars_num = els_in_cycle_reserv * sizeof (set_el_t);
memset (excl_set, 0, chars_num);
for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
if (((unsigned char *) in_set) [excl_char_num])
for (i = CHAR_BIT - 1; i >= 0; i--)
if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
{
start_unit_num = excl_char_num * CHAR_BIT + i;
if (start_unit_num >= description->units_num)
return excl_set;
for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
{
excl_set [unit_num]
|= unit_excl_set_table [start_unit_num] [unit_num];
}
}
return excl_set;
}
static pattern_reserv_t *unit_presence_set_table;
static pattern_reserv_t *unit_final_presence_set_table;
static pattern_reserv_t *unit_absence_set_table;
static pattern_reserv_t *unit_final_absence_set_table;
static pattern_reserv_t
form_reserv_sets_list (pattern_set_el_t pattern_list)
{
pattern_set_el_t el;
pattern_reserv_t first, curr, prev;
int i;
prev = first = NULL;
for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
{
curr = create_node (sizeof (struct pattern_reserv));
curr->reserv = alloc_empty_reserv_sets ();
curr->next_pattern_reserv = NULL;
for (i = 0; i < el->units_num; i++)
{
SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
el->unit_decls [i]->in_set_p = TRUE;
}
if (prev != NULL)
prev->next_pattern_reserv = curr;
else
first = curr;
prev = curr;
}
return first;
}
static void
initiate_presence_absence_pattern_sets (void)
{
decl_t decl;
int i;
obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
obstack_finish (&irp);
obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
obstack_finish (&irp);
obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
obstack_finish (&irp);
obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
obstack_finish (&irp);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
{
unit_presence_set_table [DECL_UNIT (decl)->unit_num]
= form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
= form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
unit_absence_set_table [DECL_UNIT (decl)->unit_num]
= form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
= form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
}
}
}
static int
check_presence_pattern_sets (reserv_sets_t checked_set,
reserv_sets_t origional_set,
int final_p)
{
int char_num;
int chars_num;
int i;
int start_unit_num;
int unit_num;
int presence_p;
pattern_reserv_t pat_reserv;
chars_num = els_in_cycle_reserv * sizeof (set_el_t);
for (char_num = 0; char_num < chars_num; char_num++)
if (((unsigned char *) origional_set) [char_num])
for (i = CHAR_BIT - 1; i >= 0; i--)
if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
{
start_unit_num = char_num * CHAR_BIT + i;
if (start_unit_num >= description->units_num)
break;
if ((final_p
&& unit_final_presence_set_table [start_unit_num] == NULL)
|| (!final_p
&& unit_presence_set_table [start_unit_num] == NULL))
continue;
presence_p = FALSE;
for (pat_reserv = (final_p
? unit_final_presence_set_table [start_unit_num]
: unit_presence_set_table [start_unit_num]);
pat_reserv != NULL;
pat_reserv = pat_reserv->next_pattern_reserv)
{
for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
!= pat_reserv->reserv [unit_num])
break;
presence_p = presence_p || unit_num >= els_in_cycle_reserv;
}
if (!presence_p)
return FALSE;
}
return TRUE;
}
static int
check_absence_pattern_sets (reserv_sets_t checked_set,
reserv_sets_t origional_set,
int final_p)
{
int char_num;
int chars_num;
int i;
int start_unit_num;
int unit_num;
pattern_reserv_t pat_reserv;
chars_num = els_in_cycle_reserv * sizeof (set_el_t);
for (char_num = 0; char_num < chars_num; char_num++)
if (((unsigned char *) origional_set) [char_num])
for (i = CHAR_BIT - 1; i >= 0; i--)
if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
{
start_unit_num = char_num * CHAR_BIT + i;
if (start_unit_num >= description->units_num)
break;
for (pat_reserv = (final_p
? unit_final_absence_set_table [start_unit_num]
: unit_absence_set_table [start_unit_num]);
pat_reserv != NULL;
pat_reserv = pat_reserv->next_pattern_reserv)
{
for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
!= pat_reserv->reserv [unit_num]
&& pat_reserv->reserv [unit_num])
break;
if (unit_num >= els_in_cycle_reserv)
return FALSE;
}
}
return TRUE;
}
static regexp_t
copy_insn_regexp (regexp_t regexp)
{
regexp_t result;
int i;
switch (regexp->mode)
{
case rm_reserv:
result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
break;
case rm_unit:
result = copy_node (regexp, sizeof (struct regexp));
break;
case rm_repeat:
result = copy_node (regexp, sizeof (struct regexp));
REGEXP_REPEAT (result)->regexp
= copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
break;
case rm_sequence:
result = copy_node (regexp,
sizeof (struct regexp) + sizeof (regexp_t)
* (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
REGEXP_SEQUENCE (result)->regexps [i]
= copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
break;
case rm_allof:
result = copy_node (regexp,
sizeof (struct regexp) + sizeof (regexp_t)
* (REGEXP_ALLOF (regexp)->regexps_num - 1));
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
REGEXP_ALLOF (result)->regexps [i]
= copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
break;
case rm_oneof:
result = copy_node (regexp,
sizeof (struct regexp) + sizeof (regexp_t)
* (REGEXP_ONEOF (regexp)->regexps_num - 1));
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
REGEXP_ONEOF (result)->regexps [i]
= copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
break;
case rm_nothing:
result = copy_node (regexp, sizeof (struct regexp));
break;
default:
gcc_unreachable ();
}
return result;
}
static int regexp_transformed_p;
static regexp_t
transform_1 (regexp_t regexp)
{
int i;
int repeat_num;
regexp_t operand;
pos_t pos;
if (regexp->mode == rm_repeat)
{
repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
gcc_assert (repeat_num > 1);
operand = REGEXP_REPEAT (regexp)->regexp;
pos = regexp->mode;
regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
* (repeat_num - 1));
regexp->mode = rm_sequence;
regexp->pos = pos;
REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
for (i = 0; i < repeat_num; i++)
REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
regexp_transformed_p = 1;
}
return regexp;
}
static regexp_t
transform_2 (regexp_t regexp)
{
if (regexp->mode == rm_sequence)
{
regexp_t sequence = NULL;
regexp_t result;
int sequence_index = 0;
int i, j;
for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
{
sequence_index = i;
sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
break;
}
if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
{
gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
&& REGEXP_SEQUENCE (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_SEQUENCE (regexp)->regexps_num
+ REGEXP_SEQUENCE (sequence)->regexps_num
- 2));
result->mode = rm_sequence;
result->pos = regexp->pos;
REGEXP_SEQUENCE (result)->regexps_num
= (REGEXP_SEQUENCE (regexp)->regexps_num
+ REGEXP_SEQUENCE (sequence)->regexps_num - 1);
for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
if (i < sequence_index)
REGEXP_SEQUENCE (result)->regexps [i]
= copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
else if (i > sequence_index)
REGEXP_SEQUENCE (result)->regexps
[i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
= copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
else
for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
REGEXP_SEQUENCE (result)->regexps [i + j]
= copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
regexp_transformed_p = 1;
regexp = result;
}
}
else if (regexp->mode == rm_allof)
{
regexp_t allof = NULL;
regexp_t result;
int allof_index = 0;
int i, j;
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
{
allof_index = i;
allof = REGEXP_ALLOF (regexp)->regexps [i];
break;
}
if (i < REGEXP_ALLOF (regexp)->regexps_num)
{
gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
&& REGEXP_ALLOF (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_ALLOF (regexp)->regexps_num
+ REGEXP_ALLOF (allof)->regexps_num - 2));
result->mode = rm_allof;
result->pos = regexp->pos;
REGEXP_ALLOF (result)->regexps_num
= (REGEXP_ALLOF (regexp)->regexps_num
+ REGEXP_ALLOF (allof)->regexps_num - 1);
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
if (i < allof_index)
REGEXP_ALLOF (result)->regexps [i]
= copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
else if (i > allof_index)
REGEXP_ALLOF (result)->regexps
[i + REGEXP_ALLOF (allof)->regexps_num - 1]
= copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
else
for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
REGEXP_ALLOF (result)->regexps [i + j]
= copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
regexp_transformed_p = 1;
regexp = result;
}
}
else if (regexp->mode == rm_oneof)
{
regexp_t oneof = NULL;
regexp_t result;
int oneof_index = 0;
int i, j;
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
{
oneof_index = i;
oneof = REGEXP_ONEOF (regexp)->regexps [i];
break;
}
if (i < REGEXP_ONEOF (regexp)->regexps_num)
{
gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
&& REGEXP_ONEOF (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_ONEOF (regexp)->regexps_num
+ REGEXP_ONEOF (oneof)->regexps_num - 2));
result->mode = rm_oneof;
result->pos = regexp->pos;
REGEXP_ONEOF (result)->regexps_num
= (REGEXP_ONEOF (regexp)->regexps_num
+ REGEXP_ONEOF (oneof)->regexps_num - 1);
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
if (i < oneof_index)
REGEXP_ONEOF (result)->regexps [i]
= copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
else if (i > oneof_index)
REGEXP_ONEOF (result)->regexps
[i + REGEXP_ONEOF (oneof)->regexps_num - 1]
= copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
else
for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
REGEXP_ONEOF (result)->regexps [i + j]
= copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
regexp_transformed_p = 1;
regexp = result;
}
}
return regexp;
}
static regexp_t
transform_3 (regexp_t regexp)
{
if (regexp->mode == rm_sequence)
{
regexp_t oneof = NULL;
int oneof_index = 0;
regexp_t result;
regexp_t sequence;
int i, j;
for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
{
oneof_index = i;
oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
break;
}
if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
{
gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
&& REGEXP_SEQUENCE (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_ONEOF (oneof)->regexps_num - 1));
result->mode = rm_oneof;
result->pos = regexp->pos;
REGEXP_ONEOF (result)->regexps_num
= REGEXP_ONEOF (oneof)->regexps_num;
for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
{
sequence
= create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
sequence->mode = rm_sequence;
sequence->pos = regexp->pos;
REGEXP_SEQUENCE (sequence)->regexps_num
= REGEXP_SEQUENCE (regexp)->regexps_num;
REGEXP_ONEOF (result)->regexps [i] = sequence;
for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
if (j != oneof_index)
REGEXP_SEQUENCE (sequence)->regexps [j]
= copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
else
REGEXP_SEQUENCE (sequence)->regexps [j]
= copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
}
regexp_transformed_p = 1;
regexp = result;
}
}
else if (regexp->mode == rm_allof)
{
regexp_t oneof = NULL;
regexp_t seq;
int oneof_index = 0;
int max_seq_length, allof_length;
regexp_t result;
regexp_t allof = NULL;
regexp_t allof_op = NULL;
int i, j;
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
{
oneof_index = i;
oneof = REGEXP_ALLOF (regexp)->regexps [i];
break;
}
if (i < REGEXP_ALLOF (regexp)->regexps_num)
{
gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
&& REGEXP_ALLOF (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_ONEOF (oneof)->regexps_num - 1));
result->mode = rm_oneof;
result->pos = regexp->pos;
REGEXP_ONEOF (result)->regexps_num
= REGEXP_ONEOF (oneof)->regexps_num;
for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
{
allof
= create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (REGEXP_ALLOF (regexp)->regexps_num - 1));
allof->mode = rm_allof;
allof->pos = regexp->pos;
REGEXP_ALLOF (allof)->regexps_num
= REGEXP_ALLOF (regexp)->regexps_num;
REGEXP_ONEOF (result)->regexps [i] = allof;
for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
if (j != oneof_index)
REGEXP_ALLOF (allof)->regexps [j]
= copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
else
REGEXP_ALLOF (allof)->regexps [j]
= copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
}
regexp_transformed_p = 1;
regexp = result;
}
max_seq_length = 0;
if (regexp->mode == rm_allof)
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
{
switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
{
case rm_sequence:
seq = REGEXP_ALLOF (regexp)->regexps [i];
if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
break;
case rm_unit:
case rm_nothing:
break;
default:
max_seq_length = 0;
goto break_for;
}
}
break_for:
if (max_seq_length != 0)
{
gcc_assert (max_seq_length != 1
&& REGEXP_ALLOF (regexp)->regexps_num > 1);
result = create_node (sizeof (struct regexp)
+ sizeof (regexp_t) * (max_seq_length - 1));
result->mode = rm_sequence;
result->pos = regexp->pos;
REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
for (i = 0; i < max_seq_length; i++)
{
allof_length = 0;
for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
{
case rm_sequence:
if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
->regexps [j])->regexps_num))
{
allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
->regexps [j])
->regexps [i]);
allof_length++;
}
break;
case rm_unit:
case rm_nothing:
if (i == 0)
{
allof_op = REGEXP_ALLOF (regexp)->regexps [j];
allof_length++;
}
break;
default:
break;
}
if (allof_length == 1)
REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
else
{
allof = create_node (sizeof (struct regexp)
+ sizeof (regexp_t)
* (allof_length - 1));
allof->mode = rm_allof;
allof->pos = regexp->pos;
REGEXP_ALLOF (allof)->regexps_num = allof_length;
REGEXP_SEQUENCE (result)->regexps [i] = allof;
allof_length = 0;
for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
&& (i <
(REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
->regexps [j])->regexps_num)))
{
allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
->regexps [j])
->regexps [i]);
REGEXP_ALLOF (allof)->regexps [allof_length]
= allof_op;
allof_length++;
}
else if (i == 0
&& (REGEXP_ALLOF (regexp)->regexps [j]->mode
== rm_unit
|| (REGEXP_ALLOF (regexp)->regexps [j]->mode
== rm_nothing)))
{
allof_op = REGEXP_ALLOF (regexp)->regexps [j];
REGEXP_ALLOF (allof)->regexps [allof_length]
= allof_op;
allof_length++;
}
}
}
regexp_transformed_p = 1;
regexp = result;
}
}
return regexp;
}
static regexp_t
regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
{
int i;
switch (regexp->mode)
{
case rm_sequence:
for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
REGEXP_SEQUENCE (regexp)->regexps [i]
= regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
func);
break;
case rm_allof:
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
REGEXP_ALLOF (regexp)->regexps [i]
= regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
break;
case rm_oneof:
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
REGEXP_ONEOF (regexp)->regexps [i]
= regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
break;
case rm_repeat:
REGEXP_REPEAT (regexp)->regexp
= regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
break;
case rm_nothing:
case rm_unit:
break;
default:
gcc_unreachable ();
}
return (*func) (regexp);
}
static regexp_t
transform_regexp (regexp_t regexp)
{
regexp = regexp_transform_func (regexp, transform_1);
do
{
regexp_transformed_p = 0;
regexp = regexp_transform_func (regexp, transform_2);
regexp = regexp_transform_func (regexp, transform_3);
}
while (regexp_transformed_p);
return regexp;
}
static void
transform_insn_regexps (void)
{
decl_t decl;
int i;
transform_time = create_ticker ();
add_advance_cycle_insn_decl ();
if (progress_flag)
fprintf (stderr, "Reservation transformation...");
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
DECL_INSN_RESERV (decl)->transformed_regexp
= transform_regexp (copy_insn_regexp
(DECL_INSN_RESERV (decl)->regexp));
}
if (progress_flag)
fprintf (stderr, "done\n");
ticker_off (&transform_time);
}
static int annotation_message_reported_p;
struct unit_usage
{
unit_decl_t unit_decl;
struct unit_usage *next;
};
typedef struct unit_usage *unit_usage_t;
DEF_VEC_P(unit_usage_t);
DEF_VEC_ALLOC_P(unit_usage_t,heap);
static struct obstack unit_usages;
static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
static void
store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
int alt_num)
{
size_t length;
unit_decl_t unit_decl;
unit_usage_t unit_usage_ptr;
int index;
gcc_assert (regexp && regexp->mode == rm_oneof
&& alt_num < REGEXP_ONEOF (regexp)->regexps_num);
unit_decl = REGEXP_UNIT (unit)->unit_decl;
length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
obstack_blank (&unit_usages, sizeof (struct unit_usage));
unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
obstack_finish (&unit_usages);
unit_usage_ptr->unit_decl = unit_decl;
index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
unit_decl->last_distribution_check_cycle = -1;
}
static void
check_regexp_units_distribution (const char *insn_reserv_name,
regexp_t regexp)
{
int i, j, k, cycle;
regexp_t seq, allof, unit;
struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
if (regexp == NULL || regexp->mode != rm_oneof)
return;
obstack_init (&unit_usages);
cycle_alt_unit_usages = 0;
for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
{
seq = REGEXP_ONEOF (regexp)->regexps [i];
switch (seq->mode)
{
case rm_sequence:
for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
{
allof = REGEXP_SEQUENCE (seq)->regexps [j];
switch (allof->mode)
{
case rm_allof:
for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
{
unit = REGEXP_ALLOF (allof)->regexps [k];
if (unit->mode == rm_unit)
store_alt_unit_usage (regexp, unit, j, i);
else
gcc_assert (unit->mode == rm_nothing);
}
break;
case rm_unit:
store_alt_unit_usage (regexp, allof, j, i);
break;
case rm_nothing:
break;
default:
gcc_unreachable ();
}
}
break;
case rm_allof:
for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
{
unit = REGEXP_ALLOF (seq)->regexps [k];
switch (unit->mode)
{
case rm_unit:
store_alt_unit_usage (regexp, unit, 0, i);
break;
case rm_nothing:
break;
default:
gcc_unreachable ();
}
}
break;
case rm_unit:
store_alt_unit_usage (regexp, seq, 0, i);
break;
case rm_nothing:
break;
default:
gcc_unreachable ();
}
}
for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
{
cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
unit_usage_ptr != NULL;
unit_usage_ptr = unit_usage_ptr->next)
if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
{
unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
&& k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
k++)
{
for (other_unit_usage_ptr
= VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
other_unit_usage_ptr != NULL;
other_unit_usage_ptr = other_unit_usage_ptr->next)
if (unit_usage_ptr->unit_decl->automaton_decl
== other_unit_usage_ptr->unit_decl->automaton_decl)
break;
if (other_unit_usage_ptr == NULL
&& (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
!= NULL))
break;
}
if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
&& k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
{
if (!annotation_message_reported_p)
{
fprintf (stderr, "\n");
error ("The following units do not satisfy units-automata distribution rule");
error (" (A unit of given unit automaton should be on each reserv. altern.)");
annotation_message_reported_p = TRUE;
}
error ("Unit %s, reserv. %s, cycle %d",
unit_usage_ptr->unit_decl->name, insn_reserv_name,
cycle);
}
}
}
VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
obstack_free (&unit_usages, NULL);
}
static void
check_unit_distributions_to_automata (void)
{
decl_t decl;
int i;
if (progress_flag)
fprintf (stderr, "Check unit distributions to automata...");
annotation_message_reported_p = FALSE;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
check_regexp_units_distribution
(DECL_INSN_RESERV (decl)->name,
DECL_INSN_RESERV (decl)->transformed_regexp);
}
if (progress_flag)
fprintf (stderr, "done\n");
}
static state_t state_being_formed;
static alt_state_t alt_state_being_formed;
static int
process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
int curr_cycle)
{
int i;
if (regexp == NULL)
return curr_cycle;
switch (regexp->mode)
{
case rm_unit:
if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
== automaton->automaton_order_num)
set_state_reserv (state_being_formed, curr_cycle,
REGEXP_UNIT (regexp)->unit_decl->unit_num);
return curr_cycle;
case rm_sequence:
for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
curr_cycle
= process_seq_for_forming_states
(REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
return curr_cycle;
case rm_allof:
{
int finish_cycle = 0;
int cycle;
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
{
cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
->regexps [i],
automaton, curr_cycle);
if (finish_cycle < cycle)
finish_cycle = cycle;
}
return finish_cycle;
}
case rm_nothing:
return curr_cycle;
default:
gcc_unreachable ();
}
}
static void
finish_forming_alt_state (alt_state_t alt_state,
automaton_t automaton ATTRIBUTE_UNUSED)
{
state_t state_in_table;
state_t corresponding_state;
corresponding_state = alt_state->state;
state_in_table = insert_state (corresponding_state);
if (state_in_table != corresponding_state)
{
free_state (corresponding_state);
alt_state->state = state_in_table;
}
}
static ainsn_t curr_ainsn;
static void
process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
int inside_oneof_p)
{
int i;
if (regexp->mode != rm_oneof)
{
alt_state_being_formed = get_free_alt_state ();
state_being_formed = get_free_state (1, automaton);
alt_state_being_formed->state = state_being_formed;
alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
curr_ainsn->alt_states = alt_state_being_formed;
(void) process_seq_for_forming_states (regexp, automaton, 0);
finish_forming_alt_state (alt_state_being_formed, automaton);
}
else
{
gcc_assert (!inside_oneof_p);
for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
automaton, 1);
}
}
static void
create_alt_states (automaton_t automaton)
{
struct insn_reserv_decl *reserv_decl;
for (curr_ainsn = automaton->ainsn_list;
curr_ainsn != NULL;
curr_ainsn = curr_ainsn->next_ainsn)
{
reserv_decl = curr_ainsn->insn_reserv_decl;
if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
{
curr_ainsn->alt_states = NULL;
process_alts_for_forming_states (reserv_decl->transformed_regexp,
automaton, 0);
curr_ainsn->sorted_alt_states
= uniq_sort_alt_states (curr_ainsn->alt_states);
}
}
}
static void
form_ainsn_with_same_reservs (automaton_t automaton)
{
ainsn_t curr_ainsn;
size_t i;
VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
for (curr_ainsn = automaton->ainsn_list;
curr_ainsn != NULL;
curr_ainsn = curr_ainsn->next_ainsn)
if (curr_ainsn->insn_reserv_decl
== DECL_INSN_RESERV (advance_cycle_insn_decl))
{
curr_ainsn->next_same_reservs_insn = NULL;
curr_ainsn->first_insn_with_same_reservs = 1;
}
else
{
for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
if (alt_states_eq
(curr_ainsn->sorted_alt_states,
VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
break;
curr_ainsn->next_same_reservs_insn = NULL;
if (i < VEC_length (ainsn_t, last_insns))
{
curr_ainsn->first_insn_with_same_reservs = 0;
VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
= curr_ainsn;
VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
}
else
{
VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
curr_ainsn->first_insn_with_same_reservs = 1;
}
}
VEC_free (ainsn_t,heap, last_insns);
}
static reserv_sets_t
form_reservs_matter (automaton_t automaton)
{
int cycle, unit;
reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
for (cycle = 0; cycle < max_cycles_num; cycle++)
for (unit = 0; unit < description->units_num; unit++)
if (units_array [unit]->automaton_decl
== automaton->corresponding_automaton_decl
&& (cycle >= units_array [unit]->min_occ_cycle_num
|| units_array [unit]->query_p
|| units_array [unit]->in_set_p))
set_unit_reserv (reservs_matter, cycle, unit);
return reservs_matter;
}
static void
make_automaton (automaton_t automaton)
{
ainsn_t ainsn;
struct insn_reserv_decl *insn_reserv_decl;
alt_state_t alt_state;
state_t state;
state_t start_state;
state_t state2;
ainsn_t advance_cycle_ainsn;
arc_t added_arc;
VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
int states_n;
reserv_sets_t reservs_matter = form_reservs_matter (automaton);
start_state = insert_state (get_free_state (1, automaton));
automaton->start_state = start_state;
start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
VEC_safe_push (state_t,heap, state_stack, start_state);
states_n = 1;
while (VEC_length (state_t, state_stack) != 0)
{
state = VEC_pop (state_t, state_stack);
advance_cycle_ainsn = NULL;
for (ainsn = automaton->ainsn_list;
ainsn != NULL;
ainsn = ainsn->next_ainsn)
if (ainsn->first_insn_with_same_reservs)
{
insn_reserv_decl = ainsn->insn_reserv_decl;
if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
{
added_arc = NULL;
for (alt_state = ainsn->alt_states;
alt_state != NULL;
alt_state = alt_state->next_alt_state)
{
state2 = alt_state->state;
if (!intersected_state_reservs_p (state, state2))
{
state2 = states_union (state, state2, reservs_matter);
if (!state2->it_was_placed_in_stack_for_NDFA_forming)
{
state2->it_was_placed_in_stack_for_NDFA_forming
= 1;
VEC_safe_push (state_t,heap, state_stack, state2);
states_n++;
if (progress_flag && states_n % 100 == 0)
fprintf (stderr, ".");
}
added_arc = add_arc (state, state2, ainsn);
if (!ndfa_flag)
break;
}
}
if (!ndfa_flag && added_arc != NULL)
{
for (alt_state = ainsn->alt_states;
alt_state != NULL;
alt_state = alt_state->next_alt_state)
state2 = alt_state->state;
}
}
else
advance_cycle_ainsn = ainsn;
}
state2 = state_shift (state, reservs_matter);
if (!state2->it_was_placed_in_stack_for_NDFA_forming)
{
state2->it_was_placed_in_stack_for_NDFA_forming = 1;
VEC_safe_push (state_t,heap, state_stack, state2);
states_n++;
if (progress_flag && states_n % 100 == 0)
fprintf (stderr, ".");
}
gcc_assert (advance_cycle_ainsn);
add_arc (state, state2, advance_cycle_ainsn);
}
VEC_free (state_t,heap, state_stack);
}
static void
form_arcs_marked_by_insn (state_t state)
{
decl_t decl;
arc_t arc;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
}
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
{
gcc_assert (arc->insn);
arc->next_arc_marked_by_insn
= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
}
}
static int
create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
VEC(state_t,heap) **state_stack)
{
state_t state;
alt_state_t alt_state, curr_alt_state;
alt_state_t new_alt_state;
arc_t curr_arc;
arc_t next_arc;
state_t state_in_table;
state_t temp_state;
alt_state_t canonical_alt_states_list;
int alts_number;
int new_state_p = 0;
if (arcs_marked_by_insn == NULL)
return new_state_p;
if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
state = arcs_marked_by_insn->to_state;
else
{
gcc_assert (ndfa_flag);
state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
curr_alt_state = NULL;
for (curr_arc = arcs_marked_by_insn;
curr_arc != NULL;
curr_arc = curr_arc->next_arc_marked_by_insn)
if (curr_arc->to_state->component_states == NULL)
{
new_alt_state = get_free_alt_state ();
new_alt_state->next_alt_state = curr_alt_state;
new_alt_state->state = curr_arc->to_state;
curr_alt_state = new_alt_state;
}
else
for (alt_state = curr_arc->to_state->component_states;
alt_state != NULL;
alt_state = alt_state->next_sorted_alt_state)
{
new_alt_state = get_free_alt_state ();
new_alt_state->next_alt_state = curr_alt_state;
new_alt_state->state = alt_state->state;
gcc_assert (!alt_state->state->component_states);
curr_alt_state = new_alt_state;
}
canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
if (canonical_alt_states_list->next_sorted_alt_state == NULL)
{
temp_state = state;
state = canonical_alt_states_list->state;
free_state (temp_state);
}
else
{
state->component_states = canonical_alt_states_list;
state_in_table = insert_state (state);
if (state_in_table != state)
{
gcc_assert
(state_in_table->it_was_placed_in_stack_for_DFA_forming);
free_state (state);
state = state_in_table;
}
else
{
gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
new_state_p = 1;
for (curr_alt_state = state->component_states;
curr_alt_state != NULL;
curr_alt_state = curr_alt_state->next_sorted_alt_state)
for (curr_arc = first_out_arc (curr_alt_state->state);
curr_arc != NULL;
curr_arc = next_out_arc (curr_arc))
add_arc (state, curr_arc->to_state, curr_arc->insn);
}
arcs_marked_by_insn->to_state = state;
for (alts_number = 0,
curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
curr_arc != NULL;
curr_arc = next_arc)
{
next_arc = curr_arc->next_arc_marked_by_insn;
remove_arc (original_state, curr_arc);
alts_number++;
}
}
}
if (!state->it_was_placed_in_stack_for_DFA_forming)
{
state->it_was_placed_in_stack_for_DFA_forming = 1;
VEC_safe_push (state_t,heap, *state_stack, state);
}
return new_state_p;
}
static void
NDFA_to_DFA (automaton_t automaton)
{
state_t start_state;
state_t state;
decl_t decl;
VEC(state_t,heap) *state_stack;
int i;
int states_n;
state_stack = VEC_alloc (state_t,heap, 0);
start_state = automaton->start_state;
start_state->it_was_placed_in_stack_for_DFA_forming = 1;
VEC_safe_push (state_t,heap, state_stack, start_state);
states_n = 1;
while (VEC_length (state_t, state_stack) != 0)
{
state = VEC_pop (state_t, state_stack);
form_arcs_marked_by_insn (state);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv
&& create_composed_state
(state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
&state_stack))
{
states_n++;
if (progress_flag && states_n % 100 == 0)
fprintf (stderr, ".");
}
}
}
VEC_free (state_t,heap, state_stack);
}
static int curr_state_graph_pass_num;
static void
pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
{
arc_t arc;
if (start_state->pass_num == curr_state_graph_pass_num)
return;
start_state->pass_num = curr_state_graph_pass_num;
(*applied_func) (start_state);
for (arc = first_out_arc (start_state);
arc != NULL;
arc = next_out_arc (arc))
pass_state_graph (arc->to_state, applied_func);
}
static void
pass_states (automaton_t automaton, void (*applied_func) (state_t state))
{
curr_state_graph_pass_num++;
pass_state_graph (automaton->start_state, applied_func);
}
static void
initiate_pass_states (void)
{
curr_state_graph_pass_num = 0;
}
static VEC(state_t,heap) *all_achieved_states;
static void
add_achieved_state (state_t state)
{
VEC_safe_push (state_t,heap, all_achieved_states, state);
}
static void
set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
{
arc_t arc;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
{
gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
arc->insn->insn_reserv_decl->equiv_class_num
= (odd_iteration_flag
? arc->to_state->equiv_class_num_1
: arc->to_state->equiv_class_num_2);
gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
}
}
static void
clear_arc_insns_equiv_num (state_t state)
{
arc_t arc;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
arc->insn->insn_reserv_decl->equiv_class_num = 0;
}
static int
first_cycle_unit_presence (state_t state, int unit_num)
{
alt_state_t alt_state;
if (state->component_states == NULL)
return test_unit_reserv (state->reservs, 0, unit_num);
else
{
for (alt_state = state->component_states;
alt_state != NULL;
alt_state = alt_state->next_sorted_alt_state)
if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
return true;
}
return false;
}
static void
cache_presence (state_t state)
{
int i, num = 0;
unsigned int sz;
sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
/ (sizeof (int) * CHAR_BIT);
state->presence_signature = create_node (sz * sizeof (int));
for (i = 0; i < description->units_num; i++)
if (units_array [i]->query_p)
{
int presence1_p = first_cycle_unit_presence (state, i);
state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
|= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
num++;
}
}
static int
state_is_differed (state_t state, state_t another_state,
int odd_iteration_flag)
{
arc_t arc;
unsigned int sz, si;
gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
/ (sizeof (int) * CHAR_BIT);
for (si = 0; si < sz; si++)
gcc_assert (state->presence_signature[si]
== another_state->presence_signature[si]);
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
{
if ((odd_iteration_flag
? arc->to_state->equiv_class_num_1
: arc->to_state->equiv_class_num_2)
!= arc->insn->insn_reserv_decl->equiv_class_num)
return 1;
}
return 0;
}
static int
compare_states_for_equiv (const void *state_ptr_1,
const void *state_ptr_2)
{
state_t s1 = *(state_t *)state_ptr_1;
state_t s2 = *(state_t *)state_ptr_2;
unsigned int sz, si;
if (s1->num_out_arcs < s2->num_out_arcs)
return -1;
else if (s1->num_out_arcs > s2->num_out_arcs)
return 1;
sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
/ (sizeof (int) * CHAR_BIT);
for (si = 0; si < sz; si++)
if (s1->presence_signature[si] < s2->presence_signature[si])
return -1;
else if (s1->presence_signature[si] > s2->presence_signature[si])
return 1;
return 0;
}
static int
init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
{
size_t i;
state_t prev = 0;
int class_num = 1;
*classes = VEC_alloc (state_t,heap, 150);
for (i = 0; i < VEC_length (state_t, states); i++)
{
state_t state = VEC_index (state_t, states, i);
if (prev)
{
if (compare_states_for_equiv (&prev, &state) != 0)
{
VEC_safe_push (state_t,heap, *classes, prev);
class_num++;
prev = NULL;
}
}
state->equiv_class_num_1 = class_num;
state->next_equiv_class_state = prev;
prev = state;
}
if (prev)
VEC_safe_push (state_t,heap, *classes, prev);
return class_num;
}
static void
copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
{
VEC_free (state_t,heap, *to);
*to = VEC_copy (state_t,heap, from);
}
static int
partition_equiv_class (state_t first_state, int odd_iteration_flag,
VEC(state_t,heap) **next_iteration_classes,
int *new_equiv_class_num_ptr)
{
state_t new_equiv_class;
int partition_p;
state_t curr_state;
state_t prev_state;
state_t next_state;
partition_p = 0;
while (first_state != NULL)
{
new_equiv_class = NULL;
if (first_state->next_equiv_class_state != NULL)
{
set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
for (prev_state = first_state,
curr_state = first_state->next_equiv_class_state;
curr_state != NULL;
curr_state = next_state)
{
next_state = curr_state->next_equiv_class_state;
if (state_is_differed (curr_state, first_state,
odd_iteration_flag))
{
prev_state->next_equiv_class_state = next_state;
curr_state->next_equiv_class_state = new_equiv_class;
if (new_equiv_class == NULL)
(*new_equiv_class_num_ptr)++;
if (odd_iteration_flag)
curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
else
curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
new_equiv_class = curr_state;
partition_p = 1;
}
else
prev_state = curr_state;
}
clear_arc_insns_equiv_num (first_state);
}
if (new_equiv_class != NULL)
VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
first_state = new_equiv_class;
}
return partition_p;
}
static void
evaluate_equiv_classes (automaton_t automaton,
VEC(state_t,heap) **equiv_classes)
{
int new_equiv_class_num;
int odd_iteration_flag;
int finish_flag;
VEC (state_t,heap) *next_iteration_classes;
size_t i;
all_achieved_states = VEC_alloc (state_t,heap, 1500);
pass_states (automaton, add_achieved_state);
pass_states (automaton, cache_presence);
qsort (VEC_address (state_t, all_achieved_states),
VEC_length (state_t, all_achieved_states),
sizeof (state_t), compare_states_for_equiv);
odd_iteration_flag = 0;
new_equiv_class_num = init_equiv_class (all_achieved_states,
&next_iteration_classes);
do
{
odd_iteration_flag = !odd_iteration_flag;
finish_flag = 1;
copy_equiv_class (equiv_classes, next_iteration_classes);
for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
if (odd_iteration_flag)
VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
= VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
else
VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
= VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
odd_iteration_flag,
&next_iteration_classes,
&new_equiv_class_num))
finish_flag = 0;
}
while (!finish_flag);
VEC_free (state_t,heap, next_iteration_classes);
VEC_free (state_t,heap, all_achieved_states);
}
static void
merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
{
state_t curr_state;
state_t new_state;
state_t first_class_state;
alt_state_t alt_states;
alt_state_t alt_state, new_alt_state;
arc_t curr_arc;
arc_t next_arc;
size_t i;
for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
{
curr_state = VEC_index (state_t, equiv_classes, i);
if (curr_state->next_equiv_class_state != NULL)
{
new_state = get_free_state (0, automaton);
alt_states = NULL;
first_class_state = curr_state;
for (curr_state = first_class_state;
curr_state != NULL;
curr_state = curr_state->next_equiv_class_state)
{
curr_state->equiv_class_state = new_state;
if (curr_state->component_states == NULL)
{
new_alt_state = get_free_alt_state ();
new_alt_state->state = curr_state;
new_alt_state->next_alt_state = alt_states;
alt_states = new_alt_state;
}
else
for (alt_state = curr_state->component_states;
alt_state != NULL;
alt_state = alt_state->next_sorted_alt_state)
{
new_alt_state = get_free_alt_state ();
new_alt_state->state = alt_state->state;
new_alt_state->next_alt_state = alt_states;
alt_states = new_alt_state;
}
}
new_state->component_states = uniq_sort_alt_states (alt_states);
}
else
curr_state->equiv_class_state = curr_state;
}
for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
{
curr_state = VEC_index (state_t, equiv_classes, i);
if (curr_state->next_equiv_class_state != NULL)
{
first_class_state = curr_state;
for (curr_arc = first_out_arc (first_class_state);
curr_arc != NULL;
curr_arc = next_out_arc (curr_arc))
add_arc (first_class_state->equiv_class_state,
curr_arc->to_state->equiv_class_state,
curr_arc->insn);
for (curr_state = first_class_state;
curr_state != NULL;
curr_state = curr_state->next_equiv_class_state)
{
if (automaton->start_state == curr_state)
automaton->start_state = curr_state->equiv_class_state;
for (curr_arc = first_out_arc (curr_state);
curr_arc != NULL;
curr_arc = next_arc)
{
next_arc = next_out_arc (curr_arc);
free_arc (curr_arc);
}
}
}
else
{
for (curr_arc = first_out_arc (curr_state);
curr_arc != NULL;
curr_arc = next_out_arc (curr_arc))
curr_arc->to_state = curr_arc->to_state->equiv_class_state;
}
}
}
static void
set_new_cycle_flags (state_t state)
{
arc_t arc;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
if (arc->insn->insn_reserv_decl
== DECL_INSN_RESERV (advance_cycle_insn_decl))
arc->to_state->new_cycle_p = 1;
}
static void
minimize_DFA (automaton_t automaton)
{
VEC(state_t,heap) *equiv_classes = 0;
evaluate_equiv_classes (automaton, &equiv_classes);
merge_states (automaton, equiv_classes);
pass_states (automaton, set_new_cycle_flags);
VEC_free (state_t,heap, equiv_classes);
}
static int curr_counted_states_num;
static int curr_counted_arcs_num;
static void
incr_states_and_arcs_nums (state_t state)
{
arc_t arc;
curr_counted_states_num++;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
curr_counted_arcs_num++;
}
static void
count_states_and_arcs (automaton_t automaton, int *states_num,
int *arcs_num)
{
curr_counted_states_num = 0;
curr_counted_arcs_num = 0;
pass_states (automaton, incr_states_and_arcs_nums);
*states_num = curr_counted_states_num;
*arcs_num = curr_counted_arcs_num;
}
static void
build_automaton (automaton_t automaton)
{
int states_num;
int arcs_num;
ticker_on (&NDFA_time);
if (progress_flag)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (stderr, "Create anonymous automaton");
else
fprintf (stderr, "Create automaton `%s'",
automaton->corresponding_automaton_decl->name);
fprintf (stderr, " (1 dot is 100 new states):");
}
make_automaton (automaton);
if (progress_flag)
fprintf (stderr, " done\n");
ticker_off (&NDFA_time);
count_states_and_arcs (automaton, &states_num, &arcs_num);
automaton->NDFA_states_num = states_num;
automaton->NDFA_arcs_num = arcs_num;
ticker_on (&NDFA_to_DFA_time);
if (progress_flag)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (stderr, "Make anonymous DFA");
else
fprintf (stderr, "Make DFA `%s'",
automaton->corresponding_automaton_decl->name);
fprintf (stderr, " (1 dot is 100 new states):");
}
NDFA_to_DFA (automaton);
if (progress_flag)
fprintf (stderr, " done\n");
ticker_off (&NDFA_to_DFA_time);
count_states_and_arcs (automaton, &states_num, &arcs_num);
automaton->DFA_states_num = states_num;
automaton->DFA_arcs_num = arcs_num;
if (!no_minimization_flag)
{
ticker_on (&minimize_time);
if (progress_flag)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (stderr, "Minimize anonymous DFA...");
else
fprintf (stderr, "Minimize DFA `%s'...",
automaton->corresponding_automaton_decl->name);
}
minimize_DFA (automaton);
if (progress_flag)
fprintf (stderr, "done\n");
ticker_off (&minimize_time);
count_states_and_arcs (automaton, &states_num, &arcs_num);
automaton->minimal_DFA_states_num = states_num;
automaton->minimal_DFA_arcs_num = arcs_num;
}
}
static int curr_state_order_num;
static void
set_order_state_num (state_t state)
{
state->order_state_num = curr_state_order_num;
curr_state_order_num++;
}
static void
enumerate_states (automaton_t automaton)
{
curr_state_order_num = 0;
pass_states (automaton, set_order_state_num);
automaton->achieved_states_num = curr_state_order_num;
}
static ainsn_t
insert_ainsn_into_equiv_class (ainsn_t ainsn,
ainsn_t cyclic_equiv_class_insn_list)
{
if (cyclic_equiv_class_insn_list == NULL)
ainsn->next_equiv_class_insn = ainsn;
else
{
ainsn->next_equiv_class_insn
= cyclic_equiv_class_insn_list->next_equiv_class_insn;
cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
}
return ainsn;
}
static void
delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
{
ainsn_t curr_equiv_class_insn;
ainsn_t prev_equiv_class_insn;
prev_equiv_class_insn = equiv_class_insn;
for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
curr_equiv_class_insn != equiv_class_insn;
curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
prev_equiv_class_insn = curr_equiv_class_insn;
if (prev_equiv_class_insn != equiv_class_insn)
prev_equiv_class_insn->next_equiv_class_insn
= equiv_class_insn->next_equiv_class_insn;
}
static void
process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
{
ainsn_t next_insn;
ainsn_t curr_insn;
ainsn_t cyclic_insn_list;
arc_t arc;
gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
curr_insn = ainsn;
cyclic_insn_list = NULL;
do
{
next_insn = curr_insn->next_equiv_class_insn;
arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
if (arc == NULL
|| (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
!= arc->to_state))
{
delete_ainsn_from_equiv_class (curr_insn);
cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
cyclic_insn_list);
}
curr_insn = next_insn;
}
while (curr_insn != ainsn);
}
static void
process_state_for_insn_equiv_partition (state_t state)
{
arc_t arc;
arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
process_insn_equiv_class (arc->insn, insn_arcs_array);
free (insn_arcs_array);
}
static void
set_insn_equiv_classes (automaton_t automaton)
{
ainsn_t ainsn;
ainsn_t first_insn;
ainsn_t curr_insn;
ainsn_t cyclic_insn_list;
ainsn_t insn_with_same_reservs;
int equiv_classes_num;
cyclic_insn_list = NULL;
for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
if (ainsn->first_insn_with_same_reservs)
cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
cyclic_insn_list);
pass_states (automaton, process_state_for_insn_equiv_partition);
for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
ainsn->insn_equiv_class_num = -1;
equiv_classes_num = 0;
for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
if (ainsn->insn_equiv_class_num < 0)
{
first_insn = ainsn;
gcc_assert (first_insn->first_insn_with_same_reservs);
first_insn->first_ainsn_with_given_equivalence_num = 1;
curr_insn = first_insn;
do
{
for (insn_with_same_reservs = curr_insn;
insn_with_same_reservs != NULL;
insn_with_same_reservs
= insn_with_same_reservs->next_same_reservs_insn)
insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
curr_insn = curr_insn->next_equiv_class_insn;
}
while (curr_insn != first_insn);
equiv_classes_num++;
}
automaton->insn_equiv_classes_num = equiv_classes_num;
}
#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
static double
estimate_one_automaton_bound (void)
{
decl_t decl;
double one_automaton_estimation_bound;
double root_value;
int i;
one_automaton_estimation_bound = 1.0;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
{
root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
- DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
/ automata_num);
if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
> one_automaton_estimation_bound)
one_automaton_estimation_bound *= root_value;
}
}
return one_automaton_estimation_bound;
}
static int
compare_max_occ_cycle_nums (const void *unit_decl_1,
const void *unit_decl_2)
{
if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
< (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
return 1;
else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
== (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
return 0;
else
return -1;
}
static void
units_to_automata_heuristic_distr (void)
{
double estimation_bound;
int automaton_num;
int rest_units_num;
double bound_value;
unit_decl_t *unit_decls;
int i, j;
if (description->units_num == 0)
return;
estimation_bound = estimate_one_automaton_bound ();
unit_decls = XNEWVEC (unit_decl_t, description->units_num);
for (i = 0, j = 0; i < description->decls_num; i++)
if (description->decls[i]->mode == dm_unit)
unit_decls[j++] = DECL_UNIT (description->decls[i]);
gcc_assert (j == description->units_num);
qsort (unit_decls, description->units_num,
sizeof (unit_decl_t), compare_max_occ_cycle_nums);
automaton_num = 0;
bound_value = unit_decls[0]->max_occ_cycle_num;
unit_decls[0]->corresponding_automaton_num = automaton_num;
for (i = 1; i < description->units_num; i++)
{
rest_units_num = description->units_num - i + 1;
gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
if (automaton_num < automata_num - 1
&& ((automata_num - automaton_num - 1 == rest_units_num)
|| (bound_value
> (estimation_bound
/ unit_decls[i]->max_occ_cycle_num))))
{
bound_value = unit_decls[i]->max_occ_cycle_num;
automaton_num++;
}
else
bound_value *= unit_decls[i]->max_occ_cycle_num;
unit_decls[i]->corresponding_automaton_num = automaton_num;
}
gcc_assert (automaton_num == automata_num - 1);
free (unit_decls);
}
static ainsn_t
create_ainsns (void)
{
decl_t decl;
ainsn_t first_ainsn;
ainsn_t curr_ainsn;
ainsn_t prev_ainsn;
int i;
first_ainsn = NULL;
prev_ainsn = NULL;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
{
curr_ainsn = create_node (sizeof (struct ainsn));
curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
curr_ainsn->important_p = FALSE;
curr_ainsn->next_ainsn = NULL;
if (prev_ainsn == NULL)
first_ainsn = curr_ainsn;
else
prev_ainsn->next_ainsn = curr_ainsn;
prev_ainsn = curr_ainsn;
}
}
return first_ainsn;
}
static void
units_to_automata_distr (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
{
if (DECL_UNIT (decl)->automaton_decl == NULL
|| (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
== NULL))
DECL_UNIT (decl)->corresponding_automaton_num = 0;
else
DECL_UNIT (decl)->corresponding_automaton_num
= (DECL_UNIT (decl)->automaton_decl
->corresponding_automaton->automaton_order_num);
}
}
}
static void
create_automata (void)
{
automaton_t curr_automaton;
automaton_t prev_automaton;
decl_t decl;
int curr_automaton_num;
int i;
if (automata_num != 0)
{
units_to_automata_heuristic_distr ();
for (prev_automaton = NULL, curr_automaton_num = 0;
curr_automaton_num < automata_num;
curr_automaton_num++, prev_automaton = curr_automaton)
{
curr_automaton = create_node (sizeof (struct automaton));
curr_automaton->ainsn_list = create_ainsns ();
curr_automaton->corresponding_automaton_decl = NULL;
curr_automaton->next_automaton = NULL;
curr_automaton->automaton_order_num = curr_automaton_num;
if (prev_automaton == NULL)
description->first_automaton = curr_automaton;
else
prev_automaton->next_automaton = curr_automaton;
}
}
else
{
curr_automaton_num = 0;
prev_automaton = NULL;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_automaton
&& DECL_AUTOMATON (decl)->automaton_is_used)
{
curr_automaton = create_node (sizeof (struct automaton));
curr_automaton->ainsn_list = create_ainsns ();
curr_automaton->corresponding_automaton_decl
= DECL_AUTOMATON (decl);
curr_automaton->next_automaton = NULL;
DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
curr_automaton->automaton_order_num = curr_automaton_num;
if (prev_automaton == NULL)
description->first_automaton = curr_automaton;
else
prev_automaton->next_automaton = curr_automaton;
curr_automaton_num++;
prev_automaton = curr_automaton;
}
}
if (curr_automaton_num == 0)
{
curr_automaton = create_node (sizeof (struct automaton));
curr_automaton->ainsn_list = create_ainsns ();
curr_automaton->corresponding_automaton_decl = NULL;
curr_automaton->next_automaton = NULL;
description->first_automaton = curr_automaton;
}
units_to_automata_distr ();
}
NDFA_time = create_ticker ();
ticker_off (&NDFA_time);
NDFA_to_DFA_time = create_ticker ();
ticker_off (&NDFA_to_DFA_time);
minimize_time = create_ticker ();
ticker_off (&minimize_time);
equiv_time = create_ticker ();
ticker_off (&equiv_time);
for (curr_automaton = description->first_automaton;
curr_automaton != NULL;
curr_automaton = curr_automaton->next_automaton)
{
if (progress_flag)
{
if (curr_automaton->corresponding_automaton_decl == NULL)
fprintf (stderr, "Prepare anonymous automaton creation ... ");
else
fprintf (stderr, "Prepare automaton `%s' creation...",
curr_automaton->corresponding_automaton_decl->name);
}
create_alt_states (curr_automaton);
form_ainsn_with_same_reservs (curr_automaton);
if (progress_flag)
fprintf (stderr, "done\n");
build_automaton (curr_automaton);
enumerate_states (curr_automaton);
ticker_on (&equiv_time);
set_insn_equiv_classes (curr_automaton);
ticker_off (&equiv_time);
}
}
static void
form_regexp (regexp_t regexp)
{
int i;
switch (regexp->mode)
{
case rm_unit: case rm_reserv:
{
const char *name = (regexp->mode == rm_unit
? REGEXP_UNIT (regexp)->name
: REGEXP_RESERV (regexp)->name);
obstack_grow (&irp, name, strlen (name));
break;
}
case rm_sequence:
for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
{
if (i != 0)
obstack_1grow (&irp, ',');
form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
}
break;
case rm_allof:
obstack_1grow (&irp, '(');
for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
{
if (i != 0)
obstack_1grow (&irp, '+');
if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
|| REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
obstack_1grow (&irp, '(');
form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
|| REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
obstack_1grow (&irp, ')');
}
obstack_1grow (&irp, ')');
break;
case rm_oneof:
for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
{
if (i != 0)
obstack_1grow (&irp, '|');
if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
obstack_1grow (&irp, '(');
form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
obstack_1grow (&irp, ')');
}
break;
case rm_repeat:
{
char digits [30];
if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
|| REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
|| REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
obstack_1grow (&irp, '(');
form_regexp (REGEXP_REPEAT (regexp)->regexp);
if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
|| REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
|| REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
obstack_1grow (&irp, ')');
sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
obstack_grow (&irp, digits, strlen (digits));
break;
}
case rm_nothing:
obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
break;
default:
gcc_unreachable ();
}
}
static const char *
regexp_representation (regexp_t regexp)
{
form_regexp (regexp);
obstack_1grow (&irp, '\0');
return obstack_base (&irp);
}
static void
finish_regexp_representation (void)
{
int length = obstack_object_size (&irp);
obstack_blank_fast (&irp, -length);
}
static void
output_range_type (FILE *f, long int min_range_value,
long int max_range_value)
{
if (min_range_value >= 0 && max_range_value <= 255)
fprintf (f, "unsigned char");
else if (min_range_value >= -127 && max_range_value <= 127)
fprintf (f, "signed char");
else if (min_range_value >= 0 && max_range_value <= 65535)
fprintf (f, "unsigned short");
else if (min_range_value >= -32767 && max_range_value <= 32767)
fprintf (f, "short");
else
fprintf (f, "int");
}
#define ON_THE_PATH -2
static int
longest_path_length (state_t state)
{
arc_t arc;
int length, result;
if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
{
gcc_assert (state->longest_path_length != ON_THE_PATH);
return state->longest_path_length;
}
result = 0;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
if (arc->to_state != state
&& (arc->insn->insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl)))
{
length = longest_path_length (arc->to_state);
if (length > result)
result = length;
}
state->longest_path_length = result + 1;
return result;
}
static void
output_vect (vla_hwint_t vect)
{
int els_on_line;
size_t vect_length = VEC_length (vect_el_t, vect);
size_t i;
els_on_line = 1;
if (vect_length == 0)
fputs ("0 /* This is dummy el because the vect is empty */", output_file);
else
for (i = 0; i < vect_length; i++)
{
fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
if (els_on_line == 10)
{
els_on_line = 0;
fputs (",\n", output_file);
}
else if (i < vect_length-1)
fputs (", ", output_file);
els_on_line++;
}
}
#define CHIP_NAME "DFA_chip"
static void
output_chip_member_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_automaton_state",
automaton->corresponding_automaton_decl->name);
}
static void
output_temp_chip_member_name (FILE *f, automaton_t automaton)
{
fprintf (f, "_");
output_chip_member_name (f, automaton);
}
#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
static void
output_translate_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "translate_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
}
static void
output_trans_full_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "transitions_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_transitions",
automaton->corresponding_automaton_decl->name);
}
static void
output_trans_comb_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "transitions_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_transitions",
automaton->corresponding_automaton_decl->name);
}
static void
output_trans_check_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "check_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
}
static void
output_trans_base_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "base_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
}
static void
output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_min_issue_delay",
automaton->corresponding_automaton_decl->name);
}
static void
output_dead_lock_vect_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
}
static void
output_reserved_units_table_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
else
fprintf (f, "%s_reserved_units",
automaton->corresponding_automaton_decl->name);
}
#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
#define STATE_TYPE_NAME "state_t"
#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
#define INTERNAL_RESET_FUNC_NAME "internal_reset"
#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
#define SIZE_FUNC_NAME "state_size"
#define TRANSITION_FUNC_NAME "state_transition"
#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
#define RESET_FUNC_NAME "state_reset"
#define INSN_LATENCY_FUNC_NAME "insn_latency"
#define PRINT_RESERVATION_FUNC_NAME "print_reservation"
#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
#define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
#define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
#define DFA_START_FUNC_NAME "dfa_start"
#define DFA_FINISH_FUNC_NAME "dfa_finish"
#define STATE_NAME "state"
#define INSN_PARAMETER_NAME "insn"
#define INSN2_PARAMETER_NAME "insn2"
#define CHIP_PARAMETER_NAME "chip"
#define FILE_PARAMETER_NAME "f"
#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
#define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
#define INTERNAL_INSN_CODE_NAME "insn_code"
#define INTERNAL_INSN2_CODE_NAME "insn2_code"
#define TEMPORARY_VARIABLE_NAME "temp"
#define I_VARIABLE_NAME "i"
#define RESULT_VARIABLE_NAME "res"
#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
static void
output_state_member_type (FILE *f, automaton_t automaton)
{
output_range_type (f, 0, automaton->achieved_states_num);
}
static void
output_chip_definitions (void)
{
automaton_t automaton;
fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
fprintf (output_file, " ");
output_state_member_type (output_file, automaton);
fprintf (output_file, " ");
output_chip_member_name (output_file, automaton);
fprintf (output_file, ";\n");
}
fprintf (output_file, "};\n\n");
#if 0
fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
#endif
}
static void
output_translate_vect (automaton_t automaton)
{
ainsn_t ainsn;
int insn_value;
vla_hwint_t translate_vect;
translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
for (insn_value = 0; insn_value < description->insns_num; insn_value++)
VEC_quick_push (vect_el_t, translate_vect,
automaton->insn_equiv_classes_num);
for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
VEC_replace (vect_el_t, translate_vect,
ainsn->insn_reserv_decl->insn_num,
ainsn->insn_equiv_class_num);
fprintf (output_file,
"/* Vector translating external insn codes to internal ones.*/\n");
fprintf (output_file, "static const ");
output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
fprintf (output_file, " ");
output_translate_vect_name (output_file, automaton);
fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
output_vect (translate_vect);
fprintf (output_file, "};\n\n");
VEC_free (vect_el_t,heap, translate_vect);
}
static int undefined_vect_el_value;
static int
comb_vect_p (state_ainsn_table_t tab)
{
return (2 * VEC_length (vect_el_t, tab->full_vect)
> 5 * VEC_length (vect_el_t, tab->comb_vect));
}
static state_ainsn_table_t
create_state_ainsn_table (automaton_t automaton)
{
state_ainsn_table_t tab;
int full_vect_length;
int i;
tab = create_node (sizeof (struct state_ainsn_table));
tab->automaton = automaton;
tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
tab->base_vect = 0;
VEC_safe_grow (vect_el_t,heap, tab->base_vect,
automaton->achieved_states_num);
full_vect_length = (automaton->insn_equiv_classes_num
* automaton->achieved_states_num);
tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
for (i = 0; i < full_vect_length; i++)
VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
tab->min_base_vect_el_value = 0;
tab->max_base_vect_el_value = 0;
tab->min_comb_vect_el_value = 0;
tab->max_comb_vect_el_value = 0;
return tab;
}
static void
output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
void (*output_full_vect_name_func) (FILE *, automaton_t),
void (*output_comb_vect_name_func) (FILE *, automaton_t),
void (*output_check_vect_name_func) (FILE *, automaton_t),
void (*output_base_vect_name_func) (FILE *, automaton_t))
{
if (!comb_vect_p (tab))
{
fprintf (output_file, "/* Vector for %s. */\n", table_name);
fprintf (output_file, "static const ");
output_range_type (output_file, tab->min_comb_vect_el_value,
tab->max_comb_vect_el_value);
fprintf (output_file, " ");
(*output_full_vect_name_func) (output_file, tab->automaton);
fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
output_vect (tab->full_vect);
fprintf (output_file, "};\n\n");
}
else
{
fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
fprintf (output_file, "static const ");
output_range_type (output_file, tab->min_comb_vect_el_value,
tab->max_comb_vect_el_value);
fprintf (output_file, " ");
(*output_comb_vect_name_func) (output_file, tab->automaton);
fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
output_vect (tab->comb_vect);
fprintf (output_file, "};\n\n");
fprintf (output_file, "/* Check vector for %s. */\n", table_name);
fprintf (output_file, "static const ");
output_range_type (output_file, 0, tab->automaton->achieved_states_num);
fprintf (output_file, " ");
(*output_check_vect_name_func) (output_file, tab->automaton);
fprintf (output_file, "[] = {\n");
output_vect (tab->check_vect);
fprintf (output_file, "};\n\n");
fprintf (output_file, "/* Base vector for %s. */\n", table_name);
fprintf (output_file, "static const ");
output_range_type (output_file, tab->min_base_vect_el_value,
tab->max_base_vect_el_value);
fprintf (output_file, " ");
(*output_base_vect_name_func) (output_file, tab->automaton);
fprintf (output_file, "[] = {\n");
output_vect (tab->base_vect);
fprintf (output_file, "};\n\n");
}
}
static void
add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
{
int vect_length;
size_t real_vect_length;
int comb_vect_index;
int comb_vect_els_num;
int vect_index;
int first_unempty_vect_index;
int additional_els_num;
int no_state_value;
vect_el_t vect_el;
int i;
unsigned long vect_mask, comb_vect_mask;
vect_length = VEC_length (vect_el_t, vect);
gcc_assert (vect_length);
gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
real_vect_length = tab->automaton->insn_equiv_classes_num;
{
size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
VEC_safe_grow (vect_el_t,heap, tab->full_vect,
full_base + vect_length);
for (i = 0; i < vect_length; i++)
VEC_replace (vect_el_t, tab->full_vect, full_base + i,
VEC_index (vect_el_t, vect, i));
}
gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
== VEC_length (vect_el_t, tab->check_vect));
comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
for (first_unempty_vect_index = 0;
first_unempty_vect_index < vect_length;
first_unempty_vect_index++)
if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
!= undefined_vect_el_value)
break;
if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
{
for (comb_vect_index = 0;
comb_vect_index < comb_vect_els_num;
comb_vect_index++)
{
for (vect_index = first_unempty_vect_index;
vect_index < vect_length
&& vect_index + comb_vect_index < comb_vect_els_num;
vect_index++)
if (VEC_index (vect_el_t, vect, vect_index)
!= undefined_vect_el_value
&& (VEC_index (vect_el_t, tab->comb_vect,
vect_index + comb_vect_index)
!= undefined_vect_el_value))
break;
if (vect_index >= vect_length
|| vect_index + comb_vect_index >= comb_vect_els_num)
break;
}
goto found;
}
vect_mask = 0;
for (vect_index = first_unempty_vect_index;
vect_index < vect_length;
vect_index++)
{
vect_mask = vect_mask << 1;
if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
vect_mask |= 1;
}
comb_vect_index = 0;
if (comb_vect_els_num == 0)
goto found;
comb_vect_mask = 0;
for (vect_index = first_unempty_vect_index;
vect_index < vect_length && vect_index < comb_vect_els_num;
vect_index++)
{
comb_vect_mask <<= 1;
if (vect_index + comb_vect_index < comb_vect_els_num
&& VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
!= undefined_vect_el_value)
comb_vect_mask |= 1;
}
if ((vect_mask & comb_vect_mask) == 0)
goto found;
for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
comb_vect_index++, i++)
{
comb_vect_mask = (comb_vect_mask << 1) | 1;
comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
== undefined_vect_el_value);
if ((vect_mask & comb_vect_mask) == 0)
goto found;
}
for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
{
comb_vect_mask <<= 1;
if ((vect_mask & comb_vect_mask) == 0)
goto found;
}
found:
additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
if (additional_els_num < 0)
additional_els_num = 0;
vect_el = undefined_vect_el_value;
no_state_value = tab->automaton->achieved_states_num;
while (additional_els_num > 0)
{
VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
additional_els_num--;
}
gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
>= comb_vect_index + real_vect_length);
for (vect_index = 0; vect_index < vect_length; vect_index++)
if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
{
vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
comb_vect_index + vect_index)
== undefined_vect_el_value);
gcc_assert (x >= 0);
if (tab->max_comb_vect_el_value < x)
tab->max_comb_vect_el_value = x;
if (tab->min_comb_vect_el_value > x)
tab->min_comb_vect_el_value = x;
VEC_replace (vect_el_t, tab->comb_vect,
comb_vect_index + vect_index, x);
VEC_replace (vect_el_t, tab->check_vect,
comb_vect_index + vect_index, vect_num);
}
if (tab->max_comb_vect_el_value < undefined_vect_el_value)
tab->max_comb_vect_el_value = undefined_vect_el_value;
if (tab->min_comb_vect_el_value > undefined_vect_el_value)
tab->min_comb_vect_el_value = undefined_vect_el_value;
if (tab->max_base_vect_el_value < comb_vect_index)
tab->max_base_vect_el_value = comb_vect_index;
if (tab->min_base_vect_el_value > comb_vect_index)
tab->min_base_vect_el_value = comb_vect_index;
VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
}
static int
out_state_arcs_num (state_t state)
{
int result;
arc_t arc;
result = 0;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
{
gcc_assert (arc->insn);
if (arc->insn->first_ainsn_with_given_equivalence_num)
result++;
}
return result;
}
static int
compare_transition_els_num (const void *state_ptr_1,
const void *state_ptr_2)
{
int transition_els_num_1;
int transition_els_num_2;
transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
if (transition_els_num_1 < transition_els_num_2)
return 1;
else if (transition_els_num_1 == transition_els_num_2)
return 0;
else
return -1;
}
static void
add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
{
int equiv_class_num;
int vect_index;
gcc_assert (ainsn);
equiv_class_num = ainsn->insn_equiv_class_num;
for (vect_index = VEC_length (vect_el_t, *vect);
vect_index <= equiv_class_num;
vect_index++)
VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
}
static VEC(state_t,heap) *output_states_vect;
static void
add_states_vect_el (state_t state)
{
VEC_safe_push (state_t,heap, output_states_vect, state);
}
static void
output_trans_table (automaton_t automaton)
{
size_t i;
arc_t arc;
vla_hwint_t transition_vect = 0;
undefined_vect_el_value = automaton->achieved_states_num;
automaton->trans_table = create_state_ainsn_table (automaton);
output_states_vect = 0;
pass_states (automaton, add_states_vect_el);
qsort (VEC_address (state_t, output_states_vect),
VEC_length (state_t, output_states_vect),
sizeof (state_t), compare_transition_els_num);
for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
{
VEC_truncate (vect_el_t, transition_vect, 0);
for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
arc != NULL;
arc = next_out_arc (arc))
{
gcc_assert (arc->insn);
if (arc->insn->first_ainsn_with_given_equivalence_num)
add_vect_el (&transition_vect, arc->insn,
arc->to_state->order_state_num);
}
add_vect (automaton->trans_table,
VEC_index (state_t, output_states_vect, i)->order_state_num,
transition_vect);
}
output_state_ainsn_table
(automaton->trans_table, "state transitions",
output_trans_full_vect_name, output_trans_comb_vect_name,
output_trans_check_vect_name, output_trans_base_vect_name);
VEC_free (state_t,heap, output_states_vect);
VEC_free (vect_el_t,heap, transition_vect);
}
static int curr_state_pass_num;
static int
min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
{
arc_t arc;
int min_insn_issue_delay, insn_issue_delay;
if (state->state_pass_num == curr_state_pass_num
|| state->min_insn_issue_delay != -1)
return state->min_insn_issue_delay;
state->state_pass_num = curr_state_pass_num;
min_insn_issue_delay = -1;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
if (arc->insn == ainsn)
{
min_insn_issue_delay = 0;
break;
}
else
{
insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
if (insn_issue_delay != -1)
{
if (arc->insn->insn_reserv_decl
== DECL_INSN_RESERV (advance_cycle_insn_decl))
insn_issue_delay++;
if (min_insn_issue_delay == -1
|| min_insn_issue_delay > insn_issue_delay)
{
min_insn_issue_delay = insn_issue_delay;
if (insn_issue_delay == 0)
break;
}
}
}
return min_insn_issue_delay;
}
static int
min_issue_delay (state_t state, ainsn_t ainsn)
{
curr_state_pass_num++;
state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
return state->min_insn_issue_delay;
}
static void
initiate_min_issue_delay_pass_states (void)
{
curr_state_pass_num = 0;
}
static void
output_min_issue_delay_table (automaton_t automaton)
{
vla_hwint_t min_issue_delay_vect;
vla_hwint_t compressed_min_issue_delay_vect;
vect_el_t min_delay;
ainsn_t ainsn;
size_t i, min_issue_delay_len;
size_t compressed_min_issue_delay_len;
size_t cfactor;
output_states_vect = 0;
pass_states (automaton, add_states_vect_el);
min_issue_delay_len = (VEC_length (state_t, output_states_vect)
* automaton->insn_equiv_classes_num);
min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
for (i = 0; i < min_issue_delay_len; i++)
VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
automaton->max_min_delay = 0;
for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
if (ainsn->first_ainsn_with_given_equivalence_num)
{
for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
{
state_t s = VEC_index (state_t, output_states_vect, i);
min_delay = min_issue_delay (s, ainsn);
if (automaton->max_min_delay < min_delay)
automaton->max_min_delay = min_delay;
VEC_replace (vect_el_t, min_issue_delay_vect,
s->order_state_num
* automaton->insn_equiv_classes_num
+ ainsn->insn_equiv_class_num,
min_delay);
}
}
fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
fprintf (output_file, "static const ");
output_range_type (output_file, 0, automaton->max_min_delay);
fprintf (output_file, " ");
output_min_issue_delay_vect_name (output_file, automaton);
fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
if (automaton->max_min_delay < 2)
cfactor = 8;
else if (automaton->max_min_delay < 4)
cfactor = 4;
else if (automaton->max_min_delay < 16)
cfactor = 2;
else
cfactor = 1;
automaton->min_issue_delay_table_compression_factor = cfactor;
compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
compressed_min_issue_delay_vect
= VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
for (i = 0; i < compressed_min_issue_delay_len; i++)
VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
for (i = 0; i < min_issue_delay_len; i++)
{
size_t ci = i / cfactor;
vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
}
output_vect (compressed_min_issue_delay_vect);
fprintf (output_file, "};\n\n");
VEC_free (state_t,heap, output_states_vect);
VEC_free (vect_el_t,heap, min_issue_delay_vect);
VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
}
static void
output_dead_lock_vect (automaton_t automaton)
{
size_t i;
arc_t arc;
vla_hwint_t dead_lock_vect = 0;
automaton->locked_states = 0;
output_states_vect = 0;
pass_states (automaton, add_states_vect_el);
VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
VEC_length (state_t, output_states_vect));
for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
{
state_t s = VEC_index (state_t, output_states_vect, i);
arc = first_out_arc (s);
gcc_assert (arc);
if (next_out_arc (arc) == NULL
&& (arc->insn->insn_reserv_decl
== DECL_INSN_RESERV (advance_cycle_insn_decl)))
{
VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
automaton->locked_states++;
}
else
VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
}
if (automaton->locked_states == 0)
return;
fprintf (output_file, "/* Vector for locked state flags. */\n");
fprintf (output_file, "static const ");
output_range_type (output_file, 0, 1);
fprintf (output_file, " ");
output_dead_lock_vect_name (output_file, automaton);
fprintf (output_file, "[] = {\n");
output_vect (dead_lock_vect);
fprintf (output_file, "};\n\n");
VEC_free (state_t,heap, output_states_vect);
VEC_free (vect_el_t,heap, dead_lock_vect);
}
static void
output_reserved_units_table (automaton_t automaton)
{
vla_hwint_t reserved_units_table = 0;
int state_byte_size;
int reserved_units_size;
size_t n;
int i;
if (description->query_units_num == 0)
return;
output_states_vect = 0;
pass_states (automaton, add_states_vect_el);
state_byte_size = (description->query_units_num + 7) / 8;
reserved_units_size = (VEC_length (state_t, output_states_vect)
* state_byte_size);
reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
for (i = 0; i < reserved_units_size; i++)
VEC_quick_push (vect_el_t, reserved_units_table, 0);
for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
{
state_t s = VEC_index (state_t, output_states_vect, n);
for (i = 0; i < description->units_num; i++)
if (units_array [i]->query_p
&& first_cycle_unit_presence (s, i))
{
int ri = (s->order_state_num * state_byte_size
+ units_array [i]->query_num / 8);
vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
x += 1 << (units_array [i]->query_num % 8);
VEC_replace (vect_el_t, reserved_units_table, ri, x);
}
}
fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
fprintf (output_file, "/* Vector for reserved units of states. */\n");
fprintf (output_file, "static const ");
output_range_type (output_file, 0, 255);
fprintf (output_file, " ");
output_reserved_units_table_name (output_file, automaton);
fprintf (output_file, "[] = {\n");
output_vect (reserved_units_table);
fprintf (output_file, "};\n#endif /* #if %s */\n\n",
CPU_UNITS_QUERY_MACRO_NAME);
VEC_free (state_t,heap, output_states_vect);
VEC_free (vect_el_t,heap, reserved_units_table);
}
static void
output_tables (void)
{
automaton_t automaton;
initiate_min_issue_delay_pass_states ();
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
output_translate_vect (automaton);
output_trans_table (automaton);
output_min_issue_delay_table (automaton);
output_dead_lock_vect (automaton);
output_reserved_units_table (automaton);
}
fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
}
static void
output_max_insn_queue_index_def (void)
{
int i, max, latency;
decl_t decl;
max = description->max_insn_reserv_cycles;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
{
latency = DECL_INSN_RESERV (decl)->default_latency;
if (latency > max)
max = latency;
}
else if (decl->mode == dm_bypass)
{
latency = DECL_BYPASS (decl)->latency;
if (latency > max)
max = latency;
}
}
for (i = 0; (1 << i) <= max; i++)
;
gcc_assert (i >= 0);
fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
(1 << i) - 1);
}
static void
output_insn_code_cases (void (*output_automata_list_code)
(automata_list_el_t))
{
decl_t decl, decl2;
int i, j;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
DECL_INSN_RESERV (decl)->processed_p = FALSE;
}
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv
&& !DECL_INSN_RESERV (decl)->processed_p)
{
for (j = i; j < description->decls_num; j++)
{
decl2 = description->decls [j];
if (decl2->mode == dm_insn_reserv
&& (DECL_INSN_RESERV (decl2)->important_automata_list
== DECL_INSN_RESERV (decl)->important_automata_list))
{
DECL_INSN_RESERV (decl2)->processed_p = TRUE;
fprintf (output_file, " case %d: /* %s */\n",
DECL_INSN_RESERV (decl2)->insn_num,
DECL_INSN_RESERV (decl2)->name);
}
}
(*output_automata_list_code)
(DECL_INSN_RESERV (decl)->important_automata_list);
}
}
}
static void
output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
{
automata_list_el_t el;
automaton_t automaton;
for (el = automata_list; el != NULL; el = el->next_automata_list_el)
{
automaton = el->automaton;
fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
output_min_issue_delay_vect_name (output_file, automaton);
fprintf (output_file,
(automaton->min_issue_delay_table_compression_factor != 1
? " [(" : " ["));
output_translate_vect_name (output_file, automaton);
fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, automaton);
fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
if (automaton->min_issue_delay_table_compression_factor == 1)
fprintf (output_file, "];\n");
else
{
fprintf (output_file, ") / %d];\n",
automaton->min_issue_delay_table_compression_factor);
fprintf (output_file, " %s = (%s >> (8 - (",
TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
output_translate_vect_name (output_file, automaton);
fprintf
(output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
INTERNAL_INSN_CODE_NAME,
automaton->min_issue_delay_table_compression_factor,
8 / automaton->min_issue_delay_table_compression_factor,
(1 << (8 / automaton->min_issue_delay_table_compression_factor))
- 1);
}
if (el == automata_list)
fprintf (output_file, " %s = %s;\n",
RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
else
{
fprintf (output_file, " if (%s > %s)\n",
TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
fprintf (output_file, " %s = %s;\n",
RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
}
}
fprintf (output_file, " break;\n\n");
}
static void
output_internal_min_issue_delay_func (void)
{
fprintf (output_file,
"static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_NAME, CHIP_PARAMETER_NAME);
fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
output_insn_code_cases (output_automata_list_min_issue_delay_code);
fprintf (output_file,
"\n default:\n %s = -1;\n break;\n }\n",
RESULT_VARIABLE_NAME);
fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
fprintf (output_file, "}\n\n");
}
static void
output_automata_list_transition_code (automata_list_el_t automata_list)
{
automata_list_el_t el, next_el;
fprintf (output_file, " {\n");
if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
for (el = automata_list;; el = next_el)
{
next_el = el->next_automata_list_el;
if (next_el == NULL)
break;
fprintf (output_file, " ");
output_state_member_type (output_file, el->automaton);
fprintf (output_file, " ");
output_temp_chip_member_name (output_file, el->automaton);
fprintf (output_file, ";\n");
}
for (el = automata_list; el != NULL; el = el->next_automata_list_el)
if (comb_vect_p (el->automaton->trans_table))
{
fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
output_trans_base_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
fprintf (output_file, "] + ");
output_translate_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
fprintf (output_file, " if (");
output_trans_check_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s] != %s->",
TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
fprintf (output_file, ")\n");
fprintf (output_file, " return %s (%s, %s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_PARAMETER_NAME);
fprintf (output_file, " else\n");
fprintf (output_file, " ");
if (el->next_automata_list_el != NULL)
output_temp_chip_member_name (output_file, el->automaton);
else
{
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
}
fprintf (output_file, " = ");
output_trans_comb_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
}
else
{
fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
output_trans_full_vect_name (output_file, el->automaton);
fprintf (output_file, " [");
output_translate_vect_name (output_file, el->automaton);
fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
fprintf (output_file, " * %d];\n",
el->automaton->insn_equiv_classes_num);
fprintf (output_file, " if (%s >= %d)\n",
TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
fprintf (output_file, " return %s (%s, %s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_PARAMETER_NAME);
fprintf (output_file, " else\n ");
if (el->next_automata_list_el != NULL)
output_temp_chip_member_name (output_file, el->automaton);
else
{
fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
}
fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
}
if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
for (el = automata_list;; el = next_el)
{
next_el = el->next_automata_list_el;
if (next_el == NULL)
break;
fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, el->automaton);
fprintf (output_file, " = ");
output_temp_chip_member_name (output_file, el->automaton);
fprintf (output_file, ";\n");
}
fprintf (output_file, " return -1;\n");
fprintf (output_file, " }\n");
}
static void
output_internal_trans_func (void)
{
fprintf (output_file,
"static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
CHIP_NAME, CHIP_PARAMETER_NAME);
fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
output_insn_code_cases (output_automata_list_transition_code);
fprintf (output_file, "\n default:\n return -1;\n }\n");
fprintf (output_file, "}\n\n");
}
static void
output_internal_insn_code_evaluation (const char *insn_name,
const char *insn_code_name,
int code)
{
fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
DFA_INSN_CODE_FUNC_NAME, insn_name);
fprintf (output_file, " if (%s > %s)\n return %d;\n",
insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
fprintf (output_file, " }\n else\n %s = %s;\n\n",
insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
}
static void
output_dfa_insn_code_func (void)
{
fprintf (output_file, "\
static void\n\
dfa_insn_code_enlarge (int uid)\n\
{\n\
int i = %s;\n\
%s = 2 * uid;\n\
%s = xrealloc (%s,\n\
%s * sizeof(int));\n\
for (; i < %s; i++)\n\
%s[i] = -1;\n}\n\n",
DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
DFA_INSN_CODES_VARIABLE_NAME);
fprintf (output_file, "\
static inline int\n%s (rtx %s)\n\
{\n\
int uid = INSN_UID (%s);\n\
int %s;\n\n",
DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
fprintf (output_file,
" if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
fprintf (output_file, " %s = %s[uid];\n",
INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
fprintf (output_file, "\
if (%s < 0)\n\
{\n\
%s = %s (%s);\n\
%s[uid] = %s;\n\
}\n",
INTERNAL_INSN_CODE_NAME,
INTERNAL_INSN_CODE_NAME,
INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
}
static void
output_trans_func (void)
{
fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
INSN_PARAMETER_NAME);
fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
INTERNAL_INSN_CODE_NAME, -1);
fprintf (output_file, " return %s (%s, %s);\n}\n\n",
INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
}
static void
output_min_issue_delay_func (void)
{
fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
INSN_PARAMETER_NAME);
fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
fprintf (output_file, " if (%s > %s)\n return 0;\n",
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
fprintf (output_file, " }\n else\n %s = %s;\n",
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
fprintf (output_file, "\n return %s (%s, %s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
STATE_NAME);
fprintf (output_file, "}\n\n");
}
static void
output_internal_dead_lock_func (void)
{
automaton_t automaton;
fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
fprintf (output_file, "{\n");
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
if (automaton->locked_states)
{
fprintf (output_file, " if (");
output_dead_lock_vect_name (output_file, automaton);
fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
output_chip_member_name (output_file, automaton);
fprintf (output_file, "])\n return 1/* TRUE */;\n");
}
fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
}
static void
output_dead_lock_func (void)
{
fprintf (output_file, "int\n%s (%s %s)\n",
DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
fprintf (output_file, "{\n return %s (%s);\n}\n\n",
INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
}
static void
output_internal_reset_func (void)
{
fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
CHIP_PARAMETER_NAME, CHIP_NAME);
}
static void
output_size_func (void)
{
fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
}
static void
output_reset_func (void)
{
fprintf (output_file, "void\n%s (%s %s)\n",
RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
STATE_NAME);
}
static void
output_min_insn_conflict_delay_func (void)
{
fprintf (output_file,
"int\n%s (%s %s, rtx %s, rtx %s)\n",
MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
INTERNAL_INSN2_CODE_NAME);
output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
INTERNAL_INSN_CODE_NAME, 0);
output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
INTERNAL_INSN2_CODE_NAME, 0);
fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
CHIP_NAME, STATE_NAME, CHIP_NAME);
fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
fprintf (output_file, " transition = %s (%s, &%s);\n",
INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
fprintf (output_file, " gcc_assert (transition <= 0);\n");
fprintf (output_file, " return %s (%s, &%s);\n",
INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
CHIP_NAME);
fprintf (output_file, "}\n\n");
}
static void
output_internal_insn_latency_func (void)
{
decl_t decl;
struct bypass_decl *bypass;
int i, j, col;
const char *tabletype = "unsigned char";
for (i = 0; i < description->decls_num; i++)
if (description->decls[i]->mode == dm_insn_reserv)
{
decl = description->decls[i];
if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
&& tabletype[0] != 'i')
tabletype = "unsigned short";
if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
tabletype = "int";
}
fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
INSN2_PARAMETER_NAME);
fprintf (output_file, "{\n");
if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
{
fputs (" return 0;\n}\n\n", output_file);
return;
}
fprintf (output_file, " static const %s default_latencies[] =\n {",
tabletype);
for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
if (description->decls[i]->mode == dm_insn_reserv
&& description->decls[i] != advance_cycle_insn_decl)
{
if ((col = (col+1) % 8) == 0)
fputs ("\n ", output_file);
decl = description->decls[i];
gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
fprintf (output_file, "% 4d,",
DECL_INSN_RESERV (decl)->default_latency);
}
gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
fputs ("\n };\n", output_file);
fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
for (i = 0; i < description->decls_num; i++)
if (description->decls[i]->mode == dm_insn_reserv
&& DECL_INSN_RESERV (description->decls[i])->bypass_list)
{
decl = description->decls [i];
fprintf (output_file,
" case %d:\n switch (%s)\n {\n",
DECL_INSN_RESERV (decl)->insn_num,
INTERNAL_INSN2_CODE_NAME);
for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
bypass != NULL;
bypass = bypass->next)
{
gcc_assert (bypass->in_insn_reserv->insn_num
!= (DECL_INSN_RESERV
(advance_cycle_insn_decl)->insn_num));
fprintf (output_file, " case %d:\n",
bypass->in_insn_reserv->insn_num);
if (bypass->bypass_guard_name == NULL)
fprintf (output_file, " return %d;\n",
bypass->latency);
else
{
fprintf (output_file,
" if (%s (%s, %s))\n",
bypass->bypass_guard_name, INSN_PARAMETER_NAME,
INSN2_PARAMETER_NAME);
fprintf (output_file,
" return %d;\n break;\n",
bypass->latency);
}
}
fputs (" }\n break;\n", output_file);
}
fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
INTERNAL_INSN_CODE_NAME);
}
static void
output_insn_latency_func (void)
{
fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
fprintf (output_file, "{\n int %s, %s;\n",
INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
INTERNAL_INSN_CODE_NAME, 0);
output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
INTERNAL_INSN2_CODE_NAME, 0);
fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
INTERNAL_INSN_LATENCY_FUNC_NAME,
INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
}
static void
output_print_reservation_func (void)
{
decl_t decl;
int i, j;
fprintf (output_file,
"void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
INSN_PARAMETER_NAME);
if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
{
fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
NOTHING_NAME, FILE_PARAMETER_NAME);
return;
}
fputs (" static const char *const reservation_names[] =\n {",
output_file);
for (i = 0, j = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
{
gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
j++;
fprintf (output_file, "\n \"%s\",",
regexp_representation (DECL_INSN_RESERV (decl)->regexp));
finish_regexp_representation ();
}
}
gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
INSN_PARAMETER_NAME,
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
fprintf (output_file, " else\n\
{\n\
%s = %s (%s);\n\
if (%s > %s)\n\
%s = %s;\n\
}\n",
INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
INSN_PARAMETER_NAME,
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
}
static int
units_cmp (const void *unit1, const void *unit2)
{
const unit_decl_t u1 = *(unit_decl_t *) unit1;
const unit_decl_t u2 = *(unit_decl_t *) unit2;
return strcmp (u1->name, u2->name);
}
#define NAME_CODE_STRUCT_NAME "name_code"
#define NAME_CODE_TABLE_NAME "name_code_table"
#define NAME_MEMBER_NAME "name"
#define CODE_MEMBER_NAME "code"
#define CMP_VARIABLE_NAME "cmp"
#define LOW_VARIABLE_NAME "l"
#define MIDDLE_VARIABLE_NAME "m"
#define HIGH_VARIABLE_NAME "h"
static void
output_get_cpu_unit_code_func (void)
{
int i;
unit_decl_t *units;
fprintf (output_file, "int\n%s (const char *%s)\n",
GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
fprintf (output_file, " static struct %s %s [] =\n {\n",
NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
units = xmalloc (sizeof (unit_decl_t) * description->units_num);
memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
for (i = 0; i < description->units_num; i++)
if (units [i]->query_p)
fprintf (output_file, " {\"%s\", %d},\n",
units[i]->name, units[i]->query_num);
fprintf (output_file, " };\n\n");
fprintf (output_file, " /* The following is binary search: */\n");
fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
fprintf (output_file, " while (%s <= %s)\n {\n",
LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
fprintf (output_file, " %s = (%s + %s) / 2;\n",
MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
fprintf (output_file, " %s = %s - 1;\n",
HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
fprintf (output_file, " %s = %s + 1;\n",
LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
fprintf (output_file, " else\n");
fprintf (output_file, " return %s [%s].%s;\n }\n",
NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
fprintf (output_file, " return -1;\n}\n\n");
free (units);
}
static void
output_cpu_unit_reservation_p (void)
{
automaton_t automaton;
fprintf (output_file, "int\n%s (%s %s, int %s)\n",
CPU_UNIT_RESERVATION_P_FUNC_NAME,
STATE_TYPE_NAME, STATE_NAME,
CPU_CODE_PARAMETER_NAME);
fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
description->query_units_num);
if (description->query_units_num > 0)
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
fprintf (output_file, " if ((");
output_reserved_units_table_name (output_file, automaton);
fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
output_chip_member_name (output_file, automaton);
fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
(description->query_units_num + 7) / 8,
CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
fprintf (output_file, " return 1;\n");
}
fprintf (output_file, " return 0;\n}\n\n");
}
static void
output_dfa_clean_insn_cache_func (void)
{
fprintf (output_file,
"void\n%s (void)\n{\n int %s;\n\n",
DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
fprintf (output_file,
" for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
I_VARIABLE_NAME, I_VARIABLE_NAME,
DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
fprintf (output_file,
"void\n%s (rtx %s)\n{\n int %s;\n\n",
DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
I_VARIABLE_NAME);
fprintf (output_file,
" %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
I_VARIABLE_NAME);
}
static void
output_dfa_start_func (void)
{
fprintf (output_file,
"void\n%s (void)\n{\n %s = get_max_uid ();\n",
DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
}
static void
output_dfa_finish_func (void)
{
fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
}
static void
output_regexp (regexp_t regexp)
{
fprintf (output_description_file, "%s", regexp_representation (regexp));
finish_regexp_representation ();
}
static void
output_unit_set_el_list (unit_set_el_t list)
{
unit_set_el_t el;
for (el = list; el != NULL; el = el->next_unit_set_el)
{
if (el != list)
fprintf (output_description_file, ", ");
fprintf (output_description_file, "%s", el->unit_decl->name);
}
}
static void
output_pattern_set_el_list (pattern_set_el_t list)
{
pattern_set_el_t el;
int i;
for (el = list; el != NULL; el = el->next_pattern_set_el)
{
if (el != list)
fprintf (output_description_file, ", ");
for (i = 0; i < el->units_num; i++)
fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
el->unit_decls [i]->name);
}
}
static void
output_description (void)
{
decl_t decl;
int i;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit)
{
if (DECL_UNIT (decl)->excl_list != NULL)
{
fprintf (output_description_file, "unit %s exlusion_set: ",
DECL_UNIT (decl)->name);
output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
fprintf (output_description_file, "\n");
}
if (DECL_UNIT (decl)->presence_list != NULL)
{
fprintf (output_description_file, "unit %s presence_set: ",
DECL_UNIT (decl)->name);
output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
fprintf (output_description_file, "\n");
}
if (DECL_UNIT (decl)->final_presence_list != NULL)
{
fprintf (output_description_file, "unit %s final_presence_set: ",
DECL_UNIT (decl)->name);
output_pattern_set_el_list
(DECL_UNIT (decl)->final_presence_list);
fprintf (output_description_file, "\n");
}
if (DECL_UNIT (decl)->absence_list != NULL)
{
fprintf (output_description_file, "unit %s absence_set: ",
DECL_UNIT (decl)->name);
output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
fprintf (output_description_file, "\n");
}
if (DECL_UNIT (decl)->final_absence_list != NULL)
{
fprintf (output_description_file, "unit %s final_absence_set: ",
DECL_UNIT (decl)->name);
output_pattern_set_el_list
(DECL_UNIT (decl)->final_absence_list);
fprintf (output_description_file, "\n");
}
}
}
fprintf (output_description_file, "\n");
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_reserv)
{
fprintf (output_description_file, "reservation %s: ",
DECL_RESERV (decl)->name);
output_regexp (DECL_RESERV (decl)->regexp);
fprintf (output_description_file, "\n");
}
else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
{
fprintf (output_description_file, "insn reservation %s ",
DECL_INSN_RESERV (decl)->name);
print_rtl (output_description_file,
DECL_INSN_RESERV (decl)->condexp);
fprintf (output_description_file, ": ");
output_regexp (DECL_INSN_RESERV (decl)->regexp);
fprintf (output_description_file, "\n");
}
else if (decl->mode == dm_bypass)
fprintf (output_description_file, "bypass %d %s %s\n",
DECL_BYPASS (decl)->latency,
DECL_BYPASS (decl)->out_insn_name,
DECL_BYPASS (decl)->in_insn_name);
}
fprintf (output_description_file, "\n\f\n");
}
static void
output_automaton_name (FILE *f, automaton_t automaton)
{
if (automaton->corresponding_automaton_decl == NULL)
fprintf (f, "#%d", automaton->automaton_order_num);
else
fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
}
#define MAX_LINE_LENGTH 70
static void
output_automaton_units (automaton_t automaton)
{
decl_t decl;
const char *name;
int curr_line_length;
int there_is_an_automaton_unit;
int i;
fprintf (output_description_file, "\n Corresponding units:\n");
fprintf (output_description_file, " ");
curr_line_length = 4;
there_is_an_automaton_unit = 0;
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_unit
&& (DECL_UNIT (decl)->corresponding_automaton_num
== automaton->automaton_order_num))
{
there_is_an_automaton_unit = 1;
name = DECL_UNIT (decl)->name;
if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
{
curr_line_length = strlen (name) + 4;
fprintf (output_description_file, "\n ");
}
else
{
curr_line_length += strlen (name) + 1;
fprintf (output_description_file, " ");
}
fprintf (output_description_file, "%s", name);
}
}
if (!there_is_an_automaton_unit)
fprintf (output_description_file, "<None>");
fprintf (output_description_file, "\n\n");
}
static VEC(reserv_sets_t,heap) *state_reservs;
static void
add_state_reservs (state_t state)
{
alt_state_t curr_alt_state;
if (state->component_states != NULL)
for (curr_alt_state = state->component_states;
curr_alt_state != NULL;
curr_alt_state = curr_alt_state->next_sorted_alt_state)
add_state_reservs (curr_alt_state->state);
else
VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
}
static void
output_state_arcs (state_t state)
{
arc_t arc;
ainsn_t ainsn;
const char *insn_name;
int curr_line_length;
for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
{
ainsn = arc->insn;
gcc_assert (ainsn->first_insn_with_same_reservs);
fprintf (output_description_file, " ");
curr_line_length = 7;
fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
do
{
insn_name = ainsn->insn_reserv_decl->name;
if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
{
if (ainsn != arc->insn)
{
fprintf (output_description_file, ",\n ");
curr_line_length = strlen (insn_name) + 6;
}
else
curr_line_length += strlen (insn_name);
}
else
{
curr_line_length += strlen (insn_name);
if (ainsn != arc->insn)
{
curr_line_length += 2;
fprintf (output_description_file, ", ");
}
}
fprintf (output_description_file, "%s", insn_name);
ainsn = ainsn->next_same_reservs_insn;
}
while (ainsn != NULL);
fprintf (output_description_file, " %d \n",
arc->to_state->order_state_num);
}
fprintf (output_description_file, "\n");
}
static int
state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
{
return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
*(reserv_sets_t *) reservs_ptr_2);
}
static void
remove_state_duplicate_reservs (void)
{
size_t i, j;
for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
VEC_index (reserv_sets_t, state_reservs, i)))
{
j++;
VEC_replace (reserv_sets_t, state_reservs, j,
VEC_index (reserv_sets_t, state_reservs, i));
}
VEC_truncate (reserv_sets_t, state_reservs, j + 1);
}
static void
output_state (state_t state)
{
size_t i;
state_reservs = 0;
fprintf (output_description_file, " State #%d", state->order_state_num);
fprintf (output_description_file,
state->new_cycle_p ? " (new cycle)\n" : "\n");
add_state_reservs (state);
qsort (VEC_address (reserv_sets_t, state_reservs),
VEC_length (reserv_sets_t, state_reservs),
sizeof (reserv_sets_t), state_reservs_cmp);
remove_state_duplicate_reservs ();
for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
{
fprintf (output_description_file, " ");
output_reserv_sets (output_description_file,
VEC_index (reserv_sets_t, state_reservs, i));
fprintf (output_description_file, "\n");
}
fprintf (output_description_file, "\n");
output_state_arcs (state);
VEC_free (reserv_sets_t,heap, state_reservs);
}
static void
output_automaton_descriptions (void)
{
automaton_t automaton;
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
fprintf (output_description_file, "\nAutomaton ");
output_automaton_name (output_description_file, automaton);
fprintf (output_description_file, "\n");
output_automaton_units (automaton);
pass_states (automaton, output_state);
}
}
static void
output_statistics (FILE *f)
{
automaton_t automaton;
int states_num;
#ifndef NDEBUG
int transition_comb_vect_els = 0;
int transition_full_vect_els = 0;
int min_issue_delay_vect_els = 0;
int locked_states = 0;
#endif
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
fprintf (f, "\nAutomaton ");
output_automaton_name (f, automaton);
fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
automaton->NDFA_states_num, automaton->NDFA_arcs_num);
fprintf (f, " %5d DFA states, %5d DFA arcs\n",
automaton->DFA_states_num, automaton->DFA_arcs_num);
states_num = automaton->DFA_states_num;
if (!no_minimization_flag)
{
fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
automaton->minimal_DFA_states_num,
automaton->minimal_DFA_arcs_num);
states_num = automaton->minimal_DFA_states_num;
}
fprintf (f, " %5d all insns %5d insn equivalence classes\n",
description->insns_num, automaton->insn_equiv_classes_num);
fprintf (f, " %d locked states\n", automaton->locked_states);
#ifndef NDEBUG
fprintf
(f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
(long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
(long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
(comb_vect_p (automaton->trans_table)
? "use comb vect" : "use simple vect"));
fprintf
(f, "%5ld min delay table els, compression factor %d\n",
(long) states_num * automaton->insn_equiv_classes_num,
automaton->min_issue_delay_table_compression_factor);
transition_comb_vect_els
+= VEC_length (vect_el_t, automaton->trans_table->comb_vect);
transition_full_vect_els
+= VEC_length (vect_el_t, automaton->trans_table->full_vect);
min_issue_delay_vect_els
+= states_num * automaton->insn_equiv_classes_num;
locked_states
+= automaton->locked_states;
#endif
}
#ifndef NDEBUG
fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
allocated_states_num, allocated_arcs_num);
fprintf (f, "%5d all allocated alternative states\n",
allocated_alt_states_num);
fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
transition_comb_vect_els, transition_full_vect_els);
fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
fprintf (f, "%5d all locked states\n", locked_states);
#endif
}
static void
output_time_statistics (FILE *f)
{
fprintf (f, "\n transformation: ");
print_active_time (f, transform_time);
fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
print_active_time (f, NDFA_time);
if (ndfa_flag)
{
fprintf (f, ", NDFA -> DFA: ");
print_active_time (f, NDFA_to_DFA_time);
}
fprintf (f, "\n DFA minimization: ");
print_active_time (f, minimize_time);
fprintf (f, ", making insn equivalence: ");
print_active_time (f, equiv_time);
fprintf (f, "\n all automaton generation: ");
print_active_time (f, automaton_generation_time);
fprintf (f, ", output: ");
print_active_time (f, output_time);
fprintf (f, "\n");
}
static void
generate (void)
{
automata_num = split_argument;
if (description->units_num < automata_num)
automata_num = description->units_num;
initiate_states ();
initiate_arcs ();
initiate_automata_lists ();
initiate_pass_states ();
initiate_excl_sets ();
initiate_presence_absence_pattern_sets ();
automaton_generation_time = create_ticker ();
create_automata ();
ticker_off (&automaton_generation_time);
}
#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
static const char *
file_name_suffix (const char *file_name)
{
const char *last_period;
for (last_period = NULL; *file_name != '\0'; file_name++)
if (*file_name == '.')
last_period = file_name;
return (last_period == NULL ? file_name : last_period);
}
static const char *
base_file_name (const char *file_name)
{
int directory_name_length;
directory_name_length = strlen (file_name);
#ifdef WIN32
while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
&& file_name[directory_name_length] != '\\')
#else
while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
#endif
directory_name_length--;
return file_name + directory_name_length + 1;
}
static void
initiate_automaton_gen (int argc, char **argv)
{
const char *base_name;
int i;
ndfa_flag = 0;
split_argument = 0;
no_minimization_flag = 0;
time_flag = 0;
v_flag = 0;
w_flag = 0;
progress_flag = 0;
for (i = 2; i < argc; i++)
if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
no_minimization_flag = 1;
else if (strcmp (argv [i], TIME_OPTION) == 0)
time_flag = 1;
else if (strcmp (argv [i], V_OPTION) == 0)
v_flag = 1;
else if (strcmp (argv [i], W_OPTION) == 0)
w_flag = 1;
else if (strcmp (argv [i], NDFA_OPTION) == 0)
ndfa_flag = 1;
else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
progress_flag = 1;
else if (strcmp (argv [i], "-split") == 0)
{
if (i + 1 >= argc)
fatal ("-split has no argument.");
fatal ("option `-split' has not been implemented yet\n");
}
obstack_init (&irp);
initiate_automaton_decl_table ();
initiate_insn_decl_table ();
initiate_decl_table ();
output_file = stdout;
output_description_file = NULL;
base_name = base_file_name (argv[1]);
obstack_grow (&irp, base_name,
strlen (base_name) - strlen (file_name_suffix (base_name)));
obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
obstack_1grow (&irp, '\0');
output_description_file_name = obstack_base (&irp);
obstack_finish (&irp);
}
static void
check_automata_insn_issues (void)
{
automaton_t automaton;
ainsn_t ainsn, reserv_ainsn;
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
for (ainsn = automaton->ainsn_list;
ainsn != NULL;
ainsn = ainsn->next_ainsn)
if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
{
for (reserv_ainsn = ainsn;
reserv_ainsn != NULL;
reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
if (automaton->corresponding_automaton_decl != NULL)
{
if (!w_flag)
error ("Automaton `%s': Insn `%s' will never be issued",
automaton->corresponding_automaton_decl->name,
reserv_ainsn->insn_reserv_decl->name);
else
warning
(0, "Automaton `%s': Insn `%s' will never be issued",
automaton->corresponding_automaton_decl->name,
reserv_ainsn->insn_reserv_decl->name);
}
else
{
if (!w_flag)
error ("Insn `%s' will never be issued",
reserv_ainsn->insn_reserv_decl->name);
else
warning (0, "Insn `%s' will never be issued",
reserv_ainsn->insn_reserv_decl->name);
}
}
}
}
static VEC(state_t,heap) *automaton_states;
static void
add_automaton_state (state_t state)
{
VEC_safe_push (state_t,heap, automaton_states, state);
}
static void
form_important_insn_automata_lists (void)
{
automaton_t automaton;
decl_t decl;
ainsn_t ainsn;
arc_t arc;
int i;
size_t n;
automaton_states = 0;
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
{
VEC_truncate (state_t, automaton_states, 0);
pass_states (automaton, add_automaton_state);
for (n = 0; n < VEC_length (state_t, automaton_states); n++)
{
state_t s = VEC_index (state_t, automaton_states, n);
for (arc = first_out_arc (s);
arc != NULL;
arc = next_out_arc (arc))
if (arc->to_state != s)
{
gcc_assert (arc->insn->first_insn_with_same_reservs);
for (ainsn = arc->insn;
ainsn != NULL;
ainsn = ainsn->next_same_reservs_insn)
ainsn->important_p = TRUE;
}
}
}
VEC_free (state_t,heap, automaton_states);
for (i = 0; i < description->decls_num; i++)
{
decl = description->decls [i];
if (decl->mode == dm_insn_reserv)
{
automata_list_start ();
for (automaton = description->first_automaton;
automaton != NULL;
automaton = automaton->next_automaton)
for (ainsn = automaton->ainsn_list;
ainsn != NULL;
ainsn = ainsn->next_ainsn)
if (ainsn->important_p
&& ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
{
automata_list_add (automaton);
break;
}
DECL_INSN_RESERV (decl)->important_automata_list
= automata_list_finish ();
}
}
}
static void
expand_automata (void)
{
int i;
description = create_node (sizeof (struct description)
+ sizeof (decl_t) * VEC_length (decl_t, decls));
description->decls_num = VEC_length (decl_t, decls);
description->query_units_num = 0;
for (i = 0; i < description->decls_num; i++)
{
description->decls [i] = VEC_index (decl_t, decls, i);
if (description->decls [i]->mode == dm_unit
&& DECL_UNIT (description->decls [i])->query_p)
DECL_UNIT (description->decls [i])->query_num
= description->query_units_num++;
}
all_time = create_ticker ();
check_time = create_ticker ();
if (progress_flag)
fprintf (stderr, "Check description...");
check_all_description ();
if (progress_flag)
fprintf (stderr, "done\n");
ticker_off (&check_time);
generation_time = create_ticker ();
if (!have_error)
{
transform_insn_regexps ();
check_unit_distributions_to_automata ();
}
if (!have_error)
{
generate ();
check_automata_insn_issues ();
}
if (!have_error)
{
form_important_insn_automata_lists ();
}
ticker_off (&generation_time);
}
static void
write_automata (void)
{
output_time = create_ticker ();
if (progress_flag)
fprintf (stderr, "Forming and outputting automata tables...");
output_tables ();
if (progress_flag)
{
fprintf (stderr, "done\n");
fprintf (stderr, "Output functions to work with automata...");
}
output_chip_definitions ();
output_max_insn_queue_index_def ();
output_internal_min_issue_delay_func ();
output_internal_trans_func ();
fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
fprintf (output_file, "\nstatic int %s;\n\n",
DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
output_dfa_insn_code_func ();
output_trans_func ();
output_min_issue_delay_func ();
output_internal_dead_lock_func ();
output_dead_lock_func ();
output_size_func ();
output_internal_reset_func ();
output_reset_func ();
output_min_insn_conflict_delay_func ();
output_internal_insn_latency_func ();
output_insn_latency_func ();
output_print_reservation_func ();
fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
output_get_cpu_unit_code_func ();
output_cpu_unit_reservation_p ();
fprintf (output_file, "\n#endif /* #if %s */\n\n",
CPU_UNITS_QUERY_MACRO_NAME);
output_dfa_clean_insn_cache_func ();
output_dfa_start_func ();
output_dfa_finish_func ();
if (progress_flag)
fprintf (stderr, "done\n");
if (v_flag)
{
output_description_file = fopen (output_description_file_name, "w");
if (output_description_file == NULL)
{
perror (output_description_file_name);
exit (FATAL_EXIT_CODE);
}
if (progress_flag)
fprintf (stderr, "Output automata description...");
output_description ();
output_automaton_descriptions ();
if (progress_flag)
fprintf (stderr, "done\n");
output_statistics (output_description_file);
}
output_statistics (stderr);
ticker_off (&output_time);
output_time_statistics (stderr);
finish_states ();
finish_arcs ();
finish_automata_lists ();
if (time_flag)
{
fprintf (stderr, "Summary:\n");
fprintf (stderr, " check time ");
print_active_time (stderr, check_time);
fprintf (stderr, ", generation time ");
print_active_time (stderr, generation_time);
fprintf (stderr, ", all time ");
print_active_time (stderr, all_time);
fprintf (stderr, "\n");
}
if (output_description_file != NULL)
{
fflush (output_description_file);
if (ferror (stdout) != 0)
fatal ("Error in writing DFA description file %s",
output_description_file_name);
fclose (output_description_file);
}
finish_automaton_decl_table ();
finish_insn_decl_table ();
finish_decl_table ();
obstack_free (&irp, NULL);
if (have_error && output_description_file != NULL)
remove (output_description_file_name);
}
int
main (int argc, char **argv)
{
rtx desc;
progname = "genautomata";
if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
initiate_automaton_gen (argc, argv);
while (1)
{
int lineno;
int insn_code_number;
desc = read_md_rtx (&lineno, &insn_code_number);
if (desc == NULL)
break;
switch (GET_CODE (desc))
{
case DEFINE_CPU_UNIT:
gen_cpu_unit (desc);
break;
case DEFINE_QUERY_CPU_UNIT:
gen_query_cpu_unit (desc);
break;
case DEFINE_BYPASS:
gen_bypass (desc);
break;
case EXCLUSION_SET:
gen_excl_set (desc);
break;
case PRESENCE_SET:
gen_presence_set (desc);
break;
case FINAL_PRESENCE_SET:
gen_final_presence_set (desc);
break;
case ABSENCE_SET:
gen_absence_set (desc);
break;
case FINAL_ABSENCE_SET:
gen_final_absence_set (desc);
break;
case DEFINE_AUTOMATON:
gen_automaton (desc);
break;
case AUTOMATA_OPTION:
gen_automata_option (desc);
break;
case DEFINE_RESERVATION:
gen_reserv (desc);
break;
case DEFINE_INSN_RESERVATION:
gen_insn_reserv (desc);
break;
default:
break;
}
}
if (have_error)
return FATAL_EXIT_CODE;
puts ("/* Generated automatically by the program `genautomata'\n"
" from the machine description file `md'. */\n\n"
"#include \"config.h\"\n"
"#include \"system.h\"\n"
"#include \"coretypes.h\"\n"
"#include \"tm.h\"\n"
"#include \"rtl.h\"\n"
"#include \"tm_p.h\"\n"
"#include \"insn-config.h\"\n"
"#include \"recog.h\"\n"
"#include \"regs.h\"\n"
"#include \"real.h\"\n"
"#include \"output.h\"\n"
"#include \"insn-attr.h\"\n"
"#include \"toplev.h\"\n"
"#include \"flags.h\"\n"
"#include \"function.h\"\n");
if (VEC_length (decl_t, decls) > 0)
{
expand_automata ();
write_automata ();
}
fflush (stdout);
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}