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