1 |
12 |
jlechner |
/* Handle types for the GNU compiler for the Java(TM) language.
|
2 |
|
|
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
|
3 |
|
|
Free Software Foundation, Inc.
|
4 |
|
|
|
5 |
|
|
This file is part of GCC.
|
6 |
|
|
|
7 |
|
|
GCC is free software; you can redistribute it and/or modify
|
8 |
|
|
it under the terms of the GNU General Public License as published by
|
9 |
|
|
the Free Software Foundation; either version 2, or (at your option)
|
10 |
|
|
any later version.
|
11 |
|
|
|
12 |
|
|
GCC is distributed in the hope that it will be useful,
|
13 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 |
|
|
GNU General Public License for more details.
|
16 |
|
|
|
17 |
|
|
You should have received a copy of the GNU General Public License
|
18 |
|
|
along with GCC; see the file COPYING. If not, write to
|
19 |
|
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
20 |
|
|
Boston, MA 02110-1301, USA.
|
21 |
|
|
|
22 |
|
|
Java and all Java-based marks are trademarks or registered trademarks
|
23 |
|
|
of Sun Microsystems, Inc. in the United States and other countries.
|
24 |
|
|
The Free Software Foundation is independent of Sun Microsystems, Inc. */
|
25 |
|
|
|
26 |
|
|
/* Written by Per Bothner <bothner@cygnus.com> */
|
27 |
|
|
|
28 |
|
|
#include "config.h"
|
29 |
|
|
#include "system.h"
|
30 |
|
|
#include "coretypes.h"
|
31 |
|
|
#include "tm.h"
|
32 |
|
|
#include "tree.h"
|
33 |
|
|
#include "real.h"
|
34 |
|
|
#include "obstack.h"
|
35 |
|
|
#include "flags.h"
|
36 |
|
|
#include "java-tree.h"
|
37 |
|
|
#include "jcf.h"
|
38 |
|
|
#include "convert.h"
|
39 |
|
|
#include "toplev.h"
|
40 |
|
|
#include "ggc.h"
|
41 |
|
|
|
42 |
|
|
static tree convert_ieee_real_to_integer (tree, tree);
|
43 |
|
|
static tree parse_signature_type (const unsigned char **,
|
44 |
|
|
const unsigned char *);
|
45 |
|
|
static tree lookup_do (tree, int, tree, tree, tree (*)(tree));
|
46 |
|
|
static tree build_null_signature (tree);
|
47 |
|
|
|
48 |
|
|
tree * type_map;
|
49 |
|
|
|
50 |
|
|
/* Set the type of the local variable with index SLOT to TYPE. */
|
51 |
|
|
|
52 |
|
|
void
|
53 |
|
|
set_local_type (int slot, tree type)
|
54 |
|
|
{
|
55 |
|
|
int max_locals = DECL_MAX_LOCALS(current_function_decl);
|
56 |
|
|
int nslots = TYPE_IS_WIDE (type) ? 2 : 1;
|
57 |
|
|
|
58 |
|
|
if (slot < 0 || slot + nslots - 1 >= max_locals)
|
59 |
|
|
abort ();
|
60 |
|
|
|
61 |
|
|
type_map[slot] = type;
|
62 |
|
|
while (--nslots > 0)
|
63 |
|
|
type_map[++slot] = void_type_node;
|
64 |
|
|
}
|
65 |
|
|
|
66 |
|
|
/* Convert an IEEE real to an integer type. The result of such a
|
67 |
|
|
conversion when the source operand is a NaN isn't defined by
|
68 |
|
|
IEEE754, but by the Java language standard: it must be zero. Also,
|
69 |
|
|
overflows must be clipped to within range. This conversion
|
70 |
|
|
produces something like:
|
71 |
|
|
|
72 |
|
|
((expr >= (float)MAX_INT)
|
73 |
|
|
? MAX_INT
|
74 |
|
|
: ((expr <= (float)MIN_INT)
|
75 |
|
|
? MIN_INT
|
76 |
|
|
: ((expr != expr)
|
77 |
|
|
? 0
|
78 |
|
|
: (int)expr))) */
|
79 |
|
|
|
80 |
|
|
static tree
|
81 |
|
|
convert_ieee_real_to_integer (tree type, tree expr)
|
82 |
|
|
{
|
83 |
|
|
tree result;
|
84 |
|
|
expr = save_expr (expr);
|
85 |
|
|
|
86 |
|
|
result = fold_build3 (COND_EXPR, type,
|
87 |
|
|
fold_build2 (NE_EXPR, boolean_type_node, expr, expr),
|
88 |
|
|
convert (type, integer_zero_node),
|
89 |
|
|
convert_to_integer (type, expr));
|
90 |
|
|
|
91 |
|
|
result = fold_build3 (COND_EXPR, type,
|
92 |
|
|
fold_build2 (LE_EXPR, boolean_type_node, expr,
|
93 |
|
|
convert (TREE_TYPE (expr),
|
94 |
|
|
TYPE_MIN_VALUE (type))),
|
95 |
|
|
TYPE_MIN_VALUE (type),
|
96 |
|
|
result);
|
97 |
|
|
|
98 |
|
|
result = fold_build3 (COND_EXPR, type,
|
99 |
|
|
fold_build2 (GE_EXPR, boolean_type_node, expr,
|
100 |
|
|
convert (TREE_TYPE (expr),
|
101 |
|
|
TYPE_MAX_VALUE (type))),
|
102 |
|
|
TYPE_MAX_VALUE (type),
|
103 |
|
|
result);
|
104 |
|
|
|
105 |
|
|
return result;
|
106 |
|
|
}
|
107 |
|
|
|
108 |
|
|
/* Create an expression whose value is that of EXPR,
|
109 |
|
|
converted to type TYPE. The TREE_TYPE of the value
|
110 |
|
|
is always TYPE. This function implements all reasonable
|
111 |
|
|
conversions; callers should filter out those that are
|
112 |
|
|
not permitted by the language being compiled. */
|
113 |
|
|
|
114 |
|
|
tree
|
115 |
|
|
convert (tree type, tree expr)
|
116 |
|
|
{
|
117 |
|
|
enum tree_code code = TREE_CODE (type);
|
118 |
|
|
|
119 |
|
|
if (!expr)
|
120 |
|
|
return error_mark_node;
|
121 |
|
|
|
122 |
|
|
if (type == TREE_TYPE (expr)
|
123 |
|
|
|| TREE_CODE (expr) == ERROR_MARK)
|
124 |
|
|
return expr;
|
125 |
|
|
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
126 |
|
|
return error_mark_node;
|
127 |
|
|
if (code == VOID_TYPE)
|
128 |
|
|
return build1 (CONVERT_EXPR, type, expr);
|
129 |
|
|
if (code == BOOLEAN_TYPE || code == CHAR_TYPE)
|
130 |
|
|
return fold_convert (type, expr);
|
131 |
|
|
if (code == INTEGER_TYPE)
|
132 |
|
|
{
|
133 |
|
|
if ((really_constant_p (expr)
|
134 |
|
|
|| (! flag_unsafe_math_optimizations
|
135 |
|
|
&& ! flag_emit_class_files))
|
136 |
|
|
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
|
137 |
|
|
&& TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
|
138 |
|
|
return convert_ieee_real_to_integer (type, expr);
|
139 |
|
|
else
|
140 |
|
|
{
|
141 |
|
|
/* fold very helpfully sets the overflow status if a type
|
142 |
|
|
overflows in a narrowing integer conversion, but Java
|
143 |
|
|
doesn't care. */
|
144 |
|
|
tree tmp = fold (convert_to_integer (type, expr));
|
145 |
|
|
if (TREE_CODE (tmp) == INTEGER_CST)
|
146 |
|
|
TREE_OVERFLOW (tmp) = 0;
|
147 |
|
|
return tmp;
|
148 |
|
|
}
|
149 |
|
|
}
|
150 |
|
|
if (code == REAL_TYPE)
|
151 |
|
|
return fold (convert_to_real (type, expr));
|
152 |
|
|
if (code == POINTER_TYPE)
|
153 |
|
|
return fold (convert_to_pointer (type, expr));
|
154 |
|
|
error ("conversion to non-scalar type requested");
|
155 |
|
|
return error_mark_node;
|
156 |
|
|
}
|
157 |
|
|
|
158 |
|
|
|
159 |
|
|
/* Return a data type that has machine mode MODE.
|
160 |
|
|
If the mode is an integer,
|
161 |
|
|
then UNSIGNEDP selects between signed and unsigned types. */
|
162 |
|
|
|
163 |
|
|
tree
|
164 |
|
|
java_type_for_mode (enum machine_mode mode, int unsignedp)
|
165 |
|
|
{
|
166 |
|
|
if (mode == TYPE_MODE (int_type_node))
|
167 |
|
|
return unsignedp ? unsigned_int_type_node : int_type_node;
|
168 |
|
|
if (mode == TYPE_MODE (long_type_node))
|
169 |
|
|
return unsignedp ? unsigned_long_type_node : long_type_node;
|
170 |
|
|
if (mode == TYPE_MODE (short_type_node))
|
171 |
|
|
return unsignedp ? unsigned_short_type_node : short_type_node;
|
172 |
|
|
if (mode == TYPE_MODE (byte_type_node))
|
173 |
|
|
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
174 |
|
|
if (mode == TYPE_MODE (float_type_node))
|
175 |
|
|
return float_type_node;
|
176 |
|
|
if (mode == TYPE_MODE (double_type_node))
|
177 |
|
|
return double_type_node;
|
178 |
|
|
|
179 |
|
|
return 0;
|
180 |
|
|
}
|
181 |
|
|
|
182 |
|
|
/* Return an integer type with BITS bits of precision,
|
183 |
|
|
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
|
184 |
|
|
|
185 |
|
|
tree
|
186 |
|
|
java_type_for_size (unsigned bits, int unsignedp)
|
187 |
|
|
{
|
188 |
|
|
if (bits <= TYPE_PRECISION (byte_type_node))
|
189 |
|
|
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
190 |
|
|
if (bits <= TYPE_PRECISION (short_type_node))
|
191 |
|
|
return unsignedp ? unsigned_short_type_node : short_type_node;
|
192 |
|
|
if (bits <= TYPE_PRECISION (int_type_node))
|
193 |
|
|
return unsignedp ? unsigned_int_type_node : int_type_node;
|
194 |
|
|
if (bits <= TYPE_PRECISION (long_type_node))
|
195 |
|
|
return unsignedp ? unsigned_long_type_node : long_type_node;
|
196 |
|
|
return 0;
|
197 |
|
|
}
|
198 |
|
|
|
199 |
|
|
/* Return a type the same as TYPE except unsigned or
|
200 |
|
|
signed according to UNSIGNEDP. */
|
201 |
|
|
|
202 |
|
|
tree
|
203 |
|
|
java_signed_or_unsigned_type (int unsignedp, tree type)
|
204 |
|
|
{
|
205 |
|
|
if (! INTEGRAL_TYPE_P (type))
|
206 |
|
|
return type;
|
207 |
|
|
if (TYPE_PRECISION (type) == TYPE_PRECISION (int_type_node))
|
208 |
|
|
return unsignedp ? unsigned_int_type_node : int_type_node;
|
209 |
|
|
if (TYPE_PRECISION (type) == TYPE_PRECISION (byte_type_node))
|
210 |
|
|
return unsignedp ? unsigned_byte_type_node : byte_type_node;
|
211 |
|
|
if (TYPE_PRECISION (type) == TYPE_PRECISION (short_type_node))
|
212 |
|
|
return unsignedp ? unsigned_short_type_node : short_type_node;
|
213 |
|
|
if (TYPE_PRECISION (type) == TYPE_PRECISION (long_type_node))
|
214 |
|
|
return unsignedp ? unsigned_long_type_node : long_type_node;
|
215 |
|
|
return type;
|
216 |
|
|
}
|
217 |
|
|
|
218 |
|
|
/* Return a signed type the same as TYPE in other respects. */
|
219 |
|
|
|
220 |
|
|
tree
|
221 |
|
|
java_signed_type (tree type)
|
222 |
|
|
{
|
223 |
|
|
return java_signed_or_unsigned_type (0, type);
|
224 |
|
|
}
|
225 |
|
|
|
226 |
|
|
/* Return an unsigned type the same as TYPE in other respects. */
|
227 |
|
|
|
228 |
|
|
tree
|
229 |
|
|
java_unsigned_type (tree type)
|
230 |
|
|
{
|
231 |
|
|
return java_signed_or_unsigned_type (1, type);
|
232 |
|
|
}
|
233 |
|
|
|
234 |
|
|
/* Mark EXP saying that we need to be able to take the
|
235 |
|
|
address of it; it should not be allocated in a register.
|
236 |
|
|
Value is true if successful. */
|
237 |
|
|
|
238 |
|
|
bool
|
239 |
|
|
java_mark_addressable (tree exp)
|
240 |
|
|
{
|
241 |
|
|
tree x = exp;
|
242 |
|
|
while (1)
|
243 |
|
|
switch (TREE_CODE (x))
|
244 |
|
|
{
|
245 |
|
|
case ADDR_EXPR:
|
246 |
|
|
case COMPONENT_REF:
|
247 |
|
|
case ARRAY_REF:
|
248 |
|
|
case REALPART_EXPR:
|
249 |
|
|
case IMAGPART_EXPR:
|
250 |
|
|
x = TREE_OPERAND (x, 0);
|
251 |
|
|
break;
|
252 |
|
|
|
253 |
|
|
case TRUTH_ANDIF_EXPR:
|
254 |
|
|
case TRUTH_ORIF_EXPR:
|
255 |
|
|
case COMPOUND_EXPR:
|
256 |
|
|
x = TREE_OPERAND (x, 1);
|
257 |
|
|
break;
|
258 |
|
|
|
259 |
|
|
case COND_EXPR:
|
260 |
|
|
return java_mark_addressable (TREE_OPERAND (x, 1))
|
261 |
|
|
&& java_mark_addressable (TREE_OPERAND (x, 2));
|
262 |
|
|
|
263 |
|
|
case CONSTRUCTOR:
|
264 |
|
|
TREE_ADDRESSABLE (x) = 1;
|
265 |
|
|
return true;
|
266 |
|
|
|
267 |
|
|
case INDIRECT_REF:
|
268 |
|
|
/* We sometimes add a cast *(TYPE*)&FOO to handle type and mode
|
269 |
|
|
incompatibility problems. Handle this case by marking FOO. */
|
270 |
|
|
if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR
|
271 |
|
|
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)
|
272 |
|
|
{
|
273 |
|
|
x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
|
274 |
|
|
break;
|
275 |
|
|
}
|
276 |
|
|
if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
|
277 |
|
|
{
|
278 |
|
|
x = TREE_OPERAND (x, 0);
|
279 |
|
|
break;
|
280 |
|
|
}
|
281 |
|
|
return true;
|
282 |
|
|
|
283 |
|
|
case VAR_DECL:
|
284 |
|
|
case CONST_DECL:
|
285 |
|
|
case PARM_DECL:
|
286 |
|
|
case RESULT_DECL:
|
287 |
|
|
case FUNCTION_DECL:
|
288 |
|
|
TREE_ADDRESSABLE (x) = 1;
|
289 |
|
|
#if 0 /* poplevel deals with this now. */
|
290 |
|
|
if (DECL_CONTEXT (x) == 0)
|
291 |
|
|
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
|
292 |
|
|
#endif
|
293 |
|
|
/* drops through */
|
294 |
|
|
default:
|
295 |
|
|
return true;
|
296 |
|
|
}
|
297 |
|
|
}
|
298 |
|
|
|
299 |
|
|
/* Thorough checking of the arrayness of TYPE. */
|
300 |
|
|
|
301 |
|
|
int
|
302 |
|
|
is_array_type_p (tree type)
|
303 |
|
|
{
|
304 |
|
|
return TREE_CODE (type) == POINTER_TYPE
|
305 |
|
|
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
|
306 |
|
|
&& TYPE_ARRAY_P (TREE_TYPE (type));
|
307 |
|
|
}
|
308 |
|
|
|
309 |
|
|
/* Return the length of a Java array type.
|
310 |
|
|
Return -1 if the length is unknown or non-constant. */
|
311 |
|
|
|
312 |
|
|
HOST_WIDE_INT
|
313 |
|
|
java_array_type_length (tree array_type)
|
314 |
|
|
{
|
315 |
|
|
tree arfld;
|
316 |
|
|
if (TREE_CODE (array_type) == POINTER_TYPE)
|
317 |
|
|
array_type = TREE_TYPE (array_type);
|
318 |
|
|
arfld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
|
319 |
|
|
if (arfld != NULL_TREE)
|
320 |
|
|
{
|
321 |
|
|
tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld));
|
322 |
|
|
if (index_type != NULL_TREE)
|
323 |
|
|
{
|
324 |
|
|
tree high = TYPE_MAX_VALUE (index_type);
|
325 |
|
|
if (TREE_CODE (high) == INTEGER_CST)
|
326 |
|
|
return TREE_INT_CST_LOW (high) + 1;
|
327 |
|
|
}
|
328 |
|
|
}
|
329 |
|
|
return -1;
|
330 |
|
|
}
|
331 |
|
|
|
332 |
|
|
/* An array of unknown length will be ultimately given a length of
|
333 |
|
|
-2, so that we can still have `length' producing a negative value
|
334 |
|
|
even if found. This was part of an optimization aiming at removing
|
335 |
|
|
`length' from static arrays. We could restore it, FIXME. */
|
336 |
|
|
|
337 |
|
|
tree
|
338 |
|
|
build_prim_array_type (tree element_type, HOST_WIDE_INT length)
|
339 |
|
|
{
|
340 |
|
|
tree index = NULL;
|
341 |
|
|
|
342 |
|
|
if (length != -1)
|
343 |
|
|
{
|
344 |
|
|
tree max_index = build_int_cst (sizetype, length - 1);
|
345 |
|
|
index = build_index_type (max_index);
|
346 |
|
|
}
|
347 |
|
|
return build_array_type (element_type, index);
|
348 |
|
|
}
|
349 |
|
|
|
350 |
|
|
/* Return a Java array type with a given ELEMENT_TYPE and LENGTH.
|
351 |
|
|
These are hashed (shared) using IDENTIFIER_SIGNATURE_TYPE.
|
352 |
|
|
The LENGTH is -1 if the length is unknown. */
|
353 |
|
|
|
354 |
|
|
tree
|
355 |
|
|
build_java_array_type (tree element_type, HOST_WIDE_INT length)
|
356 |
|
|
{
|
357 |
|
|
tree sig, t, fld, atype, arfld;
|
358 |
|
|
char buf[12];
|
359 |
|
|
tree elsig = build_java_signature (element_type);
|
360 |
|
|
tree el_name = element_type;
|
361 |
|
|
buf[0] = '[';
|
362 |
|
|
if (length >= 0)
|
363 |
|
|
sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length);
|
364 |
|
|
else
|
365 |
|
|
buf[1] = '\0';
|
366 |
|
|
sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig),
|
367 |
|
|
buf, 0, 0, "");
|
368 |
|
|
t = IDENTIFIER_SIGNATURE_TYPE (sig);
|
369 |
|
|
if (t != NULL_TREE)
|
370 |
|
|
return TREE_TYPE (t);
|
371 |
|
|
t = make_class ();
|
372 |
|
|
IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t);
|
373 |
|
|
TYPE_ARRAY_P (t) = 1;
|
374 |
|
|
|
375 |
|
|
if (TREE_CODE (el_name) == POINTER_TYPE)
|
376 |
|
|
el_name = TREE_TYPE (el_name);
|
377 |
|
|
el_name = TYPE_NAME (el_name);
|
378 |
|
|
if (TREE_CODE (el_name) == TYPE_DECL)
|
379 |
|
|
el_name = DECL_NAME (el_name);
|
380 |
|
|
{
|
381 |
|
|
char suffix[12];
|
382 |
|
|
if (length >= 0)
|
383 |
|
|
sprintf (suffix, "[%d]", (int)length);
|
384 |
|
|
else
|
385 |
|
|
strcpy (suffix, "[]");
|
386 |
|
|
TYPE_NAME (t)
|
387 |
|
|
= build_decl (TYPE_DECL,
|
388 |
|
|
identifier_subst (el_name, "", '.', '.', suffix),
|
389 |
|
|
t);
|
390 |
|
|
}
|
391 |
|
|
|
392 |
|
|
set_java_signature (t, sig);
|
393 |
|
|
set_super_info (0, t, object_type_node, 0);
|
394 |
|
|
if (TREE_CODE (element_type) == RECORD_TYPE)
|
395 |
|
|
element_type = promote_type (element_type);
|
396 |
|
|
TYPE_ARRAY_ELEMENT (t) = element_type;
|
397 |
|
|
|
398 |
|
|
/* Add length pseudo-field. */
|
399 |
|
|
fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node);
|
400 |
|
|
TYPE_FIELDS (t) = fld;
|
401 |
|
|
DECL_CONTEXT (fld) = t;
|
402 |
|
|
FIELD_PUBLIC (fld) = 1;
|
403 |
|
|
FIELD_FINAL (fld) = 1;
|
404 |
|
|
TREE_READONLY (fld) = 1;
|
405 |
|
|
|
406 |
|
|
atype = build_prim_array_type (element_type, length);
|
407 |
|
|
arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype);
|
408 |
|
|
DECL_CONTEXT (arfld) = t;
|
409 |
|
|
TREE_CHAIN (fld) = arfld;
|
410 |
|
|
DECL_ALIGN (arfld) = TYPE_ALIGN (element_type);
|
411 |
|
|
|
412 |
|
|
/* We could layout_class, but that loads java.lang.Object prematurely.
|
413 |
|
|
* This is called by the parser, and it is a bad idea to do load_class
|
414 |
|
|
* in the middle of parsing, because of possible circularity problems. */
|
415 |
|
|
push_super_field (t, object_type_node);
|
416 |
|
|
layout_type (t);
|
417 |
|
|
|
418 |
|
|
return t;
|
419 |
|
|
}
|
420 |
|
|
|
421 |
|
|
/* Promote TYPE to the type actually used for fields and parameters. */
|
422 |
|
|
|
423 |
|
|
tree
|
424 |
|
|
promote_type (tree type)
|
425 |
|
|
{
|
426 |
|
|
switch (TREE_CODE (type))
|
427 |
|
|
{
|
428 |
|
|
case RECORD_TYPE:
|
429 |
|
|
return build_pointer_type (type);
|
430 |
|
|
case BOOLEAN_TYPE:
|
431 |
|
|
if (type == boolean_type_node)
|
432 |
|
|
return promoted_boolean_type_node;
|
433 |
|
|
goto handle_int;
|
434 |
|
|
case CHAR_TYPE:
|
435 |
|
|
if (type == char_type_node)
|
436 |
|
|
return promoted_char_type_node;
|
437 |
|
|
goto handle_int;
|
438 |
|
|
case INTEGER_TYPE:
|
439 |
|
|
handle_int:
|
440 |
|
|
if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node))
|
441 |
|
|
{
|
442 |
|
|
if (type == short_type_node)
|
443 |
|
|
return promoted_short_type_node;
|
444 |
|
|
if (type == byte_type_node)
|
445 |
|
|
return promoted_byte_type_node;
|
446 |
|
|
return int_type_node;
|
447 |
|
|
}
|
448 |
|
|
/* ... else fall through ... */
|
449 |
|
|
default:
|
450 |
|
|
return type;
|
451 |
|
|
}
|
452 |
|
|
}
|
453 |
|
|
|
454 |
|
|
/* Parse a signature string, starting at *PTR and ending at LIMIT.
|
455 |
|
|
Return the seen TREE_TYPE, updating *PTR. */
|
456 |
|
|
|
457 |
|
|
static tree
|
458 |
|
|
parse_signature_type (const unsigned char **ptr, const unsigned char *limit)
|
459 |
|
|
{
|
460 |
|
|
tree type;
|
461 |
|
|
|
462 |
|
|
if (*ptr >= limit)
|
463 |
|
|
abort ();
|
464 |
|
|
|
465 |
|
|
switch (**ptr)
|
466 |
|
|
{
|
467 |
|
|
case 'B': (*ptr)++; return byte_type_node;
|
468 |
|
|
case 'C': (*ptr)++; return char_type_node;
|
469 |
|
|
case 'D': (*ptr)++; return double_type_node;
|
470 |
|
|
case 'F': (*ptr)++; return float_type_node;
|
471 |
|
|
case 'S': (*ptr)++; return short_type_node;
|
472 |
|
|
case 'I': (*ptr)++; return int_type_node;
|
473 |
|
|
case 'J': (*ptr)++; return long_type_node;
|
474 |
|
|
case 'Z': (*ptr)++; return boolean_type_node;
|
475 |
|
|
case 'V': (*ptr)++; return void_type_node;
|
476 |
|
|
case '[':
|
477 |
|
|
for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); ) (*ptr)++;
|
478 |
|
|
type = parse_signature_type (ptr, limit);
|
479 |
|
|
type = build_java_array_type (type, -1);
|
480 |
|
|
break;
|
481 |
|
|
case 'L':
|
482 |
|
|
{
|
483 |
|
|
const unsigned char *start = ++(*ptr);
|
484 |
|
|
const unsigned char *str = start;
|
485 |
|
|
for ( ; ; str++)
|
486 |
|
|
{
|
487 |
|
|
if (str >= limit)
|
488 |
|
|
abort ();
|
489 |
|
|
if (*str == ';')
|
490 |
|
|
break;
|
491 |
|
|
}
|
492 |
|
|
*ptr = str+1;
|
493 |
|
|
type = lookup_class (unmangle_classname ((const char *) start, str - start));
|
494 |
|
|
break;
|
495 |
|
|
}
|
496 |
|
|
default:
|
497 |
|
|
abort ();
|
498 |
|
|
}
|
499 |
|
|
return promote_type (type);
|
500 |
|
|
}
|
501 |
|
|
|
502 |
|
|
/* Parse a Java "mangled" signature string, starting at SIG_STRING,
|
503 |
|
|
and SIG_LENGTH bytes long.
|
504 |
|
|
Return a gcc type node. */
|
505 |
|
|
|
506 |
|
|
tree
|
507 |
|
|
parse_signature_string (const unsigned char *sig_string, int sig_length)
|
508 |
|
|
{
|
509 |
|
|
tree result_type;
|
510 |
|
|
const unsigned char *str = sig_string;
|
511 |
|
|
const unsigned char *limit = str + sig_length;
|
512 |
|
|
|
513 |
|
|
if (str < limit && str[0] == '(')
|
514 |
|
|
{
|
515 |
|
|
tree argtype_list = NULL_TREE;
|
516 |
|
|
str++;
|
517 |
|
|
while (str < limit && str[0] != ')')
|
518 |
|
|
{
|
519 |
|
|
tree argtype = parse_signature_type (&str, limit);
|
520 |
|
|
argtype_list = tree_cons (NULL_TREE, argtype, argtype_list);
|
521 |
|
|
}
|
522 |
|
|
if (str++, str >= limit)
|
523 |
|
|
abort ();
|
524 |
|
|
result_type = parse_signature_type (&str, limit);
|
525 |
|
|
argtype_list = chainon (nreverse (argtype_list), end_params_node);
|
526 |
|
|
result_type = build_function_type (result_type, argtype_list);
|
527 |
|
|
}
|
528 |
|
|
else
|
529 |
|
|
result_type = parse_signature_type (&str, limit);
|
530 |
|
|
if (str != limit)
|
531 |
|
|
error ("junk at end of signature string");
|
532 |
|
|
return result_type;
|
533 |
|
|
}
|
534 |
|
|
|
535 |
|
|
/* Convert a signature to its type.
|
536 |
|
|
* Uses IDENTIFIER_SIGNATURE_TYPE as a cache (except for primitive types).
|
537 |
|
|
*/
|
538 |
|
|
|
539 |
|
|
tree
|
540 |
|
|
get_type_from_signature (tree signature)
|
541 |
|
|
{
|
542 |
|
|
const unsigned char *sig = (const unsigned char *) IDENTIFIER_POINTER (signature);
|
543 |
|
|
int len = IDENTIFIER_LENGTH (signature);
|
544 |
|
|
tree type;
|
545 |
|
|
/* Primitive types aren't cached. */
|
546 |
|
|
if (len <= 1)
|
547 |
|
|
return parse_signature_string (sig, len);
|
548 |
|
|
type = IDENTIFIER_SIGNATURE_TYPE (signature);
|
549 |
|
|
if (type == NULL_TREE)
|
550 |
|
|
{
|
551 |
|
|
type = parse_signature_string (sig, len);
|
552 |
|
|
IDENTIFIER_SIGNATURE_TYPE (signature) = type;
|
553 |
|
|
}
|
554 |
|
|
return type;
|
555 |
|
|
}
|
556 |
|
|
|
557 |
|
|
/* Ignore signature and always return null. Used by has_method. */
|
558 |
|
|
|
559 |
|
|
static tree
|
560 |
|
|
build_null_signature (tree type ATTRIBUTE_UNUSED)
|
561 |
|
|
{
|
562 |
|
|
return NULL_TREE;
|
563 |
|
|
}
|
564 |
|
|
|
565 |
|
|
/* Return the signature string for the arguments of method type TYPE. */
|
566 |
|
|
|
567 |
|
|
tree
|
568 |
|
|
build_java_argument_signature (tree type)
|
569 |
|
|
{
|
570 |
|
|
extern struct obstack temporary_obstack;
|
571 |
|
|
tree sig = TYPE_ARGUMENT_SIGNATURE (type);
|
572 |
|
|
if (sig == NULL_TREE)
|
573 |
|
|
{
|
574 |
|
|
tree args = TYPE_ARG_TYPES (type);
|
575 |
|
|
if (TREE_CODE (type) == METHOD_TYPE)
|
576 |
|
|
args = TREE_CHAIN (args); /* Skip "this" argument. */
|
577 |
|
|
for (; args != end_params_node; args = TREE_CHAIN (args))
|
578 |
|
|
{
|
579 |
|
|
tree t = build_java_signature (TREE_VALUE (args));
|
580 |
|
|
obstack_grow (&temporary_obstack,
|
581 |
|
|
IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
|
582 |
|
|
}
|
583 |
|
|
obstack_1grow (&temporary_obstack, '\0');
|
584 |
|
|
|
585 |
|
|
sig = get_identifier (obstack_base (&temporary_obstack));
|
586 |
|
|
TYPE_ARGUMENT_SIGNATURE (type) = sig;
|
587 |
|
|
obstack_free (&temporary_obstack, obstack_base (&temporary_obstack));
|
588 |
|
|
}
|
589 |
|
|
return sig;
|
590 |
|
|
}
|
591 |
|
|
|
592 |
|
|
/* Return the signature of the given TYPE. */
|
593 |
|
|
|
594 |
|
|
tree
|
595 |
|
|
build_java_signature (tree type)
|
596 |
|
|
{
|
597 |
|
|
tree sig, t;
|
598 |
|
|
while (TREE_CODE (type) == POINTER_TYPE)
|
599 |
|
|
type = TREE_TYPE (type);
|
600 |
|
|
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
|
601 |
|
|
sig = TYPE_SIGNATURE (type);
|
602 |
|
|
if (sig == NULL_TREE)
|
603 |
|
|
{
|
604 |
|
|
char sg[2];
|
605 |
|
|
switch (TREE_CODE (type))
|
606 |
|
|
{
|
607 |
|
|
case BOOLEAN_TYPE: sg[0] = 'Z'; goto native;
|
608 |
|
|
case CHAR_TYPE: sg[0] = 'C'; goto native;
|
609 |
|
|
case VOID_TYPE: sg[0] = 'V'; goto native;
|
610 |
|
|
case INTEGER_TYPE:
|
611 |
|
|
switch (TYPE_PRECISION (type))
|
612 |
|
|
{
|
613 |
|
|
case 8: sg[0] = 'B'; goto native;
|
614 |
|
|
case 16: sg[0] = 'S'; goto native;
|
615 |
|
|
case 32: sg[0] = 'I'; goto native;
|
616 |
|
|
case 64: sg[0] = 'J'; goto native;
|
617 |
|
|
default: goto bad_type;
|
618 |
|
|
}
|
619 |
|
|
case REAL_TYPE:
|
620 |
|
|
switch (TYPE_PRECISION (type))
|
621 |
|
|
{
|
622 |
|
|
case 32: sg[0] = 'F'; goto native;
|
623 |
|
|
case 64: sg[0] = 'D'; goto native;
|
624 |
|
|
default: goto bad_type;
|
625 |
|
|
}
|
626 |
|
|
native:
|
627 |
|
|
sg[1] = 0;
|
628 |
|
|
sig = get_identifier (sg);
|
629 |
|
|
break;
|
630 |
|
|
case RECORD_TYPE:
|
631 |
|
|
if (TYPE_ARRAY_P (type))
|
632 |
|
|
{
|
633 |
|
|
t = build_java_signature (TYPE_ARRAY_ELEMENT (type));
|
634 |
|
|
sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
|
635 |
|
|
"[", 0, 0, "");
|
636 |
|
|
}
|
637 |
|
|
else
|
638 |
|
|
{
|
639 |
|
|
t = DECL_NAME (TYPE_NAME (type));
|
640 |
|
|
sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t),
|
641 |
|
|
"L", '.', '/', ";");
|
642 |
|
|
}
|
643 |
|
|
break;
|
644 |
|
|
case METHOD_TYPE:
|
645 |
|
|
case FUNCTION_TYPE:
|
646 |
|
|
{
|
647 |
|
|
extern struct obstack temporary_obstack;
|
648 |
|
|
sig = build_java_argument_signature (type);
|
649 |
|
|
obstack_1grow (&temporary_obstack, '(');
|
650 |
|
|
obstack_grow (&temporary_obstack,
|
651 |
|
|
IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig));
|
652 |
|
|
obstack_1grow (&temporary_obstack, ')');
|
653 |
|
|
|
654 |
|
|
t = build_java_signature (TREE_TYPE (type));
|
655 |
|
|
obstack_grow0 (&temporary_obstack,
|
656 |
|
|
IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
|
657 |
|
|
|
658 |
|
|
sig = get_identifier (obstack_base (&temporary_obstack));
|
659 |
|
|
obstack_free (&temporary_obstack,
|
660 |
|
|
obstack_base (&temporary_obstack));
|
661 |
|
|
}
|
662 |
|
|
break;
|
663 |
|
|
bad_type:
|
664 |
|
|
default:
|
665 |
|
|
abort ();
|
666 |
|
|
}
|
667 |
|
|
TYPE_SIGNATURE (type) = sig;
|
668 |
|
|
}
|
669 |
|
|
return sig;
|
670 |
|
|
}
|
671 |
|
|
|
672 |
|
|
/* Save signature string SIG (an IDENTIFIER_NODE) in TYPE for future use. */
|
673 |
|
|
|
674 |
|
|
void
|
675 |
|
|
set_java_signature (tree type, tree sig)
|
676 |
|
|
{
|
677 |
|
|
tree old_sig;
|
678 |
|
|
while (TREE_CODE (type) == POINTER_TYPE)
|
679 |
|
|
type = TREE_TYPE (type);
|
680 |
|
|
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
|
681 |
|
|
old_sig = TYPE_SIGNATURE (type);
|
682 |
|
|
if (old_sig != NULL_TREE && old_sig != sig)
|
683 |
|
|
abort ();
|
684 |
|
|
TYPE_SIGNATURE (type) = sig;
|
685 |
|
|
#if 0 /* careful about METHOD_TYPE */
|
686 |
|
|
if (IDENTIFIER_SIGNATURE_TYPE (sig) == NULL_TREE && TREE_PERMANENT (type))
|
687 |
|
|
IDENTIFIER_SIGNATURE_TYPE (sig) = type;
|
688 |
|
|
#endif
|
689 |
|
|
}
|
690 |
|
|
|
691 |
|
|
/* Search in SEARCHED_CLASS and its superclasses for a method matching
|
692 |
|
|
METHOD_NAME and signature METHOD_SIGNATURE. This function will
|
693 |
|
|
only search for methods declared in the class hierarchy; interfaces
|
694 |
|
|
will not be considered. Returns NULL_TREE if the method is not
|
695 |
|
|
found. */
|
696 |
|
|
tree
|
697 |
|
|
lookup_argument_method (tree searched_class, tree method_name,
|
698 |
|
|
tree method_signature)
|
699 |
|
|
{
|
700 |
|
|
return lookup_do (searched_class, 0,
|
701 |
|
|
method_name, method_signature,
|
702 |
|
|
build_java_argument_signature);
|
703 |
|
|
}
|
704 |
|
|
|
705 |
|
|
/* Like lookup_argument_method, but lets the caller set any flags
|
706 |
|
|
desired. */
|
707 |
|
|
tree
|
708 |
|
|
lookup_argument_method_generic (tree searched_class, tree method_name,
|
709 |
|
|
tree method_signature, int flags)
|
710 |
|
|
{
|
711 |
|
|
return lookup_do (searched_class, flags,
|
712 |
|
|
method_name, method_signature,
|
713 |
|
|
build_java_argument_signature);
|
714 |
|
|
}
|
715 |
|
|
|
716 |
|
|
|
717 |
|
|
/* Search in class SEARCHED_CLASS (and its superclasses) for a method
|
718 |
|
|
matching METHOD_NAME and signature METHOD_SIGNATURE. Return a
|
719 |
|
|
FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast
|
720 |
|
|
lookup_argument_method, which ignores return type.) If
|
721 |
|
|
SEARCHED_CLASS is an interface, search it too. */
|
722 |
|
|
tree
|
723 |
|
|
lookup_java_method (tree searched_class, tree method_name,
|
724 |
|
|
tree method_signature)
|
725 |
|
|
{
|
726 |
|
|
return lookup_do (searched_class, SEARCH_INTERFACE, method_name,
|
727 |
|
|
method_signature, build_java_signature);
|
728 |
|
|
}
|
729 |
|
|
|
730 |
|
|
/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME. */
|
731 |
|
|
int
|
732 |
|
|
has_method (tree class, tree method_name)
|
733 |
|
|
{
|
734 |
|
|
return lookup_do (class, SEARCH_INTERFACE,
|
735 |
|
|
method_name, NULL_TREE,
|
736 |
|
|
build_null_signature) != NULL_TREE;
|
737 |
|
|
}
|
738 |
|
|
|
739 |
|
|
/* Search in class SEARCHED_CLASS, but not its superclasses, for a
|
740 |
|
|
method matching METHOD_NAME and signature SIGNATURE. A private
|
741 |
|
|
helper for lookup_do. */
|
742 |
|
|
static tree
|
743 |
|
|
shallow_find_method (tree searched_class, int flags, tree method_name,
|
744 |
|
|
tree signature, tree (*signature_builder) (tree))
|
745 |
|
|
{
|
746 |
|
|
tree method;
|
747 |
|
|
for (method = TYPE_METHODS (searched_class);
|
748 |
|
|
method != NULL_TREE; method = TREE_CHAIN (method))
|
749 |
|
|
{
|
750 |
|
|
tree method_sig = (*signature_builder) (TREE_TYPE (method));
|
751 |
|
|
if (DECL_NAME (method) == method_name && method_sig == signature)
|
752 |
|
|
{
|
753 |
|
|
/* If the caller requires a visible method, then we
|
754 |
|
|
skip invisible methods here. */
|
755 |
|
|
if (! (flags & SEARCH_VISIBLE)
|
756 |
|
|
|| ! METHOD_INVISIBLE (method))
|
757 |
|
|
return method;
|
758 |
|
|
}
|
759 |
|
|
}
|
760 |
|
|
return NULL_TREE;
|
761 |
|
|
}
|
762 |
|
|
|
763 |
|
|
/* Search in the superclasses of SEARCHED_CLASS for a method matching
|
764 |
|
|
METHOD_NAME and signature SIGNATURE. A private helper for
|
765 |
|
|
lookup_do. */
|
766 |
|
|
static tree
|
767 |
|
|
find_method_in_superclasses (tree searched_class, int flags,
|
768 |
|
|
tree method_name, tree signature,
|
769 |
|
|
tree (*signature_builder) (tree))
|
770 |
|
|
{
|
771 |
|
|
tree klass;
|
772 |
|
|
for (klass = CLASSTYPE_SUPER (searched_class); klass != NULL_TREE;
|
773 |
|
|
klass = CLASSTYPE_SUPER (klass))
|
774 |
|
|
{
|
775 |
|
|
tree method;
|
776 |
|
|
method = shallow_find_method (klass, flags, method_name,
|
777 |
|
|
signature, signature_builder);
|
778 |
|
|
if (method != NULL_TREE)
|
779 |
|
|
return method;
|
780 |
|
|
}
|
781 |
|
|
|
782 |
|
|
return NULL_TREE;
|
783 |
|
|
}
|
784 |
|
|
|
785 |
|
|
/* Search in the interfaces of SEARCHED_CLASS and its superinterfaces
|
786 |
|
|
for a method matching METHOD_NAME and signature SIGNATURE. A
|
787 |
|
|
private helper for lookup_do. */
|
788 |
|
|
static tree
|
789 |
|
|
find_method_in_interfaces (tree searched_class, int flags, tree method_name,
|
790 |
|
|
tree signature, tree (*signature_builder) (tree))
|
791 |
|
|
{
|
792 |
|
|
int i;
|
793 |
|
|
tree binfo, base_binfo;
|
794 |
|
|
|
795 |
|
|
for (binfo = TYPE_BINFO (searched_class), i = 1;
|
796 |
|
|
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
|
797 |
|
|
{
|
798 |
|
|
tree iclass = BINFO_TYPE (base_binfo);
|
799 |
|
|
tree method;
|
800 |
|
|
|
801 |
|
|
/* If the superinterface hasn't been loaded yet, do so now. */
|
802 |
|
|
if (CLASS_FROM_SOURCE_P (iclass))
|
803 |
|
|
safe_layout_class (iclass);
|
804 |
|
|
else if (!CLASS_LOADED_P (iclass))
|
805 |
|
|
load_class (iclass, 1);
|
806 |
|
|
|
807 |
|
|
/* First, we look in ICLASS. If that doesn't work we'll
|
808 |
|
|
recursively look through all its superinterfaces. */
|
809 |
|
|
method = shallow_find_method (iclass, flags, method_name,
|
810 |
|
|
signature, signature_builder);
|
811 |
|
|
if (method != NULL_TREE)
|
812 |
|
|
return method;
|
813 |
|
|
|
814 |
|
|
method = find_method_in_interfaces
|
815 |
|
|
(iclass, flags, method_name, signature, signature_builder);
|
816 |
|
|
if (method != NULL_TREE)
|
817 |
|
|
return method;
|
818 |
|
|
}
|
819 |
|
|
|
820 |
|
|
return NULL_TREE;
|
821 |
|
|
}
|
822 |
|
|
|
823 |
|
|
|
824 |
|
|
/* Search in class SEARCHED_CLASS (and its superclasses) for a method
|
825 |
|
|
matching METHOD_NAME and signature SIGNATURE. FLAGS control some
|
826 |
|
|
parameters of the search.
|
827 |
|
|
|
828 |
|
|
SEARCH_INTERFACE means also search interfaces and superinterfaces
|
829 |
|
|
of SEARCHED_CLASS.
|
830 |
|
|
|
831 |
|
|
SEARCH_SUPER means skip SEARCHED_CLASS and start with its
|
832 |
|
|
superclass.
|
833 |
|
|
|
834 |
|
|
SEARCH_VISIBLE means skip methods for which METHOD_INVISIBLE is
|
835 |
|
|
set.
|
836 |
|
|
|
837 |
|
|
Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is
|
838 |
|
|
used on method candidates to build their (sometimes partial)
|
839 |
|
|
signature. */
|
840 |
|
|
static tree
|
841 |
|
|
lookup_do (tree searched_class, int flags, tree method_name,
|
842 |
|
|
tree signature, tree (*signature_builder) (tree))
|
843 |
|
|
{
|
844 |
|
|
tree method;
|
845 |
|
|
tree orig_class = searched_class;
|
846 |
|
|
|
847 |
|
|
if (searched_class == NULL_TREE)
|
848 |
|
|
return NULL_TREE;
|
849 |
|
|
|
850 |
|
|
if (flags & SEARCH_SUPER)
|
851 |
|
|
{
|
852 |
|
|
searched_class = CLASSTYPE_SUPER (searched_class);
|
853 |
|
|
if (searched_class == NULL_TREE)
|
854 |
|
|
return NULL_TREE;
|
855 |
|
|
}
|
856 |
|
|
|
857 |
|
|
/* First look in our own methods. */
|
858 |
|
|
method = shallow_find_method (searched_class, flags, method_name,
|
859 |
|
|
signature, signature_builder);
|
860 |
|
|
if (method)
|
861 |
|
|
return method;
|
862 |
|
|
|
863 |
|
|
/* Then look in our superclasses. */
|
864 |
|
|
if (! CLASS_INTERFACE (TYPE_NAME (searched_class)))
|
865 |
|
|
method = find_method_in_superclasses (searched_class, flags, method_name,
|
866 |
|
|
signature, signature_builder);
|
867 |
|
|
if (method)
|
868 |
|
|
return method;
|
869 |
|
|
|
870 |
|
|
/* If that doesn't work, look in our interfaces. */
|
871 |
|
|
if (flags & SEARCH_INTERFACE)
|
872 |
|
|
method = find_method_in_interfaces (orig_class, flags, method_name,
|
873 |
|
|
signature, signature_builder);
|
874 |
|
|
|
875 |
|
|
return method;
|
876 |
|
|
}
|
877 |
|
|
|
878 |
|
|
/* Search in class CLAS for a constructor matching METHOD_SIGNATURE.
|
879 |
|
|
Return a FUNCTION_DECL on success, or NULL_TREE if none found. */
|
880 |
|
|
|
881 |
|
|
tree
|
882 |
|
|
lookup_java_constructor (tree clas, tree method_signature)
|
883 |
|
|
{
|
884 |
|
|
tree method = TYPE_METHODS (clas);
|
885 |
|
|
for ( ; method != NULL_TREE; method = TREE_CHAIN (method))
|
886 |
|
|
{
|
887 |
|
|
tree method_sig = build_java_signature (TREE_TYPE (method));
|
888 |
|
|
if (DECL_CONSTRUCTOR_P (method) && method_sig == method_signature)
|
889 |
|
|
return method;
|
890 |
|
|
}
|
891 |
|
|
return NULL_TREE;
|
892 |
|
|
}
|
893 |
|
|
|
894 |
|
|
/* Return a type which is the Binary Numeric Promotion of the pair T1,
|
895 |
|
|
T2 and convert EXP1 and/or EXP2. See 5.6.2 Binary Numeric
|
896 |
|
|
Promotion. It assumes that both T1 and T2 are eligible to BNP. */
|
897 |
|
|
|
898 |
|
|
tree
|
899 |
|
|
binary_numeric_promotion (tree t1, tree t2, tree *exp1, tree *exp2)
|
900 |
|
|
{
|
901 |
|
|
if (t1 == double_type_node || t2 == double_type_node)
|
902 |
|
|
{
|
903 |
|
|
if (t1 != double_type_node)
|
904 |
|
|
*exp1 = convert (double_type_node, *exp1);
|
905 |
|
|
if (t2 != double_type_node)
|
906 |
|
|
*exp2 = convert (double_type_node, *exp2);
|
907 |
|
|
return double_type_node;
|
908 |
|
|
}
|
909 |
|
|
if (t1 == float_type_node || t2 == float_type_node)
|
910 |
|
|
{
|
911 |
|
|
if (t1 != float_type_node)
|
912 |
|
|
*exp1 = convert (float_type_node, *exp1);
|
913 |
|
|
if (t2 != float_type_node)
|
914 |
|
|
*exp2 = convert (float_type_node, *exp2);
|
915 |
|
|
return float_type_node;
|
916 |
|
|
}
|
917 |
|
|
if (t1 == long_type_node || t2 == long_type_node)
|
918 |
|
|
{
|
919 |
|
|
if (t1 != long_type_node)
|
920 |
|
|
*exp1 = convert (long_type_node, *exp1);
|
921 |
|
|
if (t2 != long_type_node)
|
922 |
|
|
*exp2 = convert (long_type_node, *exp2);
|
923 |
|
|
return long_type_node;
|
924 |
|
|
}
|
925 |
|
|
|
926 |
|
|
if (t1 != int_type_node)
|
927 |
|
|
*exp1 = convert (int_type_node, *exp1);
|
928 |
|
|
if (t2 != int_type_node)
|
929 |
|
|
*exp2 = convert (int_type_node, *exp2);
|
930 |
|
|
return int_type_node;
|
931 |
|
|
}
|