9. Tool of genattrtab
9.1. Overview
Above we see tool genattr generates the file insn-attr.h. This file contains the declaration of routines. Now it is time to see where their definitions come from. Here they are output by genattratab. Again we still take the examples in previous section in this section.
Generally, there are 2 kinds of machine description files for target platform. The first one defines the patterns that can recognize input RTL instructions and provide information for outputting assembly for the target platform. This file is shared by machines using the same instruction set. We have seen this in 3. Tool of genrecog and 5. Tool of genoutput .
While the other file is specialized for architecture. Currently, there are two ways to describe the atchitecture, one is via define_function_unit which describes the chip in the position of function units (refer to section 8.1.2 Overview of DEFINE_FUNCTION_UNIT pattern ), and the newer one is by define_insn_reservation which describes the chip in the view from instructions (refer to section 8.1.3 Overview of DEFINE_INSN_RESERVATION pattern ).
Besides these patterns, we need other patterns to provide the details about instructions. For the old way, define_attr, define_insn, define_delay will be found. And for the new way, define_attr, define_insn, define_delay, define_automaton, define_bypass, present_set etc will be present.
9.2. Program Entry
5988 int
5989 main (int argc, char **argv) in genattrtab.c
5990 {
5991 rtx desc;
5992 struct attr_desc *attr;
5993 struct insn_def *id;
5994 rtx tem;
5995 int i;
5996
5997 progname = "genattrtab";
5998
5999 if (argc <= 1)
6000 fatal ("no input file name");
6001
6002 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
6003 return (FATAL_EXIT_CODE);
6004
6005 obstack_init (hash_obstack );
6006 obstack_init (temp_obstack );
6007
6008 /* Set up true and false rtx's */
6009 true_rtx = rtx_alloc (CONST_INT);
6010 XWINT (true_rtx , 0) = 1;
6011 false_rtx = rtx_alloc (CONST_INT);
6012 XWINT (false_rtx , 0) = 0;
6013 ATTR_IND_SIMPLIFIED_P (true_rtx ) = ATTR_IND_SIMPLIFIED_P (false_rtx ) = 1;
6014 ATTR_PERMANENT_P (true_rtx ) = ATTR_PERMANENT_P (false_rtx ) = 1;
6015
6016 alternative_name = DEF_ATTR_STRING ("alternative");
6017 length_str = DEF_ATTR_STRING ("length");
6018 delay_type_str = DEF_ATTR_STRING ("*delay_type");
6019 delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");
6020 num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");
6021
6022 printf ("/* Generated automatically by the program `genattrtab'/n/
6023 from the machine description file `md'. *//n/n");
6024
6025 /* Read the machine description. */
6026
6027 initiate_automaton_gen (argc, argv);
We first have a look at the definition of macros used above.
98 #define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), unchanging)) in genattrtab.c
100 #define ATTR_PERMANENT_P(RTX) ( RTX_FLAG ((RTX), integrated)) in genattrtab.c
402 #define RTX_FLAG(RTX, FLAG) ((RTX)->FLAG) in rtl.h
For DEF_ATTR_STRING, it refers to function attr_string . This function will save the string into the hash table (attr_hash_table ).
382 #define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S))) in genattrtab.c
778 static char *
779 attr_string (const char *str, int len) in genattrtab.c
780 {
781 struct attr_hash *h;
782 int hashcode;
783 int i;
784 char *new_str;
785
786 /* Compute the hash code. */
787 hashcode = (len + 1) * 613 + (unsigned) str[0];
788 for (i = 1; i <= len; i += 2)
789 hashcode = ((hashcode * 613) + (unsigned) str[i]);
790 if (hashcode < 0)
791 hashcode = -hashcode;
792
793 /* Search the table for the string. */
794 for (h = attr_hash_table [hashcode % RTL_HASH_SIZE]; h; h = h->next)
795 if (h->hashcode == -hashcode && h->u.str[0] == str[0]
796 && !strncmp (h->u.str, str, len))
797 return h->u.str; /* <-- return if found. */
798
799 /* Not found; create a permanent copy and add it to the hash table. */
800 new_str = obstack_alloc (hash_obstack , len + 1);
801 memcpy (new_str, str, len);
802 new_str[len] = '/0';
803 attr_hash_add_string (hashcode, new_str);
804
805 return new_str; /* Return the new string. */
806 }
At line 794, table attr_hash_table contains elements of type attr_hash which has following definition.
493 struct attr_hash in genattrtab.c
494 {
495 struct attr_hash *next; /* Next structure in the bucket. */
496 int hashcode; /* Hash code of this rtx or string. */
497 union
498 {
499 char *str; /* The string (negative hash codes) */
500 rtx rtl; /* or the RTL recorded here. */
501 } u;
502 };
9.3. Preparation
As usual way, the tool needs to read in the machine description file and build data for them.
9634 void
9635 initiate_automaton_gen (int argc, char **argv) in genattrtab.c
9636 {
9637 const char *base_name;
9638 int i;
9639
9640 ndfa_flag = 0;
9641 split_argument = 0; /* default value */
9642 no_minimization_flag = 0;
9643 time_flag = 0;
9644 v_flag = 0;
9645 w_flag = 0;
9646 progress_flag = 0;
9647 for (i = 2; i < argc; i++)
9648 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9649 no_minimization_flag = 1;
9650 else if (strcmp (argv [i], TIME_OPTION) == 0)
9651 time_flag = 1;
9652 else if (strcmp (argv [i], V_OPTION) == 0)
9653 v_flag = 1;
9654 else if (strcmp (argv [i], W_OPTION) == 0)
9655 w_flag = 1;
9656 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9657 ndfa_flag = 1;
9658 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9659 progress_flag = 1;
9660 else if (strcmp (argv [i], "-split") == 0)
9661 {
9662 if (i + 1 >= argc)
9663 fatal ("-split has no argument.");
9664 fatal ("option `-split' has not been implemented yet/n");
9665 /* split_argument = atoi (argument_vect [i + 1]); */
9666 }
9667 VLA_PTR_CREATE (decls , 150, "decls");
9668 /* Initialize IR storage. */
9669 obstack_init (&irp );
9670 initiate_automaton_decl_table ();
9671 initiate_insn_decl_table ();
9672 initiate_decl_table ();
9673 output_file = stdout;
9674 output_description_file = NULL;
9675 base_name = base_file_name (argv[1]);
9676 obstack_grow (&irp , base_name,
9677 strlen (base_name) - strlen (file_name_suffix (base_name)));
9678 obstack_grow (&irp , STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9679 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9680 obstack_1grow (&irp , '/0');
9681 output_description_file_name = obstack_base (&irp );
9682 obstack_finish (&irp );
9683 }
9.3.1. Variable Length Array Pointer
In this tool, a facility called variable length array pointer is used. At line 9667 above, is an example.
547 #define VLA_PTR_CREATE(vla, allocated_length, name) / in genautomata.c
548 do /
549 { /
550 vla_ptr_t *const _vla_ptr = &(vla); /
551 /
552 VARRAY_GENERIC_PTR_INIT (_vla_ptr->varray, allocated_length, name);/
553 _vla_ptr->length = 0; /
554 } /
555 while (0)
The variable length array pointer has following definitions:
138 typedef struct { in genautomata.c
139 size_t length; /* current size of vla. */
140 varray_type varray; /* container for vla. */
132 struct varray_head_tag GTY(()) { in varray.h
133 size_t num_elements; /* Maximum element number allocated. */
134 size_t elements_used; /* The number of elements used, if
135 using VARRAY_PUSH/VARRAY_POP. */
136 enum varray_data_enum type; /* The kind of elements in the varray. */
137 const char *name; /* name of the varray for reporting errors */
138 varray_data GTY ((desc ("%0.type"))) data; /* The data elements follow,
139 must be last. */
140 };
141 typedef struct varray_head_tag *varray_type;
varray_data_enum tells what kinds of data vla can hold. Its value can map to the member of varray_data one by one.
63 enum varray_data_enum { in varray .h
64 VARRAY_DATA_C,
65 VARRAY_DATA_UC,
66 VARRAY_DATA_S,
67 VARRAY_DATA_US,
68 VARRAY_DATA_I,
69 VARRAY_DATA_U,
70 VARRAY_DATA_L,
71 VARRAY_DATA_UL,
72 VARRAY_DATA_HINT,
73 VARRAY_DATA_UHINT,
74 VARRAY_DATA_GENERIC,
75 VARRAY_DATA_CPTR,
76 VARRAY_DATA_RTX,
77 VARRAY_DATA_RTVEC,
78 VARRAY_DATA_TREE,
79 VARRAY_DATA_BITMAP,
80 VARRAY_DATA_REG,
81 VARRAY_DATA_CONST_EQUIV,
82 VARRAY_DATA_BB,
83 VARRAY_DATA_TE,
84 NUM_VARRAY_DATA
85 };
Notice that varray_data in fact is a variable array; it can be any length as long as the system affording.
88 typedef union varray_data_tag GTY (()) { in varray.h
89 char GTY ((length ("%0.num_elements"),
90 tag ("VARRAY_DATA_C"))) c[1];
91 unsigned char GTY ((length ("%0.num_elements"),
92 tag ("VARRAY_DATA_UC"))) uc[1];
93 short GTY ((length ("%0.num_elements"),
94 tag ("VARRAY_DATA_S"))) s[1];
95 unsigned short GTY ((length ("%0.num_elements"),
96 tag ("VARRAY_DATA_US"))) us[1];
97 int GTY ((length ("%0.num_elements"),
98 tag ("VARRAY_DATA_I"))) i[1];
99 unsigned int GTY ((length ("%0.num_elements"),
100 tag ("VARRAY_DATA_U"))) u[1];
101 long GTY ((length ("%0.num_elements"),
102 tag ("VARRAY_DATA_L"))) l[1];
103 unsigned long GTY ((length ("%0.num_elements"),
104 tag ("VARRAY_DATA_UL"))) ul[1];
105 HOST_WIDE_INT GTY ((length ("%0.num_elements"),
106 tag ("VARRAY_DATA_HINT"))) hint[1];
107 unsigned HOST_WIDE_INT GTY ((length ("%0.num_elements"),
108 tag ("VARRAY_DATA_UHINT"))) uhint[1];
109 PTR GTY ((length ("%0.num_elements"), use_param (""),
110 tag ("VARRAY_DATA_GENERIC"))) generic[1];
111 char *GTY ((length ("%0.num_elements"),
112 tag ("VARRAY_DATA_CPTR"))) cptr[1];
113 rtx GTY ((length ("%0.num_elements"),
114 tag ("VARRAY_DATA_RTX"))) rtx[1];
115 rtvec GTY ((length ("%0.num_elements"),
116 tag ("VARRAY_DATA_RTVEC"))) rtvec[1];
117 tree GTY ((length ("%0.num_elements"),
118 tag ("VARRAY_DATA_TREE"))) tree[1];
119 struct bitmap_head_def *GTY ((length ("%0.num_elements"),
120 tag ("VARRAY_DATA_BITMAP"))) bitmap[1];
121 struct reg_info_def *GTY ((length ("%0.num_elements"), skip (""),
122 tag ("VARRAY_DATA_REG"))) reg[1];
123 struct const_equiv_data GTY ((length ("%0.num_elements"),
124 tag ("VARRAY_DATA_CONST_EQUIV"))) const_equiv[1];
125 struct basic_block_def *GTY ((length ("%0.num_elements"), skip (""),
126 tag ("VARRAY_DATA_BB"))) bb[1];
127 struct elt_list *GTY ((length ("%0.num_elements"),
128 tag ("VARRAY_DATA_TE"))) te[1];
Above in VLA_PTR_CREATE , at line 552, VARRAY_GENERIC_PTR_INIT allocates memory for the varray, and the type of the element will be VARRAY_DATA_GENERIC (PTR of varray_data ).
177 #define VARRAY_GENERIC_PTR_INIT(va, num, name) / in varray.h
178 va = varray_init (num, VARRAY_DATA_GENERIC, name)
115 varray_type
116 varray_init (size_t num_elements, enum varray_data_enum element_kind, in varray.c
117 const char *name)
118 {
119 size_t data_size = num_elements * element[element_kind].size;
120 varray_type ptr;
121 #ifdef GATHER_STATISTICS
122 struct varray_descriptor *desc = varray_descriptor (name);
123
124 desc->created++;
125 desc->allocated += data_size + VARRAY_HDR_SIZE;
126 #endif
127 if (element[element_kind].uses_ggc)
128 ptr = ggc_alloc_cleared (VARRAY_HDR_SIZE + data_size);
129 else
130 ptr = xcalloc (VARRAY_HDR_SIZE + data_size, 1);
131
132 ptr->num_elements = num_elements;
133 ptr->elements_used = 0;
134 ptr->type = element_kind;
135 ptr->name = name;
136 return ptr;
137 }
Then following, the hash tables for declarations are initiated by following functions.
2237 static void
2238 initiate_automaton_decl_table (void) in genattrtab.c
2239 {
2240 work_automaton_decl.mode = dm_automaton;
2241 automaton_decl_table = htab_create (10, automaton_decl_hash,
2242 automaton_decl_eq_p, (htab_del) 0);
2243 }
2336 static void
2337 initiate_insn_decl_table (void) in genattrtab.c
2338 {
2339 work_insn_decl.mode = dm_insn_reserv;
2340 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2341 (htab_del) 0);
2342 }
2438 static void
2439 initiate_decl_table (void) in genattrtab.c
2440 {
2441 work_decl.mode = dm_unit;
2442 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2443 }
Continue with main , after allocating the resource needed, system begins to read in the machine description file.
main (continued)
5988 while (1)
5989 {
5990 int lineno;
5991
5992 desc = read_md_rtx (&lineno, &insn_code_number );
5993 if (desc == NULL)
5994 break ;
5995
5996 switch (GET_CODE (desc))
5997 {
5998 case DEFINE_INSN:
5999 case DEFINE_PEEPHOLE:
6000 case DEFINE_ASM_ATTRIBUTES:
6001 gen_insn (desc, lineno);
6002 break ;
6003
6004 case DEFINE_ATTR:
6005 gen_attr (desc, lineno);
6006 break ;
6007
6008 case DEFINE_DELAY:
6009 gen_delay (desc, lineno);
6010 break ;
6011
6012 case DEFINE_FUNCTION_UNIT:
6013 gen_unit (desc, lineno);
6014 break ;
6015
6016 case DEFINE_CPU_UNIT:
6017 gen_cpu_unit (desc);
6018 break ;
6019
6020 case DEFINE_QUERY_CPU_UNIT:
6021 gen_query_cpu_unit (desc);
6022 break ;
6023
6024 case DEFINE_BYPASS:
6025 gen_bypass (desc);
6026 break ;
6027
6028 case EXCLUSION_SET:
6029 gen_excl_set (desc);
6030 break ;
6031
6032 case PRESENCE_SET:
6033 gen_presence_set (desc);
6034 break ;
6035
6036 case FINAL_PRESENCE_SET:
6037 gen_final_presence_set (desc);
6038 break ;
6039
6040 case ABSENCE_SET:
6041 gen_absence_set (desc);
6042 break ;
6043
6044 case FINAL_ABSENCE_SET:
6045 gen_final_absence_set (desc);
6046 break ;
6047
6048 case DEFINE_AUTOMATON:
6049 gen_automaton (desc);
6050 break ;
6051
6052 case AUTOMATA_OPTION:
6053 gen_automata_option (desc);
6054 break ;
6055
6056 case DEFINE_RESERVATION:
6057 gen_reserv (desc);
6058 break;
6059
6060 case DEFINE_INSN_RESERVATION:
6061 gen_insn_reserv (desc);
6062 break ;
6063
6064 default :
6065 break ;
6066 }
6067 if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)
6068 insn_index_number ++;
6069 }