在backend_init中,接下来调用init_function_once。
8140 void
8141 init_function_once (void) in function.c
8142 {
8143 VARRAY_INT_INIT (prologue, 0, "prologue");
8144 VARRAY_INT_INIT (epilogue, 0, "epilogue");
8145 VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue");
8146 }
上面,prologue记录了构成序幕(prologue)指令的INSN_UIDs,epilogue则记录了构成结尾(epilogue)指令的INSN_UIDs,而sibcall_epilogue记录了在函数中构成每个兄弟调用结尾指令的INSN_UIDs。对于每个由编译器产生的指令,其INSN_UID是一个唯一的号码,用于区分源代码中的指令。它们不必要为顺序递增。对于rtx对象INSN,INSN_UID是其第一个孩子。prologue,epilogue及sibcall_epilogue都是varray_type类型,这是能保存多种类型的虚拟数组。varray_type的定义与rtx十分相似。这是个有趣的数据结构。
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_head_tag不仅仅是定义了成员类型及大小尺寸的头,还包含了主体——varray_data。
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];
129 } varray_data;
VARRAY_INT_INIT把这些varray初始化为0个int类型的元素——现在它是空的。
159 #define VARRAY_INT_INIT(va, num, name) / in varray.h
160 va = varray_init (num, VARRAY_DATA_I, 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 }
为了确定数组成员所保存的数据类型及其大小,还需要一些信息。这些信息就保存在名为element的静态常量数组中,其定义如下。
87 static const struct { in varray.c
88 unsigned char size;
89 bool uses_ggc;
90 } element[NUM_VARRAY_DATA] = {
91 { sizeof (char), 1 },
92 { sizeof (unsigned char), 1 },
93 { sizeof (short), 1 },
94 { sizeof (unsigned short), 1 },
95 { sizeof (int), 1 },
96 { sizeof (unsigned int), 1 },
97 { sizeof (long), 1 },
98 { sizeof (unsigned long), 1 },
99 { sizeof (HOST_WIDE_INT), 1 },
100 { sizeof (unsigned HOST_WIDE_INT), 1 },
101 { sizeof (void *), 1 },
102 { sizeof (char *), 1 },
103 { sizeof (struct rtx_def *), 1 },
104 { sizeof (struct rtvec_def *), 1 },
105 { sizeof (union tree_node *), 1 },
106 { sizeof (struct bitmap_head_def *), 1 },
107 { sizeof (struct reg_info_def *), 0 },
108 { sizeof (struct const_equiv_data), 0 },
109 { sizeof (struct basic_block_def *), 0 },
110 { sizeof (struct elt_list *), 1 },
111 };
回到backend_init,接下来调用的函数是init_varasm_once。
4584 void
4585 init_varasm_once (void) in varasm.c
4586 {
4587 in_named_htab = htab_create_ggc (31, in_named_entry_hash,
4588 in_named_entry_eq, NULL);
4589 const_desc_htab = htab_create_ggc (1009, const_desc_hash,
4590 const_desc_eq, NULL);
4591
4592 const_alias_set = new_alias_set ();
4593 }
上面的in_named_htab是用于保存各具名段标识符的哈希表。const_desc_htab则是保存汇编生成阶段的rtx常量对象的哈希表。const_alias_set则用于描述这些常量的别名集(常量的别名集只包含自身)。