Re: ADDR_EXPR and temporaries

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux