1 /* Convert language-specific tree expression to rtl instructions,
2 for GNU compiler. Copyright (C) 1988 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "cplus-tree.h"
30 cplus_expand_expr (exp
, target
, tmode
, modifier
)
33 enum machine_mode tmode
;
34 enum expand_modifier modifier
;
36 register rtx op0
, op1
, temp
;
37 tree type
= TREE_TYPE (exp
);
38 register enum machine_mode mode
= TYPE_MODE (type
);
39 register enum tree_code code
= TREE_CODE (exp
);
40 rtx original_target
= target
;
41 int ignore
= target
== const0_rtx
;
43 if (ignore
) target
= 0, original_target
= 0;
45 /* No sense saving up arithmetic to be done
46 if it's all in the wrong mode to form part of an address.
47 And force_operand won't know whether to sign-extend or zero-extend. */
49 if (mode
!= Pmode
&& modifier
== EXPAND_SUM
)
50 modifier
= EXPAND_NORMAL
;
56 /* Something needs to be initialized, but we didn't know
57 where that thing was when building the tree. For example,
58 it could be the return value of a function, or a parameter
59 to a function which lays down in the stack, or a temporary
60 variable which must be passed by reference .
62 Cleanups are handled in a language-specific way: they
63 might be run by the called function (true in GNU C++
64 for parameters with cleanups), or they might be
65 run by the caller, after the call (true in GNU C++
66 for other cleanup needs). */
68 tree func
= TREE_OPERAND (exp
, 0);
69 tree args
= TREE_OPERAND (exp
, 1);
70 tree type
= TREE_TYPE (exp
), slot
;
71 tree fn_type
= TREE_TYPE (TREE_TYPE (func
));
72 tree return_type
= TREE_TYPE (fn_type
);
73 rtx call_target
, return_target
;
75 /* The expression `init' wants to initialize what
76 `target' represents. SLOT holds the slot for TARGET. */
77 slot
= TREE_OPERAND (exp
, 2);
81 /* Should always be called with a target in BLKmode case. */
82 assert (mode
!= BLKmode
);
83 assert (DECL_RTL (slot
) != 0);
85 target
= gen_reg_rtx (mode
);
88 /* The target the initializer will initialize (CALL_TARGET)
89 must now be directed to initialize the target we are
90 supposed to initialize (TARGET). The semantics for
91 choosing what CALL_TARGET is is language-specific,
92 as is building the call which will perform the
93 initialization. It is left here to show the choices that
96 if (TREE_CODE (func
) == ADDR_EXPR
97 && TREE_CODE (TREE_OPERAND (func
, 0)) == FUNCTION_DECL
98 && DECL_CONSTRUCTOR_P (TREE_OPERAND (func
, 0)))
100 type
= TYPE_POINTER_TO (type
);
101 TREE_VALUE (args
) = build1 (ADDR_EXPR
, type
, slot
);
104 else if (TREE_CODE (return_type
) == REFERENCE_TYPE
)
111 call_target
= target
;
113 return_target
= expand_expr (build (CALL_EXPR
, type
, func
, args
, 0), call_target
, mode
, 0);
114 if (call_target
== 0)
115 call_target
= return_target
;
116 else if (call_target
!= return_target
)
117 emit_move_insn (call_target
, return_target
);
119 if (TREE_CODE (return_type
) == REFERENCE_TYPE
)
123 if (GET_CODE (call_target
) == REG
124 && REGNO (call_target
) < FIRST_PSEUDO_REGISTER
)
127 type
= TREE_TYPE (exp
);
129 init
= build (RTL_EXPR
, return_type
, 0, call_target
);
130 /* We got back a reference to the type we want. Now intialize
132 expand_aggr_init (slot
, init
, 0);
135 if (DECL_RTL (slot
) != target
)
136 emit_move_insn (DECL_RTL (slot
), target
);
137 return DECL_RTL (slot
);
146 /* If DECL had its rtl moved from where callers expect it
147 to be, fix it up. RESULT is the nominal rtl for the RESULT_DECL,
148 which may be a pseudo instead of a hard register. */
151 fixup_result_decl (decl
, result
)
157 if (REGNO (result
) >= FIRST_PSEUDO_REGISTER
)
159 rtx real_decl_result
;
161 #ifdef FUNCTION_OUTGOING_VALUE
163 = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl
), current_function_decl
);
166 = FUNCTION_VALUE (TREE_TYPE (decl
), current_function_decl
);
168 REG_FUNCTION_VALUE_P (real_decl_result
) = 1;
169 result
= real_decl_result
;
171 emit_move_insn (result
, DECL_RTL (decl
));
172 emit_insn (gen_rtx (USE
, VOIDmode
, result
));