Studying note of GCC-3.4.6 source (164)

    技术2026-06-12  0

    5.13.4.7.1.3.  Build nodes for the function call

    Return from build_function_call , coerced_params at line 2494 holds the converted arguments. If the function invoked is builtin funciton, the builtin functions can be expanded here and no need to create CALL_EXPR node as there is no function to call.

     

    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 }

     

    See for other builtin functions, the function returns NULL. Those builtin functions tegother with other non-builtin functions should have node of CALL_EXPR be built for by following funciton. Note that TREE_TYPE of the FUNCTION_DECL is the returned type of the function, if this returned type is a class type (see line 4708 below), build_cplus_new then builds the TARGET_EXPR for this returned value; and then fn at line 4709 refers to the TARGET_EXPR created.

     

    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 }

     

    The CALL_EXPR node is in fact built by build_call . Below at line 267, node of EMPTY_CLASS_EXPR represents an empty class object. The TREE_TYPE of the node gives the class type. No doubt, instance of empty class can be shared and no need to create distinctive instances, so it needesn’t copy the value of the empty class from argument. Of course, this share should not be taken among different empty classes, as though they have same value, but they stand for different types and have different semantic meaning; and see template technique widely uses empty classes as tags.

     

    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  }

     

    Next at line 4691, get_callee_fndecl fetches the function being invoked in the CALL_EXPR just built by build_call . See that get_callee_fndecl would return NULL if we can’t find FUNCTION_DECL part in the CALL_EXPR. As part of grammar, if a function doesn't declare to throw any specified exception nor nothrow, it can throw any exception; and if it is handling currently defining function, it also needs mark corresponding flag at line 4695.

    5.13.4.7.2.        Finish the invocation of initialization function

    If code for defining function to invoke initialization functions with specified priority is generated, below finish_objects first finishes the definition of the function. Next the target hook have_ctors_dtors returns true if the target supports some "native" method of collecting constructors and destructors to be run at startup and exit. It is false if we must use `collect2' (many target systems do not have support in the assembler and linker for "constructors"--initialization functions to be called before the official "start" of `main'. On such systems, GNU CC uses a utility called `collect2' to arrange to call these functions at start time). Upon our target system, macro USE_COLLECT2 is defined in the makefile to indicate the using of collect2; so code passing line 1959 is skipped.

     

    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)