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

5.13.4.7.1.3. 为函数调用构建节点 从build_function_call返回,在2494行的coerced_params保存了转换后的实参。如果被调用的函数是内建函数,这个内建函数可以在这里被展开,因为没有函数可以调用,不需要创建CALL_EXPR节点。 3716 tree 3717 expand_tree_builtin (tree function, tree params, tree coerced_params) in c-common.c 3718 { 3719 if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL) 3720 return NULL_TREE; 3721 3722 switch (DECL_FUNCTION_CODE (function)) 3723 { 3724 case BUILT_IN_ABS: 3725 case BUILT_IN_LABS: 3726 case BUILT_IN_LLABS: 3727 case BUILT_IN_IMAXABS: 3728 case BUILT_IN_FABS: 3729 case BUILT_IN_FABSL: 3730 case BUILT_IN_FABSF: 3731 if (coerced_params == 0) 3732 return integer_zero_node; 3733 return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0); 3734 3735 case BUILT_IN_CONJ: 3736 case BUILT_IN_CONJF: 3737 case BUILT_IN_CONJL: 3738 if (coerced_params == 0) 3739 return integer_zero_node; 3740 return build_unary_op (CONJ_EXPR, TREE_VALUE (coerced_params), 0); 3741 3742 case BUILT_IN_CREAL: 3743 case BUILT_IN_CREALF: 3744 case BUILT_IN_CREALL: 3745 if (coerced_params == 0) 3746 return integer_zero_node; 3747 return non_lvalue (build_unary_op (REALPART_EXPR, 3748 TREE_VALUE (coerced_params), 0)); 3749 3750 case BUILT_IN_CIMAG: 3751 case BUILT_IN_CIMAGF: 3752 case BUILT_IN_CIMAGL: 3753 if (coerced_params == 0) 3754 return integer_zero_node; 3755 return non_lvalue (build_unary_op (IMAGPART_EXPR, 3756 TREE_VALUE (coerced_params), 0)); 3757 3758 case BUILT_IN_ISGREATER: 3759 return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR); 3760 3761 case BUILT_IN_ISGREATEREQUAL: 3762 return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR); 3763 3764 case BUILT_IN_ISLESS: 3765 return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR); 3766 3767 case BUILT_IN_ISLESSEQUAL: 3768 return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR); 3769 3770 case BUILT_IN_ISLESSGREATER: 3771 return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR); 3772 3773 case BUILT_IN_ISUNORDERED: 3774 return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR); 3775 3776 default: 3777 break; 3778 } 3779 3780 return NULL_TREE; 3781 } 看到对于其他内建函数,该函数返回NULL。这些内建函数及其他非内建函数,应该通过下面的函数来为之构建CALL_EXPR节点。注意到FUNCTION_DECL的TREE_TYPE是该函数的返回类型,如果这个返回类型是一个类类型(参见下面4708行),那么build_cplus_new为这个返回值构建TARGET_EXPR;4709行的fn指向这个TARGET_EXPR。 4670 tree 4671 build_cxx_call(tree fn, tree args, tree converted_args) in call.c 4672 { 4673 tree fndecl; 4674 4675 /* Recognize certain built-in functions so we can make tree-codes 4676 other than CALL_EXPR. We do this when it enables fold-const.c 4677 to do something useful. */ 4678 if (TREE_CODE (fn) == ADDR_EXPR 4679 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL 4680 && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) 4681 { 4682 tree exp; 4683 exp = expand_tree_builtin (TREE_OPERAND (fn, 0), args, converted_args); 4684 if (exp) 4685 return exp; 4686 } 4687 4688 fn = build_call (fn, converted_args); 4689 4690 /* If this call might throw an exception, note that fact. */ 4691 fndecl = get_callee_fndecl (fn); 4692 if ((!fndecl || !TREE_NOTHROW (fndecl)) 4693 && at_function_scope_p () 4694 && cfun) 4695 cp_function_chain->can_throw = 1; 4696 4697 /* Some built-in function calls will be evaluated at compile-time in 4698 fold (). */ 4699 fn = fold (fn); 4700 4701 if (VOID_TYPE_P (TREE_TYPE (fn))) 4702 return fn; 4703 4704 fn = require_complete_type (fn); 4705 if (fn == error_mark_node) 4706 return error_mark_node; 4707 4708 if (IS_AGGR_TYPE (TREE_TYPE (fn))) 4709 fn = build_cplus_new (TREE_TYPE (fn), fn); 4710 return convert_from_reference (fn); 4711 } 这个CALL_EXPR节点实际上由build_call构建。在下面267行,EMPTY_CLASS_EXPR节点代表一个空的类对象。该节点的TREE_TYPE给出这个类类型。毫无疑问,空类的实例可以被共享,而不需要构建个别的实例,因此不需要从实参拷贝该空类的值。显然,这个共享不能发生在不同空类之间,虽然它们都具有相同的值,但它们代表不同的类型,具有不同的语法意义;并且注意模板技巧广泛地使用空类作为标签。 205 tree 206 build_call (tree function, tree parms) in tree.c 207 { 208 int is_constructor = 0; 209 int nothrow; 210 tree tmp; 211 tree decl; 212 tree result_type; 213 tree fntype; 214 215 function = build_addr_func (function); 216 217 if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) 218 { 219 sorry ("unable to call pointer to member function here"); 220 return error_mark_node; 221 } 222 223 fntype = TREE_TYPE (TREE_TYPE (function)); 224 result_type = TREE_TYPE (fntype); 225 226 if (TREE_CODE (function) == ADDR_EXPR 227 && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) 228 decl = TREE_OPERAND (function, 0); 229 else 230 decl = NULL_TREE; 231 232 /* We check both the decl and the type; a function may be known not to 233 throw without being declared throw(). */ 234 nothrow = ((decl && TREE_NOTHROW (decl)) 235 || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function)))); 236 237 if (decl && TREE_THIS_VOLATILE (decl) && cfun) 238 current_function_returns_abnormally = 1; 239 240 if (decl && TREE_DEPRECATED (decl)) 241 warn_deprecated_use (decl); 242 require_complete_eh_spec_types (fntype, decl); 243 244 if (decl && DECL_CONSTRUCTOR_P (decl)) 245 is_constructor = 1; 246 247 if (decl && ! TREE_USED (decl)) 248 { 249 /* We invoke build_call directly for several library functions. 250 These may have been declared normally if we're building libgcc, 251 so we can't just check DECL_ARTIFICIAL. */ 252 if (DECL_ARTIFICIAL (decl) 253 || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "__", 2)) 254 mark_used (decl); 255 else 256 abort (); 257 } 258 259 /* Don't pass empty class objects by value. This is useful 260 for tags in STL, which are used to control overload resolution. 261 We don't need to handle other cases of copying empty classes. */ 262 if (! decl || ! DECL_BUILT_IN (decl)) 263 for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp)) 264 if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) 265 && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) 266 { 267 tree t = build (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp))); 268 TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t), 269 TREE_VALUE (tmp), t); 270 } 271 272 function = build (CALL_EXPR, result_type, function, parms); 273 TREE_HAS_CONSTRUCTOR (function) = is_constructor; 274 TREE_NOTHROW (function) = nothrow; 275 276 return function; 277 } 接着在4691行,get_callee_fndecl获取了由build_call构建的CALL_EXPR所调用的函数。看到如果我们不能在CALL_EXPR中找到FUNCTION_DECL部分,get_callee_fndecl将返回NULL。作为语法的一部分,如果一个函数没有声明抛出任何指定的异常,或nothrow,它可以抛出任何异常;如果处理正在定义的函数,在4695行,也需要做相应的标记。 5.13.4.7.2. 完成初始化函数的调用 如果产生了,根据指定优先级调用初始化函数的,函数定义,下面的finish_objects首先完成该函数的定义。接着目标平台钩子have_ctors_dtors返回true,如果该目标平台支持某些“自然的”方法来收集构造函数及析构函数在启动及退出时运行。这是false,如果我们使用‘collect2’(许多目标系统,在其汇编器及链接器中,不提供对“构造函数”——在‘main’的正式“开始”之前调用的初始化函数。在这样的系统上,GNU CC使用一个叫‘collect2’程序在开始时刻安排对这些函数的调用)。在我们的目标系统上,宏USE_COLLECT2被在makefile中定义来表示使用collect2;因此1959行后的代码被跳过。 1943 static void 1944 finish_objects (int method_type, int initp, tree body) in decl2.c 1945 { 1946 tree fn; 1947 1948 /* Finish up. */ 1949 finish_compound_stmt (body); 1950 fn = finish_function (0); 1951 expand_or_defer_fn (fn); 1952 1953 /* When only doing semantic analysis, and no RTL generation, we 1954 can't call functions that directly emit assembly code; there is 1955 no assembly file in which to put the code. */ 1956 if (flag_syntax_only) 1957 return; 1958 1959 if (targetm.have_ctors_dtors) 1960 { 1961 rtx fnsym = XEXP (DECL_RTL (fn), 0); 1962 if (method_type == 'I') 1963 (* targetm.asm_out.constructor) (fnsym, initp); 1964 else 1965 (* targetm.asm_out.destructor) (fnsym, initp); 1966 } 1967 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值