Gcc source code analysis, build_function_call () function analysis, gcc function library
In the file c-typeck.c
This place in the c-parse.tab.y file is called!
Primary:
| Primary '('exprlist')' % prec '.'
{$ = Build_function_call ($1, $3 );}
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list -- a chain of TREE_LIST nodes -- in which
TREE_VALUE of each node is a parameter-expression.
FUNCTION's data type may be a function type or a pointer-to-function .*/
Tree
Build_function_call (function, params)
Tree function, params;
{
Register tree fntype;
Register tree value_type;
Register tree coerced_params;
Tree name = NULL_TREE;
Tree actualparameterlist ();
/* Build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context .*/
If (TREE_CODE (function) = NOP_EXPR
& TREE_TYPE (function) = TREE_TYPE (TREE_OPERAND (function, 0 )))
Function = TREE_OPERAND (function, 0 );
/* Convert anything with function type to a pointer-to-function .*/
If (TREE_CODE (function) = FUNCTION_DECL)
{
Name = DECL_NAME (function );
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(Because calling an inline function does not mean the function
Needs to be separately compiled ).*/
Function = build (ADDR_EXPR, build_pointer_type (TREE_TYPE (function )),
Function );
}
Else
Function = default_conversion (function );
Fntype = TREE_TYPE (function );
If (TREE_CODE (fntype) = ERROR_MARK)
Return error_mark_node;
If (! (TREE_CODE (fntype) = POINTER_TYPE
& TREE_CODE (TREE_TYPE (fntype) = FUNCTION_TYPE ))
{
Error ("called object is not a function ");
Return error_mark_node;
}
/* Fntype now gets the type of function pointed .*/
Fntype = TREE_TYPE (fntype );
/* Convert the parameters to the types declared in
Function prototype, or apply default promotions .*/
Coerced_params = actualparameterlist (TYPE_ARG_TYPES (fntype), params, name );
/* Recognize certain built-in functions so we can make tree-codes
Other than CALL_EXPR. We do this when it enables fold-const.c
To do something useful .*/
If (TREE_CODE (function) = ADDR_EXPR
& TREE_CODE (TREE_OPERAND (function, 0) = FUNCTION_DECL)
Switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0 )))
{
Case BUILT_IN_ABS:
Case BUILT_IN_LABS:
Case BUILT_IN_FABS:
If (coerced_params = 0)
Return integer_zero_node;
Return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0 );
}
Value_type = TREE_TYPE (fntype )? TREE_TYPE (fntype): void_type_node;
{
Register tree result =
Build (CALL_EXPR, value_type, function, coerced_params, NULL_TREE );
TREE_VOLATILE (result) = 1;
If (value_type = void_type_node)
Return result;
Return require_complete_type (result );
}
}
Function = build (ADDR_EXPR, build_pointer_type (TREE_TYPE (function )),
Function );
The following tree is generated after the preceding statement.
<Addr_expr 84090
Type <pointer_type 98f48
Type <function_type 956e8 type <integer_type 1_d0 * int>
Permanent EP
Size <integer_cst 82dd8 literal permanent 8
Align 32 size_unit 8 sep_unit 0 symtab 0
Arg-typepes <tree_list 95698 permanent value <pointer_type 9117c>
Pointer_to_this <pointer_type 98f48> chain <function_type 959b0>
Permanent unsigned SI
Size <integer_cst 8254c literal permanent 4
Align 32 size_unit 8 sep_unit 32 symtab 0
Arg 0 <function_decl 95740 printf type <function_type 956e8>
External public permanent used QI file/usr/include/stdio. h line 214
Align 1 size_unit 1 offset 0
Chain <function_decl 954d8 ungetc type <function_type 8f4f0>
External public permanent QI file/usr/include/stdio. h line 212
Align 1 size_unit 1 offset 0 chain <function_decl 95280 fputs>