您的位置:首页 > 编程语言

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

2010-03-04 11:49 507 查看

1.6. 为类型创建节点 – 第一部分

1.6.1. 创建函数类型的节点

首先,看看FUNCTION_TYPE节点是个什么东西:
FUNCTION_TYPE[2]
² 用于表示普通函数和静态成员函数。域TREE_TYPE给出了函数的返回类型。域TYPE_ARG_TYPES是一个包含实参类型的TREE_LIST。其中每一节点的TREE_VALUE是对应实参的类型,TREE_PURPOSE如果非空,是默认参数值。如果链表结尾的节点是void_list_node(一个TREE_LIST节点,它的TREE_VALUE是void_type_node),那么该函数类型不接受可变数量参数。否则,该函数类型接受可变数量参数。
注意在C(不是C++)中,一个被声明为类似void f()的函数是可接受可变数量参数的非原型函数,这种函数节点的TYPE_ARG_TYPES是NULL。

1.6.1.1. 由函数形参创建函数类型节点

函数build_function_type_list接受分立的形参节点,它主要被后端调用。

3876 tree
3877 build_function_type_list (tree return_type, ...) in tree.c
3878 {
3879 tree t, args, last;
3880 va_list p;
3881
3882 va_start (p, return_type);
3883
3884 t = va_arg (p, tree);
3885 for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
3886 args = tree_cons (NULL_TREE, t, args);
3887
3888 last = args;
3889 args = nreverse (args);
3890 TREE_CHAIN (last) = void_list_node;
3891 args = build_function_type (return_type, args);
3892
3893 va_end (p);
3894 return args;
3895 }

注意,形参节点以声明的次序传给build_function_type_list。在3889行,这些参数被反序(即汇编中参数被处理的次序)。

1.6.1.2. 由函数形参链表创建函数类型节点

前端更多地使用下面的函数来创建函数类型节点。函数的参数arg_types是一个tree_list,它把所有形参按声明次序的反序串在一起。

3845 tree
3846 build_function_type (tree value_type, tree arg_types) in tree.c
3847 {
3848 tree t;
3849 unsigned int hashcode;
3850
3851 if (TREE_CODE (value_type) == FUNCTION_TYPE)
3852 {
3853 error ("function return type cannot be function");
3854 value_type = integer_type_node;
3855 }
3856
3857 /* Make a node of the sort we want. */
3858 t = make_node (FUNCTION_TYPE);
3859 TREE_TYPE (t) = value_type;
3860 TYPE_ARG_TYPES (t) = arg_types;
3861
3862 /* If we already have such a type, use the old one and free this one. */
3863 hashcode = TYPE_HASH (value_type) + type_hash_list (arg_types);
3864 t = type_hash_canon (hashcode, t);
3865
3866 if (!COMPLETE_TYPE_P (t))
3867 layout_type (t);
3868 return t;
3869 }

函数的类型由其返回值和形参列表决定,例如:int f (int, int)和int g (int, int)的类型是相同的。为了确保类型节点和类型定义一一对应,所有的类型节点都被保存在哈希表type_hash_table中。

1.6.1.3. 对函数类型的布局

在目标文件中,函数定义被放于代码段中。同样出于访问效率,函数定义的起始地址是有对齐要求的。因此,函数类型也需要布局。

1528 void
1529 layout_type (tree type) in stor-layout.c
1530 {
1531 if (type == 0)
1532 abort ();
1533
1534 /* Do nothing if type has been laid out before. */
1535 if (TYPE_SIZE (type))
1536 return;
1537
1538 switch (TREE_CODE (type))
1539 {

1595 case FUNCTION_TYPE:
1596 case METHOD_TYPE:
1597 TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
1598 TYPE_SIZE (type) = bitsize_int (2 * POINTER_SIZE);
1599 TYPE_SIZE_UNIT (type) = size_int ((2 * POINTER_SIZE) / BITS_PER_UNIT);
1600 break;

1796 }

1801 if (TREE_CODE (type) != RECORD_TYPE
1802 && TREE_CODE (type) != UNION_TYPE
1803 && TREE_CODE (type) != QUAL_UNION_TYPE)
1804 finalize_type_size (type);

1818 }

从代码中可见,FUNCTION_TYPE和METHOD_TYPE都被定义为含有大小为2*POINTER_SIZE的整型模式。在finalize_type_size中类型的对齐量被设为指针的2倍。

1.6.2. 创建索引节点

这个函数所创建的整型节点将作为一个ARRAY_TYPE类型的TYPE_DOMAIN节点。参数maxval应该是最大边界值(数组长度减1)。

3724 tree
3725 build_index_type (tree maxval) in tree.c
3726 {
3727 tree itype = make_node (INTEGER_TYPE);
3728
3729 TREE_TYPE (itype) = sizetype;
3730 TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
3731 TYPE_MIN_VALUE (itype) = size_zero_node;
3732 TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
3733 TYPE_MODE (itype) = TYPE_MODE (sizetype);
3734 TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
3735 TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
3736 TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
3737 TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (sizetype);
3738
3739 if (host_integerp (maxval, 1))
3740 return type_hash_canon (tree_low_cst (maxval, 1), itype);
3741 else
3742 return itype;
3743 }

注意到索引节点的类型是size_t。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: