您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (60)

2010-07-16 10:54 351 查看
4.3.1.7.5.6.5. Processing attributes of builtin
4.3.1.7.5.6.5.1. Install attribute handlers
Though we create nodes for attributes of builtin functions, we still don’t install them into the builtin function. And even there is no attribute, we should express this fact in the function node explicitly.

builtin_function_1 (continue)

3253 /* Possibly apply some default attributes to this built-in function. */
3254 if (attrs)
3255 decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
3256 else
3257 decl_attributes (&decl, NULL_TREE, 0);
3258
3259 return decl;
3260 }

Obviously, the language determines the set of available attributes, further some attributes’ processing methods depend on target. So first, we need to select out the correct methods according to the language and the target.

139 tree
140 decl_attributes (tree *node, tree attributes, int flags) in attribs.c
141 {
142 tree a;
143 tree returned_attrs = NULL_TREE;
144
145 if (!attributes_initialized)
146 init_attributes ();

Attribute handling methods are collected by attribute_spec with other running information. In GCC v3.4.6, the methods are grouped into 4 sets.

42 static const struct attribute_spec *attribute_tables[4]; in attribs.c

2181 struct attribute_spec in tree.h
2182 {
2183 /* The name of the attribute (without any leading or trailing __),
2184 or NULL to mark the end of a table of attributes. */
2185 const char *const name;
2186 /* The minimum length of the list of arguments of the attribute. */
2187 const int min_length;
2188 /* The maximum length of the list of arguments of the attribute
2189 (-1 for no maximum). */
2190 const int max_length;
2191 /* Whether this attribute requires a DECL. If it does, it will be passed
2192 from types of DECLs, function return types and array element types to
2193 the DECLs, function types and array types respectively; but when
2194 applied to a type in any other circumstances, it will be ignored with
2195 a warning. (If greater control is desired for a given attribute,
2196 this should be false, and the flags argument to the handler may be
2197 used to gain greater control in that case.) */
2198 const bool decl_required;
2199 /* Whether this attribute requires a type. If it does, it will be passed
2200 from a DECL to the type of that DECL. */
2201 const bool type_required;
2202 /* Whether this attribute requires a function (or method) type. If it does,
2203 it will be passed from a function pointer type to the target type,
2204 and from a function return type (which is not itself a function
2205 pointer type) to the function type. */
2206 const bool function_type_required;
2207 /* Function to handle this attribute. NODE points to the node to which
2208 the attribute is to be applied. If a DECL, it should be modified in
2209 place; if a TYPE, a copy should be created. NAME is the name of the
2210 attribute (possibly with leading or trailing __). ARGS is the TREE_LIST
2211 of the arguments (which may be NULL). FLAGS gives further information
2212 about the context of the attribute. Afterwards, the attributes will
2213 be added to the DECL_ATTRIBUTES or TYPE_ATTRIBUTES, as appropriate,
2214 unless *NO_ADD_ATTRS is set to true (which should be done on error,
2215 as well as in any other cases when the attributes should not be added
2216 to the DECL or TYPE). Depending on FLAGS, any attributes to be
2217 applied to another type or DECL later may be returned;
2218 otherwise the return value should be NULL_TREE. This pointer may be
2219 NULL if no special handling is required beyond the checks implied
2220 by the rest of this structure. */
2221 tree (*const handler) (tree *node, tree name, tree args,
2222 int flags, bool *no_add_attrs);
2223 };

The detail information about these 4 sets are given in following 4 tables.
name
min args
max args
del_req
type_req
func_req
handler
packed
0
0
false
false
false
handle_packed_attribute
nocommon
0
0
true
false
false
handle_nocommon_attribute
common
0
0
true
false
false
handle_common_attribute
noreturn
0
0
true
false
false
handle_noreturn_attribute
volatile
0
0
true
false
false
handle_noreturn_attribute
noinline
0
0
true
false
false
handle_noinline_attribute
always_inline
0
0
true
false
false
handle_always_inline_attribute
used
0
0
true
false
false
handle_used_attribute
unused
0
0
false
false
false
handle_unused_attribute
const
0
0
true
false
false
handle_const_attribute
transparent_union
0
0
false
false
false
handle_transparent_union_attribute
constructor
0
0
true
false
false
handle_constructor_attribute
destructor
0
0
true
false
false
handle_destructor_attribute
mode
1
1
false
true
false
handle_mode_attribute
section
1
1
true
false
false
handle_section_attribute
aligned
0
1
false
false
false
handle_aligned_attribute
weak
0
0
true
false
false
handle_weak_attribute
alias
1
1
true
false
false
handle_alias_attribute
no_instrument_function
0
0
true
false
false
handle_no_instrument_function_attribute
malloc
0
0
true
false
false
handle_malloc_attribute
no_stack_limit
0
0
true
false
false
handle_no_limit_stack_attribute
pure
0
0
true
false
false
handle_pure_attribute
deprecated
0
0
false
false
false
handle_deprecated_attribute
vector_size
1
1
false
true
false
handle_vector_size_attribute
visibility
1
1
true
false
false
handle_visibility_attribute
tls_model
1
1
true
false
false
handle_tls_model_attribute
nonnull
0
-1
false
true
true
handle_nonnull_attribute
nothrow
0
0
true
false
false
handle_nothrow_attribute
may_alias
0
0
false
true
false
NULL
cleanup
1
1
true
false
false
handle_cleanup_attribute
warn_unused_result
0
0
false
true
true
handle_warn_unused_result_attribute
Table 12: builtin functions of common_attribute_table for C++
name
min args
max args
del_req
type_req
func_req
handler
java_interface
0
0
false
false
false
handle_java_interface_attribute
com_interface
0
0
false
false
false
handle_com_interface_attribute
init_priority
1
1
true
false
false
handle_init_priority_attribute
Table 13: builtin function of attribute_table for C++
name
min args
max args
del_req
type_req
func_req
handler
format
3
3
false
true
true
handle_format_attribute
format_arg
1
1
false
true
true
handle_format_arg_attribute
Table 14: builtin function of format_attribute_table for C++
name
min args
max args
del_req
type_req
func_req
handler
stdcall
0
0
false
true
true
ix86_handle_cdecl_attribute
fastcall
0
0
false
true
true
ix86_handle_cdecl_attribute
cdecl
0
0
false
true
true
ix86_handle_cdecl_attribute
regparm
1
1
false
true
true
ix86_handle_regparm_attribute
ms_struct
0
0
false
false
false
ix86_handle_struct_attribute
gcc_struct
0
0
false
false
false
ix86_handle_struct_attribute
Table 15: builtin function of ix86_attribute_table for x86 machine
In below code, it can see that the first 3 tables are set by language hook, which have their content filled by the language; and in the last table are attributes unrelated to language but depend on target.

55 static void
56 init_attributes (void) in attribs.c
57 {
58 size_t i;
59
60 attribute_tables[0] = lang_hooks.common_attribute_table;
61 attribute_tables[1] = lang_hooks.attribute_table;
62 attribute_tables[2] = lang_hooks.format_attribute_table;
63 attribute_tables[3] = targetm.attribute_table;
64
65 /* Translate NULL pointers to pointers to the empty table. */
66 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
67 if (attribute_tables[i] == NULL)
68 attribute_tables[i] = empty_attribute_table;
69
70 #ifdef ENABLE_CHECKING
...
125 #endif
126
127 attributes_initialized = true;
128 }

Remember that in the builtin function “__builtin_vprintf”, its attributes are given in built_in_attributes [ATTR_FORMAT_PRINTF_1_0], and its structure is shown is below figure.



In this image, it is clearly that attributes are linked tegother by field chain, with field purpose tells out what it is for and field value gives out its content. Notice that purpose field in fact is a node of identifier.

decl_attributes (continue)

148 (*targetm.insert_attributes) (*node, &attributes);
149
150 for (a = attributes; a; a = TREE_CHAIN (a))
151 {
152 tree name = TREE_PURPOSE (a);
153 tree args = TREE_VALUE (a);
154 tree *anode = node;
155 const struct attribute_spec *spec = NULL;
156 bool no_add_attrs = 0;
157 tree fn_ptr_tmp = NULL_TREE;
158 size_t i;
159
160 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
161 {
162 int j;
163
164 for (j = 0; attribute_tables[i][j].name != NULL; j++)
165 {
166 if (is_attribute_p (attribute_tables[i][j].name, name))
167 {
168 spec = &attribute_tables[i][j];
169 break;
170 }
171 }
172 if (spec != NULL)
173 break;
174 }
175
176 if (spec == NULL)
177 {
178 warning ("`%s' attribute directive ignored",
179 IDENTIFIER_POINTER (name));
180 continue;
181 }
182 else if (list_length (args) < spec->min_length
183 || (spec->max_length >= 0
184 && list_length (args) > spec->max_length))
185 {
186 error ("wrong number of arguments specified for `%s' attribute",
187 IDENTIFIER_POINTER (name));
188 continue;
189 }

At line 148, for x86 machine, insert_attributes is not redefined. It does nothing by default. Andnote that anode and node are both pointer of pointer, node always keeps the address of the tree node, and anode transfer within the node for searching the real object the attributes being applied. To clarify the real kind of the node, argument flags is used give out the detail. Currently, below enumerators are in used:
ATTR_FLAG_DECL_NEXT: node is the type of a declaration, and any attributes that should be passed in again to be applied to the declaration rather than the type should be returned.
ATTR_FLAG_FUNCTION_NEXT: node is a function-return-type, and any attributes that should be passed in again to be applied to the function type rather than the return type should be returned.
ATTR_FLAG_ARRAY_NEXT: node is an array-element-type, and any attributes that should be passed in again to be applied to the array type rather than the element type should be returned.
ATTR_FLAG_TYPE_IN_PLACE: node is a struct, union or enum type being created, and should be modified in place.
ATTR_FLAG_BUILT_IN: The attributes are being applied by default to a library function whose name indicates known behavior, and should be silently ignored if they are not in fact compatible with the function type.
Here for builtin “__builtin_vprintf”, argument flags is ATTR_FLAG_BUILT_IN.

decl_attributes (continue)

191 if (spec->decl_required && !DECL_P (*anode))
192 {
193 if (flags & ((int) ATTR_FLAG_DECL_NEXT
194 | (int) ATTR_FLAG_FUNCTION_NEXT
195 | (int) ATTR_FLAG_ARRAY_NEXT))
196 {
197 /* Pass on this attribute to be tried again. */
198 returned_attrs = tree_cons (name, args, returned_attrs);
199 continue;
200 }
201 else
202 {
203 warning ("`%s' attribute does not apply to types",
204 IDENTIFIER_POINTER (name));
205 continue;
206 }
207 }
208
209 /* If we require a type, but were passed a decl, set up to make a
210 new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE
211 would have applied if we'd been passed a type, but we cannot modify
212 the decl's type in place here. */
213 if (spec->type_required && DECL_P (*anode))
214 {
215 anode = &TREE_TYPE (*anode);
216 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
217 }
218
219 if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
220 && TREE_CODE (*anode) != METHOD_TYPE)
221 {
222 if (TREE_CODE (*anode) == POINTER_TYPE
223 && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
224 || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
225 {
226 /* OK, this is a bit convoluted. We can't just make a copy
227 of the pointer type and modify its TREE_TYPE, because if
228 we change the attributes of the target type the pointer
229 type needs to have a different TYPE_MAIN_VARIANT. So we
230 pull out the target type now, frob it as appropriate, and
231 rebuild the pointer type later.
232
233 This would all be simpler if attributes were part of the
234 declarator, grumble grumble. */
235 fn_ptr_tmp = TREE_TYPE (*anode);
236 anode = &fn_ptr_tmp;
237 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
238 }
239 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
240 {
241 /* Pass on this attribute to be tried again. */
242 returned_attrs = tree_cons (name, args, returned_attrs);
243 continue;
244 }
245
246 if (TREE_CODE (*anode) != FUNCTION_TYPE
247 && TREE_CODE (*anode) != METHOD_TYPE)
248 {
249 warning ("`%s' attribute only applies to function types",
250 IDENTIFIER_POINTER (name));
251 continue;
252 }
253 }
254
255 if (spec->handler != NULL)
256 returned_attrs = chainon ((*spec->handler) (anode, name, args,
257 flags, &no_add_attrs),
258 returned_attrs);

Refer to builtin function for format_attribute_table for C++, for attribute of format, it requires type and function type, but node is a FUNCTION_DECL. However, at line 215, anode is updated to the type of declaration - builtin_types [BT_FN_INT_CONST_STRING_VALIST_ARG].
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: