From 42c089971e4987c1fc1338d7ff659f2be9c9b7e5 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 2 Sep 2009 10:43:10 +0000 Subject: trans.c (gnat_gimplify_expr): Gimplify the SAVE_EXPR built for misaligned arguments. * gcc-interface/trans.c (gnat_gimplify_expr) : Gimplify the SAVE_EXPR built for misaligned arguments. Remove redundant stuff. (addressable_p): Return true for more rvalues. Co-Authored-By: Olivier Hainque From-SVN: r151319 --- gcc/ada/gcc-interface/trans.c | 72 +++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 41 deletions(-) (limited to 'gcc/ada/gcc-interface') diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 7333f8c..29ab72a 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -5794,17 +5794,17 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, case ADDR_EXPR: op = TREE_OPERAND (expr, 0); - /* If we're taking the address of a constant CONSTRUCTOR, force it to + /* If we are taking the address of a constant CONSTRUCTOR, force it to be put into static memory. We know it's going to be readonly given - the semantics we have and it's required to be static memory in - the case when the reference is in an elaboration procedure. */ + the semantics we have and it's required to be in static memory when + the reference is in an elaboration procedure. */ if (TREE_CODE (op) == CONSTRUCTOR && TREE_CONSTANT (op)) { tree new_var = create_tmp_var (TREE_TYPE (op), "C"); + TREE_ADDRESSABLE (new_var) = 1; TREE_READONLY (new_var) = 1; TREE_STATIC (new_var) = 1; - TREE_ADDRESSABLE (new_var) = 1; DECL_INITIAL (new_var) = op; TREE_OPERAND (expr, 0) = new_var; @@ -5812,44 +5812,28 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, return GS_ALL_DONE; } - /* If we are taking the address of a SAVE_EXPR, we are typically - processing a misaligned argument to be passed by reference in a - procedure call. We just mark the operand as addressable + not - readonly here and let the common gimplifier code perform the - temporary creation, initialization, and "instantiation" in place of - the SAVE_EXPR in further operands, in particular in the copy back - code inserted after the call. */ - else if (TREE_CODE (op) == SAVE_EXPR) - { - TREE_ADDRESSABLE (op) = 1; - TREE_READONLY (op) = 0; - } - - /* We let the gimplifier process &COND_EXPR and expect it to yield the - address of the selected operand when it is addressable. Besides, we - also expect addressable_p to only let COND_EXPRs where both arms are - addressable reach here. */ - else if (TREE_CODE (op) == COND_EXPR) - ; - - /* Otherwise, if we are taking the address of something that is neither - reference, declaration, or constant, make a variable for the operand - here and then take its address. If we don't do it this way, we may - confuse the gimplifier because it needs to know the variable is - addressable at this point. This duplicates code in - internal_get_tmp_var, which is unfortunate. */ - else if (TREE_CODE_CLASS (TREE_CODE (op)) != tcc_reference - && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_declaration - && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_constant) + /* If we are taking the address of a SAVE_EXPR, we are typically dealing + with a misaligned argument to be passed by reference in a subprogram + call. We cannot let the common gimplifier code perform the creation + of the temporary and its initialization because, in order to ensure + that the final copy operation is a store and since the temporary made + for a SAVE_EXPR is not addressable, it may create another temporary, + addressable this time, which would break the back copy mechanism for + an IN OUT parameter. */ + if (TREE_CODE (op) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (op)) { - tree new_var = create_tmp_var (TREE_TYPE (op), "A"); - gimple stmt; - + tree mod, val = TREE_OPERAND (op, 0); + tree new_var = create_tmp_var (TREE_TYPE (op), "S"); TREE_ADDRESSABLE (new_var) = 1; - stmt = gimplify_assign (new_var, op, pre_p); - if (EXPR_HAS_LOCATION (op)) - gimple_set_location (stmt, EXPR_LOCATION (op)); + mod = build2 (INIT_EXPR, TREE_TYPE (new_var), new_var, val); + if (EXPR_HAS_LOCATION (val)) + SET_EXPR_LOCATION (mod, EXPR_LOCATION (val)); + gimplify_and_add (mod, pre_p); + ggc_free (mod); + + TREE_OPERAND (op, 0) = new_var; + SAVE_EXPR_RESOLVED_P (op) = 1; TREE_OPERAND (expr, 0) = new_var; recompute_tree_invariant_for_addr_expr (expr); @@ -5866,7 +5850,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, if ((TREE_CODE (op) == TYPE_DECL || TREE_CODE (op) == VAR_DECL) && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (op))) switch (TREE_CODE (TREE_TYPE (op))) - { + { case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: @@ -5895,7 +5879,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, default: break; - } + } /* ... fall through ... */ @@ -6942,12 +6926,18 @@ addressable_p (tree gnu_expr, tree gnu_type) case UNCONSTRAINED_ARRAY_REF: case INDIRECT_REF: + return true; + case CONSTRUCTOR: case STRING_CST: case INTEGER_CST: case NULL_EXPR: case SAVE_EXPR: case CALL_EXPR: + case PLUS_EXPR: + case MINUS_EXPR: + /* All rvalues are deemed addressable since taking their address will + force a temporary to be created by the middle-end. */ return true; case COND_EXPR: -- cgit v1.1