1*c87b03e5Sespie /* Built-in and inline functions for gcj
2*c87b03e5Sespie Copyright (C) 2001
3*c87b03e5Sespie Free Software Foundation, Inc.
4*c87b03e5Sespie
5*c87b03e5Sespie This file is part of GNU CC.
6*c87b03e5Sespie
7*c87b03e5Sespie GNU CC is free software; you can redistribute it and/or modify
8*c87b03e5Sespie it under the terms of the GNU General Public License as published by
9*c87b03e5Sespie the Free Software Foundation; either version 2, or (at your option)
10*c87b03e5Sespie any later version.
11*c87b03e5Sespie
12*c87b03e5Sespie GNU CC is distributed in the hope that it will be useful,
13*c87b03e5Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
14*c87b03e5Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*c87b03e5Sespie GNU General Public License for more details.
16*c87b03e5Sespie
17*c87b03e5Sespie You should have received a copy of the GNU General Public License
18*c87b03e5Sespie along with GNU CC; see the file COPYING. If not, write to
19*c87b03e5Sespie the Free Software Foundation, 59 Temple Place - Suite 330,
20*c87b03e5Sespie Boston, MA 02111-1307, USA.
21*c87b03e5Sespie
22*c87b03e5Sespie Java and all Java-based marks are trademarks or registered trademarks
23*c87b03e5Sespie of Sun Microsystems, Inc. in the United States and other countries.
24*c87b03e5Sespie The Free Software Foundation is independent of Sun Microsystems, Inc. */
25*c87b03e5Sespie
26*c87b03e5Sespie /* Written by Tom Tromey <tromey@redhat.com>. */
27*c87b03e5Sespie
28*c87b03e5Sespie #include "config.h"
29*c87b03e5Sespie #include "system.h"
30*c87b03e5Sespie #include "tree.h"
31*c87b03e5Sespie #include "ggc.h"
32*c87b03e5Sespie #include "flags.h"
33*c87b03e5Sespie #include "langhooks.h"
34*c87b03e5Sespie #include "java-tree.h"
35*c87b03e5Sespie
36*c87b03e5Sespie enum builtin_type
37*c87b03e5Sespie {
38*c87b03e5Sespie #define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
39*c87b03e5Sespie #define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
40*c87b03e5Sespie #define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
41*c87b03e5Sespie #define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
42*c87b03e5Sespie #define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
43*c87b03e5Sespie #define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
44*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
45*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
46*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
47*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
48*c87b03e5Sespie #define DEF_POINTER_TYPE(NAME, TYPE) NAME,
49*c87b03e5Sespie #include "builtin-types.def"
50*c87b03e5Sespie #undef DEF_PRIMITIVE_TYPE
51*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_0
52*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_1
53*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_2
54*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_3
55*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_4
56*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_VAR_0
57*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_VAR_1
58*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_VAR_2
59*c87b03e5Sespie #undef DEF_FUNCTION_TYPE_VAR_3
60*c87b03e5Sespie #undef DEF_POINTER_TYPE
61*c87b03e5Sespie BT_LAST
62*c87b03e5Sespie };
63*c87b03e5Sespie
64*c87b03e5Sespie static tree max_builtin PARAMS ((tree, tree));
65*c87b03e5Sespie static tree min_builtin PARAMS ((tree, tree));
66*c87b03e5Sespie static tree abs_builtin PARAMS ((tree, tree));
67*c87b03e5Sespie static tree cos_builtin PARAMS ((tree, tree));
68*c87b03e5Sespie static tree sin_builtin PARAMS ((tree, tree));
69*c87b03e5Sespie static tree sqrt_builtin PARAMS ((tree, tree));
70*c87b03e5Sespie
71*c87b03e5Sespie static tree build_function_call_expr PARAMS ((tree, tree));
72*c87b03e5Sespie static void define_builtin PARAMS ((enum built_in_function,
73*c87b03e5Sespie const char *,
74*c87b03e5Sespie enum built_in_class,
75*c87b03e5Sespie tree, int));
76*c87b03e5Sespie static tree define_builtin_type PARAMS ((int, int, int, int, int));
77*c87b03e5Sespie
78*c87b03e5Sespie
79*c87b03e5Sespie
80*c87b03e5Sespie /* Functions of this type are used to inline a given call. Such a
81*c87b03e5Sespie function should either return an expression, if the call is to be
82*c87b03e5Sespie inlined, or NULL_TREE if a real call should be emitted. Arguments
83*c87b03e5Sespie are method return type and arguments to call. */
84*c87b03e5Sespie typedef tree builtin_creator_function PARAMS ((tree, tree));
85*c87b03e5Sespie
86*c87b03e5Sespie /* Hold a char*, before initialization, or a tree, after
87*c87b03e5Sespie initialization. */
88*c87b03e5Sespie union string_or_tree GTY(())
89*c87b03e5Sespie {
90*c87b03e5Sespie const char * GTY ((tag ("0"))) s;
91*c87b03e5Sespie tree GTY ((tag ("1"))) t;
92*c87b03e5Sespie };
93*c87b03e5Sespie
94*c87b03e5Sespie /* Used to hold a single builtin record. */
95*c87b03e5Sespie struct builtin_record GTY(())
96*c87b03e5Sespie {
97*c87b03e5Sespie union string_or_tree GTY ((desc ("1"))) class_name;
98*c87b03e5Sespie union string_or_tree GTY ((desc ("1"))) method_name;
99*c87b03e5Sespie builtin_creator_function * GTY((skip (""))) creator;
100*c87b03e5Sespie };
101*c87b03e5Sespie
102*c87b03e5Sespie static GTY(()) struct builtin_record java_builtins[] =
103*c87b03e5Sespie {
104*c87b03e5Sespie { { "java.lang.Math" }, { "min" }, min_builtin },
105*c87b03e5Sespie { { "java.lang.Math" }, { "max" }, max_builtin },
106*c87b03e5Sespie { { "java.lang.Math" }, { "abs" }, abs_builtin },
107*c87b03e5Sespie { { "java.lang.Math" }, { "cos" }, cos_builtin },
108*c87b03e5Sespie { { "java.lang.Math" }, { "sin" }, sin_builtin },
109*c87b03e5Sespie { { "java.lang.Math" }, { "sqrt" }, sqrt_builtin },
110*c87b03e5Sespie { { NULL }, { NULL }, NULL }
111*c87b03e5Sespie };
112*c87b03e5Sespie
113*c87b03e5Sespie /* This is only used transiently, so we don't mark it as roots for the
114*c87b03e5Sespie GC. */
115*c87b03e5Sespie static tree builtin_types[(int) BT_LAST];
116*c87b03e5Sespie
117*c87b03e5Sespie
118*c87b03e5Sespie /* Internal functions which implement various builtin conversions. */
119*c87b03e5Sespie
120*c87b03e5Sespie static tree
max_builtin(method_return_type,method_arguments)121*c87b03e5Sespie max_builtin (method_return_type, method_arguments)
122*c87b03e5Sespie tree method_return_type, method_arguments;
123*c87b03e5Sespie {
124*c87b03e5Sespie return build (MAX_EXPR, method_return_type,
125*c87b03e5Sespie TREE_VALUE (method_arguments),
126*c87b03e5Sespie TREE_VALUE (TREE_CHAIN (method_arguments)));
127*c87b03e5Sespie }
128*c87b03e5Sespie
129*c87b03e5Sespie static tree
min_builtin(method_return_type,method_arguments)130*c87b03e5Sespie min_builtin (method_return_type, method_arguments)
131*c87b03e5Sespie tree method_return_type, method_arguments;
132*c87b03e5Sespie {
133*c87b03e5Sespie return build (MIN_EXPR, method_return_type,
134*c87b03e5Sespie TREE_VALUE (method_arguments),
135*c87b03e5Sespie TREE_VALUE (TREE_CHAIN (method_arguments)));
136*c87b03e5Sespie }
137*c87b03e5Sespie
138*c87b03e5Sespie static tree
abs_builtin(method_return_type,method_arguments)139*c87b03e5Sespie abs_builtin (method_return_type, method_arguments)
140*c87b03e5Sespie tree method_return_type, method_arguments;
141*c87b03e5Sespie {
142*c87b03e5Sespie return build1 (ABS_EXPR, method_return_type,
143*c87b03e5Sespie TREE_VALUE (method_arguments));
144*c87b03e5Sespie }
145*c87b03e5Sespie
146*c87b03e5Sespie /* Mostly copied from ../builtins.c. */
147*c87b03e5Sespie static tree
build_function_call_expr(tree fn,tree arglist)148*c87b03e5Sespie build_function_call_expr (tree fn, tree arglist)
149*c87b03e5Sespie {
150*c87b03e5Sespie tree call_expr;
151*c87b03e5Sespie
152*c87b03e5Sespie call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
153*c87b03e5Sespie call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
154*c87b03e5Sespie call_expr, arglist);
155*c87b03e5Sespie TREE_SIDE_EFFECTS (call_expr) = 1;
156*c87b03e5Sespie return call_expr;
157*c87b03e5Sespie }
158*c87b03e5Sespie
159*c87b03e5Sespie static tree
cos_builtin(method_return_type,method_arguments)160*c87b03e5Sespie cos_builtin (method_return_type, method_arguments)
161*c87b03e5Sespie tree method_return_type ATTRIBUTE_UNUSED, method_arguments;
162*c87b03e5Sespie {
163*c87b03e5Sespie /* FIXME: this assumes that jdouble and double are the same. */
164*c87b03e5Sespie tree fn = built_in_decls[BUILT_IN_COS];
165*c87b03e5Sespie if (fn == NULL_TREE)
166*c87b03e5Sespie return NULL_TREE;
167*c87b03e5Sespie return build_function_call_expr (fn, method_arguments);
168*c87b03e5Sespie }
169*c87b03e5Sespie
170*c87b03e5Sespie static tree
sin_builtin(method_return_type,method_arguments)171*c87b03e5Sespie sin_builtin (method_return_type, method_arguments)
172*c87b03e5Sespie tree method_return_type ATTRIBUTE_UNUSED, method_arguments;
173*c87b03e5Sespie {
174*c87b03e5Sespie /* FIXME: this assumes that jdouble and double are the same. */
175*c87b03e5Sespie tree fn = built_in_decls[BUILT_IN_SIN];
176*c87b03e5Sespie if (fn == NULL_TREE)
177*c87b03e5Sespie return NULL_TREE;
178*c87b03e5Sespie return build_function_call_expr (fn, method_arguments);
179*c87b03e5Sespie }
180*c87b03e5Sespie
181*c87b03e5Sespie static tree
sqrt_builtin(method_return_type,method_arguments)182*c87b03e5Sespie sqrt_builtin (method_return_type, method_arguments)
183*c87b03e5Sespie tree method_return_type ATTRIBUTE_UNUSED, method_arguments;
184*c87b03e5Sespie {
185*c87b03e5Sespie /* FIXME: this assumes that jdouble and double are the same. */
186*c87b03e5Sespie tree fn = built_in_decls[BUILT_IN_SQRT];
187*c87b03e5Sespie if (fn == NULL_TREE)
188*c87b03e5Sespie return NULL_TREE;
189*c87b03e5Sespie return build_function_call_expr (fn, method_arguments);
190*c87b03e5Sespie }
191*c87b03e5Sespie
192*c87b03e5Sespie
193*c87b03e5Sespie
194*c87b03e5Sespie /* Define a single builtin. */
195*c87b03e5Sespie static void
define_builtin(val,name,class,type,fallback_p)196*c87b03e5Sespie define_builtin (val, name, class, type, fallback_p)
197*c87b03e5Sespie enum built_in_function val;
198*c87b03e5Sespie const char *name;
199*c87b03e5Sespie enum built_in_class class;
200*c87b03e5Sespie tree type;
201*c87b03e5Sespie int fallback_p;
202*c87b03e5Sespie {
203*c87b03e5Sespie tree decl;
204*c87b03e5Sespie
205*c87b03e5Sespie if (! name || ! type)
206*c87b03e5Sespie return;
207*c87b03e5Sespie
208*c87b03e5Sespie if (strncmp (name, "__builtin_", strlen ("__builtin_")) != 0)
209*c87b03e5Sespie abort ();
210*c87b03e5Sespie decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
211*c87b03e5Sespie DECL_EXTERNAL (decl) = 1;
212*c87b03e5Sespie TREE_PUBLIC (decl) = 1;
213*c87b03e5Sespie if (fallback_p)
214*c87b03e5Sespie SET_DECL_ASSEMBLER_NAME (decl,
215*c87b03e5Sespie get_identifier (name + strlen ("__builtin_")));
216*c87b03e5Sespie make_decl_rtl (decl, NULL);
217*c87b03e5Sespie pushdecl (decl);
218*c87b03e5Sespie DECL_BUILT_IN_CLASS (decl) = class;
219*c87b03e5Sespie DECL_FUNCTION_CODE (decl) = val;
220*c87b03e5Sespie built_in_decls[val] = decl;
221*c87b03e5Sespie }
222*c87b03e5Sespie
223*c87b03e5Sespie /* Compute the type for a builtin. */
224*c87b03e5Sespie static tree
define_builtin_type(ret,arg1,arg2,arg3,arg4)225*c87b03e5Sespie define_builtin_type (ret, arg1, arg2, arg3, arg4)
226*c87b03e5Sespie int ret, arg1, arg2, arg3, arg4;
227*c87b03e5Sespie {
228*c87b03e5Sespie tree args;
229*c87b03e5Sespie
230*c87b03e5Sespie if (builtin_types[ret] == NULL_TREE)
231*c87b03e5Sespie return NULL_TREE;
232*c87b03e5Sespie
233*c87b03e5Sespie args = void_list_node;
234*c87b03e5Sespie
235*c87b03e5Sespie if (arg4 != -1)
236*c87b03e5Sespie {
237*c87b03e5Sespie if (builtin_types[arg4] == NULL_TREE)
238*c87b03e5Sespie return NULL_TREE;
239*c87b03e5Sespie args = tree_cons (NULL_TREE, builtin_types[arg4], args);
240*c87b03e5Sespie }
241*c87b03e5Sespie if (arg3 != -1)
242*c87b03e5Sespie {
243*c87b03e5Sespie if (builtin_types[arg3] == NULL_TREE)
244*c87b03e5Sespie return NULL_TREE;
245*c87b03e5Sespie args = tree_cons (NULL_TREE, builtin_types[arg3], args);
246*c87b03e5Sespie }
247*c87b03e5Sespie if (arg2 != -1)
248*c87b03e5Sespie {
249*c87b03e5Sespie if (builtin_types[arg2] == NULL_TREE)
250*c87b03e5Sespie return NULL_TREE;
251*c87b03e5Sespie args = tree_cons (NULL_TREE, builtin_types[arg2], args);
252*c87b03e5Sespie }
253*c87b03e5Sespie if (arg1 != -1)
254*c87b03e5Sespie {
255*c87b03e5Sespie if (builtin_types[arg1] == NULL_TREE)
256*c87b03e5Sespie return NULL_TREE;
257*c87b03e5Sespie args = tree_cons (NULL_TREE, builtin_types[arg1], args);
258*c87b03e5Sespie }
259*c87b03e5Sespie
260*c87b03e5Sespie return build_function_type (builtin_types[ret], args);
261*c87b03e5Sespie }
262*c87b03e5Sespie
263*c87b03e5Sespie
264*c87b03e5Sespie
265*c87b03e5Sespie /* Initialize the builtins. */
266*c87b03e5Sespie void
initialize_builtins()267*c87b03e5Sespie initialize_builtins ()
268*c87b03e5Sespie {
269*c87b03e5Sespie int i;
270*c87b03e5Sespie
271*c87b03e5Sespie for (i = 0; java_builtins[i].creator != NULL; ++i)
272*c87b03e5Sespie {
273*c87b03e5Sespie tree klass_id = get_identifier (java_builtins[i].class_name.s);
274*c87b03e5Sespie tree m = get_identifier (java_builtins[i].method_name.s);
275*c87b03e5Sespie
276*c87b03e5Sespie java_builtins[i].class_name.t = klass_id;
277*c87b03e5Sespie java_builtins[i].method_name.t = m;
278*c87b03e5Sespie }
279*c87b03e5Sespie
280*c87b03e5Sespie void_list_node = end_params_node;
281*c87b03e5Sespie
282*c87b03e5Sespie /* Work around C-specific junk in builtin-types.def. */
283*c87b03e5Sespie #define intmax_type_node NULL_TREE
284*c87b03e5Sespie #define c_size_type_node NULL_TREE
285*c87b03e5Sespie #define const_string_type_node NULL_TREE
286*c87b03e5Sespie #define va_list_ref_type_node NULL_TREE
287*c87b03e5Sespie #define va_list_arg_type_node NULL_TREE
288*c87b03e5Sespie #define flag_isoc99 0
289*c87b03e5Sespie
290*c87b03e5Sespie #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
291*c87b03e5Sespie builtin_types[(int) ENUM] = VALUE;
292*c87b03e5Sespie #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
293*c87b03e5Sespie builtin_types[(int) ENUM] \
294*c87b03e5Sespie = define_builtin_type (RETURN, -1, -1, -1, -1);
295*c87b03e5Sespie #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
296*c87b03e5Sespie builtin_types[(int) ENUM] \
297*c87b03e5Sespie = define_builtin_type (RETURN, ARG1, -1, -1, -1);
298*c87b03e5Sespie #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
299*c87b03e5Sespie builtin_types[(int) ENUM] \
300*c87b03e5Sespie = define_builtin_type (RETURN, ARG1, ARG2, -1, -1);
301*c87b03e5Sespie #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
302*c87b03e5Sespie builtin_types[(int) ENUM] \
303*c87b03e5Sespie = define_builtin_type (RETURN, ARG1, ARG2, ARG3, -1);
304*c87b03e5Sespie #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
305*c87b03e5Sespie builtin_types[(int) ENUM] \
306*c87b03e5Sespie = define_builtin_type (RETURN, ARG1, ARG2, ARG3, ARG4);
307*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
308*c87b03e5Sespie builtin_types[(int) ENUM] = NULL_TREE;
309*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
310*c87b03e5Sespie builtin_types[(int) ENUM] = NULL_TREE;
311*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
312*c87b03e5Sespie builtin_types[(int) ENUM] = NULL_TREE;
313*c87b03e5Sespie #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
314*c87b03e5Sespie builtin_types[(int) ENUM] = NULL_TREE;
315*c87b03e5Sespie #define DEF_POINTER_TYPE(ENUM, TYPE) \
316*c87b03e5Sespie builtin_types[(int) ENUM] = NULL_TREE;
317*c87b03e5Sespie
318*c87b03e5Sespie #include "builtin-types.def"
319*c87b03e5Sespie
320*c87b03e5Sespie #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, \
321*c87b03e5Sespie FALLBACK_P, NONANSI_P, ATTRS) \
322*c87b03e5Sespie define_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], FALLBACK_P);
323*c87b03e5Sespie #include "builtins.def"
324*c87b03e5Sespie }
325*c87b03e5Sespie
326*c87b03e5Sespie /* If the call matches a builtin, return the
327*c87b03e5Sespie appropriate builtin expression instead. */
328*c87b03e5Sespie tree
check_for_builtin(method,call)329*c87b03e5Sespie check_for_builtin (method, call)
330*c87b03e5Sespie tree method;
331*c87b03e5Sespie tree call;
332*c87b03e5Sespie {
333*c87b03e5Sespie if (! flag_emit_class_files && optimize && TREE_CODE (call) == CALL_EXPR)
334*c87b03e5Sespie {
335*c87b03e5Sespie int i;
336*c87b03e5Sespie tree method_arguments = TREE_OPERAND (call, 1);
337*c87b03e5Sespie tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
338*c87b03e5Sespie tree method_name = DECL_NAME (method);
339*c87b03e5Sespie tree method_return_type = TREE_TYPE (TREE_TYPE (method));
340*c87b03e5Sespie
341*c87b03e5Sespie for (i = 0; java_builtins[i].creator != NULL; ++i)
342*c87b03e5Sespie {
343*c87b03e5Sespie if (method_class == java_builtins[i].class_name.t
344*c87b03e5Sespie && method_name == java_builtins[i].method_name.t)
345*c87b03e5Sespie {
346*c87b03e5Sespie return (*java_builtins[i].creator) (method_return_type,
347*c87b03e5Sespie method_arguments);
348*c87b03e5Sespie }
349*c87b03e5Sespie }
350*c87b03e5Sespie }
351*c87b03e5Sespie return call;
352*c87b03e5Sespie }
353*c87b03e5Sespie
354*c87b03e5Sespie #include "gt-java-builtins.h"
355