ADDR_EXPR and temporaries
Jan Trávníček
Jan.Travnicek@fit.cvut.cz
Wed Jan 1 20:53:00 GMT 2014
Hi,
so I solved it, apparently my code missed TREE_ADDRESSABLE in
variable declaration:
tree variable_j = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier("j"), integer_type_node);
TREE_ADDRESSABLE(variable_j) = true;
DECL_CONTEXT(variable_j) = main_fn_decl;
and DECL_INITIAL is used a bit differently:
tree set_pi = build1(ADDR_EXPR,
build_pointer_type(TREE_TYPE(variable_i)), variable_i);
TREE_USED(set_pi) = true;
DECL_INITIAL(variable_pi) = set_pi;
Regards,
Jan TrĂĄvnĂèek
On 12/30/2013 02:11 PM, Jan TrĂĄvnĂèek wrote:
> Hi all,
>
> I have been trying to understand how to write front end for gcc by
> directly creating something in parse_file function. However I have a
> problem with ADDR_EXPR.
> I'm working with gcc 4.9.0 20131223 experimental (available from svn).
>
> Consider the following code:
> >>>---------------------------------------------------------------------
> tree params = NULL_TREE;
>
> tree main_fn_type = build_function_type_list(integer_type_node,
> params);
> tree main_fn_decl = build_decl(BUILTINS_LOCATION, FUNCTION_DECL,
> get_identifier("main"), main_fn_type);
>
> DECL_CONTEXT(main_fn_decl) = NULL_TREE;
> TREE_STATIC(main_fn_decl) = true;
> TREE_PUBLIC(main_fn_decl) = true;
> DECL_ARGUMENTS(main_fn_decl) = NULL_TREE;
>
> tree main_ret = build_decl(BUILTINS_LOCATION, RESULT_DECL,
> NULL_TREE, TREE_TYPE(main_fn_type));
> DECL_CONTEXT(main_ret) = main_fn_decl;
> DECL_ARTIFICIAL(main_ret) = true;
> DECL_IGNORED_P(main_ret) = true;
>
> DECL_RESULT(main_fn_decl) = main_ret;
>
> tree main_stmts = alloc_stmt_list ();
> tree main_block_decls = NULL_TREE;
>
> /* Declare a variables */
> tree variable_i = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> get_identifier("i"), integer_type_node);
> DECL_CONTEXT(variable_i) = main_fn_decl;
>
> tree variable_j = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> get_identifier("j"), integer_type_node);
> DECL_CONTEXT(variable_j) = main_fn_decl;
>
> tree variable_pi = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> get_identifier("pi"), build_pointer_type(integer_type_node));
> DECL_CONTEXT(variable_pi) = main_fn_decl;
>
> tree variable_pj = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> get_identifier("pj"), build_pointer_type(integer_type_node));
> DECL_CONTEXT(variable_pj) = main_fn_decl;
>
> TREE_CHAIN( variable_pj ) = main_block_decls;
> main_block_decls = variable_pj;
>
> TREE_CHAIN( variable_pi ) = main_block_decls;
> main_block_decls = variable_pi;
>
> TREE_CHAIN( variable_j ) = main_block_decls;
> main_block_decls = variable_j;
>
> TREE_CHAIN( variable_i ) = main_block_decls;
> main_block_decls = variable_i;
>
> /* Set variables */
> tree set_pi = build2(INIT_EXPR, TREE_TYPE(variable_pi), variable_pi,
> build1(ADDR_EXPR, TREE_TYPE(variable_pi), variable_i));
> TREE_USED(set_pi) = true;
> DECL_INITIAL(variable_pi) = set_pi;
>
> tree set_pj = build2(MODIFY_EXPR, TREE_TYPE(variable_pj),
> variable_pj, build1(ADDR_EXPR, TREE_TYPE(variable_pj), variable_j));
> TREE_USED(set_pj) = true;
> append_to_statement_list(set_pj, &main_stmts);
>
> /* Set return and return */
> tree main_set_ret = build2(MODIFY_EXPR, TREE_TYPE(main_ret),
> main_ret, build_int_cst(integer_type_node, 10));
> TREE_USED(main_set_ret) = true;
> tree main_ret_expr = build1(RETURN_EXPR, void_type_node, main_set_ret);
> append_to_statement_list(main_ret_expr, &main_stmts);
>
> /* Create main block */
> tree main_block = build_block(main_block_decls, NULL_TREE,
> main_fn_decl, NULL_TREE);
>
> DECL_INITIAL(main_fn_decl) = main_block;
> TREE_USED(main_block) = true;
>
> tree bind = build3( BIND_EXPR, void_type_node,
> BLOCK_VARS(main_block), NULL_TREE, main_block );
>
> /* Finalize the main function */
> BIND_EXPR_BODY(bind) = main_stmts;
> DECL_SAVED_TREE(main_fn_decl) = bind;
> TREE_SIDE_EFFECTS(bind) = true;
>
> debug_body(main_fn_decl);
>
> vec_safe_push( global_decls_vec, main_fn_decl );
>
> /* Prepare the function for the GCC middle-end */
> gimplify_function_tree(main_fn_decl);
> cgraph_finalize_function(main_fn_decl, false);
>
> debug_body(main_fn_decl);
> <<<---------------------------------------------------------------------
>
> then the debug_body functions print the following:
> >>>---------------------------------------------------------------------
> (nofn) ()
> {
> signed int i;
> signed int j;
> signed int * pi = pi = &i;
> signed int * pj;
>
> pj = &j;
> return 10;
> }
>
> main ()
> {
> signed int j.0;
> signed int D.30;
> signed int i;
> signed int j;
> signed int * pi = pi = &i;
> signed int * pj;
>
> j.0 = j;
> pj = &j.0;
> D.30 = 10;
> return D.30;
> }
> <<<---------------------------------------------------------------------
>
> Strange thing is why there is pi = pi in signed int * pi = pi = &i;
> but it is ok from the semantics point of view.
> And more important is why there is temporary j.0 after gimplification
> and pj is made to point at this temporary:
> j.0 = j;
> pj = &j.0;
>
> I read that ADDR_EXPR can introduces a temporary when the argument is
> not lvalue. But this is not the case.
>
> This example is simplified example of what I have been trying to do:
> Call scanf with agruments "%d" and &j. The fromating string is passed
> correctly (tested with printf), however the second argument is made a
> pointer to a temporary so it does not work.
>
> Thank you for your reply.
>
> Best regards,
> Jan TrĂĄvnĂèek
More information about the Gcc-help
mailing list