GCC-3.4.6源代码学习笔记(60)

4.3.1.7.5.6.5.              处理内建函数的属性

4.3.1.7.5.6.5.1.        建立属性处理方法

虽然我们已经为内建函数的属性创建了节点,我们还未将它们加入到内建函数的节点中。而且即使没有属性,我们也需要在函数节点中明确地表示出来。

 

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   }

 

显然,语言定义出了可用的属性集的,进一步,某些属性的处理因平台而有不同。因此,首先我们需要根据语言及目标平台设定的处理方法。

 

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_spec连同其它运行时信息收集在一起。在GCC v3.4.6,这些方法被分为4个集合。

 

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   };

 

4个集合的详细信息显示在下面的4个表中。

属性名字

最少 参数

最多参数

del_req

type_req

func_req

处理方法

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

12:用于C++common_attribute_table中的内建函数

属性名字

最少 参数

最多参数

del_req

type_req

func_req

处理方法

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

13:用于C++attribute_table中的内建函数

属性名字

最少 参数

最多参数

del_req

type_req

func_req

处理方法

format

3

3

false

true

true

handle_format_attribute

format_arg

1

1

false

true

true

handle_format_arg_attribute

14:用于C++format_attribute_table中的内建函数

属性名字

最少 参数

最多参数

del_req

type_req

func_req

处理方法

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

15:用于C++ix86_attribute_table中的内建函数

从下面的代码中,可以看到前3个表来自语言钩子,由语言来决定其内容;而最后的一个表是与语言无关,但依赖于平台的属性。

 

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    }

 

回忆对于内建函数“__builtin_vprintf”,其属性是built_in_attributes [ATTR_FORMAT_PRINTF_1_0],其节点形式如下图所示。

d

在上图中,可以清楚地看到属性节点通过域chain链接在一起,而域purpose则告知该属性作何用,并域value给出其内容。注意,域purpose实际上指向一个标识符节点。

 

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        }

 

148行,对于x86机器,没有重新定义insert_attributes。默认地这个函数什么都不做。同时注意anodenode都是指针的指针,node一直保存着对应节点的地址,而anode根据情况,在节点中移动,寻找属性所应用的真正对象。为了澄清node的真正类属,参数flags给出了细节。当前,我们能用到如下的值:

ATTR_FLAG_DECL_NEXTnode是一个声明的类型,任一应该重新传入,以应用于声明而不是类型的属性,应该直接被返回。

ATTR_FLAG_FUNCTION_NEXTnode是一个函数返回类型,任一应该重新传入,以应用于函数类型,而不是返回类型的属性,应该被直接返回。

ATTR_FLAG_ARRAY_NEXTnode是一个数组元素的类型,任一应该重新传入,以应用于数组类型,而不是数组元素类型的属性,应该被直接返回。

ATTR_FLAG_TYPE_IN_PLACEnode是一个正在被创建的structunionenum类型,应该直接进行修改。

ATTR_FLAG_BUILT_IN:该属性默认地被应用于一个库函数,其名字显示其行为已知。如果属性事实上与函数类型不相符,它们将被无声地忽略。

这里,对于内建函数“__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);

 

参考C++format_attribute_table表,对于属性format,它应用于类型或函数类型,但node是一个FUNCTION_DECL。不过在215行,anode被更新为声明的类型——builtin_types [BT_FN_INT_CONST_STRING_VALIST_ARG]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值