Patchwork Builtin infrastructure change

login
register
mail settings
Submitter Michael Meissner
Date Oct. 6, 2011, 1:02 p.m.
Message ID <20111006130256.GA15890@hungry-tiger.westford.ibm.com>
Download mbox | patch
Permalink /patch/118093/
State New
Headers show

Comments

Michael Meissner - Oct. 6, 2011, 1:02 p.m.
On Tue, Oct 04, 2011 at 02:44:00PM +0200, Richard Guenther wrote:
> +/* Return the tree node for a builtin function or NULL, indexing into the
> +   array.  */
> +static inline tree
> +built_in_set_decl_add (enum built_in_function fncode, int addend)
> +{
> +  return built_in_decls ((enum built_in_function)(((int)fncode) + addend));
> +}
> 
> this doesn't seem to "set" anything.  Mistake?

Ok, I deleted the decl_add function and just fixed the places that need to do
arithmetic to do it with the appropriate casts to satisfy C++.

I also made the observation that the implicit declaration was always the same
as the explicit, so i replaced the implicit array with a bool array that says
whether the implicit function was defined.
 
> +static inline tree
> +built_in_decls (enum built_in_function fncode)
> 
> I'd prefer singular, built_in_decl () instead of plural.
> 
> +static inline tree
> +implicit_built_in_decls (enum built_in_function fncode)

For reading, the functions are now:

	built_in_decls		-> builtin_decl_explicit
	implicit_built_in_decls	-> builtin_decl_implicit

For writing, the functions are:

	built_in_decls		-> set_builtin_decl_explicit
	implicit_built_in_decls	-> set_builtin_decl_implicit

In this round I also added _p functions to say whether the function exists, so
that when lazy builtins are added, it won't force the creation of the
declaration until the function is actually used.

> Likewise.
> 
> +/* Initialize an implicit builtin function.  */
> +static inline void
> +built_in_set_implicit (enum built_in_function fncode, tree implicit)
> 
> and built_in_set_implicit_decl (or rather set_implicit_built_in_decl - hm,
> I guess I'm now bikeshedding ;)).
> 
> The patch is ok with the built_in_set_decl_add mystery resolved
> (I'd best not have the function at all but perform the ugly add and casting
> in the few callers -- it _is_ ugly to do that after all, so it might as well
> look so ;)).
> 
> It would be nice to use singular/plural consistently (different currently
> for set and get, I prefer singular).  The rest of the bikeshedding - oh well ;)

I have now done side by side bootstraps and builds with these patches.  On the
x86 (with Fedora 13), I built and tested the C, C++, Objective C, Java, Ada,
and Go languages with no regressions (and one pass since one varient of a test
took too long and failed with a timeout on the unpatched sources when I was
using the laptop to do other work as well).  On a power6 box with RHEL 6.1, I
have done the same for C, C++, Objective C, Java, and Ada languages with no
regressions.  Go doesn't build on powerpc-linux due to a missing declaration of
PthreadRegs that I need to track down.

Are these patches ok to apply?

[gcc]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* tree.h (built_in_decls): Delete old interface with two parallel
	arrays to hold standard builtin declarations, and replace it with
	a function based interface that can support creating builtins on
	the fly in the future.  Change all uses, and poison the old
	names.  Make sure 0 is not a legitimate builtin index.
	(implicit_built_in_decls): Ditto.
	(built_in_info): Ditto.
	(BUILTIN_VALID_P): Ditto.
	(builtin_decl_explicit): Ditto.
	(builtin_decl_implicit): Ditto.
	(set_builtin_decl): Ditto.
	(set_builtin_decl_implicit_p): Ditto.
	(builtin_decl_explicit_p): Ditto.
	(builtin_decl_implicit_p): Ditto.
	* tree-complex.c (expand_complex_libcall): Ditto.
	* tree-loop-distribution.c (generate_memset_zero): Ditto.
	* tree-ssa-strlen.c (get_string_length): Ditto.
	(handle_builtin_strcpy): Ditto.
	(handle_builtin_strcat): Ditto.
	* tree.c (iterative_hash_expr): Ditto.
	(local_define_builtin): Ditto.
	(build_common_builtin_nodes): Ditto.
	* builtins.c (built_in_decls): Ditto.
	(implicit_built_in_decls): Ditto.
	(built_in_info): Ditto
	(expand_builtin_classify_type): Ditto.
	(mathfn_built_in_1): Ditto.
	(expand_builtin_cexpi): Ditto.
	(expand_builtin_mempcpy_args): Ditto.
	(expand_builtin_stpcpy): Ditto.
	(gimplify_va_arg_expr): Ditto.
	(expand_builtin_sync_operation): Ditto.
	(build_builtin_expect_predicate): Ditto.
	(fold_builtin_memory_op): Ditto.
	(fold_builtin_strcpy): Ditto.
	(fold_builtin_stpcpy): Ditto.
	(fold_builtin_strncpy): Ditto.
	(fold_builtin_interclass_mathfn): Ditto.
	(fold_builtin_classify): Ditto.
	(fold_builtin_2): Ditto.
	(fold_builtin_strstr): Ditto.
	(fold_builtin_strrchr): Ditto.
	(fold_builtin_strpbrk): Ditto.
	(fold_builtin_strcat): Ditto.
	(fold_builtin_strncat): Ditto.
	(fold_builtin_strcspn): Ditto.
	(fold_builtin_fputs): Ditto.
	(fold_builtin_sprintf): Ditto.
	(fold_builtin_snprintf): Ditto.
	(expand_builtin_memory_chk): Ditto.
	(fold_builtin_memory_chk): Ditto.
	(fold_builtin_stxcpy_chk): Ditto.
	(fold_builtin_strncpy_chk): Ditto.
	(fold_builtin_strcat_chk): Ditto.
	(fold_builtin_strncat_chk): Ditto.
	(fold_builtin_sprintf_chk_1): Ditto.
	(fold_builtin_snprintf_chk_1): Ditto.
	(fold_builtin_printf): Ditto.
	(fold_builtin_fprintf): Ditto.
	(fold_call_stmt): Ditto.
	(set_builtin_user_assembler_name): Ditto.
	* tree-emutls.c (emutls_common_1): Ditto.
	* omp-low.c (scan_omp): Ditto.
	(lower_rec_input_clauses): Ditto.
	(lower_reduction_clauses): Ditto.
	(expand_parallel_call): Ditto.
	(expand_task_call): Ditto.
	(maybe_catch_exception): Ditto.
	(optimize_omp_library_calls): Ditto.
	(expand_omp_for_generic): Ditto.
	(expand_omp_for_static_nochunk): Ditto.
	(expand_omp_for_static_chunk): Ditto.
	(expand_omp_sections): Ditto.
	(expand_omp_atomic_fetch_op): Ditto.
	(expand_omp_atomic_pipeline): Ditto.
	(expand_omp_atomic_mutex): Ditto.
	(lower_omp_single_simple): Ditto.
	(lower_omp_single_copy): Ditto.
	(lower_omp_master): Ditto.
	(lower_omp_ordered): Ditto.
	(lower_omp_critical): Ditto.
	* tree-ssa-ccp.c (optimize_stdarg_builtin): Ditto.
	* builtins.c (DEF_BUILTIN_STUB): Ditto.
	(BUILT_IN_NONE): Ditto.
	* tree-ssa-math-opts.c (execute_optimize_bswap): Ditto.
	* gimple-low.c (lower_function_body): Ditto.
	(lower_builtin_setjmp): Ditto.
	* c-decl.c (merge_decls): Ditto.
	* tree-eh.c (lower_resx): Ditto.
	(lower_resx): Ditto.
	(lower_eh_dispatch): Ditto.
	* function (gimplify_parameters): Ditto.
	* c-typeck.c (build_function_call_vec): Ditto.
	* gimplify.c (build_stack_save_restore): Ditto.
	(gimplify_vla_decl): Ditto.
	(gimplify_modify_expr_to_memcpy): Ditto.
	(gimplify_modify_expr_to_memset): Ditto.
	(gimplify_variable_sized_compare): Ditto.
	(gimplify_function_tree): Ditto.
	* calls.c (emit_call_1): Ditto.
	* tree-ssa-forprop.c (simplify_builtin_call): Ditto.
	* tree-nested.c (convert_nl_goto_reference): Ditto.
	(convert_tramp_reference_op): Ditto.
	(finalize_nesting_tree_1): Ditto.
	* tree-ssa-loop-prefetch.c (issue_prefetch_ref): Ditto.
	(tree_ssa_prefetch_arrays): Ditto.
	* tree-streamer-in.c (streamer_get_builtin_tree): Ditto.
	* system.h (built_in_decls): Ditto.
	(implicit_built_in_decls): Ditto.
	* tree-vect-generic.c (expand_vector_operations_1): Ditto.
	* config/sparc/sparc.c (sparc_gimplify_va_arg): Ditto.
	* config/i386/i386.c (ix86_gimplify_va_arg): Ditto.
	(ix86_veclibabi_svml): Ditto.
	(ix86_veclibabi_acml): Ditto.
	* config/vms/vms.c (vms_patch_builtins): Ditto.
	* config/ia64/ia64.c (ia64_init_builtins): Ditto.
	* config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Ditto.
	(rs6000_builtin_vectorized_libmass): Ditto.
	(rs6000_init_builtins): Ditto.
	* config/darwin.c (darwin_override_options): Ditto.
	(darwin_patch_builtin): Ditto.
	(darwin_rename_builtins): Ditto.
	* config/pa/pa.c (pa_init_builtins): Ditto.

[gcc/c-family]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* c-common.c (def_builtin_1): Delete old interface with two
	parallel arrays to hold standard builtin declarations, and replace
	it with a function based interface that can support creating
	builtins on the fly in the future.  Change all uses, and poison
	the old	names.  Make sure 0 is not a legitimate builtin index.
	* c-omp.c (c_finish_omp_barrier): Ditto.
	(c_finish_omp_taskwait): Ditto.
	(c_finish_omp_flush): Ditto.

[gcc/java]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* class.c (build_static_field_ref): Delete old interface with two
	parallel arrays to hold standard builtin declarations, and replace
	it with a function based interface that can support creating
	builtins on the fly in the future.  Change all uses, and poison
	the old names.  Make sure 0 is not a legitimate builtin index.
	* decl.c (java_init_decl_processing): Ditto.
	* except.c (compareAndSwapLong_builtin): Ditto.
	(compareAndSwapObject_builtin): Ditto.
	(putVolatile_builtin): Ditto.
	(define_builtin): Ditto.
	(check_for_builtin): Ditto.
	* expr.c (rewrite_arglist_getcaller): Ditto.
	(expand_java_field_op): Ditto.

[gcc/objc]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* objc-next-runtime-abi-01.c (objc_build_exc_ptr): Delete old
	interface with two parallel arrays to hold standard builtin
	declarations, and replace it with a function based interface that
	can support creating builtins on the fly in the future.  Change
	all uses, and poison the old names.  Make sure 0 is not a
	legitimate builtin index.
	* objc-next-runtime-abi-02.c (objc_build_exc_ptr): Ditto.
	* objc-gnu-runtime-abi-01.c (objc_build_exc_ptr): Ditto.

[gcc/cp]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* decl.c (duplicate_decls): Delete old interface with two parallel
	arrays to hold standard builtin declarations, and replace it with
	a function based interface that can support creating builtins on
	the fly in the future.  Change all uses, and poison the old
	names.  Make sure 0 is not a legitimate builtin index.
	* except.c (build_eh_type_type): Ditto.
	(choose_personality_routine): Ditto.
	* semantics.c (finish_omp_atomic): Ditto.
	(finish_omp_barrier): Ditto.
	(finish_omp_flush): Ditto.
	(finish_omp_taskwait): Ditto.

[gcc/go]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gofrontend/gogo-tree.cc (define_builtin): Delete old interface
	with two parallel arrays to hold standard builtin declarations,
	and replace it with a function based interface that can support
	creating builtins on the fly in the future.  Change all uses, and
	poison the old names.  Make sure 0 is not a legitimate builtin
	index.
	(Gogo::make_trampoline(tree): Ditto.

[gcc/ada]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc-interface/utils.c (def_builtin_1): Delete old interface with
	two parallel arrays to hold standard builtin declarations, and
	replace it with a function based interface that can support
	creating builtins on the fly in the future.  Change all uses, and
	poison the old names.  Make sure 0 is not a legitimate builtin
	index.
	* gcc-interface/trans.c (Exception_Handler_to_gnu_zcx): Ditto.
	(gnat_to_gnu): Ditto.

[gcc/fortran]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* trans-expr.c (gfc_conv_power_op): Delete old interface with two
	parallel arrays to hold standard builtin declarations, and replace
	it with a function based interface that can support creating
	builtins on the fly in the future.  Change all uses, and poison
	the old names.  Make sure 0 is not a legitimate builtin index.
	(fill_with_spaces): Ditto.
	(gfc_trans_string_copy): Ditto.
	(gfc_trans_zero_assign): Ditto.
	(gfc_build_memcpy_call): Ditto.
	(alloc_scalar_allocatable_for_assignment): Ditto.
	* trans-array.c (gfc_trans_array_constructor_value): Ditto.
	(duplicate_allocatable): Ditto.
	(gfc_alloc_allocatable_for_assignment): Ditto.
	* trans-openmp.c (gfc_omp_clause_copy_ctor): Ditto.
	(gfc_omp_clause_assign_op): Ditto.
	(gfc_trans_omp_atomic): Ditto.
	(gfc_trans_omp_do): Ditto.
	(gfc_trans_omp_task): Ditto.
	* trans-stmt.c (gfc_trans_stop): Ditto.
	(gfc_trans_sync): Ditto.
	(gfc_trans_allocate): Ditto.
	(gfc_trans_deallocate): Ditto.
	* trans.c (gfc_call_malloc): Ditto.
	(gfc_allocate_using_malloc): Ditto.
	(gfc_call_free): Ditto.
	(gfc_deallocate_with_status): Ditto.
	(gfc_deallocate_scalar_with_status): Ditto.
	* f95-lang.c (gfc_define_builtin): Ditto.
	(gfc_init_builtin_functions): Ditto.
	* trans-decl.c (create_main_function): Ditto.
	* trans-intrinsic.c (builtin_decl_for_precision): Ditto.

[gcc/lto]
2011-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* lto-lang.c (def_builtin_1): Delete old interface with two
	parallel arrays to hold standard builtin declarations, and replace
	it with a function based interface that can support creating
	builtins on the fly in the future.  Change all uses, and poison
	the old names.  Make sure 0 is not a legitimate builtin index.
Tobias Burnus - Oct. 6, 2011, 1:23 p.m.
On 10/06/2011 03:02 PM, Michael Meissner wrote:
> On the x86 (with Fedora 13), I built and tested the C, C++, Objective C, Java, Ada,
> and Go languages with no regressions

> On a power6 box with RHEL 6.1, I
> have done the same for C, C++, Objective C, Java, and Ada languages with no
> regressions.

Any reason for not building and testing Fortran? Especially as you patch 
gcc/fortran/{trans*.c,f95-lang.c}?

Tobias

> [gcc/fortran]
> 2011-10-05  Michael Meissner<meissner@linux.vnet.ibm.com>
>
> 	* trans-expr.c (gfc_conv_power_op): Delete old interface with two
> 	parallel arrays to hold standard builtin declarations, and replace
> 	it with a function based interface that can support creating
> 	builtins on the fly in the future.  Change all uses, and poison
> 	the old names.  Make sure 0 is not a legitimate builtin index.
> 	(fill_with_spaces): Ditto.
> 	(gfc_trans_string_copy): Ditto.
> 	(gfc_trans_zero_assign): Ditto.
> 	(gfc_build_memcpy_call): Ditto.
> 	(alloc_scalar_allocatable_for_assignment): Ditto.
> 	* trans-array.c (gfc_trans_array_constructor_value): Ditto.
> 	(duplicate_allocatable): Ditto.
> 	(gfc_alloc_allocatable_for_assignment): Ditto.
> 	* trans-openmp.c (gfc_omp_clause_copy_ctor): Ditto.
> 	(gfc_omp_clause_assign_op): Ditto.
> 	(gfc_trans_omp_atomic): Ditto.
> 	(gfc_trans_omp_do): Ditto.
> 	(gfc_trans_omp_task): Ditto.
> 	* trans-stmt.c (gfc_trans_stop): Ditto.
> 	(gfc_trans_sync): Ditto.
> 	(gfc_trans_allocate): Ditto.
> 	(gfc_trans_deallocate): Ditto.
> 	* trans.c (gfc_call_malloc): Ditto.
> 	(gfc_allocate_using_malloc): Ditto.
> 	(gfc_call_free): Ditto.
> 	(gfc_deallocate_with_status): Ditto.
> 	(gfc_deallocate_scalar_with_status): Ditto.
> 	* f95-lang.c (gfc_define_builtin): Ditto.
> 	(gfc_init_builtin_functions): Ditto.
> 	* trans-decl.c (create_main_function): Ditto.
> 	* trans-intrinsic.c (builtin_decl_for_precision): Ditto.
Michael Meissner - Oct. 6, 2011, 2:44 p.m.
On Thu, Oct 06, 2011 at 03:23:07PM +0200, Tobias Burnus wrote:
> On 10/06/2011 03:02 PM, Michael Meissner wrote:
> >On the x86 (with Fedora 13), I built and tested the C, C++, Objective C, Java, Ada,
> >and Go languages with no regressions
> 
> >On a power6 box with RHEL 6.1, I
> >have done the same for C, C++, Objective C, Java, and Ada languages with no
> >regressions.
> 
> Any reason for not building and testing Fortran? Especially as you
> patch gcc/fortran/{trans*.c,f95-lang.c}?
> 
> Tobias

Brain fault on my part.  I tested the previous set of patches with Fortran.
Since I had to explicitly add the languages to pick up Ada and Go, I seemed to
have dropped Fortran.  Sigh.  Sorry about that.  I just started the powerpc
bootstrap, since that is a lot faster.

Patch

Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c	(.../trunk)	(revision 179514)
+++ gcc/tree-complex.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -956,7 +956,7 @@  expand_complex_libcall (gimple_stmt_iter
 	     (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
   else
     gcc_unreachable ();
-  fn = built_in_decls[bcode];
+  fn = builtin_decl_explicit (bcode);
 
   stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
   gimple_call_set_lhs (stmt, lhs);
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(.../trunk)	(revision 179514)
+++ gcc/c-family/c-common.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -5168,15 +5168,14 @@  def_builtin_1 (enum built_in_function fn
   decl = add_builtin_function (name, fntype, fncode, fnclass,
 			       (fallback_p ? libname : NULL),
 			       fnattrs);
+
+  set_builtin_decl (fncode, decl, implicit_p);
+
   if (both_p
       && !flag_no_builtin && !builtin_function_disabled_p (libname)
       && !(nonansi_p && flag_no_nonansi_builtin))
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
-
-  built_in_decls[(int) fncode] = decl;
-  if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
 }
 
 /* Nonzero if the type T promotes to int.  This is (nearly) the
@@ -9144,11 +9143,13 @@  resolve_overloaded_builtin (location_t l
       {
 	int n = sync_resolve_size (function, params);
 	tree new_function, first_param, result;
+	enum built_in_function fncode;
 
 	if (n == 0)
 	  return error_mark_node;
 
-	new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+	fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
+	new_function = builtin_decl_explicit (fncode);
 	if (!sync_resolve_params (function, new_function, params))
 	  return error_mark_node;
 
Index: gcc/c-family/c-omp.c
===================================================================
--- gcc/c-family/c-omp.c	(.../trunk)	(revision 179514)
+++ gcc/c-family/c-omp.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -77,7 +77,7 @@  c_finish_omp_barrier (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -91,7 +91,7 @@  c_finish_omp_taskwait (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+  x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -105,7 +105,7 @@  c_finish_omp_taskyield (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
@@ -260,7 +260,7 @@  c_finish_omp_flush (location_t loc)
 {
   tree x;
 
-  x = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+  x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   x = build_call_expr_loc (loc, x, 0);
   add_stmt (x);
 }
Index: gcc/tree-loop-distribution.c
===================================================================
--- gcc/tree-loop-distribution.c	(.../trunk)	(revision 179514)
+++ gcc/tree-loop-distribution.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -289,7 +289,7 @@  generate_memset_zero (gimple stmt, tree 
   mem = force_gimple_operand (addr_base, &stmts, true, NULL);
   gimple_seq_add_seq (&stmt_list, stmts);
 
-  fn = build_fold_addr_expr (implicit_built_in_decls [BUILT_IN_MEMSET]);
+  fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
   fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
   gimple_seq_add_stmt (&stmt_list, fn_call);
   gsi_insert_seq_after (&bsi, stmt_list, GSI_CONTINUE_LINKING);
Index: gcc/java/class.c
===================================================================
--- gcc/java/class.c	(.../trunk)	(revision 179514)
+++ gcc/java/class.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1266,7 +1266,7 @@  build_static_field_ref (tree fdecl)
       int cpool_index = alloc_constant_fieldref (output_class, fdecl);
       tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
       tree test
-        = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2,
+        = build_call_expr (builtin_decl_implicit (BUILT_IN_EXPECT), 2,
 			   build2 (EQ_EXPR, boolean_type_node,
 				   cache_entry, null_pointer_node),
 			   boolean_false_node);
Index: gcc/java/decl.c
===================================================================
--- gcc/java/decl.c	(.../trunk)	(revision 179514)
+++ gcc/java/decl.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1135,7 +1135,7 @@  java_init_decl_processing (void)
 
   initialize_builtins ();
 
-  soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
+  soft_fmod_node = builtin_decl_explicit (BUILT_IN_FMOD);
 
   parse_version ();
 }
Index: gcc/java/except.c
===================================================================
--- gcc/java/except.c	(.../trunk)	(revision 179514)
+++ gcc/java/except.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -520,8 +520,8 @@  expand_end_java_handler (struct eh_range
 	    type = throwable_type_node;
 	  eh_type = prepare_eh_table_type (type);
 
-	  x = build_call_expr (built_in_decls[BUILT_IN_EH_POINTER],
-				1, integer_zero_node);
+	  x = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
+			       1, integer_zero_node);
 	  x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
 	  tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
 
Index: gcc/java/builtins.c
===================================================================
--- gcc/java/builtins.c	(.../trunk)	(revision 179514)
+++ gcc/java/builtins.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -324,13 +324,13 @@  compareAndSwapInt_builtin (tree method_r
       || flag_use_atomic_builtins)
     {
       tree addr, stmt;
+      enum built_in_function fncode = BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4;
       UNMARSHAL5 (orig_call);
       (void) value_type; /* Avoid set but not used warning.  */
 
       addr = build_addr_sum (int_type_node, obj_arg, offset_arg);
-      stmt = build_call_expr 
-			(built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4],
-			 3, addr, expected_arg, value_arg);
+      stmt = build_call_expr (builtin_decl_explicit (fncode),
+			      3, addr, expected_arg, value_arg);
 
       return build_check_this (stmt, this_arg);
     }
@@ -351,13 +351,13 @@  compareAndSwapLong_builtin (tree method_
        but not the multi-word versions.  */
     {
       tree addr, stmt;
+      enum built_in_function fncode = BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8;
       UNMARSHAL5 (orig_call);
       (void) value_type; /* Avoid set but not used warning.  */
 
       addr = build_addr_sum (long_type_node, obj_arg, offset_arg);
-      stmt = build_call_expr 
-			(built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8],
-			 3, addr, expected_arg, value_arg);
+      stmt = build_call_expr (builtin_decl_explicit (fncode),
+			      3, addr, expected_arg, value_arg);
 
       return build_check_this (stmt, this_arg);
     }
@@ -373,7 +373,7 @@  compareAndSwapObject_builtin (tree metho
       || flag_use_atomic_builtins)
   {
     tree addr, stmt;
-    int builtin;
+    enum built_in_function builtin;
 
     UNMARSHAL5 (orig_call);
     builtin = (POINTER_SIZE == 32 
@@ -381,7 +381,7 @@  compareAndSwapObject_builtin (tree metho
 	       : BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8);
 
     addr = build_addr_sum (value_type, obj_arg, offset_arg);
-    stmt = build_call_expr (built_in_decls[builtin],
+    stmt = build_call_expr (builtin_decl_explicit (builtin),
 			    3, addr, expected_arg, value_arg);
 
     return build_check_this (stmt, this_arg);
@@ -401,7 +401,7 @@  putVolatile_builtin (tree method_return_
     = fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)),
 		    addr);
   
-  stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
+  stmt = build_call_expr (builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE), 0);
   modify_stmt = fold_build2 (MODIFY_EXPR, value_type,
 			     build_java_indirect_ref (value_type, addr,
 						      flag_check_references),
@@ -425,8 +425,7 @@  getVolatile_builtin (tree method_return_
     = fold_convert (build_pointer_type (build_type_variant 
 					(method_return_type, 0, 1)), addr);
   
-  stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
-  
+  stmt = build_call_expr (builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE), 0);
   tmp = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL, method_return_type);
   DECL_IGNORED_P (tmp) = 1;
   DECL_ARTIFICIAL (tmp) = 1;
@@ -483,8 +482,7 @@  define_builtin (enum built_in_function v
   if (flags & BUILTIN_CONST)
     TREE_READONLY (decl) = 1;
 
-  implicit_built_in_decls[val] = decl;
-  built_in_decls[val] = decl;
+  set_builtin_decl (val, decl, true);
 }
 
 
@@ -627,7 +625,7 @@  check_for_builtin (tree method, tree cal
 	         with the BC-ABI.  */
 	      if (flag_indirect_dispatch)
 	        return call;
-	      fn = built_in_decls[java_builtins[i].builtin_code];
+	      fn = builtin_decl_explicit (java_builtins[i].builtin_code);
 	      if (fn == NULL_TREE)
 		return call;
 	      return java_build_function_call_expr (fn, call);
Index: gcc/java/expr.c
===================================================================
--- gcc/java/expr.c	(.../trunk)	(revision 179514)
+++ gcc/java/expr.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2073,7 +2073,7 @@  static void
 rewrite_arglist_getcaller (VEC(tree,gc) **arglist)
 {
   tree retaddr 
-    = build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS],
+    = build_call_expr (builtin_decl_explicit (BUILT_IN_RETURN_ADDRESS),
 		       1, integer_zero_node);
 
   DECL_UNINLINABLE (current_function_decl) = 1;
@@ -2933,8 +2933,10 @@  expand_java_field_op (int is_static, int
 			    field_ref, new_value);
 
       if (TREE_THIS_VOLATILE (field_decl))
-	java_add_stmt
-	  (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+	{
+	  tree sync = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
+	  java_add_stmt (build_call_expr (sync, 0));
+	}
       	  
       java_add_stmt (modify_expr);
     }
@@ -2952,8 +2954,10 @@  expand_java_field_op (int is_static, int
       java_add_stmt (modify_expr);
 
       if (TREE_THIS_VOLATILE (field_decl))
-	java_add_stmt 
-	  (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+	{
+	  tree sync = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
+	  java_add_stmt (build_call_expr (sync, 0));
+	}
 
       push_value (temp);
     }      
Index: gcc/tree-ssa-strlen.c
===================================================================
--- gcc/tree-ssa-strlen.c	(.../trunk)	(revision 179514)
+++ gcc/tree-ssa-strlen.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -397,7 +397,7 @@  get_string_length (strinfo si)
       callee = gimple_call_fndecl (stmt);
       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
       lhs = gimple_call_lhs (stmt);
-      gcc_assert (implicit_built_in_decls[BUILT_IN_STRCPY] != NULL_TREE);
+      gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY));
       /* unshare_strinfo is intentionally not called here.  The (delayed)
 	 transformation of strcpy or strcat into stpcpy is done at the place
 	 of the former strcpy/strcat call and so can affect all the strinfos
@@ -409,7 +409,7 @@  get_string_length (strinfo si)
 	case BUILT_IN_STRCAT:
 	case BUILT_IN_STRCAT_CHK:
 	  gsi = gsi_for_stmt (stmt);
-	  fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+	  fn = builtin_decl_implicit (BUILT_IN_STRLEN);
 	  gcc_assert (lhs == NULL_TREE);
 	  lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
 	  add_referenced_var (lhs_var);
@@ -434,9 +434,9 @@  get_string_length (strinfo si)
 	case BUILT_IN_STRCPY:
 	case BUILT_IN_STRCPY_CHK:
 	  if (gimple_call_num_args (stmt) == 2)
-	    fn = implicit_built_in_decls[BUILT_IN_STPCPY];
+	    fn = builtin_decl_implicit (BUILT_IN_STPCPY);
 	  else
-	    fn = built_in_decls[BUILT_IN_STPCPY_CHK];
+	    fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
 	  gcc_assert (lhs == NULL_TREE);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
@@ -1066,8 +1066,7 @@  handle_builtin_strcpy (enum built_in_fun
       {
       case BUILT_IN_STRCPY:
       case BUILT_IN_STRCPY_CHK:
-	if (implicit_built_in_decls[BUILT_IN_STPCPY] == NULL_TREE
-	    || lhs != NULL_TREE)
+	if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
 	  return;
 	break;
       case BUILT_IN_STPCPY:
@@ -1150,12 +1149,12 @@  handle_builtin_strcpy (enum built_in_fun
   switch (bcode)
     {
     case BUILT_IN_STRCPY:
-      fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       if (lhs)
 	VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
     case BUILT_IN_STRCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+      fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
       if (lhs)
 	VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
@@ -1163,7 +1162,7 @@  handle_builtin_strcpy (enum built_in_fun
       /* This would need adjustment of the lhs (subtract one),
 	 or detection that the trailing '\0' doesn't need to be
 	 written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY];  */
+      fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);  */
       if (lhs)
 	{
 	  dsi->endptr = lhs;
@@ -1174,7 +1173,7 @@  handle_builtin_strcpy (enum built_in_fun
       /* This would need adjustment of the lhs (subtract one),
 	 or detection that the trailing '\0' doesn't need to be
 	 written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY_CHK];  */
+      fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK);  */
       if (lhs)
 	{
 	  dsi->endptr = lhs;
@@ -1396,8 +1395,7 @@  handle_builtin_strcat (enum built_in_fun
 	 with length endptr - p if we need to compute the length
 	 later on.  Don't do this transformation if we don't need
 	 it.  */
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
-	  && lhs == NULL_TREE)
+      if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
 	{
 	  if (didx == 0)
 	    {
@@ -1456,8 +1454,7 @@  handle_builtin_strcat (enum built_in_fun
   else
     {
       dsi->length = NULL;
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
-	  && lhs == NULL_TREE)
+      if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
 	dsi->dont_invalidate = true;
     }
 
@@ -1477,15 +1474,15 @@  handle_builtin_strcat (enum built_in_fun
     {
     case BUILT_IN_STRCAT:
       if (srclen != NULL_TREE)
-	fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       else
-	fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	fn = builtin_decl_implicit (BUILT_IN_STRCPY);
       break;
     case BUILT_IN_STRCAT_CHK:
       if (srclen != NULL_TREE)
-	fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
       else
-	fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+	fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
       objsz = gimple_call_arg (stmt, 2);
       break;
     default:
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(.../trunk)	(revision 179514)
+++ gcc/tree.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -4656,10 +4656,9 @@  free_lang_data_in_decl (tree decl)
            && DECL_INITIAL (decl)
            && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
     {
-      /* Strip builtins from the translation-unit BLOCK.  We still have
-	 targets without builtin_decl support and also builtins are
-	 shared nodes and thus we can't use TREE_CHAIN in multiple
-	 lists.  */
+      /* Strip builtins from the translation-unit BLOCK.  We still have targets
+	 without builtin_decl_explicit support and also builtins are shared
+	 nodes and thus we can't use TREE_CHAIN in multiple lists.  */
       tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
       while (*nextp)
         {
@@ -6942,9 +6941,9 @@  iterative_hash_expr (const_tree t, hashv
 	 or front end builtins, since the function code is overloaded in those
 	 cases.  */
       if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
-	  && built_in_decls[DECL_FUNCTION_CODE (t)])
+	  && builtin_decl_explicit_p (DECL_FUNCTION_CODE (t)))
 	{
-	  t = built_in_decls[DECL_FUNCTION_CODE (t)];
+	  t = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
 	  code = TREE_CODE (t);
 	}
       /* FALL THROUGH */
@@ -9429,8 +9428,7 @@  local_define_builtin (const char *name, 
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
 					NULL, DECL_ATTRIBUTES (decl));
 
-  built_in_decls[code] = decl;
-  implicit_built_in_decls[code] = decl;
+  set_builtin_decl (code, decl, true);
 }
 
 /* Call this function after instantiating all builtins that the language
@@ -9442,22 +9440,22 @@  build_common_builtin_nodes (void)
 {
   tree tmp, ftype;
 
-  if (built_in_decls[BUILT_IN_MEMCPY] == NULL
-      || built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+  if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
+      || !builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
     {
       ftype = build_function_type_list (ptr_type_node,
 					ptr_type_node, const_ptr_type_node,
 					size_type_node, NULL_TREE);
 
-      if (built_in_decls[BUILT_IN_MEMCPY] == NULL)
+      if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
 	local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
 			      "memcpy", ECF_NOTHROW | ECF_LEAF);
-      if (built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+      if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
 	local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
 			      "memmove", ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_MEMCMP] == NULL)
+  if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
     {
       ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
 					const_ptr_type_node, size_type_node,
@@ -9466,7 +9464,7 @@  build_common_builtin_nodes (void)
 			    "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_MEMSET] == NULL)
+  if (!builtin_decl_explicit_p (BUILT_IN_MEMSET))
     {
       ftype = build_function_type_list (ptr_type_node,
 					ptr_type_node, integer_type_node,
@@ -9475,7 +9473,7 @@  build_common_builtin_nodes (void)
 			    "memset", ECF_NOTHROW | ECF_LEAF);
     }
 
-  if (built_in_decls[BUILT_IN_ALLOCA] == NULL)
+  if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
     {
       ftype = build_function_type_list (ptr_type_node,
 					size_type_node, NULL_TREE);
@@ -9485,7 +9483,7 @@  build_common_builtin_nodes (void)
 
   /* If we're checking the stack, `alloca' can throw.  */
   if (flag_stack_check)
-    TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+    TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA)) = 0;
 
   ftype = build_function_type_list (void_type_node,
 				    ptr_type_node, ptr_type_node,
@@ -9551,7 +9549,7 @@  build_common_builtin_nodes (void)
 			 ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
 			ECF_NORETURN);
 
-  if (built_in_decls[BUILT_IN_RETURN_ADDRESS] == NULL_TREE)
+  if (builtin_decl_explicit (BUILT_IN_RETURN_ADDRESS) == NULL_TREE)
     {
       ftype = build_function_type_list (ptr_type_node, integer_type_node,
 					NULL_TREE);
@@ -9561,16 +9559,16 @@  build_common_builtin_nodes (void)
 			    ECF_NOTHROW);
     }
 
-  if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE
-      || built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+  if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER)
+      || !builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
     {
       ftype = build_function_type_list (void_type_node, ptr_type_node,
 					ptr_type_node, NULL_TREE);
-      if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE)
+      if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER))
 	local_define_builtin ("__cyg_profile_func_enter", ftype,
 			      BUILT_IN_PROFILE_FUNC_ENTER,
 			      "__cyg_profile_func_enter", 0);
-      if (built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+      if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
 	local_define_builtin ("__cyg_profile_func_exit", ftype,
 			      BUILT_IN_PROFILE_FUNC_EXIT,
 			      "__cyg_profile_func_exit", 0);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(.../trunk)	(revision 179514)
+++ gcc/tree.h	(.../branches/ibm/builtin)	(revision 179582)
@@ -335,10 +335,6 @@  extern const char * built_in_names[(int)
 #define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L
 #define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
 #define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL
-
-/* An array of _DECL trees for the above.  */
-extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
-extern GTY(()) tree implicit_built_in_decls[(int) END_BUILTINS];
 
 /* In an OMP_CLAUSE node.  */
 
@@ -5916,4 +5912,94 @@  is_lang_specific (tree t)
 /* In gimple-low.c.  */
 extern bool block_may_fallthru (const_tree);
 
+
+/* Functional interface to the builtin functions.  */
+
+/* The builtin_info structure holds the FUNCTION_DECL of the standard builtin
+   function, and a flag that says if the function is available implicitly, or
+   whether the user has to code explicit calls to __builtin_<xxx>.  */
+
+typedef struct GTY(()) builtin_info_type_d {
+  tree decl[(int)END_BUILTINS];
+  bool implicit_p[(int)END_BUILTINS];
+} builtin_info_type;
+
+extern GTY(()) builtin_info_type builtin_info;
+
+/* Valid builtin number.  */
+#define BUILTIN_VALID_P(FNCODE) \
+  (IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
+
+/* Return the tree node for an explicit standard builtin function or NULL.  */
+static inline tree
+builtin_decl_explicit (enum built_in_function fncode)
+{
+  gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+  return builtin_info.decl[(size_t)fncode];
+}
+
+/* Return the tree node for an implicit builtin function or NULL.  */
+static inline tree
+builtin_decl_implicit (enum built_in_function fncode)
+{
+  size_t uns_fncode = (size_t)fncode;
+  gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+  if (!builtin_info.implicit_p[uns_fncode])
+    return NULL_TREE;
+
+  return builtin_info.decl[uns_fncode];
+}
+
+/* Set explicit builtin function nodes and whether it is an implicit
+   function.  */
+
+static inline void
+set_builtin_decl (enum built_in_function fncode, tree decl, bool implicit_p)
+{
+  size_t ufncode = (size_t)fncode;
+
+  gcc_checking_assert (BUILTIN_VALID_P (fncode)
+		       && (decl != NULL_TREE || !implicit_p));
+
+  builtin_info.decl[ufncode] = decl;
+  builtin_info.implicit_p[ufncode] = implicit_p;
+}
+
+/* Set the implicit flag for a builtin function.  */
+
+static inline void
+set_builtin_decl_implicit_p (enum built_in_function fncode, bool implicit_p)
+{
+  size_t uns_fncode = (size_t)fncode;
+
+  gcc_checking_assert (BUILTIN_VALID_P (fncode)
+		       && builtin_info.decl[uns_fncode] != NULL_TREE);
+
+  builtin_info.implicit_p[uns_fncode] = implicit_p;
+}
+
+/* Return whether the standard builtin function can be used as an explicit
+   function.  */
+
+static inline bool
+builtin_decl_explicit_p (enum built_in_function fncode)
+{
+  gcc_checking_assert (BUILTIN_VALID_P (fncode));
+  return (builtin_info.decl[(size_t)fncode] != NULL_TREE);
+}
+
+/* Return whether the standard builtin function can be used implicitly.  */
+
+static inline bool
+builtin_decl_implicit_p (enum built_in_function fncode)
+{
+  size_t uns_fncode = (size_t)fncode;
+
+  gcc_checking_assert (BUILTIN_VALID_P (fncode));
+  return (builtin_info.decl[uns_fncode] != NULL_TREE
+	  && builtin_info.implicit_p[uns_fncode]);
+}
+
 #endif  /* GCC_TREE_H  */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(.../trunk)	(revision 179514)
+++ gcc/builtins.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -75,11 +75,7 @@  const char * built_in_names[(int) END_BU
 
 /* Setup an array of _DECL trees, make sure each element is
    initialized to NULL_TREE.  */
-tree built_in_decls[(int) END_BUILTINS];
-/* Declarations used when constructing the builtin implicitly in the compiler.
-   It may be NULL_TREE when this is invalid (for instance runtime is not
-   required to implement the function call in all cases).  */
-tree implicit_built_in_decls[(int) END_BUILTINS];
+builtin_info_type builtin_info;
 
 static const char *c_getstr (tree);
 static rtx c_readstr (const char *, enum machine_mode);
@@ -1791,17 +1787,15 @@  expand_builtin_classify_type (tree exp)
   fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
   fcodel = BUILT_IN_MATHFN##L_R ; break;
 
-/* Return mathematic function equivalent to FN but operating directly
-   on TYPE, if available.  If IMPLICIT is true find the function in
-   implicit_built_in_decls[], otherwise use built_in_decls[].  If we
-   can't do the conversion, return zero.  */
+/* Return mathematic function equivalent to FN but operating directly on TYPE,
+   if available.  If IMPLICIT is true use the implicit builtin declaration,
+   otherwise use the explicit declaration.  If we can't do the conversion,
+   return zero.  */
 
 static tree
-mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
+mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
 {
-  tree const *const fn_arr
-    = implicit ? implicit_built_in_decls : built_in_decls;
-  enum built_in_function fcode, fcodef, fcodel;
+  enum built_in_function fcode, fcodef, fcodel, fcode2;
 
   switch (fn)
     {
@@ -1898,13 +1892,18 @@  mathfn_built_in_1 (tree type, enum built
       }
 
   if (TYPE_MAIN_VARIANT (type) == double_type_node)
-    return fn_arr[fcode];
+    fcode2 = fcode;
   else if (TYPE_MAIN_VARIANT (type) == float_type_node)
-    return fn_arr[fcodef];
+    fcode2 = fcodef;
   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
-    return fn_arr[fcodel];
+    fcode2 = fcodel;
   else
     return NULL_TREE;
+
+  if (implicit_p && !builtin_decl_implicit_p (fcode2))
+    return NULL_TREE;
+
+  return builtin_decl_explicit (fcode2);
 }
 
 /* Like mathfn_built_in_1(), but always use the implicit array.  */
@@ -2554,11 +2553,11 @@  expand_builtin_cexpi (tree exp, rtx targ
       rtx op1a, op2a;
 
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
-	fn = built_in_decls[BUILT_IN_SINCOSF];
+	fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
-	fn = built_in_decls[BUILT_IN_SINCOS];
+	fn = builtin_decl_explicit (BUILT_IN_SINCOS);
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
-	fn = built_in_decls[BUILT_IN_SINCOSL];
+	fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
       else
 	gcc_unreachable ();
 
@@ -2580,11 +2579,11 @@  expand_builtin_cexpi (tree exp, rtx targ
       tree ctype = build_complex_type (type);
 
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
-	fn = built_in_decls[BUILT_IN_CEXPF];
+	fn = builtin_decl_explicit (BUILT_IN_CEXPF);
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
-	fn = built_in_decls[BUILT_IN_CEXP];
+	fn = builtin_decl_explicit (BUILT_IN_CEXP);
       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
-	fn = built_in_decls[BUILT_IN_CEXPL];
+	fn = builtin_decl_explicit (BUILT_IN_CEXPL);
       else
 	gcc_unreachable ();
 
@@ -3129,9 +3128,9 @@  expand_builtin_mempcpy_args (tree dest, 
 			     rtx target, enum machine_mode mode, int endp)
 {
     /* If return value is ignored, transform mempcpy into memcpy.  */
-  if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
+  if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
 					   dest, src, len);
       return expand_expr (result, target, mode, EXPAND_NORMAL);
@@ -3292,9 +3291,9 @@  expand_builtin_stpcpy (tree exp, rtx tar
   src = CALL_EXPR_ARG (exp, 1);
 
   /* If return value is ignored, transform stpcpy into strcpy.  */
-  if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
+  if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
       return expand_expr (result, target, mode, EXPAND_NORMAL);
     }
@@ -4353,7 +4352,7 @@  gimplify_va_arg_expr (tree *expr_p, gimp
 	 expression to exit or longjmp.  */
       gimplify_and_add (valist, pre_p);
       t = build_call_expr_loc (loc,
-			       implicit_built_in_decls[BUILT_IN_TRAP], 0);
+			       builtin_decl_implicit (BUILT_IN_TRAP), 0);
       gimplify_and_add (t, pre_p);
 
       /* This is dead code, but go ahead and finish so that the
@@ -5113,7 +5112,7 @@  expand_builtin_sync_operation (enum mach
 	  if (warned_f_a_n)
 	    break;
 
-	  fndecl = implicit_built_in_decls[BUILT_IN_SYNC_FETCH_AND_NAND_N];
+	  fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
 	  warned_f_a_n = true;
 	  break;
@@ -5127,7 +5126,7 @@  expand_builtin_sync_operation (enum mach
 	  if (warned_n_a_f)
 	    break;
 
-	  fndecl = implicit_built_in_decls[BUILT_IN_SYNC_NAND_AND_FETCH_N];
+	 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
 	  inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
 	  warned_n_a_f = true;
 	  break;
@@ -6232,7 +6231,7 @@  build_builtin_expect_predicate (location
 {
   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
 
-  fn = built_in_decls[BUILT_IN_EXPECT];
+  fn = builtin_decl_explicit (BUILT_IN_EXPECT);
   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
   ret_type = TREE_TYPE (TREE_TYPE (fn));
   pred_type = TREE_VALUE (arg_types);
@@ -8024,7 +8023,7 @@  fold_builtin_memory_op (location_t loc, 
 		  && (MIN (src_align, dest_align) / BITS_PER_UNIT
 		      >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
 	    {
-	      tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	      tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
 	      if (!fn)
 		return NULL_TREE;
               return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8083,7 +8082,7 @@  fold_builtin_memory_op (location_t loc, 
 	      else
 		return NULL_TREE;
 
-	      fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+	      fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
 	      if (!fn)
 		return NULL_TREE;
 	      return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8102,7 +8101,7 @@  fold_builtin_memory_op (location_t loc, 
 	      if (!refs_may_alias_p_1 (&destr, &srcr, false))
 		{
 		  tree fn;
-		  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+		  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
 		  if (!fn)
 		    return NULL_TREE;
 		  return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8277,7 +8276,7 @@  fold_builtin_strcpy (location_t loc, tre
   if (optimize_function_for_size_p (cfun))
     return NULL_TREE;
 
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -8316,7 +8315,7 @@  fold_builtin_stpcpy (location_t loc, tre
       && !integer_zerop (len))
     return NULL_TREE;
 
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -8375,7 +8374,7 @@  fold_builtin_strncpy (location_t loc, tr
     return NULL_TREE;
 
   /* OK transform into builtin memcpy.  */
-  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -9198,7 +9197,7 @@  fold_builtin_interclass_mathfn (location
     CASE_FLT_FN (BUILT_IN_ISINF):
       {
 	/* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
-	tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
+	tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE r;
 	char buf[128];
@@ -9214,7 +9213,7 @@  fold_builtin_interclass_mathfn (location
     case BUILT_IN_ISFINITE:
       {
 	/* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
-	tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+	tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE r;
 	char buf[128];
@@ -9237,8 +9236,8 @@  fold_builtin_interclass_mathfn (location
       {
 	/* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
 	   islessequal(fabs(x),DBL_MAX).  */
-	tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
-	tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
+	tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
+	tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
 	tree const type = TREE_TYPE (arg);
 	REAL_VALUE_TYPE rmax, rmin;
 	char buf[128];
@@ -9299,7 +9298,7 @@  fold_builtin_classify (location_t loc, t
 	   1.  So e.g. "if (isinf_sign(x))" would be folded to just
 	   "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
 	tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
-	tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
+	tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
 	tree tmp = NULL_TREE;
 
 	arg = builtin_save_expr (arg);
@@ -10022,7 +10021,7 @@  fold_builtin_2 (location_t loc, tree fnd
     case BUILT_IN_STPCPY:
       if (ignore)
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	  tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
 	  if (!fn)
 	    break;
 
@@ -10822,7 +10821,7 @@  fold_builtin_strstr (location_t loc, tre
       if (p2[1] != '\0')
 	return NULL_TREE;
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = builtin_decl_implicit (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -10942,7 +10941,7 @@  fold_builtin_strrchr (location_t loc, tr
       if (! integer_zerop (s2))
 	return NULL_TREE;
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = builtin_decl_implicit (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -11006,7 +11005,7 @@  fold_builtin_strpbrk (location_t loc, tr
       if (p2[1] != '\0')
 	return NULL_TREE;  /* Really call strpbrk.  */
 
-      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+      fn = builtin_decl_implicit (BUILT_IN_STRCHR);
       if (!fn)
 	return NULL_TREE;
 
@@ -11053,8 +11052,8 @@  fold_builtin_strcat (location_t loc ATTR
 	{
 	  /* See if we can store by pieces into (dst + strlen(dst)).  */
 	  tree newdst, call;
-	  tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
-	  tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+	  tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
+	  tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
 
 	  if (!strlen_fn || !strcpy_fn)
 	    return NULL_TREE;
@@ -11127,7 +11126,7 @@  fold_builtin_strncat (location_t loc, tr
       if (TREE_CODE (len) == INTEGER_CST && p
 	  && compare_tree_int (len, strlen (p)) >= 0)
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
+	  tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
 
 	  /* If the replacement _DECL isn't initialized, don't do the
 	     transformation.  */
@@ -11232,7 +11231,7 @@  fold_builtin_strcspn (location_t loc, tr
       /* If the second argument is "", return __builtin_strlen(s1).  */
       if (p2 && *p2 == '\0')
 	{
-	  tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+	  tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
 
 	  /* If the replacement _DECL isn't initialized, don't do the
 	     transformation.  */
@@ -11258,10 +11257,12 @@  fold_builtin_fputs (location_t loc, tree
 {
   /* If we're using an unlocked function, assume the other unlocked
      functions exist explicitly.  */
-  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
-    : implicit_built_in_decls[BUILT_IN_FPUTC];
-  tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
-    : implicit_built_in_decls[BUILT_IN_FWRITE];
+  tree const fn_fputc = (unlocked
+			 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
+			 : builtin_decl_implicit (BUILT_IN_FPUTC));
+  tree const fn_fwrite = (unlocked
+			  ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
+			  : builtin_decl_implicit (BUILT_IN_FWRITE));
 
   /* If the return value is used, don't do the transformation.  */
   if (!ignore)
@@ -11455,7 +11456,7 @@  fold_builtin_sprintf (location_t loc, tr
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
 
       if (!fn)
 	return NULL_TREE;
@@ -11475,7 +11476,7 @@  fold_builtin_sprintf (location_t loc, tr
   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
     {
       tree fn;
-      fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      fn = builtin_decl_implicit (BUILT_IN_STRCPY);
 
       if (!fn)
 	return NULL_TREE;
@@ -11497,7 +11498,7 @@  fold_builtin_sprintf (location_t loc, tr
   if (call && retval)
     {
       retval = fold_convert_loc
-	(loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
+	(loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
 	 retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
     }
@@ -11550,7 +11551,7 @@  fold_builtin_snprintf (location_t loc, t
   /* If the format doesn't contain % args or %%, use strcpy.  */
   if (strchr (fmt_str, target_percent) == NULL)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
       size_t len = strlen (fmt_str);
 
       /* Don't optimize snprintf (buf, 4, "abc", ptr++).  */
@@ -11582,7 +11583,7 @@  fold_builtin_snprintf (location_t loc, t
   /* If the format is "%s", use strcpy if the result isn't used.  */
   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
     {
-      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+      tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
       unsigned HOST_WIDE_INT origlen;
 
       /* Don't crash on snprintf (str1, cst, "%s").  */
@@ -11617,7 +11618,7 @@  fold_builtin_snprintf (location_t loc, t
 
   if (call && retval)
     {
-      tree fn = built_in_decls[BUILT_IN_SNPRINTF];
+      tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
       retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
     }
@@ -11705,16 +11706,16 @@  expand_builtin_memory_chk (tree exp, rtx
       switch (fcode)
 	{
 	case BUILT_IN_MEMCPY_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMCPY];
+	  fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
 	  break;
 	case BUILT_IN_MEMPCPY_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMPCPY];
+	  fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
 	  break;
 	case BUILT_IN_MEMMOVE_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMMOVE];
+	  fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
 	  break;
 	case BUILT_IN_MEMSET_CHK:
-	  fn = built_in_decls[BUILT_IN_MEMSET];
+	  fn = builtin_decl_explicit (BUILT_IN_MEMSET);
 	  break;
 	default:
 	  break;
@@ -11766,7 +11767,7 @@  expand_builtin_memory_chk (tree exp, rtx
 	     normal __memcpy_chk.  */
 	  if (readonly_data_expr (src))
 	    {
-	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	      tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
 	      if (!fn)
 		return NULL_RTX;
 	      fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
@@ -12030,7 +12031,7 @@  fold_builtin_memory_chk (location_t loc,
 		{
 		  /* (void) __mempcpy_chk () can be optimized into
 		     (void) __memcpy_chk ().  */
-		  fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+		  fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
 		  if (!fn)
 		    return NULL_TREE;
 
@@ -12052,16 +12053,16 @@  fold_builtin_memory_chk (location_t loc,
   switch (fcode)
     {
     case BUILT_IN_MEMCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMCPY];
+      fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
       break;
     case BUILT_IN_MEMPCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMPCPY];
+      fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
       break;
     case BUILT_IN_MEMMOVE_CHK:
-      fn = built_in_decls[BUILT_IN_MEMMOVE];
+      fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
       break;
     case BUILT_IN_MEMSET_CHK:
-      fn = built_in_decls[BUILT_IN_MEMSET];
+      fn = builtin_decl_explicit (BUILT_IN_MEMSET);
       break;
     default:
       break;
@@ -12116,7 +12117,7 @@  fold_builtin_stxcpy_chk (location_t loc,
 
 		  /* If return value of __stpcpy_chk is ignored,
 		     optimize into __strcpy_chk.  */
-		  fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+		  fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
 		  if (!fn)
 		    return NULL_TREE;
 
@@ -12128,7 +12129,7 @@  fold_builtin_stxcpy_chk (location_t loc,
 
 	      /* If c_strlen returned something, but not a constant,
 		 transform __strcpy_chk into __memcpy_chk.  */
-	      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+	      fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
 	      if (!fn)
 		return NULL_TREE;
 
@@ -12148,8 +12149,8 @@  fold_builtin_stxcpy_chk (location_t loc,
     }
 
   /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
-  fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
-		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
+  fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
+			      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -12193,7 +12194,7 @@  fold_builtin_strncpy_chk (location_t loc
     }
 
   /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
-  fn = built_in_decls[BUILT_IN_STRNCPY];
+  fn = builtin_decl_explicit (BUILT_IN_STRNCPY);
   if (!fn)
     return NULL_TREE;
 
@@ -12224,7 +12225,7 @@  fold_builtin_strcat_chk (location_t loc,
     return NULL_TREE;
 
   /* If __builtin_strcat_chk is used, assume strcat is available.  */
-  fn = built_in_decls[BUILT_IN_STRCAT];
+  fn = builtin_decl_explicit (BUILT_IN_STRCAT);
   if (!fn)
     return NULL_TREE;
 
@@ -12266,7 +12267,7 @@  fold_builtin_strncat_chk (location_t loc
 	  && ! tree_int_cst_lt (len, src_len))
 	{
 	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
-	  fn = built_in_decls[BUILT_IN_STRCAT_CHK];
+	  fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
 	  if (!fn)
 	    return NULL_TREE;
 
@@ -12276,7 +12277,7 @@  fold_builtin_strncat_chk (location_t loc
     }
 
   /* If __builtin_strncat_chk is used, assume strncat is available.  */
-  fn = built_in_decls[BUILT_IN_STRNCAT];
+  fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
   if (!fn)
     return NULL_TREE;
 
@@ -12367,8 +12368,8 @@  fold_builtin_sprintf_chk_1 (location_t l
     }
 
   /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
-  fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
-		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
+  fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
+			      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
   if (!fn)
     return NULL_TREE;
 
@@ -12456,8 +12457,8 @@  fold_builtin_snprintf_chk_1 (location_t 
 
   /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
      available.  */
-  fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
-		      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
+  fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
+			      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
   if (!fn)
     return NULL_TREE;
 
@@ -12511,13 +12512,13 @@  fold_builtin_printf (location_t loc, tre
     {
       /* If we're using an unlocked function, assume the other
 	 unlocked functions exist explicitly.  */
-      fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
-      fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
+      fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
+      fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
     }
   else
     {
-      fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
-      fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
+      fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
+      fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
     }
 
   if (!init_target_chars ())
@@ -12662,13 +12663,13 @@  fold_builtin_fprintf (location_t loc, tr
     {
       /* If we're using an unlocked function, assume the other
 	 unlocked functions exist explicitly.  */
-      fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
-      fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
+      fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
+      fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
     }
   else
     {
-      fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
-      fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
+      fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
+      fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
     }
 
   if (!init_target_chars ())
@@ -13470,7 +13471,7 @@  fold_call_stmt (gimple stmt, bool ignore
   return NULL_TREE;
 }
 
-/* Look up the function in built_in_decls that corresponds to DECL
+/* Look up the function in builtin_decl that corresponds to DECL
    and set ASMSPEC as its user assembler name.  DECL must be a
    function decl that declares a builtin.  */
 
@@ -13482,8 +13483,9 @@  set_builtin_user_assembler_name (tree de
 	      && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
 	      && asmspec != 0);
 
-  builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
-  set_user_assembler_name (builtin, asmspec);
+  builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
+  set_user_assembler_name (
+builtin, asmspec);
   switch (DECL_FUNCTION_CODE (decl))
     {
     case BUILT_IN_MEMCPY:
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(.../trunk)	(revision 179514)
+++ gcc/tree-emutls.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -387,8 +387,8 @@  emutls_common_1 (tree tls_decl, tree con
 
   word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
 
-  x = build_call_expr (built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON], 4,
-		       build_fold_addr_expr (control_decl),
+  x = build_call_expr (builtin_decl_explicit (BUILT_IN_EMUTLS_REGISTER_COMMON),
+		       4, build_fold_addr_expr (control_decl),
 		       fold_convert (word_type_node,
 				     DECL_SIZE_UNIT (tls_decl)),
 		       build_int_cst (word_type_node,
@@ -622,7 +622,7 @@  lower_emutls_function_body (struct cgrap
   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 
   d.cfun_node = node;
-  d.builtin_decl = built_in_decls[BUILT_IN_EMUTLS_GET_ADDRESS];
+  d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS);
   /* This is where we introduce the declaration to the IL and so we have to
      create a node for it.  */
   d.builtin_node = cgraph_get_create_node (d.builtin_decl);
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	(.../trunk)	(revision 179514)
+++ gcc/omp-low.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2059,7 +2059,7 @@  scan_omp (gimple_seq body, omp_context *
 static tree
 build_omp_barrier (void)
 {
-  return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
 }
 
 /* If a context was created for STMT when it was scanned, return it.  */
@@ -2300,7 +2300,7 @@  lower_rec_input_clauses (tree clauses, g
 	      if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
 		{
 		  gimple stmt;
-		  tree tmp;
+		  tree tmp, atmp;
 
 		  ptr = DECL_VALUE_EXPR (new_var);
 		  gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
@@ -2309,8 +2309,8 @@  lower_rec_input_clauses (tree clauses, g
 		  x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
 
 		  /* void *tmp = __builtin_alloca */
-		  stmt
-		    = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x);
+		  atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+		  stmt = gimple_build_call (atmp, 1, x);
 		  tmp = create_tmp_var_raw (ptr_type_node, NULL);
 		  gimple_add_tmp_var (tmp);
 		  gimple_call_set_lhs (stmt, tmp);
@@ -2354,8 +2354,8 @@  lower_rec_input_clauses (tree clauses, g
 		}
 	      else
 		{
-		  x = build_call_expr_loc (clause_loc,
-				       built_in_decls[BUILT_IN_ALLOCA], 1, x);
+		  tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+		  x = build_call_expr_loc (clause_loc, atmp, 1, x);
 		}
 
 	      x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
@@ -2493,7 +2493,8 @@  lower_rec_input_clauses (tree clauses, g
      but it certainly is to C++ operator=.  */
   if (copyin_seq)
     {
-      x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+      x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
+			   0);
       x = build2 (NE_EXPR, boolean_type_node, x,
 		  build_int_cst (TREE_TYPE (x), 0));
       x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
@@ -2688,12 +2689,14 @@  lower_reduction_clauses (tree clauses, g
 	}
     }
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
+			    0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 
   gimple_seq_add_seq (stmt_seqp, sub_seq);
 
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
+			    0);
   gimple_seq_add_stmt (stmt_seqp, stmt);
 }
 
@@ -2917,7 +2920,8 @@  expand_parallel_call (struct omp_region 
   tree t, t1, t2, val, cond, c, clauses;
   gimple_stmt_iterator gsi;
   gimple stmt;
-  int start_ix;
+  enum built_in_function start_ix;
+  int start_ix2;
   location_t clause_loc;
   VEC(tree,gc) *args;
 
@@ -2932,10 +2936,11 @@  expand_parallel_call (struct omp_region 
 	{
 	case GIMPLE_OMP_FOR:
 	  gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
-	  start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
-		     + (region->inner->sched_kind
-			== OMP_CLAUSE_SCHEDULE_RUNTIME
-			? 3 : region->inner->sched_kind);
+	  start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
+		       + (region->inner->sched_kind
+			  == OMP_CLAUSE_SCHEDULE_RUNTIME
+			  ? 3 : region->inner->sched_kind));
+	  start_ix = (enum built_in_function)start_ix2;
 	  break;
 	case GIMPLE_OMP_SECTIONS:
 	  start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
@@ -3057,7 +3062,7 @@  expand_parallel_call (struct omp_region 
   VEC_splice (tree, args, ws_args);
 
   t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
-			       built_in_decls[start_ix], args);
+			       builtin_decl_explicit (start_ix), args);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 			    false, GSI_CONTINUE_LINKING);
@@ -3073,7 +3078,8 @@  expand_parallel_call (struct omp_region 
 			    false, GSI_CONTINUE_LINKING);
 
   t = build_call_expr_loc (gimple_location (entry_stmt),
-			   built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
+			   builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
+			   0);
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 			    false, GSI_CONTINUE_LINKING);
 }
@@ -3125,7 +3131,8 @@  expand_task_call (basic_block bb, gimple
   else
     t3 = build_fold_addr_expr_loc (loc, t);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
+		       7, t1, t2, t3,
 		       gimple_omp_task_arg_size (entry_stmt),
 		       gimple_omp_task_arg_align (entry_stmt), cond, flags);
 
@@ -3150,7 +3157,7 @@  maybe_catch_exception (gimple_seq body)
   if (lang_hooks.eh_protect_cleanup_actions != NULL)
     decl = lang_hooks.eh_protect_cleanup_actions ();
   else
-    decl = built_in_decls[BUILT_IN_TRAP];
+    decl = builtin_decl_explicit (BUILT_IN_TRAP);
 
   g = gimple_build_eh_must_not_throw (decl);
   g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
@@ -3297,10 +3304,10 @@  optimize_omp_library_calls (gimple entry
 {
   basic_block bb;
   gimple_stmt_iterator gsi;
-  tree thr_num_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
-  tree num_thr_id
-    = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
+  tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+  tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
+  tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
+  tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
   bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
 		      && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
 					  OMP_CLAUSE_UNTIED) != NULL);
@@ -3325,10 +3332,10 @@  optimize_omp_library_calls (gimple entry
 		   during the execution of the task region.  */
 		if (untied_task)
 		  continue;
-		built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
+		built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
 	      }
 	    else if (DECL_NAME (decl) == num_thr_id)
-	      built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
+	      built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
 	    else
 	      continue;
 
@@ -3812,7 +3819,7 @@  expand_omp_for_generic (struct omp_regio
     {
       /* In a combined parallel loop, emit a call to
 	 GOMP_loop_foo_next.  */
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (builtin_decl_explicit (next_fn), 2,
 			   build_fold_addr_expr (istart0),
 			   build_fold_addr_expr (iend0));
     }
@@ -3848,34 +3855,36 @@  expand_omp_for_generic (struct omp_regio
 	  if (fd->chunk_size)
 	    {
 	      t = fold_convert (fd->iter_type, fd->chunk_size);
-	      t = build_call_expr (built_in_decls[start_fn], 6,
-				   t0, t1, t2, t, t3, t4);
+	      t = build_call_expr (builtin_decl_explicit (start_fn),
+				   6, t0, t1, t2, t, t3, t4);
 	    }
 	  else
-	    t = build_call_expr (built_in_decls[start_fn], 5,
-				 t0, t1, t2, t3, t4);
+	    t = build_call_expr (builtin_decl_explicit (start_fn),
+				 5, t0, t1, t2, t3, t4);
 	}
       else
 	{
 	  tree t5;
 	  tree c_bool_type;
+	  tree bfn_decl;
 
 	  /* The GOMP_loop_ull_*start functions have additional boolean
 	     argument, true for < loops and false for > loops.
 	     In Fortran, the C bool type can be different from
 	     boolean_type_node.  */
-	  c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
+	  bfn_decl = builtin_decl_explicit (start_fn);
+	  c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
 	  t5 = build_int_cst (c_bool_type,
 			      fd->loop.cond_code == LT_EXPR ? 1 : 0);
 	  if (fd->chunk_size)
 	    {
+	      tree bfn_decl = builtin_decl_explicit (start_fn);
 	      t = fold_convert (fd->iter_type, fd->chunk_size);
-	      t = build_call_expr (built_in_decls[start_fn], 7,
-				   t5, t0, t1, t2, t, t3, t4);
+	      t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
 	    }
 	  else
-	    t = build_call_expr (built_in_decls[start_fn], 6,
-				 t5, t0, t1, t2, t3, t4);
+	    t = build_call_expr (builtin_decl_explicit (start_fn),
+				 6, t5, t0, t1, t2, t3, t4);
 	}
     }
   if (TREE_TYPE (t) != boolean_type_node)
@@ -4031,7 +4040,7 @@  expand_omp_for_generic (struct omp_regio
       /* Emit code to get the next parallel iteration in L2_BB.  */
       gsi = gsi_start_bb (l2_bb);
 
-      t = build_call_expr (built_in_decls[next_fn], 2,
+      t = build_call_expr (builtin_decl_explicit (next_fn), 2,
 			   build_fold_addr_expr (istart0),
 			   build_fold_addr_expr (iend0));
       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
@@ -4046,9 +4055,9 @@  expand_omp_for_generic (struct omp_regio
   /* Add the loop cleanup function.  */
   gsi = gsi_last_bb (exit_bb);
   if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
+    t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
   else
-    t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
+    t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
   stmt = gimple_build_call (t, 0);
   gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
@@ -4169,12 +4178,12 @@  expand_omp_for_static_nochunk (struct om
   gsi = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
@@ -4391,12 +4400,12 @@  expand_omp_for_static_chunk (struct omp_
   si = gsi_last_bb (entry_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
   t = fold_convert (itype, t);
   nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
 
-  t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
   t = fold_convert (itype, t);
   threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
 				       true, GSI_SAME_STMT);
@@ -4658,14 +4667,14 @@  expand_omp_for (struct omp_region *regio
       fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
 		  ? 3 : fd.sched_kind;
       fn_index += fd.have_ordered * 4;
-      start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
-      next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
+      start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
+      next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
       if (fd.iter_type == long_long_unsigned_type_node)
 	{
-	  start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START
-		      - BUILT_IN_GOMP_LOOP_STATIC_START;
-	  next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
-		     - BUILT_IN_GOMP_LOOP_STATIC_NEXT;
+	  start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
+			- (int)BUILT_IN_GOMP_LOOP_STATIC_START);
+	  next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
+		      - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
 	}
       expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
 			      (enum built_in_function) next_ix);
@@ -4778,13 +4787,13 @@  expand_omp_sections (struct omp_region *
 	 call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node,
 			 exit_reachable ? len - 1 : len);
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
+      u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
       stmt = gimple_build_call (u, 1, t);
     }
   else
     {
       /* Otherwise, call GOMP_sections_next.  */
-      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+      u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
       stmt = gimple_build_call (u, 0);
     }
   gimple_call_set_lhs (stmt, vin);
@@ -4866,16 +4875,19 @@  expand_omp_sections (struct omp_region *
   VEC_free (tree, heap, label_vec);
 
   si = gsi_start_bb (default_bb);
-  stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+  stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
   gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
 
   if (exit_reachable)
     {
+      tree bfn_decl;
+
       /* Code to get the next section goes in L1_BB.  */
       si = gsi_last_bb (l1_bb);
       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
 
-      stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
+      bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
+      stmt = gimple_build_call (bfn_decl, 0);
       gimple_call_set_lhs (stmt, vnext);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -4885,9 +4897,9 @@  expand_omp_sections (struct omp_region *
       /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
       si = gsi_last_bb (l2_bb);
       if (gimple_omp_return_nowait_p (gsi_stmt (si)))
-	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
+	t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
       else
-	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
+	t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
       stmt = gimple_build_call (t, 0);
       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
       gsi_remove (&si, true);
@@ -4995,7 +5007,7 @@  expand_omp_atomic_fetch_op (basic_block 
 			    tree addr, tree loaded_val,
 			    tree stored_val, int index)
 {
-  enum built_in_function oldbase, newbase;
+  enum built_in_function oldbase, newbase, tmpbase;
   tree decl, itype, call;
   direct_optab optab, oldoptab, newoptab;
   tree lhs, rhs;
@@ -5085,7 +5097,9 @@  expand_omp_atomic_fetch_op (basic_block 
   else
     return false;
 
-  decl = built_in_decls[(need_new ? newbase : oldbase) + index + 1];
+  tmpbase = ((enum built_in_function)
+	     ((need_new ? newbase : oldbase) + index + 1));
+  decl = builtin_decl_explicit (tmpbase);
   if (decl == NULL_TREE)
     return false;
   itype = TREE_TYPE (TREE_TYPE (decl));
@@ -5166,8 +5180,11 @@  expand_omp_atomic_pipeline (basic_block 
   basic_block loop_header = single_succ (load_bb);
   gimple phi, stmt;
   edge e;
+  enum built_in_function fncode;
 
-  cmpxchg = built_in_decls[BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N + index + 1];
+  fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+				    + index + 1);
+  cmpxchg = builtin_decl_explicit (fncode);
   if (cmpxchg == NULL_TREE)
     return false;
   type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
@@ -5355,7 +5372,7 @@  expand_omp_atomic_mutex (basic_block loa
   si = gsi_last_bb (load_bb);
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
+  t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
   t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
@@ -5370,7 +5387,7 @@  expand_omp_atomic_mutex (basic_block loa
 			      stored_val);
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
 
-  t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
+  t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
   t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&si, true);
@@ -5806,7 +5823,7 @@  lower_omp_single_simple (gimple single_s
   gimple call, cond;
   tree lhs, decl;
 
-  decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
+  decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
   call = gimple_build_call (decl, 0);
   gimple_call_set_lhs (call, lhs);
@@ -5855,7 +5872,7 @@  lower_omp_single_simple (gimple single_s
 static void
 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
 {
-  tree ptr_type, t, l0, l1, l2;
+  tree ptr_type, t, l0, l1, l2, bfn_decl;
   gimple_seq copyin_seq;
   location_t loc = gimple_location (single_stmt);
 
@@ -5868,7 +5885,8 @@  lower_omp_single_copy (gimple single_stm
   l1 = create_artificial_label (loc);
   l2 = create_artificial_label (loc);
 
-  t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
+  t = build_call_expr_loc (loc, bfn_decl, 0);
   t = fold_convert_loc (loc, ptr_type, t);
   gimplify_assign (ctx->receiver_decl, t, pre_p);
 
@@ -5887,8 +5905,8 @@  lower_omp_single_copy (gimple single_stm
 			      &copyin_seq, ctx);
 
   t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
-  t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END],
-		       1, t);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
+  t = build_call_expr_loc (loc, bfn_decl, 1, t);
   gimplify_and_add (t, pre_p);
 
   t = build_and_jump (&l2);
@@ -5955,7 +5973,7 @@  lower_omp_single (gimple_stmt_iterator *
 static void
 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
-  tree block, lab = NULL, x;
+  tree block, lab = NULL, x, bfn_decl;
   gimple stmt = gsi_stmt (*gsi_p), bind;
   location_t loc = gimple_location (stmt);
   gimple_seq tseq;
@@ -5967,7 +5985,8 @@  lower_omp_master (gimple_stmt_iterator *
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
       				 block);
 
-  x = build_call_expr_loc (loc, built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+  bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+  x = build_call_expr_loc (loc, bfn_decl, 0);
   x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
   tseq = NULL;
@@ -6006,7 +6025,8 @@  lower_omp_ordered (gimple_stmt_iterator 
   bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
       				   block);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
+  x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
+			 0);
   gimple_bind_add_stmt (bind, x);
 
   lower_omp (gimple_omp_body (stmt), ctx);
@@ -6014,7 +6034,7 @@  lower_omp_ordered (gimple_stmt_iterator 
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
 
-  x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
+  x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
   gimple_bind_add_stmt (bind, x);
 
   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
@@ -6080,19 +6100,19 @@  lower_omp_critical (gimple_stmt_iterator
       else
 	decl = (tree) n->value;
 
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
+      lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
       lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
+      unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
       unlock = build_call_expr_loc (loc, unlock, 1,
 				build_fold_addr_expr_loc (loc, decl));
     }
   else
     {
-      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
+      lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
       lock = build_call_expr_loc (loc, lock, 0);
 
-      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
+      unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
       unlock = build_call_expr_loc (loc, unlock, 0);
     }
 
Index: gcc/objc/objc-next-runtime-abi-01.c
===================================================================
--- gcc/objc/objc-next-runtime-abi-01.c	(.../trunk)	(revision 179514)
+++ gcc/objc/objc-next-runtime-abi-01.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2919,7 +2919,7 @@  objc_build_exc_ptr (struct objc_try_cont
   else
     {
       tree t;
-      t = built_in_decls[BUILT_IN_EH_POINTER];
+      t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
       t = build_call_expr (t, 1, integer_zero_node);
       return fold_convert (objc_object_type, t);
     }
Index: gcc/objc/objc-next-runtime-abi-02.c
===================================================================
--- gcc/objc/objc-next-runtime-abi-02.c	(.../trunk)	(revision 179514)
+++ gcc/objc/objc-next-runtime-abi-02.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -3676,7 +3676,7 @@  static tree
 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
 {
   tree t;
-  t = built_in_decls[BUILT_IN_EH_POINTER];
+  t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
   t = build_call_expr (t, 1, integer_zero_node);
   return fold_convert (objc_object_type, t);
 }
Index: gcc/objc/objc-gnu-runtime-abi-01.c
===================================================================
--- gcc/objc/objc-gnu-runtime-abi-01.c	(.../trunk)	(revision 179514)
+++ gcc/objc/objc-gnu-runtime-abi-01.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2226,7 +2226,7 @@  static tree
 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
 {
   tree t;
-  t = built_in_decls[BUILT_IN_EH_POINTER];
+  t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
   t = build_call_expr (t, 1, integer_zero_node);
   return fold_convert (objc_object_type, t);
 }
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(.../trunk)	(revision 179514)
+++ gcc/cp/decl.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1357,11 +1357,13 @@  duplicate_decls (tree newdecl, tree oldd
       if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
 	  && DECL_ANTICIPATED (olddecl)
 	  && TREE_NOTHROW (newdecl)
-	  && !TREE_NOTHROW (olddecl)
-	  && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
-	  && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
-	  && types_match)
-	TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+	  && !TREE_NOTHROW (olddecl))
+	{
+	  enum built_in_function fncode = DECL_FUNCTION_CODE (olddecl);
+	  tree tmpdecl = builtin_decl_explicit (fncode);
+	  if (tmpdecl && tmpdecl != olddecl && types_match)
+	    TREE_NOTHROW (tmpdecl)  = 1;
+	}
 
       /* Whether or not the builtin can throw exceptions has no
 	 bearing on this declarator.  */
@@ -2136,17 +2138,21 @@  duplicate_decls (tree newdecl, tree oldd
 		 regardless of declaration matches.  */
 	      COPY_DECL_RTL (olddecl, newdecl);
 	      if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-		switch (DECL_FUNCTION_CODE (newdecl))
-		  {
-		    /* If a compatible prototype of these builtin functions
-		       is seen, assume the runtime implements it with the
-		       expected semantics.  */
-		  case BUILT_IN_STPCPY:
-		    implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
-		      = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
-		  default:
-		    break;
-		  }
+		{
+		  enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+		  switch (fncode)
+		    {
+		      /* If a compatible prototype of these builtin functions
+			 is seen, assume the runtime implements it with the
+			 expected semantics.  */
+		    case BUILT_IN_STPCPY:
+		      if (builtin_decl_explicit_p (fncode))
+			set_builtin_decl_implicit_p (fncode, true);
+		      break;
+		    default:
+		      break;
+		    }
+		}
 	    }
 
 	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	(.../trunk)	(revision 179514)
+++ gcc/cp/except.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -140,7 +140,7 @@  build_eh_type_type (tree type)
 tree
 build_exc_ptr (void)
 {
-  return build_call_n (built_in_decls [BUILT_IN_EH_POINTER],
+  return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER),
 		       1, integer_zero_node);
 }
 
@@ -333,7 +333,7 @@  choose_personality_routine (enum languag
 
     case lang_java:
       state = chose_java;
-      terminate_node = built_in_decls [BUILT_IN_ABORT];
+      terminate_node = builtin_decl_explicit (BUILT_IN_ABORT);
       pragma_java_exceptions = true;
       break;
 
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(.../trunk)	(revision 179514)
+++ gcc/cp/semantics.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -4784,7 +4784,7 @@  finish_omp_atomic (enum tree_code code, 
 void
 finish_omp_barrier (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4794,7 +4794,7 @@  finish_omp_barrier (void)
 void
 finish_omp_flush (void)
 {
-  tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+  tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4804,7 +4804,7 @@  finish_omp_flush (void)
 void
 finish_omp_taskwait (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
@@ -4814,7 +4814,7 @@  finish_omp_taskwait (void)
 void
 finish_omp_taskyield (void)
 {
-  tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+  tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
   VEC(tree,gc) *vec = make_tree_vector ();
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
   release_tree_vector (vec);
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c	(.../trunk)	(revision 179514)
+++ gcc/tree-ssa-ccp.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2172,7 +2172,7 @@  optimize_stdarg_builtin (gimple call)
     case BUILT_IN_VA_START:
       if (!va_list_simple_ptr
 	  || targetm.expand_builtin_va_start != NULL
-          || built_in_decls[BUILT_IN_NEXT_ARG] == NULL)
+          || builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
 	return NULL_TREE;
 
       if (gimple_call_num_args (call) != 2)
@@ -2185,7 +2185,7 @@  optimize_stdarg_builtin (gimple call)
 	return NULL_TREE;
 
       lhs = build_fold_indirect_ref_loc (loc, lhs);
-      rhs = build_call_expr_loc (loc, built_in_decls[BUILT_IN_NEXT_ARG],
+      rhs = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_NEXT_ARG),
                              1, integer_zero_node);
       rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
       return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(.../trunk)	(revision 179514)
+++ gcc/builtins.def	(.../branches/ibm/builtin)	(revision 179582)
@@ -131,8 +131,8 @@  along with GCC; see the file COPYING3.  
    define it here at all.  */
 #undef DEF_BUILTIN_STUB
 #define DEF_BUILTIN_STUB(ENUM, NAME) \
-  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, 0, 0, false, false, \
-	       false, 0, false, false)
+  DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \
+	       false, ATTR_LAST, false, false)
 
 /* Builtin used by the implementation of GNU OpenMP.  None of these are
    actually implemented in the compiler; they're all in libgomp.  */
@@ -173,6 +173,9 @@  along with GCC; see the file COPYING3.  
 #undef ATTR_MATHFN_FPROUNDING_STORE
 #define ATTR_MATHFN_FPROUNDING_STORE ATTR_NOTHROW_LEAF_LIST
 
+/* Make sure 0 is not a legitimate builtin.  */
+DEF_BUILTIN_STUB(BUILT_IN_NONE, (const char *)0)
+
 /* Category: math builtins.  */
 DEF_LIB_BUILTIN        (BUILT_IN_ACOS, "acos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSF, "acosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c	(.../trunk)	(revision 179514)
+++ gcc/tree-ssa-math-opts.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1805,9 +1805,9 @@  execute_optimize_bswap (void)
   if (sizeof (HOST_WIDEST_INT) < 8)
     return 0;
 
-  bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
+  bswap32_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP32)
 	       && optab_handler (bswap_optab, SImode) != CODE_FOR_nothing);
-  bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
+  bswap64_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP64)
 	       && (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
 		   || (bswap32_p && word_mode == SImode)));
 
@@ -1818,13 +1818,13 @@  execute_optimize_bswap (void)
      assumes that the return and argument type are the same.  */
   if (bswap32_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP32];
+      tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
       bswap32_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
   if (bswap64_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP64];
+      tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
       bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
@@ -1858,14 +1858,14 @@  execute_optimize_bswap (void)
 	    case 32:
 	      if (bswap32_p)
 		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP32];
+		  fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
 		  bswap_type = bswap32_type;
 		}
 	      break;
 	    case 64:
 	      if (bswap64_p)
 		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP64];
+		  fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
 		  bswap_type = bswap64_type;
 		}
 	      break;
Index: gcc/gimple-low.c
===================================================================
--- gcc/gimple-low.c	(.../trunk)	(revision 179514)
+++ gcc/gimple-low.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -169,7 +169,7 @@  lower_function_body (void)
 	 and insert.  */
       disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
       arg = build_addr (disp_label, current_function_decl);
-      t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER];
+      t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
       x = gimple_build_call (t, 1, arg);
       gimple_call_set_lhs (x, disp_var);
 
@@ -861,7 +861,7 @@  lower_builtin_setjmp (gimple_stmt_iterat
 
   /* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert.  */
   arg = build_addr (next_label, current_function_decl);
-  t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP];
+  t = builtin_decl_implicit (BUILT_IN_SETJMP_SETUP);
   g = gimple_build_call (t, 2, gimple_call_arg (stmt, 0), arg);
   gimple_set_location (g, loc);
   gimple_set_block (g, gimple_block (stmt));
@@ -886,7 +886,7 @@  lower_builtin_setjmp (gimple_stmt_iterat
 
   /* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert.  */
   arg = build_addr (next_label, current_function_decl);
-  t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER];
+  t = builtin_decl_implicit (BUILT_IN_SETJMP_RECEIVER);
   g = gimple_build_call (t, 1, arg);
   gimple_set_location (g, loc);
   gimple_set_block (g, gimple_block (stmt));
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(.../trunk)	(revision 179514)
+++ gcc/go/gofrontend/gogo-tree.cc	(.../branches/ibm/builtin)	(revision 179582)
@@ -69,8 +69,7 @@  define_builtin(built_in_function bcode, 
 				   libname, NULL_TREE);
   if (const_p)
     TREE_READONLY(decl) = 1;
-  built_in_decls[bcode] = decl;
-  implicit_built_in_decls[bcode] = decl;
+  set_builtin_decl (bcode, decl, true);
   builtin_functions[name] = decl;
   if (libname != NULL)
     {
@@ -2311,14 +2310,13 @@  Gogo::make_trampoline(tree fnaddr, tree 
   x = save_expr(x);
 
   // Initialize the trampoline.
-  tree ini = build_call_expr(implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE],
+  tree ini = build_call_expr(builtin_decl_implicit(BUILT_IN_INIT_TRAMPOLINE),
 			     3, x, fnaddr, closure);
 
   // On some targets the trampoline address needs to be adjusted.  For
   // example, when compiling in Thumb mode on the ARM, the address
   // needs to have the low bit set.
-  x = build_call_expr(implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE],
-		      1, x);
+  x = build_call_expr(builtin_decl_explicit(BUILT_IN_ADJUST_TRAMPOLINE), 1, x);
   x = fold_convert(TREE_TYPE(fnaddr), x);
 
   return build2(COMPOUND_EXPR, TREE_TYPE(x), ini, x);
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	(.../trunk)	(revision 179514)
+++ gcc/ada/gcc-interface/utils.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -5629,7 +5629,7 @@  def_builtin_1 (enum built_in_function fn
 
   /* Preserve an already installed decl.  It most likely was setup in advance
      (e.g. as part of the internal builtins) for specific reasons.  */
-  if (built_in_decls[(int) fncode] != NULL_TREE)
+  if (builtin_decl_explicit (fncode) != NULL_TREE)
     return;
 
   gcc_assert ((!both_p && !fallback_p)
@@ -5646,9 +5646,7 @@  def_builtin_1 (enum built_in_function fn
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
-  if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+  set_builtin_decl (fncode, decl, implicit_p);
 }
 
 static int flag_isoc94 = 0;
Index: gcc/ada/gcc-interface/trans.c
===================================================================
--- gcc/ada/gcc-interface/trans.c	(.../trunk)	(revision 179514)
+++ gcc/ada/gcc-interface/trans.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -3899,7 +3899,7 @@  Exception_Handler_to_gnu_zcx (Node_Id gn
      time, and reuse it to feed the end_handler hook's argument at exit.  */
 
   gnu_current_exc_ptr
-    = build_call_expr (built_in_decls [BUILT_IN_EH_POINTER],
+    = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
 		       1, integer_zero_node);
   prev_gnu_incoming_exc_ptr = gnu_incoming_exc_ptr;
   gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
@@ -5189,7 +5189,7 @@  gnat_to_gnu (Node_Id gnat_node)
 	      to_ptr = build_fold_addr_expr (to);
 	      from_ptr = build_fold_addr_expr (from);
 
-	      t = implicit_built_in_decls[BUILT_IN_MEMMOVE];
+	      t = builtin_decl_implicit (BUILT_IN_MEMMOVE);
 	      gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size);
 	   }
 	}
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(.../trunk)	(revision 179514)
+++ gcc/c-decl.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2372,17 +2372,21 @@  merge_decls (tree newdecl, tree olddecl,
 	    {
 	      C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
 	      if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-		switch (DECL_FUNCTION_CODE (newdecl))
-		  {
-		  /* If a compatible prototype of these builtin functions
-		     is seen, assume the runtime implements it with the
-		     expected semantics.  */
-		  case BUILT_IN_STPCPY:
-		    implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
-		      = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
-		  default:
-		    break;
-		  }
+		{
+		  enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+		  switch (fncode)
+		    {
+		      /* If a compatible prototype of these builtin functions
+			 is seen, assume the runtime implements it with the
+			 expected semantics.  */
+		    case BUILT_IN_STPCPY:
+		      if (builtin_decl_explicit_p (fncode))
+			set_builtin_decl_implicit_p (fncode, true);
+		      break;
+		    default:
+		      break;
+		    }
+		}
 	    }
 	  else
 	    C_DECL_BUILTIN_PROTOTYPE (newdecl)
@@ -4338,7 +4342,7 @@  finish_decl (tree decl, location_t init_
     }
 
   /* If this is a function and an assembler name is specified, reset DECL_RTL
-     so we can give it its new name.  Also, update built_in_decls if it
+     so we can give it its new name.  Also, update builtin_decl if it
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(.../trunk)	(revision 179514)
+++ gcc/tree-eh.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2934,7 +2934,7 @@  lower_resx (basic_block bb, gimple stmt,
 
 	 Resolve this by expanding the resx node to an abort.  */
 
-      fn = implicit_built_in_decls[BUILT_IN_TRAP];
+      fn = builtin_decl_implicit (BUILT_IN_TRAP);
       x = gimple_build_call (fn, 0);
       gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 
@@ -2991,7 +2991,7 @@  lower_resx (basic_block bb, gimple stmt,
 	  edge_iterator ei;
 	  tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
 
-	  fn = implicit_built_in_decls[BUILT_IN_EH_COPY_VALUES];
+	  fn = builtin_decl_implicit (BUILT_IN_EH_COPY_VALUES);
 	  src_nr = build_int_cst (integer_type_node, src_r->index);
 	  x = gimple_build_call (fn, 2, dst_nr, src_nr);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
@@ -3026,13 +3026,13 @@  lower_resx (basic_block bb, gimple stmt,
 	 with no arguments for C++ and Java.  Check for that.  */
       if (src_r->use_cxa_end_cleanup)
 	{
-	  fn = implicit_built_in_decls[BUILT_IN_CXA_END_CLEANUP];
+	  fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP);
 	  x = gimple_build_call (fn, 0);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 	}
       else
 	{
-	  fn = implicit_built_in_decls[BUILT_IN_EH_POINTER];
+	  fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
 	  src_nr = build_int_cst (integer_type_node, src_r->index);
 	  x = gimple_build_call (fn, 1, src_nr);
 	  var = create_tmp_var (ptr_type_node, NULL);
@@ -3040,7 +3040,7 @@  lower_resx (basic_block bb, gimple stmt,
 	  gimple_call_set_lhs (x, var);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 
-	  fn = implicit_built_in_decls[BUILT_IN_UNWIND_RESUME];
+	  fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
 	  x = gimple_build_call (fn, 1, var);
 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 	}
@@ -3206,7 +3206,7 @@  lower_eh_dispatch (basic_block src, gimp
 	  }
 	else
 	  {
-	    fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+	    fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
 	    x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
 							 region_nr));
 	    filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
@@ -3232,7 +3232,7 @@  lower_eh_dispatch (basic_block src, gimp
 	edge b_e = BRANCH_EDGE (src);
 	edge f_e = FALLTHRU_EDGE (src);
 
-	fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+	fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
 	x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
 						     region_nr));
 	filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-expr.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1124,22 +1124,22 @@  gfc_conv_power_op (gfc_se * se, gfc_expr
 	      switch (kind)
 		{
 		case 0:
-		  fndecl = built_in_decls[BUILT_IN_POWIF];
+		  fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
 		  break;
 		
 		case 1:
-		  fndecl = built_in_decls[BUILT_IN_POWI];
+		  fndecl = builtin_decl_explicit (BUILT_IN_POWI);
 		  break;
 
 		case 2:
-		  fndecl = built_in_decls[BUILT_IN_POWIL];
+		  fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
 		  break;
 
 		case 3:
 		  /* Use the __builtin_powil() only if real(kind=16) is 
 		     actually the C long double type.  */
 		  if (!gfc_real16_is_float128)
-		    fndecl = built_in_decls[BUILT_IN_POWIL];
+		    fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
 		  break;
 
 		default:
@@ -3855,7 +3855,8 @@  fill_with_spaces (tree start, tree type,
   /* For a simple char type, we can call memset().  */
   if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
     return build_call_expr_loc (input_location,
-			    built_in_decls[BUILT_IN_MEMSET], 3, start,
+			    builtin_decl_explicit (BUILT_IN_MEMSET),
+			    3, start,
 			    build_int_cst (gfc_get_int_type (gfc_c_int_kind),
 					   lang_hooks.to_target_charset (' ')),
 			    size);
@@ -4015,13 +4016,13 @@  gfc_trans_string_copy (stmtblock_t * blo
   cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen,
 			   dlen);
   tmp2 = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMMOVE],
-			  3, dest, src, dlen);
+			      builtin_decl_explicit (BUILT_IN_MEMMOVE),
+			      3, dest, src, dlen);
 
   /* Else copy and pad with spaces.  */
   tmp3 = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMMOVE],
-			  3, dest, src, slen);
+			      builtin_decl_explicit (BUILT_IN_MEMMOVE),
+			      3, dest, src, slen);
 
   tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
   tmp4 = fill_with_spaces (tmp4, chartype,
@@ -5816,8 +5817,8 @@  gfc_trans_zero_assign (gfc_expr * expr)
 
   /* Construct call to __builtin_memset.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_MEMSET],
-			 3, dest, integer_zero_node, len);
+			     builtin_decl_explicit (BUILT_IN_MEMSET),
+			     3, dest, integer_zero_node, len);
   return fold_convert (void_type_node, tmp);
 }
 
@@ -5845,7 +5846,8 @@  gfc_build_memcpy_call (tree dst, tree sr
 
   /* Construct call to __builtin_memcpy.  */
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_MEMCPY], 3, dst, src, len);
+			     builtin_decl_explicit (BUILT_IN_MEMCPY),
+			     3, dst, src, len);
   return fold_convert (void_type_node, tmp);
 }
 
@@ -6056,8 +6058,8 @@  alloc_scalar_allocatable_for_assignment 
     }
 
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
-			     size_in_bytes);
+			     builtin_decl_explicit (BUILT_IN_MALLOC),
+			     1, size_in_bytes);
   tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   gfc_add_modify (block, lse.expr, tmp);
   if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
@@ -6083,8 +6085,8 @@  alloc_scalar_allocatable_for_assignment 
 		      build_empty_stmt (input_location));
       gfc_add_expr_to_block (block, tmp);
       tmp = build_call_expr_loc (input_location,
-				 built_in_decls[BUILT_IN_REALLOC], 2,
-				 fold_convert (pvoid_type_node, lse.expr),
+				 builtin_decl_explicit (BUILT_IN_REALLOC),
+				 2, fold_convert (pvoid_type_node, lse.expr),
 				 size_in_bytes);
       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
       gfc_add_modify (block, lse.expr, tmp);
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-array.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1470,8 +1470,8 @@  gfc_trans_array_constructor_value (stmtb
 	      size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
 	      bound = build_int_cst (size_type_node, n * size);
 	      tmp = build_call_expr_loc (input_location,
-				     built_in_decls[BUILT_IN_MEMCPY], 3,
-				     tmp, init, bound);
+					 builtin_decl_explict (BUILT_IN_MEMCPY),
+					 3, tmp, init, bound);
 	      gfc_add_expr_to_block (&body, tmp);
 
 	      *poffset = fold_build2_loc (input_location, PLUS_EXPR,
@@ -6632,7 +6632,7 @@  duplicate_allocatable (tree dest, tree s
 	  gfc_add_expr_to_block (&block, tmp);
 	}
 
-      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
       tmp = build_call_expr_loc (input_location, tmp, 3,
 				 dest, src, size);
     }
@@ -6656,7 +6656,7 @@  duplicate_allocatable (tree dest, tree s
 
       /* We know the temporary and the value will be the same length,
 	 so can use memcpy.  */
-      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
       tmp = build_call_expr_loc (input_location,
 			tmp, 3, gfc_conv_descriptor_data_get (dest),
 			gfc_conv_descriptor_data_get (src), size);
@@ -7412,7 +7412,7 @@  gfc_alloc_allocatable_for_assignment (gf
      in the array reference - (*desc.data)[<element>]. */
   gfc_init_block (&realloc_block);
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_REALLOC], 2,
+			     builtin_decl_explict (BUILT_IN_REALLOC), 2,
 			     fold_convert (pvoid_type_node, array1),
 			     size2);
   gfc_conv_descriptor_data_set (&realloc_block,
@@ -7428,8 +7428,8 @@  gfc_alloc_allocatable_for_assignment (gf
   /* Malloc expression.  */
   gfc_init_block (&alloc_block);
   tmp = build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
-			     size2);
+			     builtin_decl_explicit (BUILT_IN_MALLOC),
+			     1, size2);
   gfc_conv_descriptor_data_set (&alloc_block,
 				desc, tmp);
   tmp = gfc_conv_descriptor_dtype (desc);
Index: gcc/fortran/trans-openmp.c
===================================================================
--- gcc/fortran/trans-openmp.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-openmp.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -249,7 +249,8 @@  gfc_omp_clause_copy_ctor (tree clause, t
   gfc_conv_descriptor_data_set (&cond_block, dest, ptr);
 
   call = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
+			  builtin_decl_explict (BUILT_IN_MEMCPY),
+			  3, ptr,
 			  fold_convert (pvoid_type_node,
 					gfc_conv_descriptor_data_get (src)),
 			  size);
@@ -300,7 +301,7 @@  gfc_omp_clause_assign_op (tree clause AT
 			  size, esize);
   size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
   call = build_call_expr_loc (input_location,
-			  built_in_decls[BUILT_IN_MEMCPY], 3,
+			  builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
 			  fold_convert (pvoid_type_node,
 					gfc_conv_descriptor_data_get (dest)),
 			  fold_convert (pvoid_type_node,
@@ -1273,7 +1274,7 @@  gfc_trans_omp_atomic (gfc_code *code)
 static tree
 gfc_trans_omp_barrier (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
+  tree decl = builtin_decl_explicit ([BUILT_IN_GOMP_BARRIER);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
@@ -1547,7 +1548,7 @@  gfc_trans_omp_do (gfc_code *code, stmtbl
 static tree
 gfc_trans_omp_flush (void)
 {
-  tree decl = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+  tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
@@ -1738,14 +1739,14 @@  gfc_trans_omp_task (gfc_code *code)
 static tree
 gfc_trans_omp_taskwait (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_TASKWAIT];
+  tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
 static tree
 gfc_trans_omp_taskyield (void)
 {
-  tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+  tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
   return build_call_expr_loc (input_location, decl, 0);
 }
 
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-stmt.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -602,7 +602,7 @@  gfc_trans_stop (gfc_code *code, bool err
   if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
     {
       /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY.  */
-      tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+      tmp = builtin_decl_explict (BUILT_IN_SYNC_SYNCHRONIZE);
       tmp = build_call_expr_loc (input_location, tmp, 0);
       gfc_add_expr_to_block (&se.pre, tmp);
 
@@ -774,7 +774,7 @@  gfc_trans_sync (gfc_code *code, gfc_exec
       image control statements SYNC IMAGES and SYNC ALL.  */
    if (gfc_option.coarray == GFC_FCOARRAY_LIB)
      {
-	tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+       tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
 	tmp = build_call_expr_loc (input_location, tmp, 0);
 	gfc_add_expr_to_block (&se.pre, tmp);
      }
@@ -5076,7 +5076,7 @@  gfc_trans_allocate (gfc_code * code)
 			      slen);
 
       dlen = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_MEMCPY], 3,
+				  builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
 		gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
 
       tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
@@ -5251,7 +5251,7 @@  gfc_trans_deallocate (gfc_code *code)
 			      slen);
 
       dlen = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_MEMCPY], 3,
+				  builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
 		gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
 
       tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, astat,
Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -512,7 +512,7 @@  gfc_trans_runtime_check (bool error, boo
 tree
 gfc_call_malloc (stmtblock_t * block, tree type, tree size)
 {
-  tree tmp, msg, malloc_result, null_result, res;
+  tree tmp, msg, malloc_result, null_result, res, malloc_tree;
   stmtblock_t block2;
 
   size = gfc_evaluate_now (size, block);
@@ -529,10 +529,11 @@  gfc_call_malloc (stmtblock_t * block, tr
   size = fold_build2_loc (input_location, MAX_EXPR, size_type_node, size,
 			  build_int_cst (size_type_node, 1));
 
+  malloc_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
   gfc_add_modify (&block2, res,
 		  fold_convert (prvoid_type_node,
 				build_call_expr_loc (input_location,
-				   built_in_decls[BUILT_IN_MALLOC], 1, size)));
+						     malloc_tree, 1, size)));
 
   /* Optionally check whether malloc was successful.  */
   if (gfc_option.rtcheck & GFC_RTCHECK_MEM)
@@ -604,7 +605,7 @@  gfc_allocate_using_malloc (stmtblock_t *
   gfc_add_modify (block, pointer,
 	  fold_convert (TREE_TYPE (pointer),
 		build_call_expr_loc (input_location,
-			     built_in_decls[BUILT_IN_MALLOC], 1,
+			     builtin_decl_explicit (BUILT_IN_MALLOC), 1,
 			     fold_build2_loc (input_location,
 				      MAX_EXPR, size_type_node, size,
 				      build_int_cst (size_type_node, 1)))));
@@ -783,7 +784,8 @@  gfc_call_free (tree var)
   cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var,
 			  build_int_cst (pvoid_type_node, 0));
   call = build_call_expr_loc (input_location,
-			      built_in_decls[BUILT_IN_FREE], 1, var);
+			      builtin_decl_explicit (BUILT_IN_FREE),
+			      1, var);
   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, call,
 			 build_empty_stmt (input_location));
   gfc_add_expr_to_block (&block, tmp);
@@ -871,8 +873,8 @@  gfc_deallocate_with_status (tree pointer
   /* When POINTER is not NULL, we free it.  */
   gfc_start_block (&non_null);
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_FREE], 1,
-			 fold_convert (pvoid_type_node, pointer));
+			     builtin_decl_explicit (BUILT_IN_FREE), 1,
+			     fold_convert (pvoid_type_node, pointer));
   gfc_add_expr_to_block (&non_null, tmp);
 
   if (status != NULL_TREE && !integer_zerop (status))
@@ -968,8 +970,8 @@  gfc_deallocate_scalar_with_status (tree 
     }
   
   tmp = build_call_expr_loc (input_location,
-			 built_in_decls[BUILT_IN_FREE], 1,
-			 fold_convert (pvoid_type_node, pointer));
+			     builtin_decl_explicit (BUILT_IN_FREE), 1,
+			     fold_convert (pvoid_type_node, pointer));
   gfc_add_expr_to_block (&non_null, tmp);
 
   if (status != NULL_TREE && !integer_zerop (status))
Index: gcc/fortran/f95-lang.c
===================================================================
--- gcc/fortran/f95-lang.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/f95-lang.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -653,8 +653,7 @@  gfc_define_builtin (const char *name, tr
     DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
 					NULL, DECL_ATTRIBUTES (decl));
 
-  built_in_decls[code] = decl;
-  implicit_built_in_decls[code] = decl;
+  set_builtin_decl (code, decl, true);
 }
 
 
@@ -1005,7 +1004,7 @@  gfc_init_builtin_functions (void)
                                     size_type_node, NULL_TREE);
   gfc_define_builtin ("__builtin_malloc", ftype, BUILT_IN_MALLOC,
 		      "malloc", ATTR_NOTHROW_LEAF_LIST);
-  DECL_IS_MALLOC (built_in_decls[BUILT_IN_MALLOC]) = 1;
+  DECL_IS_MALLOC (builtin_decl_explicit (BUILT_IN_MALLOC)) = 1;
 
   ftype = build_function_type_list (pvoid_type_node,
                                     size_type_node, pvoid_type_node,
@@ -1121,7 +1120,7 @@  gfc_init_builtin_functions (void)
 
   gfc_define_builtin ("__builtin_trap", builtin_types[BT_FN_VOID],
 		      BUILT_IN_TRAP, NULL, ATTR_NOTHROW_LEAF_LIST);
-  TREE_THIS_VOLATILE (built_in_decls[BUILT_IN_TRAP]) = 1;
+  TREE_THIS_VOLATILE (builtin_decl_explicit (BUILT_IN_TRAP)) = 1;
 
   gfc_define_builtin ("__emutls_get_address",
 		      builtin_types[BT_FN_PTR_PTR],
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-decl.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -4986,7 +4986,7 @@  create_main_function (tree fndecl)
     { 
       /* Per F2008, 8.5.1 END of the main program implies a
 	 SYNC MEMORY.  */ 
-      tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+      tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
       tmp = build_call_expr_loc (input_location, tmp, 0);
       gfc_add_expr_to_block (&body, tmp);
 
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c	(.../trunk)	(revision 179514)
+++ gcc/fortran/trans-intrinsic.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -139,7 +139,7 @@  static tree
 builtin_decl_for_precision (enum built_in_function base_built_in,
 			    int precision)
 {
-  int i = END_BUILTINS;
+  enum built_in_function i = END_BUILTINS;
 
   gfc_intrinsic_map_t *m;
   for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
@@ -158,7 +158,7 @@  builtin_decl_for_precision (enum built_i
       return m->real16_decl;
     }
 
-  return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
+  return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
 }
 
 
Index: gcc/function.c
===================================================================
--- gcc/function.c	(.../trunk)	(revision 179514)
+++ gcc/function.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -3638,7 +3638,7 @@  gimplify_parameters (void)
 		  DECL_IGNORED_P (addr) = 0;
 		  local = build_fold_indirect_ref (addr);
 
-		  t = built_in_decls[BUILT_IN_ALLOCA];
+		  t = builtin_decl_explicit (BUILT_IN_ALLOCA);
 		  t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm));
 		  /* The call has been built for a variable-sized object.  */
 		  CALL_ALLOCA_FOR_VAR_P (t) = 1;
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(.../trunk)	(revision 179514)
+++ gcc/c-typeck.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2766,7 +2766,8 @@  build_function_call_vec (location_t loc,
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
+      tree trap = build_function_call (loc,
+				       builtin_decl_explicit (BUILT_IN_TRAP),
 				       NULL_TREE);
       int i;
 
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(.../trunk)	(revision 179514)
+++ gcc/gimplify.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1109,12 +1109,12 @@  build_stack_save_restore (gimple *save, 
 {
   tree tmp_var;
 
-  *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+  *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
   gimple_call_set_lhs (*save, tmp_var);
 
   *restore
-    = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+    = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
 			 1, tmp_var);
 }
 
@@ -1329,7 +1329,7 @@  gimplify_vla_decl (tree decl, gimple_seq
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
+  t = builtin_decl_explicit (BUILT_IN_ALLOCA);
   t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
@@ -3210,7 +3210,7 @@  gimplify_modify_expr_to_memcpy (tree *ex
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
 
-  t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  t = builtin_decl_implicit (BUILT_IN_MEMCPY);
 
   gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
 
@@ -3257,7 +3257,7 @@  gimplify_modify_expr_to_memset (tree *ex
 
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
-  t = implicit_built_in_decls[BUILT_IN_MEMSET];
+  t = builtin_decl_implicit (BUILT_IN_MEMSET);
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
 
@@ -4680,7 +4680,7 @@  gimplify_variable_sized_compare (tree *e
   arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
   src = build_fold_addr_expr_loc (loc, op1);
   dest = build_fold_addr_expr_loc (loc, op0);
-  t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+  t = builtin_decl_implicit (BUILT_IN_MEMCMP);
   t = build_call_expr_loc (loc, t, 3, dest, src, arg);
 
   expr
@@ -7979,24 +7979,24 @@  gimplify_function_tree (tree fndecl)
       tree tmp_var;
       gimple call;
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
       call = gimple_build_call (x, 2,
 				build_fold_addr_expr (current_function_decl),
 				tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
       tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
 
-      x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
       gimple_call_set_lhs (call, tmp_var);
       gimplify_seq_add_stmt (&body, call);
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
       call = gimple_build_call (x, 2,
 				build_fold_addr_expr (current_function_decl),
 				tmp_var);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(.../trunk)	(revision 179514)
+++ gcc/calls.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -274,6 +274,7 @@  emit_call_1 (rtx funexp, tree fntree ATT
   if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
     {
       tree t = fndecl;
+
       /* Although a built-in FUNCTION_DECL and its non-__builtin
 	 counterpart compare equal and get a shared mem_attrs, they
 	 produce different dump output in compare-debug compilations,
@@ -281,10 +282,14 @@  emit_call_1 (rtx funexp, tree fntree ATT
 	 adds a different (but equivalent) entry, while the other
 	 doesn't run the garbage collector at the same spot and then
 	 shares the mem_attr with the equivalent entry. */
-      if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
-	  && built_in_decls[DECL_FUNCTION_CODE (t)])
-	t = built_in_decls[DECL_FUNCTION_CODE (t)];
-      set_mem_expr (funmem, t);
+      if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL)
+	{
+	  tree t2 = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
+	  if (t2)
+	    t = t2;
+	}
+
+	set_mem_expr (funmem, t);
     }
   else if (fntree)
     set_mem_expr (funmem, build_simple_mem_ref (CALL_EXPR_FN (fntree)));
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(.../trunk)	(revision 179514)
+++ gcc/lto/lto-lang.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -499,9 +499,7 @@  def_builtin_1 (enum built_in_function fn
     add_builtin_function (libname, libtype, fncode, fnclass,
 			  NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
-  if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+  set_builtin_decl (fncode, decl, implicit_p);
 }
 
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c	(.../trunk)	(revision 179514)
+++ gcc/tree-ssa-forwprop.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1601,7 +1601,8 @@  simplify_builtin_call (gimple_stmt_itera
 	      if (!is_gimple_val (ptr1))
 		ptr1 = force_gimple_operand_gsi (gsi_p, ptr1, true, NULL_TREE,
 						 true, GSI_SAME_STMT);
-	      gimple_call_set_fndecl (stmt2, built_in_decls [BUILT_IN_MEMCPY]);
+	      gimple_call_set_fndecl (stmt2,
+				      builtin_decl_explicit (BUILT_IN_MEMCPY));
 	      gimple_call_set_arg (stmt2, 0, ptr1);
 	      gimple_call_set_arg (stmt2, 1, new_str_cst);
 	      gimple_call_set_arg (stmt2, 2,
Index: gcc/tree-nested.c
===================================================================
--- gcc/tree-nested.c	(.../trunk)	(revision 179514)
+++ gcc/tree-nested.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1811,8 +1811,8 @@  convert_nl_goto_reference (gimple_stmt_i
   x = get_frame_field (info, target_context, field, &wi->gsi);
   x = build_addr (x, target_context);
   x = gsi_gimplify_val (info, x, &wi->gsi);
-  call = gimple_build_call (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
-			    build_addr (new_label, target_context), x);
+  call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
+			    2, build_addr (new_label, target_context), x);
   gsi_replace (&wi->gsi, call, false);
 
   /* We have handled all of STMT's operands, no need to keep going.  */
@@ -1924,7 +1924,7 @@  convert_tramp_reference_op (tree *tp, in
 
       /* Do machine-specific ugliness.  Normally this will involve
 	 computing extra alignment, but it can really be anything.  */
-      builtin = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
+      builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
       call = gimple_build_call (builtin, 1, x);
       x = init_tmp_var_with_call (info, &wi->gsi, call);
 
@@ -2399,7 +2399,7 @@  finalize_nesting_tree_1 (struct nesting_
 		      root->frame_decl, field, NULL_TREE);
 	  arg1 = build_addr (x, context);
 
-	  x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
+	  x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
 	  stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
 	  gimple_seq_add_stmt (&stmt_list, stmt);
 	}
Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
--- gcc/tree-ssa-loop-prefetch.c	(.../trunk)	(revision 179514)
+++ gcc/tree-ssa-loop-prefetch.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1117,7 +1117,7 @@  issue_prefetch_ref (struct mem_ref *ref,
 					   NULL, true, GSI_SAME_STMT);
       }
       /* Create the prefetch instruction.  */
-      prefetch = gimple_build_call (built_in_decls[BUILT_IN_PREFETCH],
+      prefetch = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
 				    3, addr, write_p, local);
       gsi_insert_before (&bsi, prefetch, GSI_SAME_STMT);
     }
@@ -1909,7 +1909,7 @@  tree_ssa_prefetch_arrays (void)
 
   initialize_original_copy_tables ();
 
-  if (!built_in_decls[BUILT_IN_PREFETCH])
+  if (!builtin_decl_explicit_p (BUILT_IN_PREFETCH))
     {
       tree type = build_function_type_list (void_type_node,
 					    const_ptr_type_node, NULL_TREE);
@@ -1917,7 +1917,7 @@  tree_ssa_prefetch_arrays (void)
 					BUILT_IN_PREFETCH, BUILT_IN_NORMAL,
 					NULL, NULL_TREE);
       DECL_IS_NOVOPS (decl) = true;
-      built_in_decls[BUILT_IN_PREFETCH] = decl;
+      set_builtin_decl (BUILT_IN_PREFETCH, decl, false);
     }
 
   /* We assume that size of cache line is a power of two, so verify this
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c	(.../trunk)	(revision 179514)
+++ gcc/tree-streamer-in.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -1049,7 +1049,7 @@  streamer_get_builtin_tree (struct lto_in
     {
       if (fcode >= END_BUILTINS)
 	fatal_error ("machine independent builtin code out of range");
-      result = built_in_decls[fcode];
+      result = builtin_decl_explicit (fcode);
       gcc_assert (result);
     }
   else if (fclass == BUILT_IN_MD)
Index: gcc/system.h
===================================================================
--- gcc/system.h	(.../trunk)	(revision 179514)
+++ gcc/system.h	(.../branches/ibm/builtin)	(revision 179582)
@@ -881,6 +881,9 @@  extern void fancy_abort (const char *, i
 	TARGET_HANDLE_OFAST TARGET_OPTION_OPTIMIZATION \
         TARGET_IRA_COVER_CLASSES TARGET_HELP
 
+/* Arrays that were deleted in favor of a functional interface.  */
+ #pragma GCC poison built_in_decls implicit_built_in_decls
+
 /* Hooks into libgcc2.  */
  #pragma GCC poison LIBGCC2_DOUBLE_TYPE_SIZE LIBGCC2_WORDS_BIG_ENDIAN \
    LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(.../trunk)	(revision 179514)
+++ gcc/tree-vect-generic.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -783,7 +783,8 @@  expand_vector_operations_1 (gimple_stmt_
 	  tree vec0;
 
 	  vec0 = gimple_assign_rhs1 (stmt);
-	  new_stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+	  new_stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP),
+					0);
 	  gsi_insert_before (gsi, new_stmt,  GSI_SAME_STMT);
 	  split_block (gimple_bb (new_stmt), new_stmt);
 	  new_stmt = gimple_build_assign (gimple_assign_lhs (stmt), vec0);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(.../trunk)	(revision 179514)
+++ gcc/config/sparc/sparc.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -6789,7 +6789,7 @@  sparc_gimplify_va_arg (tree valist, tree
     {
       tree tmp = create_tmp_var (type, "va_arg_tmp");
       tree dest_addr = build_fold_addr_expr (tmp);
-      tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+      tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
 				   3, dest_addr, addr, size_int (rsize));
       TREE_ADDRESSABLE (tmp) = 1;
       gimplify_and_add (copy, pre_p);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(.../trunk)	(revision 179514)
+++ gcc/config/i386/i386.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -7959,7 +7959,7 @@  ix86_gimplify_va_arg (tree valist, tree 
 	      else
 		{
 		  tree copy
-		    = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+		    = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
 				       3, dest_addr, src_addr,
 				       size_int (cur_size));
 		  gimplify_and_add (copy, pre_p);
@@ -28985,7 +28985,7 @@  ix86_veclibabi_svml (enum built_in_funct
       return NULL_TREE;
     }
 
-  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+  bname = IDENTIFIER_POINTER (DECL_NAME (builtin_decl_implicit (fn)));
 
   if (fn == BUILT_IN_LOGF)
     strcpy (name, "vmlsLn4");
@@ -29003,7 +29003,8 @@  ix86_veclibabi_svml (enum built_in_funct
   name[4] &= ~0x20;
 
   arity = 0;
-  for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+  for (args = DECL_ARGUMENTS (builtin_decl_implicit (fn));
+       args;
        args = TREE_CHAIN (args))
     arity++;
 
@@ -29084,11 +29085,12 @@  ix86_veclibabi_acml (enum built_in_funct
       return NULL_TREE;
     }
 
-  bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+  bname = IDENTIFIER_POINTER (DECL_NAME (builtin_decl_implicit (fn)));
   sprintf (name + 7, "%s", bname+10);
 
   arity = 0;
-  for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+  for (args = DECL_ARGUMENTS (builtin_decl_implicit (fn));
+       args;
        args = TREE_CHAIN (args))
     arity++;
 
Index: gcc/config/vms/vms.c
===================================================================
--- gcc/config/vms/vms.c	(.../trunk)	(revision 179514)
+++ gcc/config/vms/vms.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -99,8 +99,11 @@  vms_patch_builtins (void)
   unsigned int i;
 
   /* Fwrite on VMS is non-standard.  */
-  implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
-  implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
+  if (builtin_decl_implicit_p (BUILT_IN_WRITE))
+    set_builtin_decl_implicit_p (BUILT_IN_WRITE, false);
+
+  if (builtin_decl_implicit_p (BUILT_IN_WRITE_UNLOCKED))
+    set_builtin_decl_implicit_p (BUILT_IN_WRITE_UNLOCKED, false);
 
   /* Define aliases for names.  */
   for (i = 0; i < NBR_CRTL_NAMES; i++)
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(.../trunk)	(revision 179514)
+++ gcc/config/ia64/ia64.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -10100,15 +10100,12 @@  ia64_init_builtins (void)
 
   if (TARGET_HPUX)
     {
-      if (built_in_decls [BUILT_IN_FINITE])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITE],
-	  "_Isfinite");
-      if (built_in_decls [BUILT_IN_FINITEF])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF],
-	  "_Isfinitef");
-      if (built_in_decls [BUILT_IN_FINITEL])
-	set_user_assembler_name (built_in_decls [BUILT_IN_FINITEL],
-	  "_Isfinitef128");
+      if ((decl = builtin_decl_explicit (BUILT_IN_FINITE))) != NULL_TREE)
+	set_user_assembler_name (decl, "_Isfinite");
+      if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF))) != NULL_TREE)
+	set_user_assembler_name (decl, "_Isfinitef");
+      if ((decl = builtin_decl_explicit (BUILT_IN_FINITEL))) != NULL_TREE)
+	set_user_assembler_name (decl, "_Isfinitef128");
     }
 }
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../trunk)	(revision 179514)
+++ gcc/config/rs6000/rs6000.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -3739,7 +3739,7 @@  rs6000_builtin_vectorized_libmass (tree 
 	case BUILT_IN_SQRT:
 	case BUILT_IN_TAN:
 	case BUILT_IN_TANH:
-	  bdecl = implicit_built_in_decls[fn];
+	  bdecl = builtin_decl_implicit (fn);
 	  suffix = "d2";				/* pow -> powd2 */
 	  if (el_mode != DFmode
 	      || n != 2)
@@ -3776,7 +3776,7 @@  rs6000_builtin_vectorized_libmass (tree 
 	case BUILT_IN_SQRTF:
 	case BUILT_IN_TANF:
 	case BUILT_IN_TANHF:
-	  bdecl = implicit_built_in_decls[fn];
+	  bdecl = builtin_decl_implicit (fn);
 	  suffix = "4";					/* powf -> powf4 */
 	  if (el_mode != SFmode
 	      || n != 4)
@@ -9400,7 +9400,7 @@  rs6000_gimplify_va_arg (tree valist, tre
       tree tmp = create_tmp_var (type, "va_arg_tmp");
       tree dest_addr = build_fold_addr_expr (tmp);
 
-      tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+      tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
 				   3, dest_addr, addr, size_int (rsize * 4));
 
       gimplify_and_add (copy, pre_p);
@@ -12213,8 +12213,8 @@  rs6000_init_builtins (void)
 
 #if TARGET_XCOFF
   /* AIX libm provides clog as __clog.  */
-  if (built_in_decls [BUILT_IN_CLOG])
-    set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
+  if ((tdecl = builtin_decl_explicit ([BUILT_IN_CLOG))) != NULL_TREE)
+    set_user_assembler_name (tdecl, "__clog");
 #endif
 
 #ifdef SUBTARGET_INIT_BUILTINS
Index: gcc/config/darwin.c
===================================================================
--- gcc/config/darwin.c	(.../trunk)	(revision 179514)
+++ gcc/config/darwin.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -2962,7 +2962,7 @@  darwin_override_options (void)
 static void
 darwin_patch_builtin (int fncode)
 {
-  tree fn = built_in_decls[fncode];
+  tree fn = builtin_decl_explicit (fncode);
   tree sym;
   char *newname;
 
@@ -2974,7 +2974,7 @@  darwin_patch_builtin (int fncode)
 
   set_user_assembler_name (fn, newname);
 
-  fn = implicit_built_in_decls[fncode];
+  fn = builtin_decl_implicit (fncode);
   if (fn)
     set_user_assembler_name (fn, newname);
 }
@@ -3149,9 +3149,10 @@  darwin_rename_builtins (void)
      use the faster version.  */
   if (!flag_unsafe_math_optimizations)
     {
-      int dcode = (BUILT_IN_COMPLEX_DIV_MIN
-		   + DCmode - MIN_MODE_COMPLEX_FLOAT);
-      tree fn = built_in_decls[dcode];
+      enum built_in_function dcode
+	= (enum built_in_function)(BUILT_IN_COMPLEX_DIV_MIN
+				   + DCmode - MIN_MODE_COMPLEX_FLOAT);
+      tree fn = builtin_decl_explicit (dcode);
       /* Fortran and c call TARGET_INIT_BUILTINS and
 	 TARGET_INIT_LIBFUNCS at different times, so we have to put a
 	 call into each to ensure that at least one of them is called
@@ -3159,7 +3160,7 @@  darwin_rename_builtins (void)
 	 new hook to run after build_common_builtin_nodes runs.  */
       if (fn)
 	set_user_assembler_name (fn, "___ieee_divdc3");
-      fn = implicit_built_in_decls[dcode];
+      fn = builtin_decl_implicit (dcode);
       if (fn)
 	set_user_assembler_name (fn, "___ieee_divdc3");
     }
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	(.../trunk)	(revision 179514)
+++ gcc/config/pa/pa.c	(.../branches/ibm/builtin)	(revision 179582)
@@ -555,16 +555,21 @@  static void
 pa_init_builtins (void)
 {
 #ifdef DONT_HAVE_FPUTC_UNLOCKED
-  built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] =
-    built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
-  implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED]
-    = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
+  {
+    tree decl = builtin_decl_explicit (BUILT_IN_PUTC_UNLOCKED);
+    set_builtin_decl (BUILT_IN_FPUTC_UNLOCKED, decl,
+		      builtin_decl_implicit_p (BUILT_IN_PUTC_UNLOCKED));
+  }
 #endif
 #if TARGET_HPUX_11
-  if (built_in_decls [BUILT_IN_FINITE])
-    set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], "_Isfinite");
-  if (built_in_decls [BUILT_IN_FINITEF])
-    set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef");
+  {
+    tree decl;
+
+    if ((decl = builtin_decl_explicit (BUILT_IN_FINITE)) != NULL_TREE)
+      set_user_assembler_name (decl, "_Isfinite");
+    if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF)) != NULL_TREE)
+      set_user_assembler_name (decl, "_Isfinitef");
+  }
 #endif
 
   if (HPUX_LONG_DOUBLE_LIBRARY)