OSDN Git Service

9b5353b2644d3986beda8d0060365c3d08f68cdb
[pf3gnuchains/gcc-fork.git] / gcc / java / builtins.c
1 /* Built-in and inline functions for gcj
2    Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007
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 Tom Tromey <tromey@redhat.com>.  */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "ggc.h"
34 #include "flags.h"
35 #include "langhooks.h"
36 #include "java-tree.h"
37 #include <stdarg.h>
38 #include "convert.h"
39 #include "rtl.h"
40 #include "insn-codes.h"
41 #include "expr.h"
42 #include "optabs.h"
43
44 static tree max_builtin (tree, tree);
45 static tree min_builtin (tree, tree);
46 static tree abs_builtin (tree, tree);
47 static tree convert_real (tree, tree);
48
49 static tree java_build_function_call_expr (tree, tree);
50
51 static tree putObject_builtin (tree, tree);
52 static tree compareAndSwapInt_builtin (tree, tree);
53 static tree compareAndSwapLong_builtin (tree, tree);
54 static tree compareAndSwapObject_builtin (tree, tree);
55 static tree putVolatile_builtin (tree, tree);
56 static tree getVolatile_builtin (tree, tree);
57
58 \f
59
60 /* Functions of this type are used to inline a given call.  Such a
61    function should either return an expression, if the call is to be
62    inlined, or NULL_TREE if a real call should be emitted.  Arguments
63    are method return type and arguments to call.  */
64 typedef tree builtin_creator_function (tree, tree);
65
66 /* Hold a char*, before initialization, or a tree, after
67    initialization.  */
68 union string_or_tree GTY(())
69 {
70   const char * GTY ((tag ("0"))) s;
71   tree GTY ((tag ("1"))) t;
72 };
73
74 /* Used to hold a single builtin record.  */
75 struct builtin_record GTY(())
76 {
77   union string_or_tree GTY ((desc ("1"))) class_name;
78   union string_or_tree GTY ((desc ("1"))) method_name;
79   builtin_creator_function * GTY((skip)) creator;
80   enum built_in_function builtin_code;
81 };
82
83 static GTY(()) struct builtin_record java_builtins[] =
84 {
85   { { "java.lang.Math" }, { "min" }, min_builtin, 0 },
86   { { "java.lang.Math" }, { "max" }, max_builtin, 0 },
87   { { "java.lang.Math" }, { "abs" }, abs_builtin, 0 },
88   { { "java.lang.Math" }, { "acos" }, NULL, BUILT_IN_ACOS },
89   { { "java.lang.Math" }, { "asin" }, NULL, BUILT_IN_ASIN },
90   { { "java.lang.Math" }, { "atan" }, NULL, BUILT_IN_ATAN },
91   { { "java.lang.Math" }, { "atan2" }, NULL, BUILT_IN_ATAN2 },
92   { { "java.lang.Math" }, { "ceil" }, NULL, BUILT_IN_CEIL },
93   { { "java.lang.Math" }, { "cos" }, NULL, BUILT_IN_COS },
94   { { "java.lang.Math" }, { "exp" }, NULL, BUILT_IN_EXP },
95   { { "java.lang.Math" }, { "floor" }, NULL, BUILT_IN_FLOOR },
96   { { "java.lang.Math" }, { "log" }, NULL, BUILT_IN_LOG },
97   { { "java.lang.Math" }, { "pow" }, NULL, BUILT_IN_POW },
98   { { "java.lang.Math" }, { "sin" }, NULL, BUILT_IN_SIN },
99   { { "java.lang.Math" }, { "sqrt" }, NULL, BUILT_IN_SQRT },
100   { { "java.lang.Math" }, { "tan" }, NULL, BUILT_IN_TAN },
101   { { "java.lang.Float" }, { "intBitsToFloat" }, convert_real, 0 },
102   { { "java.lang.Double" }, { "longBitsToDouble" }, convert_real, 0 },
103   { { "java.lang.Float" }, { "floatToRawIntBits" }, convert_real, 0 },
104   { { "java.lang.Double" }, { "doubleToRawLongBits" }, convert_real, 0 },
105   { { "sun.misc.Unsafe" }, { "putInt" }, putObject_builtin, 0},
106   { { "sun.misc.Unsafe" }, { "putLong" }, putObject_builtin, 0},
107   { { "sun.misc.Unsafe" }, { "putObject" }, putObject_builtin, 0},
108   { { "sun.misc.Unsafe" }, { "compareAndSwapInt" }, 
109     compareAndSwapInt_builtin, 0},
110   { { "sun.misc.Unsafe" }, { "compareAndSwapLong" }, 
111     compareAndSwapLong_builtin, 0},
112   { { "sun.misc.Unsafe" }, { "compareAndSwapObject" }, 
113     compareAndSwapObject_builtin, 0},
114   { { "sun.misc.Unsafe" }, { "putOrderedInt" }, putVolatile_builtin, 0},
115   { { "sun.misc.Unsafe" }, { "putOrderedLong" }, putVolatile_builtin, 0},
116   { { "sun.misc.Unsafe" }, { "putOrderedObject" }, putVolatile_builtin, 0},
117   { { "sun.misc.Unsafe" }, { "putIntVolatile" }, putVolatile_builtin, 0},
118   { { "sun.misc.Unsafe" }, { "putLongVolatile" }, putVolatile_builtin, 0},
119   { { "sun.misc.Unsafe" }, { "putObjectVolatile" }, putVolatile_builtin, 0},
120   { { "sun.misc.Unsafe" }, { "getObjectVolatile" }, getVolatile_builtin, 0},
121   { { "sun.misc.Unsafe" }, { "getIntVolatile" }, getVolatile_builtin, 0},
122   { { "sun.misc.Unsafe" }, { "getLongVolatile" }, getVolatile_builtin, 0},
123   { { "sun.misc.Unsafe" }, { "getLong" }, getVolatile_builtin, 0},
124   { { NULL }, { NULL }, NULL, END_BUILTINS }
125 };
126
127 \f
128 /* Internal functions which implement various builtin conversions.  */
129
130 static tree
131 max_builtin (tree method_return_type, tree method_arguments)
132 {
133   /* MAX_EXPR does not handle -0.0 in the Java style.  */
134   if (TREE_CODE (method_return_type) == REAL_TYPE)
135     return NULL_TREE;
136   return fold_build2 (MAX_EXPR, method_return_type,
137                       TREE_VALUE (method_arguments),
138                       TREE_VALUE (TREE_CHAIN (method_arguments)));
139 }
140
141 static tree
142 min_builtin (tree method_return_type, tree method_arguments)
143 {
144   /* MIN_EXPR does not handle -0.0 in the Java style.  */
145   if (TREE_CODE (method_return_type) == REAL_TYPE)
146     return NULL_TREE;
147   return fold_build2 (MIN_EXPR, method_return_type,
148                       TREE_VALUE (method_arguments),
149                       TREE_VALUE (TREE_CHAIN (method_arguments)));
150 }
151
152 static tree
153 abs_builtin (tree method_return_type, tree method_arguments)
154 {
155   return fold_build1 (ABS_EXPR, method_return_type,
156                       TREE_VALUE (method_arguments));
157 }
158
159 /* Mostly copied from ../builtins.c.  */
160 static tree
161 java_build_function_call_expr (tree fn, tree arglist)
162 {
163   tree call_expr;
164
165   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
166   return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
167                       call_expr, arglist, NULL_TREE);
168 }
169
170 static tree
171 convert_real (tree method_return_type, tree method_arguments)
172 {
173   return build1 (VIEW_CONVERT_EXPR, method_return_type,
174                  TREE_VALUE (method_arguments));
175 }
176
177 \f
178
179 /* Provide builtin support for atomic operations.  These are
180    documented at length in libjava/sun/misc/Unsafe.java.  */
181
182 /* FIXME.  There are still a few things wrong with this logic.  In
183    particular, atomic writes of multi-word integers are not truly
184    atomic: this requires more work.
185
186    In general, double-word compare-and-swap cannot portably be
187    implemented, so we need some kind of fallback for 32-bit machines.
188
189 */
190
191
192 /* Macros to unmarshal arguments from a TREE_LIST into a few
193    variables.  We also convert the offset arg from a long to an
194    integer that is the same size as a pointer.  */
195
196 #define UNMARSHAL3(METHOD_ARGUMENTS)                                    \
197 tree this_arg, obj_arg, offset_arg;                                     \
198 do                                                                      \
199 {                                                                       \
200   tree chain = METHOD_ARGUMENTS;                                        \
201   this_arg = TREE_VALUE (chain);                                        \
202   chain = TREE_CHAIN (chain);                                           \
203   obj_arg = TREE_VALUE (chain);                                         \
204   chain = TREE_CHAIN (chain);                                           \
205   offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0),      \
206                              TREE_VALUE (chain));                       \
207 }                                                                       \
208 while (0)
209
210 #define UNMARSHAL4(METHOD_ARGUMENTS)                                    \
211 tree value_type, this_arg, obj_arg, offset_arg, value_arg;              \
212 do                                                                      \
213 {                                                                       \
214   tree chain = METHOD_ARGUMENTS;                                        \
215   this_arg = TREE_VALUE (chain);                                        \
216   chain = TREE_CHAIN (chain);                                           \
217   obj_arg = TREE_VALUE (chain);                                         \
218   chain = TREE_CHAIN (chain);                                           \
219   offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0),      \
220                              TREE_VALUE (chain));                       \
221   chain = TREE_CHAIN (chain);                                           \
222   value_arg = TREE_VALUE (chain);                                       \
223   value_type = TREE_TYPE (value_arg);                                   \
224 }                                                                       \
225 while (0)
226
227 #define UNMARSHAL5(METHOD_ARGUMENTS)                                    \
228 tree value_type, this_arg, obj_arg, offset_arg, expected_arg, value_arg; \
229 do                                                                      \
230 {                                                                       \
231   tree chain = METHOD_ARGUMENTS;                                        \
232   this_arg = TREE_VALUE (chain);                                        \
233   chain = TREE_CHAIN (chain);                                           \
234   obj_arg = TREE_VALUE (chain);                                         \
235   chain = TREE_CHAIN (chain);                                           \
236   offset_arg = fold_convert (java_type_for_size (POINTER_SIZE, 0),      \
237                              TREE_VALUE (chain));                       \
238   chain = TREE_CHAIN (chain);                                           \
239   expected_arg = TREE_VALUE (chain);                                    \
240   chain = TREE_CHAIN (chain);                                           \
241   value_arg = TREE_VALUE (chain);                                       \
242   value_type = TREE_TYPE (value_arg);                                   \
243 }                                                                       \
244 while (0)
245
246 /* Construct an arglist from a call.  */
247
248 static tree
249 build_arglist_for_builtin (tree arg, ...)
250 {
251   va_list ap;
252   tree nextarg;
253   tree newarglist = build_tree_list (NULL_TREE, arg);
254
255   va_start(ap, arg);
256   while ((nextarg = va_arg(ap, tree)))
257     newarglist = tree_cons (NULL_TREE, nextarg, newarglist);
258
259   return nreverse (newarglist);
260 }
261
262 /* Add an address to an offset, forming a sum.  */
263
264 static tree
265 build_addr_sum (tree type, tree addr, tree offset)
266 {
267   tree ptr_type = build_pointer_type (type);
268   return  fold_build2 (PLUS_EXPR, 
269                        ptr_type, 
270                        fold_convert (ptr_type, addr), offset);
271 }
272
273 /* Make sure that this-arg is non-NULL.  This is a security check.  */
274
275 static tree
276 build_check_this (tree stmt, tree this_arg)
277 {
278   return build2 (COMPOUND_EXPR, TREE_TYPE (stmt), 
279                  java_check_reference (this_arg, 1), stmt);
280 }
281
282 /* Now the builtins.  These correspond to the primitive functions in
283    libjava/sun/misc/natUnsafe.cc.  */
284
285 static tree
286 putObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, 
287                    tree method_arguments)
288 {
289   tree addr, stmt;
290   UNMARSHAL4 (method_arguments);
291
292   addr = build_addr_sum (value_type, obj_arg, offset_arg);
293   stmt = fold_build2 (MODIFY_EXPR, value_type,
294                       build_java_indirect_ref (value_type, addr,
295                                                flag_check_references),
296                       value_arg);
297
298   return build_check_this (stmt, this_arg);
299 }
300
301 static tree
302 compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED,
303                            tree method_arguments)
304 {
305   enum machine_mode mode = TYPE_MODE (int_type_node);
306   if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
307       || sync_compare_and_swap[mode] != CODE_FOR_nothing)
308     {
309       tree newarglist, addr, stmt;
310       UNMARSHAL5 (method_arguments);
311
312       addr = build_addr_sum (int_type_node, obj_arg, offset_arg);
313
314       newarglist 
315         = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE);
316       stmt = (build_function_call_expr
317               (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_4],
318                newarglist));
319
320       return build_check_this (stmt, this_arg);
321     }
322   return NULL_TREE;
323 }
324
325 static tree
326 compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED,
327                             tree method_arguments)
328 {
329   enum machine_mode mode = TYPE_MODE (long_type_node);
330   if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
331       || sync_compare_and_swap[mode] != CODE_FOR_nothing)
332     {
333       tree newarglist, addr, stmt;
334       UNMARSHAL5 (method_arguments);
335
336       addr = build_addr_sum (long_type_node, obj_arg, offset_arg);
337
338       newarglist 
339         = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE);
340       stmt = (build_function_call_expr
341               (built_in_decls[BUILT_IN_BOOL_COMPARE_AND_SWAP_8],
342                newarglist));
343
344       return build_check_this (stmt, this_arg);
345     }
346   return NULL_TREE;
347 }
348 static tree
349 compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, 
350                               tree method_arguments)
351 {
352   enum machine_mode mode = TYPE_MODE (ptr_type_node);
353   if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
354       || sync_compare_and_swap[mode] != CODE_FOR_nothing)
355   {
356     tree newarglist, addr, stmt;
357     int builtin;
358
359     UNMARSHAL5 (method_arguments);
360     builtin = (POINTER_SIZE == 32 
361                ? BUILT_IN_BOOL_COMPARE_AND_SWAP_4 
362                : BUILT_IN_BOOL_COMPARE_AND_SWAP_8);
363
364     addr = build_addr_sum (value_type, obj_arg, offset_arg);
365
366     newarglist 
367       = build_arglist_for_builtin (addr, expected_arg, value_arg, NULL_TREE);
368     stmt = (build_function_call_expr
369             (built_in_decls[builtin],
370              newarglist));
371
372     return build_check_this (stmt, this_arg);
373   }
374   return NULL_TREE;
375 }
376
377 static tree
378 putVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, 
379                      tree method_arguments)
380 {
381   tree newarglist, addr, stmt, modify_stmt;
382   UNMARSHAL4 (method_arguments);
383   
384   addr = build_addr_sum (value_type, obj_arg, offset_arg);
385   addr 
386     = fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)),
387                     addr);
388   
389   newarglist = NULL_TREE;
390   stmt = (build_function_call_expr
391           (built_in_decls[BUILT_IN_SYNCHRONIZE],
392            newarglist));
393   modify_stmt = fold_build2 (MODIFY_EXPR, value_type,
394                              build_java_indirect_ref (value_type, addr,
395                                                       flag_check_references),
396                              value_arg);
397   stmt = build2 (COMPOUND_EXPR, TREE_TYPE (modify_stmt), 
398                  stmt, modify_stmt);
399
400   return build_check_this (stmt, this_arg);
401 }
402
403 static tree
404 getVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED, 
405                      tree method_arguments)
406 {
407   tree newarglist, addr, stmt, modify_stmt, tmp;
408   UNMARSHAL3 (method_arguments);
409   
410   addr = build_addr_sum (method_return_type, obj_arg, offset_arg);
411   addr 
412     = fold_convert (build_pointer_type (build_type_variant 
413                                         (method_return_type, 0, 1)), addr);
414   
415   newarglist = NULL_TREE;
416   stmt = (build_function_call_expr
417           (built_in_decls[BUILT_IN_SYNCHRONIZE],
418            newarglist));
419   
420   tmp = build_decl (VAR_DECL, NULL, method_return_type);
421   DECL_IGNORED_P (tmp) = 1;
422   DECL_ARTIFICIAL (tmp) = 1;
423   pushdecl (tmp);
424
425   modify_stmt = fold_build2 (MODIFY_EXPR, method_return_type,
426                              tmp,
427                              build_java_indirect_ref (method_return_type, addr,
428                                                       flag_check_references));
429
430   stmt = build2 (COMPOUND_EXPR, void_type_node, modify_stmt, stmt);
431   stmt = build2 (COMPOUND_EXPR, method_return_type, stmt, tmp);
432   
433   return stmt;
434 }
435   
436 \f
437
438 #define BUILTIN_NOTHROW 1
439 #define BUILTIN_CONST 2
440 /* Define a single builtin.  */
441 static void
442 define_builtin (enum built_in_function val,
443                 const char *name,
444                 tree type,
445                 const char *libname,
446                 int flags)
447 {
448   tree decl;
449
450   decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
451   DECL_EXTERNAL (decl) = 1;
452   TREE_PUBLIC (decl) = 1;
453   SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
454   pushdecl (decl);
455   DECL_BUILT_IN_CLASS (decl) = BUILT_IN_NORMAL;
456   DECL_FUNCTION_CODE (decl) = val;
457   if (flags & BUILTIN_NOTHROW)
458     TREE_NOTHROW (decl) = 1;
459   if (flags & BUILTIN_CONST)
460     TREE_READONLY (decl) = 1;
461
462   implicit_built_in_decls[val] = decl;
463   built_in_decls[val] = decl;
464 }
465
466 \f
467
468 /* Initialize the builtins.  */
469 void
470 initialize_builtins (void)
471 {
472   tree double_ftype_double, double_ftype_double_double;
473   tree float_ftype_float, float_ftype_float_float;
474   tree boolean_ftype_boolean_boolean;
475   tree t;
476   int i;
477
478   for (i = 0; java_builtins[i].builtin_code != END_BUILTINS; ++i)
479     {
480       tree klass_id = get_identifier (java_builtins[i].class_name.s);
481       tree m = get_identifier (java_builtins[i].method_name.s);
482
483       java_builtins[i].class_name.t = klass_id;
484       java_builtins[i].method_name.t = m;
485     }
486
487   void_list_node = end_params_node;
488
489   t = tree_cons (NULL_TREE, float_type_node, end_params_node);
490   float_ftype_float = build_function_type (float_type_node, t);
491   t = tree_cons (NULL_TREE, float_type_node, t);
492   float_ftype_float_float = build_function_type (float_type_node, t);
493
494   t = tree_cons (NULL_TREE, double_type_node, end_params_node);
495   double_ftype_double = build_function_type (double_type_node, t);
496   t = tree_cons (NULL_TREE, double_type_node, t);
497   double_ftype_double_double = build_function_type (double_type_node, t);
498
499   define_builtin (BUILT_IN_FMOD, "__builtin_fmod",
500                   double_ftype_double_double, "fmod", BUILTIN_CONST);
501   define_builtin (BUILT_IN_FMODF, "__builtin_fmodf",
502                   float_ftype_float_float, "fmodf", BUILTIN_CONST);
503
504   define_builtin (BUILT_IN_ACOS, "__builtin_acos",
505                   double_ftype_double, "_ZN4java4lang4Math4acosEJdd",
506                   BUILTIN_CONST);
507   define_builtin (BUILT_IN_ASIN, "__builtin_asin",
508                   double_ftype_double, "_ZN4java4lang4Math4asinEJdd",
509                   BUILTIN_CONST);
510   define_builtin (BUILT_IN_ATAN, "__builtin_atan",
511                   double_ftype_double, "_ZN4java4lang4Math4atanEJdd",
512                   BUILTIN_CONST);
513   define_builtin (BUILT_IN_ATAN2, "__builtin_atan2",
514                   double_ftype_double_double, "_ZN4java4lang4Math5atan2EJddd",
515                   BUILTIN_CONST);
516   define_builtin (BUILT_IN_CEIL, "__builtin_ceil",
517                   double_ftype_double, "_ZN4java4lang4Math4ceilEJdd",
518                   BUILTIN_CONST);
519   define_builtin (BUILT_IN_COS, "__builtin_cos",
520                   double_ftype_double, "_ZN4java4lang4Math3cosEJdd",
521                   BUILTIN_CONST);
522   define_builtin (BUILT_IN_EXP, "__builtin_exp",
523                   double_ftype_double, "_ZN4java4lang4Math3expEJdd",
524                   BUILTIN_CONST);
525   define_builtin (BUILT_IN_FLOOR, "__builtin_floor",
526                   double_ftype_double, "_ZN4java4lang4Math5floorEJdd",
527                   BUILTIN_CONST);
528   define_builtin (BUILT_IN_LOG, "__builtin_log",
529                   double_ftype_double, "_ZN4java4lang4Math3logEJdd",
530                   BUILTIN_CONST);
531   define_builtin (BUILT_IN_POW, "__builtin_pow",
532                   double_ftype_double_double, "_ZN4java4lang4Math3powEJddd",
533                   BUILTIN_CONST);
534   define_builtin (BUILT_IN_SIN, "__builtin_sin",
535                   double_ftype_double, "_ZN4java4lang4Math3sinEJdd",
536                   BUILTIN_CONST);
537   define_builtin (BUILT_IN_SQRT, "__builtin_sqrt",
538                   double_ftype_double, "_ZN4java4lang4Math4sqrtEJdd",
539                   BUILTIN_CONST);
540   define_builtin (BUILT_IN_TAN, "__builtin_tan",
541                   double_ftype_double, "_ZN4java4lang4Math3tanEJdd",
542                   BUILTIN_CONST);
543   
544   t = tree_cons (NULL_TREE, boolean_type_node, end_params_node);
545   t = tree_cons (NULL_TREE, boolean_type_node, t);
546   boolean_ftype_boolean_boolean = build_function_type (boolean_type_node, t);
547   define_builtin (BUILT_IN_EXPECT, "__builtin_expect", 
548                   boolean_ftype_boolean_boolean,
549                   "__builtin_expect",
550                   BUILTIN_CONST | BUILTIN_NOTHROW);
551   define_builtin (BUILT_IN_BOOL_COMPARE_AND_SWAP_4, 
552                   "__sync_bool_compare_and_swap_4",
553                   build_function_type_list (boolean_type_node,
554                                             int_type_node, 
555                                             build_pointer_type (int_type_node),
556                                             int_type_node, NULL_TREE), 
557                   "__sync_bool_compare_and_swap_4", 0);
558   define_builtin (BUILT_IN_BOOL_COMPARE_AND_SWAP_8, 
559                   "__sync_bool_compare_and_swap_8",
560                   build_function_type_list (boolean_type_node,
561                                             long_type_node, 
562                                             build_pointer_type (long_type_node),
563                                             int_type_node, NULL_TREE), 
564                   "__sync_bool_compare_and_swap_8", 0);
565   define_builtin (BUILT_IN_SYNCHRONIZE, "__sync_synchronize",
566                   build_function_type (void_type_node, void_list_node),
567                   "__sync_synchronize", BUILTIN_NOTHROW);
568   
569   define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
570                   build_function_type_list (ptr_type_node, int_type_node, NULL_TREE),
571                   "__builtin_return_address", BUILTIN_NOTHROW);
572
573   build_common_builtin_nodes ();
574 }
575
576 /* If the call matches a builtin, return the
577    appropriate builtin expression instead.  */
578 tree
579 check_for_builtin (tree method, tree call)
580 {
581   if (optimize && TREE_CODE (call) == CALL_EXPR)
582     {
583       int i;
584       tree method_arguments = TREE_OPERAND (call, 1);
585       tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
586       tree method_name = DECL_NAME (method);
587       tree method_return_type = TREE_TYPE (TREE_TYPE (method));
588
589       for (i = 0; java_builtins[i].builtin_code != END_BUILTINS; ++i)
590         {
591           if (method_class == java_builtins[i].class_name.t
592               && method_name == java_builtins[i].method_name.t)
593             {
594               tree fn;
595
596               if (java_builtins[i].creator != NULL)
597                 {
598                   tree result
599                     = (*java_builtins[i].creator) (method_return_type,
600                                                    method_arguments);
601                   return result == NULL_TREE ? call : result;
602                 }
603
604               /* Builtin functions emit a direct call which is incompatible
605                  with the BC-ABI.  */
606               if (flag_indirect_dispatch)
607                 return call;
608               fn = built_in_decls[java_builtins[i].builtin_code];
609               if (fn == NULL_TREE)
610                 return call;
611               return java_build_function_call_expr (fn, method_arguments);
612             }
613         }
614     }
615   return call;
616 }
617
618 #include "gt-java-builtins.h"