aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1993-03-31 16:06:33 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1993-03-31 16:06:33 -0500
commit896102d0c667780bf95d2766b22ac29c365fd323 (patch)
treeacfb7fb24a2d895ae22b4f5ee5c1a3dd44a519ac
parent475dd3b4b88e80fb96e705432da37501b798c99f (diff)
downloadgcc-896102d0c667780bf95d2766b22ac29c365fd323.zip
gcc-896102d0c667780bf95d2766b22ac29c365fd323.tar.gz
gcc-896102d0c667780bf95d2766b22ac29c365fd323.tar.bz2
(expand_expr, case ADDR_EXPR): Allow taking the address of any object;
used in call-by-reference situations. From-SVN: r3970
-rw-r--r--gcc/expr.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 0ca8fe0..cdaf15f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5184,6 +5184,30 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
(modifier == EXPAND_INITIALIZER
? modifier : EXPAND_CONST_ADDRESS));
+
+ /* We would like the object in memory. If it is a constant,
+ we can have it be statically allocated into memory. For
+ a non-constant (REG or SUBREG), we need to allocate some
+ memory and store the value into it. */
+
+ if (CONSTANT_P (op0))
+ op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
+ op0);
+
+ if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
+ {
+ /* If this object is in a register, it must be not
+ be BLKmode. */
+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ enum machine_mode inner_mode = TYPE_MODE (inner_type);
+ rtx memloc
+ = assign_stack_temp (inner_mode,
+ int_size_in_bytes (inner_type), 1);
+
+ emit_move_insn (memloc, op0);
+ op0 = memloc;
+ }
+
if (GET_CODE (op0) != MEM)
abort ();