]> git.pld-linux.org Git - packages/gcc.git/commitdiff
- patches from RH
authoraflinta <aflinta@pld-linux.org>
Mon, 16 Sep 2002 00:01:29 +0000 (00:01 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    gcc32-ada-link.patch -> 1.1
    gcc32-attr-visibility.patch -> 1.1
    gcc32-attr-visibility2.patch -> 1.1
    gcc32-attr-visibility3.patch -> 1.1
    gcc32-attr-visibility4.patch -> 1.1
    gcc32-attr-visibility5.patch -> 1.1
    gcc32-boehm-gc-libs.patch -> 1.1
    gcc32-bogus-inline.patch -> 1.1
    gcc32-c++-nrv-test.patch -> 1.1
    gcc32-c++-pretty_function.patch -> 1.1
    gcc32-c++-tail-pad.patch -> 1.1
    gcc32-c++-tail-pad2.patch -> 1.1
    gcc32-c++-tsubst-asm.patch -> 1.1
    gcc32-cfg-eh.patch -> 1.1
    gcc32-debug-pr7241.patch -> 1.1
    gcc32-doc-gcov.patch -> 1.1
    gcc32-duplicate-decl.patch -> 1.1
    gcc32-dwarf2-pr6381.patch -> 1.1
    gcc32-dwarf2-pr6436-test.patch -> 1.1
    gcc32-fde-merge-compat.patch -> 1.1
    gcc32-fold-const-associate.patch -> 1.1
    gcc32-fold-const2.patch -> 1.1
    gcc32-hard-reg-sharing.patch -> 1.1
    gcc32-hard-reg-sharing2.patch -> 1.1
    gcc32-i386-default-momit-leaf-frame-pointer.patch -> 1.1
    gcc32-i386-memtest-test.patch -> 1.1
    gcc32-i386-no-default-momit-leaf-frame-pointer.patch -> 1.1
    gcc32-i386-pic-label-thunk.patch -> 1.1
    gcc32-i386-pr7242.patch -> 1.1
    gcc32-i386-profile-olfp.patch -> 1.1
    gcc32-inline-label.patch -> 1.1
    gcc32-java-no-rpath.patch -> 1.1
    gcc32-locale_in_ctype_members.patch -> 1.1
    gcc32-locale_in_monetary_members.patch -> 1.1
    gcc32-loop-prefetch.patch -> 1.1
    gcc32-pr6842.patch -> 1.1
    gcc32-rh69989.patch -> 1.1
    gcc32-sparc-sll1.patch -> 1.1
    gcc32-test-rh65771.patch -> 1.1
    gcc32-test-rotate.patch -> 1.1
    gcc32-tls-dwarf2.patch -> 1.1
    gcc32-tls.patch -> 1.1
    gcc32-tls2.patch -> 1.1
    gcc32-tls3.patch -> 1.1
    gcc32-tls4.patch -> 1.1
    gcc32-tls5.patch -> 1.1
    gcc32-typeof-asm.patch -> 1.1
    gcc32-typeof-skip-eval.patch -> 1.1

48 files changed:
gcc32-ada-link.patch [new file with mode: 0644]
gcc32-attr-visibility.patch [new file with mode: 0644]
gcc32-attr-visibility2.patch [new file with mode: 0644]
gcc32-attr-visibility3.patch [new file with mode: 0644]
gcc32-attr-visibility4.patch [new file with mode: 0644]
gcc32-attr-visibility5.patch [new file with mode: 0644]
gcc32-boehm-gc-libs.patch [new file with mode: 0644]
gcc32-bogus-inline.patch [new file with mode: 0644]
gcc32-c++-nrv-test.patch [new file with mode: 0644]
gcc32-c++-pretty_function.patch [new file with mode: 0644]
gcc32-c++-tail-pad.patch [new file with mode: 0644]
gcc32-c++-tail-pad2.patch [new file with mode: 0644]
gcc32-c++-tsubst-asm.patch [new file with mode: 0644]
gcc32-cfg-eh.patch [new file with mode: 0644]
gcc32-debug-pr7241.patch [new file with mode: 0644]
gcc32-doc-gcov.patch [new file with mode: 0644]
gcc32-duplicate-decl.patch [new file with mode: 0644]
gcc32-dwarf2-pr6381.patch [new file with mode: 0644]
gcc32-dwarf2-pr6436-test.patch [new file with mode: 0644]
gcc32-fde-merge-compat.patch [new file with mode: 0644]
gcc32-fold-const-associate.patch [new file with mode: 0644]
gcc32-fold-const2.patch [new file with mode: 0644]
gcc32-hard-reg-sharing.patch [new file with mode: 0644]
gcc32-hard-reg-sharing2.patch [new file with mode: 0644]
gcc32-i386-default-momit-leaf-frame-pointer.patch [new file with mode: 0644]
gcc32-i386-memtest-test.patch [new file with mode: 0644]
gcc32-i386-no-default-momit-leaf-frame-pointer.patch [new file with mode: 0644]
gcc32-i386-pic-label-thunk.patch [new file with mode: 0644]
gcc32-i386-pr7242.patch [new file with mode: 0644]
gcc32-i386-profile-olfp.patch [new file with mode: 0644]
gcc32-inline-label.patch [new file with mode: 0644]
gcc32-java-no-rpath.patch [new file with mode: 0644]
gcc32-locale_in_ctype_members.patch [new file with mode: 0644]
gcc32-locale_in_monetary_members.patch [new file with mode: 0644]
gcc32-loop-prefetch.patch [new file with mode: 0644]
gcc32-pr6842.patch [new file with mode: 0644]
gcc32-rh69989.patch [new file with mode: 0644]
gcc32-sparc-sll1.patch [new file with mode: 0644]
gcc32-test-rh65771.patch [new file with mode: 0644]
gcc32-test-rotate.patch [new file with mode: 0644]
gcc32-tls-dwarf2.patch [new file with mode: 0644]
gcc32-tls.patch [new file with mode: 0644]
gcc32-tls2.patch [new file with mode: 0644]
gcc32-tls3.patch [new file with mode: 0644]
gcc32-tls4.patch [new file with mode: 0644]
gcc32-tls5.patch [new file with mode: 0644]
gcc32-typeof-asm.patch [new file with mode: 0644]
gcc32-typeof-skip-eval.patch [new file with mode: 0644]

diff --git a/gcc32-ada-link.patch b/gcc32-ada-link.patch
new file mode 100644 (file)
index 0000000..dcf5016
--- /dev/null
@@ -0,0 +1,201 @@
+--- gcc/ada/link.c.jj  Tue May  7 12:50:23 2002
++++ gcc/ada/link.c     Wed Jun  5 14:45:32 2002
+@@ -158,11 +158,11 @@ const char *object_library_extension = "
+ #elif defined (linux)
+ const char *object_file_option = "";
+-const char *run_path_option = "-Wl,-rpath,";
+-char shared_libgnat_default = STATIC;
++const char *run_path_option = "";
++char shared_libgnat_default = SHARED;
+ int link_max = 2147483647;
+ unsigned char objlist_file_supported = 0;
+-unsigned char using_gnu_linker = 0;
++unsigned char using_gnu_linker = 1;
+ const char *object_library_extension = ".a";
+ #elif defined (__svr4__) && defined (i386)
+--- gcc/ada/Makefile.in.jj     Wed Jun  5 16:06:56 2002
++++ gcc/ada/Makefile.in        Wed Jun  5 16:27:33 2002
+@@ -134,7 +134,7 @@ MISCLIB =
+ objext = .o
+ exeext =
+ arext  = .a
+-soext  = .so
++soext  = .so.1
+ shext  =
+ HOST_CC=$(CC)
+@@ -1214,6 +1214,33 @@ ifeq ($(strip $(filter-out %86 linux%,$(
+   endif
+ endif
++ifeq ($(strip $(filter-out alpha% linux%,$(arch) $(osys))),)
++  MLIB_TGT=5lml-tgt
++  MISCLIB=
++  THREADSLIB=-lpthread
++  GNATLIB_SHARED=gnatlib-shared-dual
++  GMEM_LIB=gmemlib
++  LIBRARY_VERSION := $(strip $(shell grep Library_Version $(fsrcpfx)gnatvsn.ads | sed -e 's/.*GNAT Lib v\(.*\)[ "].*/\1/'))
++endif
++
++ifeq ($(strip $(filter-out sparc% linux%,$(arch) $(osys))),)
++  MLIB_TGT=5lml-tgt
++  MISCLIB=
++  THREADSLIB=-lpthread
++  GNATLIB_SHARED=gnatlib-shared-dual
++  GMEM_LIB=gmemlib
++  LIBRARY_VERSION := $(strip $(shell grep Library_Version $(fsrcpfx)gnatvsn.ads | sed -e 's/.*GNAT Lib v\(.*\)[ "].*/\1/'))
++endif
++
++ifeq ($(strip $(filter-out ia64 linux%,$(arch) $(osys))),)
++  MLIB_TGT=5lml-tgt
++  MISCLIB=
++  THREADSLIB=-lpthread
++  GNATLIB_SHARED=gnatlib-shared-dual
++  GMEM_LIB=gmemlib
++  LIBRARY_VERSION := $(strip $(shell grep Library_Version $(fsrcpfx)gnatvsn.ads | sed -e 's/.*GNAT Lib v\(.*\)[ "].*/\1/'))
++endif
++
+ ifeq ($(strip $(filter-out mips sgi irix%,$(targ))),)
+   ifeq ($(strip $(filter-out mips sgi irix6%,$(targ))),)
+     LIBGNAT_TARGET_PAIRS = \
+@@ -2179,6 +2179,9 @@ endif
+ gnatlib: ../stamp-gnatlib1 ../stamp-gnatlib2
+ #     ../xgcc -B../ -dD -E ../tconfig.h $(INCLUDES) > rts/tconfig.h
++      $(RMDIR) save
++      $(MKDIR) save
++      $(MV) *.o save/
+       $(MAKE) -C rts CC="../../xgcc -B../../" \
+               INCLUDES="$(INCLUDES_FOR_SUBDIR) -I./../.." \
+                 CFLAGS="$(GNATLIBCFLAGS) $(TARGET_LIBGCC2_CFLAGS) -DIN_RTS" \
+@@ -2192,6 +2195,8 @@ gnatlib: ../stamp-gnatlib1 ../stamp-gnat
+               srcdir=$(fsrcdir) \
+               -f ../Makefile \
+               $(GNATRTL_OBJS)
++      $(MV) save/*.o .
++      $(RMDIR) save
+       $(RM) rts/libgnat$(arext) rts/libgnarl$(arext)
+       $(AR) $(AR_FLAGS) rts/libgnat$(arext) \
+          $(addprefix rts/,$(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS))
+@@ -2315,12 +2315,12 @@ gnatlib-shared-default:
+            THREAD_KIND="$(THREAD_KIND)" \
+              gnatlib
+       $(RM) rts/libgnat$(soext) rts/libgnarl$(soext)
+-      cd rts; ../../xgcc -B../../ -shared $(TARGET_LIBGCC2_CFLAGS) \
++      cd rts; ../../xgcc -B../../ -shared -shared-libgcc $(TARGET_LIBGCC2_CFLAGS) \
+               -o libgnat-$(LIBRARY_VERSION)$(soext) $(SO_OPTS)libgnat-$(LIBRARY_VERSION)$(soext) \
+               $(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS) $(MISCLIB) -lm
+       cd rts; ../../xgcc -B../../ -shared $(TARGET_LIBGCC2_CFLAGS) \
+               -o libgnarl-$(LIBRARY_VERSION)$(soext) $(SO_OPTS)libgnarl-$(LIBRARY_VERSION)$(soext) \
+-              $(GNATRTL_TASKING_OBJS) $(THREADSLIB)
++              $(GNATRTL_TASKING_OBJS) $(THREADSLIB) ./libgnat-$(LIBRARY_VERSION)$(soext)
+       cd rts; $(LN) libgnat-$(LIBRARY_VERSION)$(soext) libgnat$(soext)
+       cd rts; $(LN) libgnarl-$(LIBRARY_VERSION)$(soext) libgnarl$(soext)
+@@ -2358,62 +2363,62 @@ TREE_H = $(srcdir)/../tree.h $(srcdir)/.
+ ada_extra_files : treeprs.ads einfo.h sinfo.h nmake.adb nmake.ads
+-b_gnat1.c : $(GNAT1_ADA_OBJS)
++b_gnat1.c : $(GNAT1_ADA_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnat1.c -n gnat1drv.ali
+ b_gnat1.o : b_gnat1.c
+-b_gnatb.c : $(GNATBIND_OBJS)
++b_gnatb.c : $(GNATBIND_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatb.c gnatbind.ali
+ b_gnatb.o : b_gnatb.c
+-b_gnatc.c : $(GNATCMD_OBJS)
++b_gnatc.c : $(GNATCMD_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatc.c gnatcmd.ali
+ b_gnatc.o : b_gnatc.c
+-b_gnatch.c : $(GNATCHOP_OBJS)
++b_gnatch.c : $(GNATCHOP_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatch.c gnatchop.ali
+ b_gnatch.o : b_gnatch.c
+-b_gnatkr.c : $(GNATKR_OBJS)
++b_gnatkr.c : $(GNATKR_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatkr.c gnatkr.ali
+ b_gnatkr.o : b_gnatkr.c
+-b_gnatl.c : $(GNATLINK_OBJS)
++b_gnatl.c : $(GNATLINK_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatl.c gnatlink.ali
+ b_gnatl.o : b_gnatl.c
+-b_gnatls.c : $(GNATLS_OBJS)
++b_gnatls.c : $(GNATLS_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatls.c gnatls.ali
+-b_gnatm.c : $(GNATMAKE_OBJS)
++b_gnatm.c : $(GNATMAKE_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatm.c gnatmake.ali
+ b_gnatm.o : b_gnatm.c
+-b_gnatmem.c : $(GNATMEM_OBJS)
++b_gnatmem.c : $(GNATMEM_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatmem.c gnatmem.ali
+ b_gnatmem.o : b_gnatmem.c
+-b_gnatp.c : $(GNATPREP_OBJS)
++b_gnatp.c : $(GNATPREP_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatp.c gnatprep.ali
+ b_gnatp.o : b_gnatp.c
+-b_gnatpa.c : $(GNATPSTA_OBJS)
++b_gnatpa.c : $(GNATPSTA_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatpa.c gnatpsta.ali
+ b_gnatpa.o : b_gnatpa.c
+-b_gnatps.c : $(GNATPSYS_OBJS)
++b_gnatps.c : $(GNATPSYS_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatps.c gnatpsys.ali
+ b_gnatps.o : b_gnatps.c
+-b_gnatxref.c : $(GNATXREF_OBJS)
++b_gnatxref.c : $(GNATXREF_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatxref.c gnatxref.ali
+ b_gnatxref.o : b_gnatxref.c
+-b_gnatfind.c : $(GNATFIND_OBJS)
++b_gnatfind.c : $(GNATFIND_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatfind.c gnatfind.ali
+ b_gnatfind.o : b_gnatfind.c
+-b_gnatdll.c : $(GNATDLL_OBJS)
++b_gnatdll.c : $(GNATDLL_OBJS) interfac.o
+       $(GNATBIND) $(ADA_INCLUDES) -o b_gnatdll.c gnatdll.ali
+ b_gnatdll.o : b_gnatdll.c
+--- gcc/ada/gnat_rm.texi.jj    Tue Apr 23 20:27:39 2002
++++ gcc/ada/gnat_rm.texi       Thu Jun  6 14:30:21 2002
+@@ -31,6 +31,10 @@
+ @settitle GNAT Reference Manual
+ @setchapternewpage odd
+ @syncodeindex fn cp
++@dircategory Programming
++@direntry
++* gnat_rm: (gnat_rm).            GNAT Reference Manual
++@end direntry
+ @titlepage
+--- gcc/ada/gnat_ug.texi.jj    Tue May  7 12:50:03 2002
++++ gcc/ada/gnat_ug.texi       Thu Jun  6 14:30:33 2002
+@@ -75,6 +75,11 @@
+ @syncodeindex fn cp
+ @c %**end of header
++@dircategory Programming
++@direntry
++* gnat_ug: (gnat_ug).            GNAT User's Guide
++@end direntry
++
+ @titlepage
+ @ifset vms
diff --git a/gcc32-attr-visibility.patch b/gcc32-attr-visibility.patch
new file mode 100644 (file)
index 0000000..51536d8
--- /dev/null
@@ -0,0 +1,283 @@
+2002-02-26  Jakub Jelinek  <jakub@redhat.com>
+
+       * attribs.c (c_common_attribute_table): Add visibility.
+       (handle_visibility_attribute): New function.
+       * varasm.c (assemble_visibility): New function.
+       * output.h (assemble_visibility): Add prototype.
+       * tree.h (MODULE_LOCAL_P): Define.
+       * crtstuff.c (__dso_handle): Use visibility attribute.
+       * config/i386/i386.h (ENCODE_SECTION_INFO): Set SYMBOL_REF_FLAG
+       for MODULE_LOCAL_P symbols too.
+       * config/ia64/ia64.c (ia64_encode_section_info): Handle
+       MODULE_LOCAL_P symbols the same way as local symbols.
+       Add SDATA_NAME_FLAG_CHAR even if decl was explicitely forced
+       into .sdata/.sbss by the user.
+       * doc/extend.texi (Function Attributes): Document visibility
+       attribute.
+
+       * gcc.dg/ia64-visibility-1.c: New test.
+
+--- gcc/attribs.c      2002/02/25 22:38:52     1.14
++++ gcc/attribs.c      2002/02/26 21:17:14     1.15
+@@ -75,6 +75,8 @@ static tree handle_weak_attribute    PARAMS
+                                                bool *));
+ static tree handle_alias_attribute    PARAMS ((tree *, tree, tree, int,
+                                                bool *));
++static tree handle_visibility_attribute       PARAMS ((tree *, tree, tree, int,
++                                               bool *));
+ static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
+                                                            tree, int,
+                                                            bool *));
+@@ -148,6 +150,8 @@ static const struct attribute_spec c_com
+                             handle_deprecated_attribute },
+   { "vector_size",          1, 1, false, true, false,
+                             handle_vector_size_attribute },
++  { "visibility",           1, 1, true,  false, false,
++                            handle_visibility_attribute },
+   { NULL,                     0, 0, false, false, false, NULL }
+ };
+@@ -1061,6 +1065,50 @@ handle_alias_attribute (node, name, args
+   return NULL_TREE;
+ }
++/* Handle an "visibility" attribute; arguments as in
++   struct attribute_spec.handler.  */
++
++static tree
++handle_visibility_attribute (node, name, args, flags, no_add_attrs)
++     tree *node;
++     tree name;
++     tree args;
++     int flags ATTRIBUTE_UNUSED;
++     bool *no_add_attrs;
++{
++  tree decl = *node;
++
++  if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
++    {
++      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++  else
++    {
++      tree id;
++
++      id = TREE_VALUE (args);
++      if (TREE_CODE (id) != STRING_CST)
++      {
++        error ("visibility arg not a string");
++        *no_add_attrs = true;
++        return NULL_TREE;
++      }
++      if (strcmp (TREE_STRING_POINTER (id), "hidden")
++        && strcmp (TREE_STRING_POINTER (id), "protected")
++        && strcmp (TREE_STRING_POINTER (id), "internal"))
++      {
++        error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
++        *no_add_attrs = true;
++        return NULL_TREE;
++      }
++
++      assemble_visibility (decl, TREE_STRING_POINTER (id));
++    }
++
++  return NULL_TREE;
++}
++
+ /* Handle a "no_instrument_function" attribute; arguments as in
+    struct attribute_spec.handler.  */
+--- gcc/varasm.c       2002/02/20 23:19:19     1.250
++++ gcc/varasm.c       2002/02/26 21:17:14     1.251
+@@ -5160,6 +5160,25 @@ assemble_alias (decl, target)
+ #endif
+ }
++/* Emit an assembler directive to set symbol for DECL visibility to
++   VISIBILITY_TYPE.  */
++
++void
++assemble_visibility (decl, visibility_type)
++     tree decl;
++     const char *visibility_type ATTRIBUTE_UNUSED;
++{
++  const char *name;
++
++  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
++
++#ifdef HAVE_GAS_HIDDEN
++  fprintf (asm_out_file, "\t.%s\t%s\n", visibility_type, name);
++#else
++  warning ("visibility attribute not supported in this configuration; ignored");
++#endif
++}
++
+ /* Returns 1 if the target configuration supports defining public symbols
+    so that one of them will be chosen at link time instead of generating a
+    multiply-defined symbol error, whether through the use of weak symbols or
+--- gcc/output.h       2002/02/17 14:23:50     1.94
++++ gcc/output.h       2002/02/26 21:17:14     1.95
+@@ -255,6 +255,8 @@ extern void assemble_constant_align        PARA
+ extern void assemble_alias            PARAMS ((tree, tree));
++extern void assemble_visibility               PARAMS ((tree, const char *));
++
+ /* Output a string of literal assembler code
+    for an `asm' keyword used between functions.  */
+ extern void assemble_asm              PARAMS ((tree));
+--- gcc/tree.h 2002/02/20 00:19:33     1.308
++++ gcc/tree.h 2002/02/26 21:17:14     1.309
+@@ -2283,6 +2283,11 @@ extern tree merge_attributes            PARAMS ((t
+ extern tree merge_dllimport_decl_attributes PARAMS ((tree, tree));
+ #endif
++/* Return true if DECL will be always resolved to a symbol defined in the
++   same module (shared library or program).  */
++#define MODULE_LOCAL_P(DECL) \
++  (lookup_attribute ("visibility", DECL_ATTRIBUTES (DECL)) != NULL)
++
+ /* Return a version of the TYPE, qualified as indicated by the
+    TYPE_QUALS, if one exists.  If no qualified version exists yet,
+    return NULL_TREE.  */
+--- gcc/crtstuff.c     2002/02/05 10:31:01     1.54
++++ gcc/crtstuff.c     2002/02/26 21:17:14     1.55
+@@ -213,13 +213,9 @@ STATIC void *__JCR_LIST__[]
+    in one DSO or the main program is not used in another object.  The
+    dynamic linker takes care of this.  */
+-/* XXX Ideally the following should be implemented using
+-       __attribute__ ((__visibility__ ("hidden")))
+-   but the __attribute__ support is not yet there.  */
+ #ifdef HAVE_GAS_HIDDEN
+-asm (".hidden\t__dso_handle");
++extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
+ #endif
+-
+ #ifdef CRTSTUFFS_O
+ void *__dso_handle = &__dso_handle;
+ #else
+--- gcc/config/i386/i386.h     2002/02/17 07:52:12     1.243
++++ gcc/config/i386/i386.h     2002/02/26 21:17:18     1.244
+@@ -2266,7 +2266,9 @@ do {                                                             \
+                                                               \
+           SYMBOL_REF_FLAG (XEXP (rtl, 0))                     \
+             = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'      \
+-               || ! TREE_PUBLIC (DECL));                      \
++               || ! TREE_PUBLIC (DECL)                        \
++               || (TREE_CODE (DECL) == VAR_DECL               \
++                   && MODULE_LOCAL_P (DECL)));                \
+         }                                                     \
+       }                                                               \
+ } while (0)
+--- gcc/config/ia64/ia64.c     2002/01/21 02:24:02     1.139
++++ gcc/config/ia64/ia64.c     2002/02/26 22:41:48     1.141
+@@ -6897,13 +6904,14 @@ ia64_encode_section_info (decl)
+      statically allocated, but the space is allocated somewhere else.  Such
+      decls can not be own data.  */
+   if (! TARGET_NO_SDATA
+-      && TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
+-      && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
+-      && ! (TREE_PUBLIC (decl)
+-          && (flag_pic
+-              || (DECL_COMMON (decl)
+-                  && (DECL_INITIAL (decl) == 0
+-                      || DECL_INITIAL (decl) == error_mark_node))))
++      && ((TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
++         && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
++         && ! (TREE_PUBLIC (decl)
++               && (flag_pic
++                   || (DECL_COMMON (decl)
++                       && (DECL_INITIAL (decl) == 0
++                           || DECL_INITIAL (decl) == error_mark_node)))))
++        || MODULE_LOCAL_P (decl))
+       /* Either the variable must be declared without a section attribute,
+        or the section must be sdata or sbss.  */
+       && (DECL_SECTION_NAME (decl) == 0
+@@ -6923,9 +6931,12 @@ ia64_encode_section_info (decl)
+       ;
+       /* If this is an incomplete type with size 0, then we can't put it in
+-       sdata because it might be too big when completed.  */
+-      else if (size > 0
+-             && size <= (HOST_WIDE_INT) ia64_section_threshold
++       sdata because it might be too big when completed.
++       Objects bigger than threshold should have SDATA_NAME_FLAG_CHAR
++       added if they are in .sdata or .sbss explicitely.  */
++      else if (((size > 0
++               && size <= (HOST_WIDE_INT) ia64_section_threshold)
++              || DECL_SECTION_NAME (decl))
+              && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
+       {
+         size_t len = strlen (symbol_str);
+--- gcc/doc/extend.texi        2002/02/23 12:59:07     1.64
++++ gcc/doc/extend.texi        2002/02/26 21:17:17     1.65
+@@ -2198,7 +2198,7 @@ The @code{alias} attribute causes the de
+ alias for another symbol, which must be specified.  For instance,
+ @smallexample
+-void __f () @{ /* do something */; @}
++void __f () @{ /* @r{Do something.} */; @}
+ void f () __attribute__ ((weak, alias ("__f")));
+ @end smallexample
+@@ -2206,6 +2206,19 @@ declares @samp{f} to be a weak alias for
+ mangled name for the target must be used.
+ Not all target machines support this attribute.
++
++@item visibility ("@var{visibility_type}")
++@cindex @code{visibility} attribute
++The @code{visibility} attribute on ELF targets causes the declaration
++to be emitted with hidden, protected or internal visibility.
++
++@smallexample
++void __attribute__ ((visibility ("protected")))
++f () @{ /* @r{Do something.} */; @}
++int i __attribute__ ((visibility ("hidden")));
++@end smallexample
++
++Not all ELF targets support this attribute.
+ @item regparm (@var{number})
+ @cindex functions that are passed arguments in registers on the 386
+--- gcc/testsuite/gcc.dg/ia64-visibility-1.c.jj        Tue Feb 26 12:30:32 2002
++++ gcc/testsuite/gcc.dg/ia64-visibility-1.c   Tue Feb 26 12:33:26 2002
+@@ -0,0 +1,36 @@
++/* Test visibility attribute.  */
++/* { dg-do compile { target ia64*-*-linux* } } */
++/* { dg-options "-O2 -fpic" } */
++/* { dg-final { scan-assembler "\\.hidden.*variable_j" } } */
++/* { dg-final { scan-assembler "\\.hidden.*variable_m" } } */
++/* { dg-final { scan-assembler "\\.protected.*baz" } } */
++/* { dg-final { scan-assembler "gprel.*variable_i" } } */
++/* { dg-final { scan-assembler "gprel.*variable_j" } } */
++/* { dg-final { scan-assembler "ltoff.*variable_k" } } */
++/* { dg-final { scan-assembler "gprel.*variable_l" } } */
++/* { dg-final { scan-assembler "gprel.*variable_m" } } */
++/* { dg-final { scan-assembler "ltoff.*variable_n" } } */
++
++static int variable_i;
++int variable_j __attribute__((visibility ("hidden")));
++int variable_k;
++struct A { char a[64]; };
++static struct A variable_l __attribute__((section (".sbss")));
++struct A variable_m __attribute__((visibility ("hidden"), section(".sbss")));
++struct A variable_n __attribute__((section (".sbss")));
++
++int foo (void)
++{
++  return variable_i + variable_j + variable_k;
++}
++
++void bar (void)
++{
++  variable_l.a[10] = 0;
++  variable_m.a[10] = 0;
++  variable_n.a[10] = 0;
++}
++
++void __attribute__((visibility ("protected"))) baz (void)
++{
++}
diff --git a/gcc32-attr-visibility2.patch b/gcc32-attr-visibility2.patch
new file mode 100644 (file)
index 0000000..a36471b
--- /dev/null
@@ -0,0 +1,109 @@
+2002-03-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/i386/i386.h (REDO_SECTION_INFO_P): Define.
+
+2002-03-02  Richard Henderson  <rth@redhat.com>
+
+       * config/i386/i386.h (ENCODE_SECTION_INFO): MODULE_LOCAL_P applies
+       to functions as well.
+
+2002-03-02  Richard Henderson  <rth@redhat.com>
+
+       * attribs.c (handle_visibility_attribute): Don't call
+       assemble_visibility.
+       * varasm.c (maybe_assemble_visibility): New.
+       (assemble_start_function, assemble_variable, assemble_alias): Use it.
+
+--- gcc/config/i386/i386.h.jj  Tue Jun  4 18:54:32 2002
++++ gcc/config/i386/i386.h     Tue Jun  4 18:54:42 2002
+@@ -2268,12 +2268,13 @@ do {                                                           \
+           SYMBOL_REF_FLAG (XEXP (rtl, 0))                     \
+             = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'      \
+                || ! TREE_PUBLIC (DECL)                        \
+-               || (TREE_CODE (DECL) == VAR_DECL               \
+-                   && MODULE_LOCAL_P (DECL)));                \
++               || MODULE_LOCAL_P (DECL));                     \
+         }                                                     \
+       }                                                               \
+ } while (0)
++#define REDO_SECTION_INFO_P(DECL) 1
++
+ /* The `FINALIZE_PIC' macro serves as a hook to emit these special
+    codes once the function is being compiled into assembly code, but
+    not before.  (It is not done before, because in the case of
+--- gcc/varasm.c.jj    Tue Jun  4 18:54:32 2002
++++ gcc/varasm.c       Tue Jun  4 18:54:42 2002
+@@ -167,6 +167,7 @@ static unsigned min_align          PARAMS ((unsi
+ static void output_constructor                PARAMS ((tree, HOST_WIDE_INT,
+                                                unsigned int));
+ static void globalize_decl            PARAMS ((tree));
++static void maybe_assemble_visibility PARAMS ((tree));
+ static int in_named_entry_eq          PARAMS ((const PTR, const PTR));
+ static hashval_t in_named_entry_hash  PARAMS ((const PTR));
+ #ifdef ASM_OUTPUT_BSS
+@@ -1238,6 +1239,8 @@ assemble_start_function (decl, fnname)
+       }
+       globalize_decl (decl);
++
++      maybe_assemble_visibility (decl);
+     }
+   /* Do any machine/system dependent processing of the function name */
+@@ -1591,6 +1594,9 @@ assemble_variable (decl, top_level, at_e
+   DECL_ALIGN (decl) = align;
+   set_mem_align (decl_rtl, align);
++  if (TREE_PUBLIC (decl))
++    maybe_assemble_visibility (decl);
++
+   /* Handle uninitialized definitions.  */
+   if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
+@@ -5167,7 +5173,11 @@ assemble_alias (decl, target)
+ #ifdef ASM_OUTPUT_DEF
+   /* Make name accessible from other files, if appropriate.  */
+   if (TREE_PUBLIC (decl))
+-    globalize_decl (decl);
++    {
++      globalize_decl (decl);
++
++      maybe_assemble_visibility (decl);
++    }
+ #ifdef ASM_OUTPUT_DEF_FROM_DECLS
+   ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
+@@ -5213,6 +5223,21 @@ assemble_visibility (decl, visibility_ty
+ #endif
+ }
++/* A helper function to call assemble_visibility when needed for a decl.  */
++
++static void
++maybe_assemble_visibility (decl)
++     tree decl;
++{
++  tree visibility = lookup_attribute ("visibility", DECL_ATTRIBUTES (decl));
++  if (visibility)
++    {
++      const char *type
++      = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (visibility)));
++      assemble_visibility (decl, type);
++    }
++}
++
+ /* Returns 1 if the target configuration supports defining public symbols
+    so that one of them will be chosen at link time instead of generating a
+    multiply-defined symbol error, whether through the use of weak symbols or
+--- gcc/attribs.c.jj   Tue Jun  4 18:54:32 2002
++++ gcc/attribs.c      Tue Jun  4 18:54:42 2002
+@@ -1101,8 +1101,6 @@ handle_visibility_attribute (node, name,
+         *no_add_attrs = true;
+         return NULL_TREE;
+       }
+-
+-      assemble_visibility (decl, TREE_STRING_POINTER (id));
+     }
+   return NULL_TREE;
diff --git a/gcc32-attr-visibility3.patch b/gcc32-attr-visibility3.patch
new file mode 100644 (file)
index 0000000..bc66ec9
--- /dev/null
@@ -0,0 +1,35 @@
+2002-07-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * varasm.c (assemble_visibility): Strip name encoding.
+
+       * gcc.dg/ia64-visibility-2.c: New test.
+
+--- gcc/testsuite/gcc.dg/ia64-visibility-2.c.jj        2002-07-31 16:31:50.000000000 +0200
++++ gcc/testsuite/gcc.dg/ia64-visibility-2.c   2002-07-31 16:32:36.000000000 +0200
+@@ -0,0 +1,15 @@
++/* Test visibility attribute.  */
++/* { dg-do link { target ia64*-*-linux* } } */
++/* { dg-options "-O2 -fpic" } */
++
++int foo (int x);
++int bar (int x) __asm__ ("foo") __attribute__ ((visibility ("hidden")));
++int bar (int x)
++{
++  return x;
++}
++
++int main ()
++{
++  return 0;
++}
+--- gcc/varasm.c.jj    2002-07-30 12:49:45.000000000 +0200
++++ gcc/varasm.c       2002-07-31 16:20:22.000000000 +0200
+@@ -5227,7 +5227,7 @@ assemble_visibility (decl, visibility_ty
+ {
+   const char *name;
+-  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
++  STRIP_NAME_ENCODING (name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ #ifdef HAVE_GAS_HIDDEN
+   fprintf (asm_out_file, "\t.%s\t%s\n", visibility_type, name);
diff --git a/gcc32-attr-visibility4.patch b/gcc32-attr-visibility4.patch
new file mode 100644 (file)
index 0000000..eccfbb9
--- /dev/null
@@ -0,0 +1,16 @@
+2002-08-23  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/alpha/alpha.c (alpha_encode_section_info): Use
+       MODULE_LOCAL_P.
+
+--- gcc/config/alpha/alpha.c.jj        2002-05-30 11:12:20.000000000 +0200
++++ gcc/config/alpha/alpha.c   2002-08-23 12:05:30.000000000 +0200
+@@ -1594,7 +1594,7 @@ alpha_encode_section_info (decl)
+   /* Linkonce and weak data is never local.  */
+   else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
+     is_local = false;
+-  else if (! TREE_PUBLIC (decl))
++  else if (! TREE_PUBLIC (decl) || MODULE_LOCAL_P (decl))
+     is_local = true;
+   /* If PIC, then assume that any global name can be overridden by
+      symbols resolved from other modules.  */
diff --git a/gcc32-attr-visibility5.patch b/gcc32-attr-visibility5.patch
new file mode 100644 (file)
index 0000000..b76b661
--- /dev/null
@@ -0,0 +1,24 @@
+2002-08-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/alpha/alpha.c (alpha_encode_section_info): Check static and
+       visibility before DECL_EXTERNAL.
+
+--- gcc/config/alpha/alpha.c.jj        2002-08-28 11:20:29.000000000 +0200
++++ gcc/config/alpha/alpha.c   2002-08-28 21:50:55.000000000 +0200
+@@ -1589,13 +1589,13 @@ alpha_encode_section_info (decl)
+   /* A variable is considered "local" if it is defined in this module.  */
+-  if (DECL_EXTERNAL (decl))
++  if (! TREE_PUBLIC (decl) || MODULE_LOCAL_P (decl))
++    is_local = true;
++  else if (DECL_EXTERNAL (decl))
+     is_local = false;
+   /* Linkonce and weak data is never local.  */
+   else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
+     is_local = false;
+-  else if (! TREE_PUBLIC (decl) || MODULE_LOCAL_P (decl))
+-    is_local = true;
+   /* If PIC, then assume that any global name can be overridden by
+      symbols resolved from other modules.  */
+   else if (flag_pic)
diff --git a/gcc32-boehm-gc-libs.patch b/gcc32-boehm-gc-libs.patch
new file mode 100644 (file)
index 0000000..fb58e1a
--- /dev/null
@@ -0,0 +1,192 @@
+--- boehm-gc/configure.in.jj   Tue Dec 18 01:27:56 2001
++++ boehm-gc/configure.in      Fri Jan 25 14:10:17 2002
+@@ -57,11 +57,18 @@ AC_ARG_ENABLE(parallel-mark,
+     esac]
+ )
++AC_CHECK_LIB(dl, dlopen, [
++EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl"
++LIBGCJGC_EXTRA_LDFLAGS="-ldl"
++])
++AC_SUBST(EXTRA_TEST_LIBS)
++
+ INCLUDES=-I${srcdir}/include
+ THREADLIBS=
+ case "$THREADS" in
+  no | none | single)
+     THREADS=none
++    LIBGCJGC_EXTRA_LDFLAGS=
+     ;;
+  posix | pthreads)
+     THREADS=posix
+@@ -105,6 +112,7 @@ case "$THREADS" in
+       ;;
+      *-*-cygwin*)
+       THREADLIBS=
++      LIBGCJGC_EXTRA_LDFLAGS=
+       ;;
+     esac
+     ;;
+@@ -116,9 +124,7 @@ case "$THREADS" in
+     ;;
+ esac
+ AC_SUBST(THREADLIBS)
+-
+-AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl")
+-AC_SUBST(EXTRA_TEST_LIBS)
++AC_SUBST(LIBGCJGC_EXTRA_LDFLAGS)
+ target_all=libgcjgc.la
+ AC_SUBST(target_all)
+--- boehm-gc/configure.jj      Thu Jan  3 14:25:13 2002
++++ boehm-gc/configure Fri Jan 25 14:10:36 2002
+@@ -2647,11 +2647,57 @@ if test "${enable_parallel_mark+set}" = 
+ fi
++echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
++echo "configure:2635: checking for dlopen in -ldl" >&5
++ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
++if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  ac_save_LIBS="$LIBS"
++LIBS="-ldl  $LIBS"
++cat > conftest.$ac_ext <<EOF
++#line 2643 "configure"
++#include "confdefs.h"
++/* Override any gcc2 internal prototype to avoid an error.  */
++/* We use char because int might match the return type of a gcc2
++    builtin and then its argument prototype would still apply.  */
++char dlopen();
++
++int main() {
++dlopen()
++; return 0; }
++EOF
++if { (eval echo configure:2654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++  rm -rf conftest*
++  eval "ac_cv_lib_$ac_lib_var=yes"
++else
++  echo "configure: failed program was:" >&5
++  cat conftest.$ac_ext >&5
++  rm -rf conftest*
++  eval "ac_cv_lib_$ac_lib_var=no"
++fi
++rm -f conftest*
++LIBS="$ac_save_LIBS"
++
++fi
++if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
++  echo "$ac_t""yes" 1>&6
++  
++EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl"
++LIBGCJGC_EXTRA_LDFLAGS="-ldl"
++
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++
++
+ INCLUDES=-I${srcdir}/include
+ THREADLIBS=
+ case "$THREADS" in
+  no | none | single)
+     THREADS=none
++    LIBGCJGC_EXTRA_LDFLAGS=
+     ;;
+  posix | pthreads)
+     THREADS=posix
+@@ -2736,6 +2782,7 @@ EOF
+       ;;
+      *-*-cygwin*)
+       THREADLIBS=
++      LIBGCJGC_EXTRA_LDFLAGS=
+       ;;
+     esac
+     ;;
+@@ -2758,48 +2805,6 @@ EOF
+ esac
+-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+-echo "configure:2763: checking for dlopen in -ldl" >&5
+-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+-  echo $ac_n "(cached) $ac_c" 1>&6
+-else
+-  ac_save_LIBS="$LIBS"
+-LIBS="-ldl  $LIBS"
+-cat > conftest.$ac_ext <<EOF
+-#line 2771 "configure"
+-#include "confdefs.h"
+-/* Override any gcc2 internal prototype to avoid an error.  */
+-/* We use char because int might match the return type of a gcc2
+-    builtin and then its argument prototype would still apply.  */
+-char dlopen();
+-
+-int main() {
+-dlopen()
+-; return 0; }
+-EOF
+-if { (eval echo configure:2782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+-  rm -rf conftest*
+-  eval "ac_cv_lib_$ac_lib_var=yes"
+-else
+-  echo "configure: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
+-  rm -rf conftest*
+-  eval "ac_cv_lib_$ac_lib_var=no"
+-fi
+-rm -f conftest*
+-LIBS="$ac_save_LIBS"
+-
+-fi
+-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+-  echo "$ac_t""yes" 1>&6
+-  EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl"
+-else
+-  echo "$ac_t""no" 1>&6
+-fi
+-
+-
+-
+ target_all=libgcjgc.la
+@@ -3215,8 +3220,9 @@ s%@OBJEXT@%$OBJEXT%g
+ s%@STRIP@%$STRIP%g
+ s%@LIBTOOL@%$LIBTOOL%g
+ s%@CXXCPP@%$CXXCPP%g
+-s%@THREADLIBS@%$THREADLIBS%g
+ s%@EXTRA_TEST_LIBS@%$EXTRA_TEST_LIBS%g
++s%@THREADLIBS@%$THREADLIBS%g
++s%@LIBGCJGC_EXTRA_LDFLAGS@%$LIBGCJGC_EXTRA_LDFLAGS%g
+ s%@target_all@%$target_all%g
+ s%@INCLUDES@%$INCLUDES%g
+ s%@CXXINCLUDES@%$CXXINCLUDES%g
+--- boehm-gc/Makefile.am.jj    Mon Oct 22 11:06:57 2001
++++ boehm-gc/Makefile.am       Fri Jan 25 14:11:35 2002
+@@ -37,7 +37,8 @@ solaris_pthreads.c solaris_threads.c spe
+ # linuxthread semaphore functions get linked:
+ libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
+ libgcjgc_la_DEPENDENCIES = @addobjs@
+-libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
++libgcjgc_la_LDFLAGS = @LIBGCJGC_EXTRA_LDFLAGS@ -version-info 1:1:0 \
++                    -rpath $(toolexeclibdir)
+ EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s \
+ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
+--- boehm-gc/Makefile.in.jj    Thu Jan  3 14:25:13 2002
++++ boehm-gc/Makefile.in       Fri Jan 25 14:12:03 2002
+@@ -118,7 +118,8 @@ libgcjgc_la_SOURCES = allchblk.c alloc.c
+ # linuxthread semaphore functions get linked:
+ libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
+ libgcjgc_la_DEPENDENCIES = @addobjs@
+-libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
++libgcjgc_la_LDFLAGS = @LIBGCJGC_EXTRA_LDFLAGS@ -version-info 1:1:0 \
++                    -rpath $(toolexeclibdir)
+ EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s rs6000_mach_dep.s sparc_mach_dep.s sparc_netbsd_mach_dep.s sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
diff --git a/gcc32-bogus-inline.patch b/gcc32-bogus-inline.patch
new file mode 100644 (file)
index 0000000..1379cb4
--- /dev/null
@@ -0,0 +1,96 @@
+2001-10-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree-inline.c (initialize_inlined_parameters): Fail if less
+       arguments are passed than expected.
+       (expand_call_inline): Cleanup if initialize_inlined_parameters
+       fails.
+
+       * g++.dg/other/inline1.C: New test.
+
+--- gcc/tree-inline.c.jj       Tue Oct  9 16:03:13 2001
++++ gcc/tree-inline.c  Fri Oct 12 17:08:23 2001
+@@ -474,17 +474,25 @@ initialize_inlined_parameters (id, args,
+   /* Loop through the parameter declarations, replacing each with an
+      equivalent VAR_DECL, appropriately initialized.  */
+-  for (p = parms, a = args; p;
+-       a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
++  for (p = parms, a = args; p; a = TREE_CHAIN (a), p = TREE_CHAIN (p))
+     {
+       tree init_stmt;
+       tree var;
+       tree value;
+       tree cleanup;
++      if (a == NULL_TREE)
++      {
++        pop_srcloc ();
++        /* If less arguments were passed than actually required,
++           issue warning and avoid inlining.  */
++        warning ("too few arguments passed to inline function, suppressing inlining");
++        return error_mark_node;
++      }
++
+       /* Find the initializer.  */
+       value = (*lang_hooks.tree_inlining.convert_parm_for_inlining)
+-            (p, a ? TREE_VALUE (a) : NULL_TREE, fn);
++            (p, TREE_VALUE (a), fn);
+       /* If the parameter is never assigned to, we may not need to
+        create a new variable here at all.  Instead, we may be able
+@@ -863,6 +871,14 @@ expand_call_inline (tp, walk_subtrees, d
+   /* Initialize the parameters.  */
+   arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn);
++  if (arg_inits == error_mark_node)
++    {
++      /* Clean up.  */
++      splay_tree_delete (id->decl_map);
++      id->decl_map = st;
++      return NULL_TREE;
++    }
++
+   /* Expand any inlined calls in the initializers.  Do this before we
+      push FN on the stack of functions we are inlining; we want to
+      inline calls to FN that appear in the initializers for the
+--- gcc/testsuite/g++.dg/other/inline1.C.jj    Fri Oct 12 16:54:05 2001
++++ gcc/testsuite/g++.dg/other/inline1.C       Fri Oct 12 17:14:35 2001
+@@ -0,0 +1,38 @@
++// { dg-do compile { target i?86-*-* } }
++// { dg-options -O }
++
++typedef unsigned int u4;
++typedef unsigned long long u8;
++typedef u8 (*u8tou8)(u8);
++
++struct C {
++  static inline u8 a(u4 x, u4 y);
++  static inline u8 b(unsigned char *p) { return c(*(u8 *)p); }
++  static inline u8 c(u8 x) {  // { dg-warning "too few arguments" "too few" }
++    return ((u8tou8)a)(x);
++  }
++};
++
++inline u8 C::a(u4 x, u4 y) {
++  return x + y;
++}
++
++u8 n = 0x123456789abcdef;
++
++struct B {
++  unsigned char *e;
++  B() { e = (unsigned char *) &n; }
++  u8 f() {
++    return C::b(e);
++  }
++};
++
++struct A {
++  B *g;
++  void foo ();
++};
++
++void A::foo ()
++{
++  g->f();
++}
diff --git a/gcc32-c++-nrv-test.patch b/gcc32-c++-nrv-test.patch
new file mode 100644 (file)
index 0000000..05cb6bd
--- /dev/null
@@ -0,0 +1,120 @@
+2002-07-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/opt/nrv5.C: New test.
+
+2002-07-05  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/opt/nrv4.C: New test.
+
+2002-04-09  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/opt/nrv3.C: New test.
+
+--- gcc/testsuite/g++.dg/opt/nrv3.C.jj Thu Apr 11 16:25:15 2002
++++ gcc/testsuite/g++.dg/opt/nrv3.C    Tue Apr  9 19:02:43 2002
+@@ -0,0 +1,24 @@
++// PR optimization/6189
++// Bug: we forgot about foo's nrv after writing it out.
++// { dg-options -O3 }
++// { dg-do run }
++
++struct A
++{
++  int i;
++};
++
++
++A foo ()
++{
++  A a;
++  a.i = 42;
++  return a;
++}
++
++
++int main()
++{
++  A b = foo();
++  return b.i != 42;
++}
+--- gcc/testsuite/g++.dg/opt/nrv4.C.jj Thu Apr 11 16:25:15 2002
++++ gcc/testsuite/g++.dg/opt/nrv4.C    Fri Jul  5 17:16:56 2002
+@@ -0,0 +1,23 @@
++// PR optimization/7145
++// Bug: The NRV optimization caused us to lose the initializer for 'ret'.
++// { dg-options -O }
++// { dg-do run }
++
++struct GdkColor {
++  long  pixel;
++  short red;
++  short green;
++  short blue;
++};
++
++inline GdkColor mkcolor() {
++  GdkColor ret={0,1,2,3};
++  return ret;
++}
++
++int
++main()
++{
++  GdkColor col=mkcolor();
++  return (col.pixel != 0 || col.red != 1 || col.green != 2 || col.blue != 3);
++}
+--- gcc/testsuite/g++.dg/opt/nrv5.C.jj Thu Apr 11 16:25:15 2002
++++ gcc/testsuite/g++.dg/opt/nrv5.C    Thu Jul 11 11:29:33 2002
+@@ -0,0 +1,52 @@
++// Test for the named return value optimization with inlining.
++// Contributed by Jakub Jelinek <jakub@redhat.com>.
++// { dg-do run }
++// { dg-options -O2 }
++
++enum E { E0, E1, E2, E3 };
++
++struct S
++{
++  E s0 : 2;
++  bool s1 : 1, s2 : 1, s3 : 1, s4 : 1, s5 : 1, s6 : 1;
++  S () : s1 (true), s2 (false), s0 (E1), s3 (true), s4 (false), s5 (true), s6 (false) {}
++  void foo (E x) { this->s0 = x; }
++};
++
++inline S foo ()
++{
++  S s;
++  s.foo (E0);
++  return s;
++}
++
++inline S bar ()
++{
++  S s;
++  s.foo (E2);
++  return s;
++}
++
++void check (S &s, bool isfoo);
++
++void test (bool isfoo)
++{
++  S a = isfoo ? foo () : bar ();
++  check (a, isfoo);
++}
++
++extern "C" void abort ();
++
++void check (S &s, bool isfoo)
++{
++  if (! s.s1 || s.s2 || ! s.s3 || s.s4 || ! s.s5 || s.s6)
++    abort ();
++  if (s.s0 != (isfoo ? E0 : E2))
++    abort ();
++}
++
++int main ()
++{
++  test (true);
++  test (false);
++}
diff --git a/gcc32-c++-pretty_function.patch b/gcc32-c++-pretty_function.patch
new file mode 100644 (file)
index 0000000..be1f5fc
--- /dev/null
@@ -0,0 +1,170 @@
+2002-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/6794
+       * decl.c (cp_make_fname_decl): If outside of function, emit
+       the variable immediately.
+       * call.c (build_call): Avoid crashing when noreturn function
+       is called outside of function context.
+
+       * g++.dg/ext/pretty1.C: New test.
+       * g++.dg/ext/pretty2.C: New test.
+
+--- gcc/cp/decl.c.jj   Tue May 21 20:27:10 2002
++++ gcc/cp/decl.c      Fri May 24 17:28:16 2002
+@@ -6772,7 +6772,10 @@ cp_make_fname_decl (id, type_dep)
+   TREE_USED (decl) = 1;
+   cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+-      
++
++  if (!current_function_decl)
++    rest_of_decl_compilation (decl, 0, 1, 0);
++
+   return decl;
+ }
+--- gcc/cp/call.c.jj   Mon Apr 15 14:48:51 2002
++++ gcc/cp/call.c      Fri May 24 12:49:22 2002
+@@ -408,7 +408,7 @@ build_call (function, parms)
+   nothrow = ((decl && TREE_NOTHROW (decl))
+            || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
+-  if (decl && TREE_THIS_VOLATILE (decl))
++  if (decl && TREE_THIS_VOLATILE (decl) && current_function_decl)
+     current_function_returns_abnormally = 1;
+   if (decl && TREE_DEPRECATED (decl))
+--- gcc/testsuite/g++.dg/ext/pretty1.C.jj      Fri May 24 18:09:27 2002
++++ gcc/testsuite/g++.dg/ext/pretty1.C Fri May 24 18:13:10 2002
+@@ -0,0 +1,67 @@
++// PR c++/6794
++// Test whether __PRETTY_FUNCTION__ works in templates, functions and
++// in initializers at global scope
++// { dg-do compile }
++// { dg-options "" }
++
++extern "C" void __assert_fail (const char *, const char *,
++                             unsigned int, const char *)
++  throw() __attribute__((noreturn));
++extern "C" void abort (void);
++extern "C" void exit (int);
++
++#define str(expr) #expr
++#define assert(expr)                                          \
++  ((expr) ? 0 : (__assert_fail (str(expr), __FILE__, __LINE__,        \
++                              __PRETTY_FUNCTION__), 0))
++
++int __attribute__((noinline))
++foo (void)
++{
++  return 1;
++}
++
++template<class T> int
++bar (T)
++{
++  return (assert (foo ()), 1);
++}
++
++template<> int
++bar<int> (int)
++{
++  return (assert (foo ()), 2);
++}
++
++int a = (assert (foo ()), 1);
++int b = (assert (foo ()), 2);
++
++int
++main ()
++{
++  double c = 1.0;
++  unsigned char *d = 0;
++  int e = (assert (foo ()), 3);
++
++  bar (c);
++  bar (d);
++  bar (e);
++}
++
++namespace N
++{
++  int f = (assert (foo ()), 4);
++}
++
++void __attribute__((noinline))
++__assert_fail (const char *cond, const char *file, unsigned int line,
++             const char *pretty) throw ()
++{
++  abort ();
++}
++
++// { dg-final { scan-assembler "int bar\\(T\\).*with T = int" } }
++// { dg-final { scan-assembler "top level" } }
++// { dg-final { scan-assembler "int main\\(\\)" } }
++// { dg-final { scan-assembler "int bar\\(T\\).*with T = double" } }
++// { dg-final { scan-assembler "int bar\\(T\\).*with T = unsigned char\*" } }
+--- gcc/testsuite/g++.dg/ext/pretty2.C.jj      Fri May 24 18:09:27 2002
++++ gcc/testsuite/g++.dg/ext/pretty2.C Fri May 24 18:13:42 2002
+@@ -0,0 +1,61 @@
++// PR c++/6794
++// Test whether __PRETTY_FUNCTION__ works in templates, functions and
++// in initializers at global scope
++// { dg-do run }
++// { dg-options "" }
++
++extern "C" void __assert_fail (const char *, const char *,
++                             unsigned int, const char *)
++  throw() __attribute__((noreturn));
++extern "C" void abort (void);
++extern "C" void exit (int);
++
++#define str(expr) #expr
++#define assert(expr)                                          \
++  ((expr) ? 0 : (__assert_fail (str(expr), __FILE__, __LINE__,        \
++                              __PRETTY_FUNCTION__), 0))
++
++int __attribute__((noinline))
++foo (void)
++{
++  return 1;
++}
++
++template<class T> int
++bar (T)
++{
++  return (assert (foo ()), 1);
++}
++
++template<> int
++bar<int> (int)
++{
++  return (assert (foo ()), 2);
++}
++
++int a = (assert (foo ()), 1);
++int b = (assert (foo ()), 2);
++
++int
++main ()
++{
++  double c = 1.0;
++  unsigned char *d = 0;
++  int e = (assert (foo ()), 3);
++
++  bar (c);
++  bar (d);
++  bar (e);
++}
++
++namespace N
++{
++  int f = (assert (foo ()), 4);
++}
++
++void __attribute__((noinline))
++__assert_fail (const char *cond, const char *file, unsigned int line,
++             const char *pretty) throw ()
++{
++  abort ();
++}
diff --git a/gcc32-c++-tail-pad.patch b/gcc32-c++-tail-pad.patch
new file mode 100644 (file)
index 0000000..c431981
--- /dev/null
@@ -0,0 +1,281 @@
+2002-08-22  Jason Merrill  <jason@redhat.com>
+
+       * langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro.
+       * langhooks.c (lhd_expr_size): Define default.
+       * langhooks.h (struct lang_hooks): Add expr_size.
+       * explow.c (expr_size): Call it.
+       (int_expr_size): New fn.
+       * expr.h: Declare it.
+       * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how
+       much to store.
+cp/
+       PR c++/5607
+       * search.c (check_final_overrider): No longer static.
+       * class.c (update_vtable_entry_for_fn): Call it.
+       * cp-tree.h: Adjust.
+
+       * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
+       (cp_expr_size): New fn.
+       * call.c (convert_arg_to_ellipsis): Promote non-POD warning to error.
+       * typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
+
+--- gcc/cp/call.c.jj   2002-04-15 14:48:51.000000000 +0200
++++ gcc/cp/call.c      2002-08-23 13:51:08.000000000 +0200
+@@ -4022,9 +4022,12 @@ convert_arg_to_ellipsis (arg)
+   
+   if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
+     {
+-      /* Undefined behaviour [expr.call] 5.2.2/7.  */
+-      warning ("cannot pass objects of non-POD type `%#T' through `...'",
+-                TREE_TYPE (arg));
++      /* Undefined behaviour [expr.call] 5.2.2/7.  We used to just warn
++       here and do a bitwise copy, but now cp_expr_size will abort if we
++       try to do that.  */
++      error ("cannot pass objects of non-POD type `%#T' through `...'",
++           TREE_TYPE (arg));
++      arg = error_mark_node;
+     }
+   return arg;
+--- gcc/cp/class.c.jj  2002-08-05 18:30:31.000000000 +0200
++++ gcc/cp/class.c     2002-08-23 13:51:08.000000000 +0200
+@@ -2454,6 +2454,10 @@ update_vtable_entry_for_fn (t, binfo, fn
+   if (overrider == error_mark_node)
+     return;
++  /* Check for unsupported covariant returns again now that we've
++     calculated the base offsets.  */
++  check_final_overrider (TREE_PURPOSE (overrider), fn);
++
+   /* Assume that we will produce a thunk that convert all the way to
+      the final overrider, and not to an intermediate virtual base.  */
+   virtual_base = NULL_TREE;
+--- gcc/cp/cp-lang.c.jj        2002-05-25 00:02:21.000000000 +0200
++++ gcc/cp/cp-lang.c   2002-08-23 13:51:08.000000000 +0200
+@@ -28,7 +28,8 @@ Boston, MA 02111-1307, USA.  */
+ #include "langhooks.h"
+ #include "langhooks-def.h"
+-static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
++static HOST_WIDE_INT cxx_get_alias_set                PARAMS ((tree));
++static tree cp_expr_size                      PARAMS ((tree));
+ #undef LANG_HOOKS_NAME
+ #define LANG_HOOKS_NAME "GNU C++"
+@@ -91,6 +92,8 @@ static HOST_WIDE_INT cxx_get_alias_set P
+ #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
+ #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
+ #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals
++#undef LANG_HOOKS_EXPR_SIZE
++#define LANG_HOOKS_EXPR_SIZE cp_expr_size
+ /* Each front end provides its own hooks, for toplev.c.  */
+ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+@@ -108,3 +111,28 @@ cxx_get_alias_set (t)
+   return c_common_get_alias_set (t);
+ }
++
++/* Langhook for expr_size: Tell the backend that the value of an expression
++   of non-POD class type does not include any tail padding; a derived class
++   might have allocated something there.  */
++
++static tree
++cp_expr_size (exp)
++     tree exp;
++{
++  if (CLASS_TYPE_P (TREE_TYPE (exp)))
++    {
++      /* The backend should not be interested in the size of an expression
++       of a type with both of these set; all copies of such types must go
++       through a constructor or assignment op.  */
++      if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
++        && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp)))
++      abort ();
++      /* This would be wrong for a type with virtual bases, but they are
++       caught by the abort above.  */
++      return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp));
++    }
++  else
++    /* Use the default code.  */
++    return lhd_expr_size (exp);
++}
+--- gcc/cp/cp-tree.h.jj        2002-07-27 01:31:05.000000000 +0200
++++ gcc/cp/cp-tree.h   2002-08-23 13:51:08.000000000 +0200
+@@ -4084,6 +4084,7 @@ extern tree lookup_conversions                   PARAMS 
+ extern tree binfo_for_vtable                  PARAMS ((tree));
+ extern tree binfo_from_vbase                  PARAMS ((tree));
+ extern tree look_for_overrides_here           PARAMS ((tree, tree));
++extern int check_final_overrider              PARAMS ((tree, tree));
+ extern tree dfs_walk                            PARAMS ((tree,
+                                                      tree (*) (tree, void *),
+                                                      tree (*) (tree, void *),
+--- gcc/cp/search.c.jj 2002-04-23 20:29:00.000000000 +0200
++++ gcc/cp/search.c    2002-08-23 13:51:08.000000000 +0200
+@@ -100,7 +100,6 @@ static tree dfs_push_decls PARAMS ((tree
+ static tree dfs_unuse_fields PARAMS ((tree, void *));
+ static tree add_conversions PARAMS ((tree, void *));
+ static int covariant_return_p PARAMS ((tree, tree));
+-static int check_final_overrider PARAMS ((tree, tree));
+ static int look_for_overrides_r PARAMS ((tree, tree));
+ static struct search_level *push_search_level
+       PARAMS ((struct stack_level *, struct obstack *));
+@@ -1800,7 +1799,7 @@ covariant_return_p (brettype, drettype)
+ /* Check that virtual overrider OVERRIDER is acceptable for base function
+    BASEFN. Issue diagnostic, and return zero, if unacceptable.  */
+-static int
++int
+ check_final_overrider (overrider, basefn)
+      tree overrider, basefn;
+ {
+--- gcc/cp/typeck.c.jj 2002-07-10 11:37:43.000000000 +0200
++++ gcc/cp/typeck.c    2002-08-23 13:51:08.000000000 +0200
+@@ -5450,7 +5450,10 @@ build_modify_expr (lhs, modifycode, rhs)
+          so the code to compute it is only emitted once.  */
+       tree cond;
+-      rhs = save_expr (rhs);
++      if (lvalue_p (rhs))
++        rhs = stabilize_reference (rhs);
++      else
++        rhs = save_expr (rhs);
+       
+       /* Check this here to avoid odd errors when trying to convert
+          a throw to the type of the COND_EXPR.  */
+--- gcc/expr.c.jj      2002-05-07 12:45:49.000000000 +0200
++++ gcc/expr.c 2002-08-23 13:51:09.000000000 +0200
+@@ -6661,8 +6661,7 @@ expand_expr (exp, target, tmode, modifie
+                                                      * TYPE_QUAL_CONST))),
+                            0, TREE_ADDRESSABLE (exp), 1);
+-        store_constructor (exp, target, 0,
+-                           int_size_in_bytes (TREE_TYPE (exp)));
++        store_constructor (exp, target, 0, int_expr_size (exp));
+         return target;
+       }
+--- gcc/explow.c.jj    2002-02-22 11:32:03.000000000 +0100
++++ gcc/explow.c       2002-08-23 13:51:08.000000000 +0200
+@@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - S
+ #include "insn-config.h"
+ #include "ggc.h"
+ #include "recog.h"
++#include "langhooks.h"
+ static rtx break_out_memory_refs      PARAMS ((rtx));
+ static void emit_stack_probe          PARAMS ((rtx));
+@@ -285,20 +286,33 @@ rtx
+ expr_size (exp)
+      tree exp;
+ {
+-  tree size;
+-
+-  if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
+-      && DECL_SIZE_UNIT (exp) != 0)
+-    size = DECL_SIZE_UNIT (exp);
+-  else
+-    size = size_in_bytes (TREE_TYPE (exp));
++  tree size = (*lang_hooks.expr_size) (exp);
+   if (TREE_CODE (size) != INTEGER_CST
+       && contains_placeholder_p (size))
+     size = build (WITH_RECORD_EXPR, sizetype, size, exp);
+   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
++}
++
++/* Return a wide integer for the size in bytes of the value of EXP, or -1
++   if the size can vary or is larger than an integer.  */
++
++HOST_WIDE_INT
++int_expr_size (exp)
++     tree exp;
++{
++  tree t = (*lang_hooks.expr_size) (exp);
++
++  if (t == 0
++      || TREE_CODE (t) != INTEGER_CST
++      || TREE_OVERFLOW (t)
++      || TREE_INT_CST_HIGH (t) != 0
++      /* If the result would appear negative, it's too big to represent.  */
++      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
++    return -1;
++  return TREE_INT_CST_LOW (t);
+ }
\f
+ /* Return a copy of X in which all memory references
+--- gcc/expr.h.jj      2002-04-02 23:17:24.000000000 +0200
++++ gcc/expr.h 2002-08-23 13:51:09.000000000 +0200
+@@ -548,6 +548,10 @@ extern unsigned int case_values_threshol
+ /* Return an rtx for the size in bytes of the value of an expr.  */
+ extern rtx expr_size PARAMS ((tree));
++/* Return a wide integer for the size in bytes of the value of EXP, or -1
++   if the size can vary or is larger than an integer.  */
++extern HOST_WIDE_INT int_expr_size PARAMS ((tree));
++
+ extern rtx lookup_static_chain PARAMS ((tree));
+ /* Convert a stack slot address ADDR valid in function FNDECL
+--- gcc/langhooks-def.h.jj     2002-05-24 23:55:54.000000000 +0200
++++ gcc/langhooks-def.h        2002-08-23 13:51:09.000000000 +0200
+@@ -48,6 +48,7 @@ extern int lhd_staticp PARAMS ((tree));
+ extern void lhd_clear_binding_stack PARAMS ((void));
+ extern void lhd_print_tree_nothing PARAMS ((FILE *, tree, int));
+ extern void lhd_set_yydebug PARAMS ((int));
++extern tree lhd_expr_size PARAMS ((tree));
+ /* Declarations of default tree inlining hooks.  */
+ tree lhd_tree_inlining_walk_subtrees          PARAMS ((tree *, int *,
+@@ -85,6 +86,7 @@ tree lhd_tree_inlining_convert_parm_for_
+ #define LANG_HOOKS_PRINT_TYPE         lhd_print_tree_nothing
+ #define LANG_HOOKS_PRINT_IDENTIFIER   lhd_print_tree_nothing
+ #define LANG_HOOKS_SET_YYDEBUG                lhd_set_yydebug
++#define LANG_HOOKS_EXPR_SIZE          lhd_expr_size
+ /* Tree inlining hooks.  */
+ #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES lhd_tree_inlining_walk_subtrees
+@@ -156,6 +158,7 @@ int lhd_tree_dump_type_quals                       PARAMS ((
+   LANG_HOOKS_PRINT_TYPE, \
+   LANG_HOOKS_PRINT_IDENTIFIER, \
+   LANG_HOOKS_SET_YYDEBUG, \
++  LANG_HOOKS_EXPR_SIZE, \
+   LANG_HOOKS_TREE_INLINING_INITIALIZER, \
+   LANG_HOOKS_TREE_DUMP_INITIALIZER \
+ }
+--- gcc/langhooks.c.jj 2002-03-23 12:02:51.000000000 +0100
++++ gcc/langhooks.c    2002-08-23 13:51:09.000000000 +0200
+@@ -303,3 +303,16 @@ lhd_tree_dump_type_quals (t)
+   return TYPE_QUALS (t);
+ }
++/* lang_hooks.expr_size: Determine the size of the value of an expression T
++   in a language-specific way.  Returns a tree for the size in bytes.  */
++
++tree
++lhd_expr_size (exp)
++     tree exp;
++{
++  if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
++      && DECL_SIZE_UNIT (exp) != 0)
++    return DECL_SIZE_UNIT (exp);
++  else
++    return size_in_bytes (TREE_TYPE (exp));
++}
+--- gcc/langhooks.h.jj 2002-05-24 23:55:54.000000000 +0200
++++ gcc/langhooks.h    2002-08-23 13:51:09.000000000 +0200
+@@ -156,6 +156,12 @@ struct lang_hooks
+      warning that the front end does not use such a parser.  */
+   void (*set_yydebug) PARAMS ((int));
++  /* Called from expr_size to calculate the size of the value of an
++     expression in a language-dependent way.  Returns a tree for the size
++     in bytes.  A frontend can call lhd_expr_size to get the default
++     semantics in cases that it doesn't want to handle specially.  */
++  tree (*expr_size) PARAMS ((tree));
++
+   struct lang_hooks_for_tree_inlining tree_inlining;
+   
+   struct lang_hooks_for_tree_dump tree_dump;
diff --git a/gcc32-c++-tail-pad2.patch b/gcc32-c++-tail-pad2.patch
new file mode 100644 (file)
index 0000000..e95c845
--- /dev/null
@@ -0,0 +1,145 @@
+2002-08-06  Jason Merrill  <jason@redhat.com>
+
+       * c-common.c (c_expand_expr) [STMT_EXPR]: If the last expression is
+       a VAR_DECL with RTL that matches the target, just return that RTL.
+
+2002-06-01  Daniel Berlin  <dberlin@dberlin.org>
+
+       * tree-inline.c (expand_call_inline): Make the statement
+       expression we generate have a COMPOUND_STMT.
+
+--- gcc/c-common.c.jj  2002-08-28 11:20:26.000000000 +0200
++++ gcc/c-common.c     2002-08-28 22:49:59.000000000 +0200
+@@ -3564,6 +3564,7 @@ c_expand_expr (exp, target, tmode, modif
+       tree rtl_expr;
+       rtx result;
+       bool preserve_result = false;
++      bool return_target = false;
+       /* Since expand_expr_stmt calls free_temp_slots after every
+          expression statement, we must call push_temp_slots here.
+@@ -3591,8 +3592,20 @@ c_expand_expr (exp, target, tmode, modif
+           if (TREE_CODE (last) == SCOPE_STMT
+               && TREE_CODE (expr) == EXPR_STMT)
+             {
+-              TREE_ADDRESSABLE (expr) = 1;
+-              preserve_result = true;
++              if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
++                  && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
++                /* If the last expression is a variable whose RTL is the
++                   same as our target, just return the target; if it
++                   isn't valid expanding the decl would produce different
++                   RTL, and store_expr would try to do a copy.  */
++                return_target = true;
++              else
++                {
++                  /* Otherwise, note that we want the value from the last
++                     expression.  */
++                  TREE_ADDRESSABLE (expr) = 1;
++                  preserve_result = true;
++                }
+             }
+         }
+@@ -3600,7 +3613,9 @@ c_expand_expr (exp, target, tmode, modif
+       expand_end_stmt_expr (rtl_expr);
+       result = expand_expr (rtl_expr, target, tmode, modifier);
+-      if (preserve_result && GET_CODE (result) == MEM)
++      if (return_target)
++        result = target;
++      else if (preserve_result && GET_CODE (result) == MEM)
+         {
+           if (GET_MODE (result) != BLKmode)
+             result = copy_to_reg (result);
+--- gcc/tree-inline.c.jj       2002-08-28 11:20:27.000000000 +0200
++++ gcc/tree-inline.c  2002-08-28 22:49:59.000000000 +0200
+@@ -773,6 +773,7 @@ expand_call_inline (tp, walk_subtrees, d
+   inline_data *id;
+   tree t;
+   tree expr;
++  tree stmt;
+   tree chain;
+   tree fn;
+   tree scope_stmt;
+@@ -864,10 +865,10 @@ expand_call_inline (tp, walk_subtrees, d
+      for the return statements within the function to jump to.  The
+      type of the statement expression is the return type of the
+      function call.  */
+-  expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE);
++  expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), make_node (COMPOUND_STMT));
+   /* There is no scope associated with the statement-expression.  */
+   STMT_EXPR_NO_SCOPE (expr) = 1;
+-
++  stmt = STMT_EXPR_STMT (expr);
+   /* Local declarations will be replaced by their equivalents in this
+      map.  */
+   st = id->decl_map;
+@@ -890,7 +891,7 @@ expand_call_inline (tp, walk_subtrees, d
+      parameters.  */
+   expand_calls_inline (&arg_inits, id);
+   /* And add them to the tree.  */
+-  STMT_EXPR_STMT (expr) = chainon (STMT_EXPR_STMT (expr), arg_inits);
++  COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits);
+   /* Record the function we are about to inline so that we can avoid
+      recursing into it.  */
+@@ -925,8 +926,8 @@ expand_call_inline (tp, walk_subtrees, d
+   SCOPE_BEGIN_P (scope_stmt) = 1;
+   SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
+   remap_block (scope_stmt, DECL_ARGUMENTS (fn), id);
+-  TREE_CHAIN (scope_stmt) = STMT_EXPR_STMT (expr);
+-  STMT_EXPR_STMT (expr) = scope_stmt;
++  TREE_CHAIN (scope_stmt) = COMPOUND_BODY (stmt);
++  COMPOUND_BODY (stmt) = scope_stmt;
+   /* Tell the debugging backends that this block represents the
+      outermost scope of the inlined function.  */
+@@ -934,34 +935,34 @@ expand_call_inline (tp, walk_subtrees, d
+     BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn);
+   /* Declare the return variable for the function.  */
+-  STMT_EXPR_STMT (expr)
+-    = chainon (STMT_EXPR_STMT (expr),
++  COMPOUND_BODY (stmt)
++    = chainon (COMPOUND_BODY (stmt),
+              declare_return_variable (id, &use_stmt));
+   /* After we've initialized the parameters, we insert the body of the
+      function itself.  */
+-  inlined_body = &STMT_EXPR_STMT (expr);
++  inlined_body = &COMPOUND_BODY (stmt);
+   while (*inlined_body)
+     inlined_body = &TREE_CHAIN (*inlined_body);
+   *inlined_body = copy_body (id);
+-  /* Close the block for the parameters.  */
+-  scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
+-  SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
+-  remap_block (scope_stmt, NULL_TREE, id);
+-  STMT_EXPR_STMT (expr)
+-    = chainon (STMT_EXPR_STMT (expr), scope_stmt);
+-
+   /* After the body of the function comes the RET_LABEL.  This must come
+      before we evaluate the returned value below, because that evalulation
+      may cause RTL to be generated.  */
+-  STMT_EXPR_STMT (expr)
+-    = chainon (STMT_EXPR_STMT (expr),
++  COMPOUND_BODY (stmt)
++    = chainon (COMPOUND_BODY (stmt),
+              build_stmt (LABEL_STMT, id->ret_label));
+   /* Finally, mention the returned value so that the value of the
+      statement-expression is the returned value of the function.  */
+-  STMT_EXPR_STMT (expr) = chainon (STMT_EXPR_STMT (expr), use_stmt);
++  COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt);
++  
++  /* Close the block for the parameters.  */
++  scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
++  SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
++  remap_block (scope_stmt, NULL_TREE, id);
++  COMPOUND_BODY (stmt)
++    = chainon (COMPOUND_BODY (stmt), scope_stmt);
+   /* Clean up.  */
+   splay_tree_delete (id->decl_map);
diff --git a/gcc32-c++-tsubst-asm.patch b/gcc32-c++-tsubst-asm.patch
new file mode 100644 (file)
index 0000000..89964dd
--- /dev/null
@@ -0,0 +1,19 @@
+2002-05-09  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/ext/asm2.C: New test.
+
+--- gcc/testsuite/g++.dg/ext/asm2.C.jj Wed May 15 13:51:22 2002
++++ gcc/testsuite/g++.dg/ext/asm2.C    Sun May 12 11:25:45 2002
+@@ -0,0 +1,12 @@
++// Bug: in a template, we forgot that this was a simple asm, and decided
++// that %edi was a malformed operand specifier.
++
++template <class T> class  I {
++public:
++ void f() { asm ("# mov %edi, %esi" ); }
++};
++
++int main () {
++  I<int> x;
++  x.f();
++}
diff --git a/gcc32-cfg-eh.patch b/gcc32-cfg-eh.patch
new file mode 100644 (file)
index 0000000..4d11138
--- /dev/null
@@ -0,0 +1,74 @@
+2002-05-28  Richard Henderson  <rth@redhat.com>
+
+       * flow.c (calculate_global_regs_live): Rename call_used to
+       invalidated_by_call.  Initialize from regs_invalidated_by_call
+       instead of call_used_regs.
+
+2002-07-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/opt/life1.C: New test.
+
+--- gcc/flow.c 28 May 2002 12:53:39 -0000      1.527
++++ gcc/flow.c 28 May 2002 20:01:29 -0000      1.528
+@@ -1048,19 +1048,19 @@ calculate_global_regs_live (blocks_in, b
+      int flags;
+ {
+   basic_block *queue, *qhead, *qtail, *qend;
+-  regset tmp, new_live_at_end, call_used;
+-  regset_head tmp_head, call_used_head;
++  regset tmp, new_live_at_end, invalidated_by_call;
++  regset_head tmp_head, invalidated_by_call_head;
+   regset_head new_live_at_end_head;
+   int i;
+   tmp = INITIALIZE_REG_SET (tmp_head);
+   new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
+-  call_used = INITIALIZE_REG_SET (call_used_head);
++  invalidated_by_call = INITIALIZE_REG_SET (invalidated_by_call_head);
+   /* Inconveniently, this is only readily available in hard reg set form.  */
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+-    if (call_used_regs[i])
+-      SET_REGNO_REG_SET (call_used, i);
++    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
++      SET_REGNO_REG_SET (invalidated_by_call, i);
+   /* Create a worklist.  Allocate an extra slot for ENTRY_BLOCK, and one
+      because the `head == tail' style test for an empty queue doesn't
+@@ -1147,7 +1147,7 @@ calculate_global_regs_live (blocks_in, b
+           if (e->flags & EDGE_EH)
+             {
+               bitmap_operation (tmp, sb->global_live_at_start,
+-                                call_used, BITMAP_AND_COMPL);
++                                invalidated_by_call, BITMAP_AND_COMPL);
+               IOR_REG_SET (new_live_at_end, tmp);
+             }
+           else
+@@ -1315,7 +1315,7 @@ calculate_global_regs_live (blocks_in, b
+   FREE_REG_SET (tmp);
+   FREE_REG_SET (new_live_at_end);
+-  FREE_REG_SET (call_used);
++  FREE_REG_SET (invalidated_by_call);
+   if (blocks_out)
+     {
+--- gcc/testsuite/g++.dg/opt/life1.C.jj        Sat Jul 20 18:57:05 2002
++++ gcc/testsuite/g++.dg/opt/life1.C   Sat Jul 20 19:00:01 2002
+@@ -0,0 +1,16 @@
++// This testcase did not set up the pic register on IA-32 due
++// to bug in calculate_global_regs_live EH edge handling.
++// { dg-do compile { target i?86-*-linux* } }
++// { dg-options "-O2 -fPIC" }
++
++struct A { };
++
++void foo (A (*fn)())
++{
++  try {
++    A a = fn ();
++  } catch (...) {
++  }
++}
++
++// { dg-final { scan-assembler "GLOBAL_OFFSET_TABLE" } }
diff --git a/gcc32-debug-pr7241.patch b/gcc32-debug-pr7241.patch
new file mode 100644 (file)
index 0000000..dbf172f
--- /dev/null
@@ -0,0 +1,21 @@
+2002-07-11  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/7241
+       * dwarf2out.c (base_type_die): Use DW_ATE_*_char even if main
+       variant is char_type_node and type name is char.
+
+--- gcc/dwarf2out.c.jj Wed Jun 19 15:09:56 2002
++++ gcc/dwarf2out.c    Thu Jul 11 20:47:52 2002
+@@ -7335,9 +7335,11 @@ base_type_die (type)
+       /* Carefully distinguish the C character types, without messing
+          up if the language is not C. Note that we check only for the names
+          that contain spaces; other names might occur by coincidence in other
+-         languages.  */
++         languages, so we only check if main variant is char_type_node.  */
+       if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE
+            && (type == char_type_node
++               || (TYPE_MAIN_VARIANT (type) == char_type_node
++                   && ! strcmp (type_name, "char"))
+                || ! strcmp (type_name, "signed char")
+                || ! strcmp (type_name, "unsigned char"))))
+       {
diff --git a/gcc32-doc-gcov.patch b/gcc32-doc-gcov.patch
new file mode 100644 (file)
index 0000000..d7abc9e
--- /dev/null
@@ -0,0 +1,72 @@
+2002-08-14  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * doc/invoke.texi (-a): Remove documentation.
+       (-fprofile-arcs): Remove reference to -a, -ax options.
+       * doc/gcov.texi (Gcov Data Files): Data might be merged.
+
+--- gcc/doc/gcov.texi.jj       2001-11-15 11:38:19.000000000 +0100
++++ gcc/doc/gcov.texi  2002-08-22 11:48:48.000000000 +0200
+@@ -388,7 +388,7 @@ built with the GCC @option{-fprofile-arc
+ separate @file{.da} file is created for each source file compiled with
+ this option, and the name of the @file{.da} file is stored as an
+ absolute pathname in the resulting object file.  This path name is
+-derived from the source file name by substituting a @file{.da} suffix.
++derived from the object file name by substituting a @file{.da} suffix.
+ The format of the @file{.da} file is fairly simple.  The first 8-byte
+ number is the number of counts in the file, followed by the counts
+--- gcc/doc/invoke.texi.jj     2002-08-08 17:55:08.000000000 +0200
++++ gcc/doc/invoke.texi        2002-08-22 11:46:49.000000000 +0200
+@@ -2831,20 +2831,6 @@ analysis program @code{gprof}.  You must
+ the source files you want data about, and you must also use it when
+ linking.
+-@cindex @code{tcov}
+-@item -a
+-@opindex a
+-Generate extra code to write profile information for basic blocks, which will
+-record the number of times each basic block is executed, the basic block start
+-address, and the function name containing the basic block.  If @option{-g} is
+-used, the line number and filename of the start of the basic block will also be
+-recorded.  If not overridden by the machine description, the default action is
+-to append to the text file @file{bb.out}.
+-
+-This data could be analyzed by a program like @code{tcov}.  Note,
+-however, that the format of the data is not what @code{tcov} expects.
+-Eventually GNU @code{gprof} should be extended to process this data.
+-
+ @item -Q
+ @opindex Q
+ Makes the compiler print out each function name as it is compiled, and
+@@ -2877,18 +2863,7 @@ optimization and code generation options
+ Control Optimization}).
+ The other use of @option{-fprofile-arcs} is for use with @code{gcov},
+-when it is used with the @option{-ftest-coverage} option.  GCC
+-supports two methods of determining code coverage: the options that
+-support @code{gcov}, and options @option{-a} and @option{-ax}, which
+-write information to text files.  The options that support @code{gcov}
+-do not need to instrument every arc in the program, so a program compiled
+-with them runs faster than a program compiled with @option{-a}, which
+-adds instrumentation code to every basic block in the program.  The
+-tradeoff: since @code{gcov} does not have execution counts for all
+-branches, it must start with the execution counts for the instrumented
+-branches, and then iterate over the program flow graph until the entire
+-graph has been solved.  Hence, @code{gcov} runs a little more slowly than
+-a program which uses information from @option{-a} and @option{-ax}.
++when it is used with the @option{-ftest-coverage} option.
+ With @option{-fprofile-arcs}, for each function of your program GCC
+ creates a program flow graph, then finds a spanning tree for the graph.
+@@ -2898,11 +2873,6 @@ executed.  When an arc is the only exit 
+ instrumentation code can be added to the block; otherwise, a new basic
+ block must be created to hold the instrumentation code.
+-This option makes it possible to estimate branch probabilities and to
+-calculate basic block execution counts.  In general, basic block
+-execution counts as provided by @option{-a} do not give enough
+-information to estimate all branch probabilities.
+-
+ @need 2000
+ @item -ftest-coverage
+ @opindex ftest-coverage
diff --git a/gcc32-duplicate-decl.patch b/gcc32-duplicate-decl.patch
new file mode 100644 (file)
index 0000000..ef913e2
--- /dev/null
@@ -0,0 +1,17 @@
+2002-01-25  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/other/redecl1.C: New test.
+
+--- gcc/testsuite/g++.dg/other/redecl1.C.jj    Fri Jan 25 00:19:22 2002
++++ gcc/testsuite/g++.dg/other/redecl1.C       Fri Jan 25 00:23:33 2002
+@@ -0,0 +1,10 @@
++// PR c++/5857
++// This testcase failed because during duplicate_decls the type was promoted
++// to int.
++
++// { dg-do compile }
++
++typedef char baz;
++extern const char foo[];
++const baz foo[] = "xyz";
++const char bar[] = "abc";
diff --git a/gcc32-dwarf2-pr6381.patch b/gcc32-dwarf2-pr6381.patch
new file mode 100644 (file)
index 0000000..644a492
--- /dev/null
@@ -0,0 +1,18 @@
+2002-05-08  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/debug/const1.C: New test.
+
+--- gcc/testsuite/g++.dg/debug/const1.C.jj     Thu Aug 30 22:30:55 2001
++++ gcc/testsuite/g++.dg/debug/const1.C        Wed May  8 17:33:04 2002
+@@ -0,0 +1,11 @@
++// PR c++/6381
++// Bug: we were emitting the initializer for bar, which referenced foo,
++// which was not emitted.
++
++// { dg-options "-O" }
++// { dg-do link }
++
++static const int foo[] = { 0 };
++static const int * const bar[] = { foo };
++
++int main() {}
diff --git a/gcc32-dwarf2-pr6436-test.patch b/gcc32-dwarf2-pr6436-test.patch
new file mode 100644 (file)
index 0000000..18df889
--- /dev/null
@@ -0,0 +1,24 @@
+2002-04-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/debug/typedef1.C: New test.
+
+--- gcc/testsuite/g++.dg/debug/typedef1.C.jj   Thu Aug 30 22:30:55 2001
++++ gcc/testsuite/g++.dg/debug/typedef1.C      Tue Apr 30 19:50:12 2002
+@@ -0,0 +1,17 @@
++// PR debug/6436
++// { dg-do compile }
++
++typedef struct 
++{
++  unsigned int a0, a1;
++} A __attribute__ ((aligned(8)));
++
++typedef struct
++{
++  A a;
++} B;
++
++struct C
++{
++  B *bp;
++};
diff --git a/gcc32-fde-merge-compat.patch b/gcc32-fde-merge-compat.patch
new file mode 100644 (file)
index 0000000..fec3650
--- /dev/null
@@ -0,0 +1,34 @@
+2001-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * frame.c (fde_merge): Choose just one from FDEs for the
+       same function in erratic array.
+
+--- gcc/unwind-dw2-fde.c.jj    Fri Jan 11 14:01:21 2002
++++ gcc/unwind-dw2-fde.c       Tue Jan 15 15:58:27 2002
+@@ -535,7 +535,7 @@ fde_merge (struct object *ob, fde_compar
+          struct fde_vector *v1, struct fde_vector *v2)
+ {
+   size_t i1, i2;
+-  fde * fde2;
++  fde * fde2 = NULL;
+   i2 = v2->count;
+   if (i2 > 0)
+@@ -544,6 +544,17 @@ fde_merge (struct object *ob, fde_compar
+       do
+       {
+         i2--;
++        if (fde2 != NULL && fde_compare (ob, v2->array[i2], fde2) == 0)
++          {
++            /* Some linkers (e.g. 2.10.91.0.2 or 2.11.92.0.8) resolve
++               section relative relocations against removed linkonce
++               section to corresponding location in the output linkonce
++               section. Always use the earliest fde in that case.  */
++            fde2 = v2->array[i2];
++            v1->array[i1+i2+1] = fde2;
++            v1->array[i1+i2] = fde2;
++            continue;
++          }
+         fde2 = v2->array[i2];
+         while (i1 > 0 && fde_compare (ob, v1->array[i1-1], fde2) > 0)
+           {
diff --git a/gcc32-fold-const-associate.patch b/gcc32-fold-const-associate.patch
new file mode 100644 (file)
index 0000000..90a9f2b
--- /dev/null
@@ -0,0 +1,58 @@
+2002-08-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * fold-const.c (associate_trees): Only optimize NEGATE_EXPR in one
+       of the operands into MINUS_EXPR if code is PLUS_EXPR.
+
+       * gcc.c-torture/execute/20020805-1.c: New test.
+
+--- gcc/testsuite/gcc.c-torture/execute/20020805-1.c.jj        2002-08-05 18:27:42.000000000 +0200
++++ gcc/testsuite/gcc.c-torture/execute/20020805-1.c   2002-08-05 18:26:42.000000000 +0200
+@@ -0,0 +1,21 @@
++/* This testcase was miscompiled on IA-32, because fold-const
++   assumed associate_trees is always done on PLUS_EXPR.  */
++
++extern void abort (void);
++extern void exit (int);
++
++void check (unsigned int m)
++{
++  if (m != (unsigned int) -1)
++    abort ();
++}
++
++unsigned int n = 1;
++
++int main (void)
++{
++  unsigned int m;
++  m = (1 | (2 - n)) | (-n);
++  check (m);
++  exit (0);
++}
+--- gcc/fold-const.c.jj        2002-08-05 18:16:25.000000000 +0200
++++ gcc/fold-const.c   2002-08-05 18:16:25.000000000 +0200
+@@ -1500,14 +1500,16 @@ associate_trees (t1, t2, code, type)
+   if (TREE_CODE (t1) == code || TREE_CODE (t2) == code
+       || TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR)
+     {
+-      if (TREE_CODE (t1) == NEGATE_EXPR)
+-      return build (MINUS_EXPR, type, convert (type, t2),
+-                    convert (type, TREE_OPERAND (t1, 0)));
+-      else if (TREE_CODE (t2) == NEGATE_EXPR)
+-      return build (MINUS_EXPR, type, convert (type, t1),
+-                    convert (type, TREE_OPERAND (t2, 0)));
+-      else
+-      return build (code, type, convert (type, t1), convert (type, t2));
++      if (code == PLUS_EXPR)
++      {
++        if (TREE_CODE (t1) == NEGATE_EXPR)
++          return build (MINUS_EXPR, type, convert (type, t2),
++                        convert (type, TREE_OPERAND (t1, 0)));
++        else if (TREE_CODE (t2) == NEGATE_EXPR)
++          return build (MINUS_EXPR, type, convert (type, t1),
++                        convert (type, TREE_OPERAND (t2, 0)));
++      }
++      return build (code, type, convert (type, t1), convert (type, t2));
+     }
+   return fold (build (code, type, convert (type, t1), convert (type, t2)));
diff --git a/gcc32-fold-const2.patch b/gcc32-fold-const2.patch
new file mode 100644 (file)
index 0000000..9b3f35e
--- /dev/null
@@ -0,0 +1,15 @@
+2002-05-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * fold-const.c (fold): Fix a typo.
+
+--- gcc/fold-const.c.jj        Wed May 15 14:02:54 2002
++++ gcc/fold-const.c   Wed May 15 14:06:09 2002
+@@ -6530,7 +6530,7 @@ fold (expr)
+           else if (TREE_INT_CST_HIGH (arg1) == -1
+                    && (TREE_INT_CST_LOW (arg1)
+-                       == ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
++                       == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
+                    && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
+             switch (TREE_CODE (t))
+               {
diff --git a/gcc32-hard-reg-sharing.patch b/gcc32-hard-reg-sharing.patch
new file mode 100644 (file)
index 0000000..ffa155c
--- /dev/null
@@ -0,0 +1,631 @@
+2002-06-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * emit-rtl.c (init_emit_once): Register static_regno_reg_rtx
+       with GC.
+       * alias.c (init_alias_once): Register static_reg_base_value
+       with GC.
+
+2002-06-13  Jeffrey Law  <law@redhat.com>
+
+       * rs6000.c (rs6000_frame_related): Avoid unwanted sharing
+       of hard registers.
+
+       * emit-rtl.c (static_regno_reg_rtx): Define.
+       (init_emit_once): Initialize static_regno_reg_rtx.
+       (init_emit): Copy static_regno_reg_rtx into regno_reg_rtx instead
+       of building new hard reg objects once per function.
+       (gen_rtx_REG): Try to share hard regs.
+       * regclass.c (init_fake_stack_mems): New function broken out from
+       init_regs.
+       * rtl.h (init_fake_stack_mems): Declare.
+       * toplev.c (lang_independent_init): Call init_regs before
+       init_emit_once.  Call init_fake_stack_mems after init_emit_once.
+
+       * alias.c (argument_registers): Remove.
+       (init_alias_once): Initialize static_reg_base_value here.  Remove
+       initialization of argument_registers.
+       (init_alias_once_per_function): Remove.
+       (init_alias_analysis): Copy all the entries from static_reg_base_value
+       into new_reg_base_value all at once.
+       * rtl.h (init_alias_once_per_function): Remove declaration.
+       * function.c (prepare_function_start): Do not call
+       init_alias_once_per_function.
+
+       * caller-save.c (init_caller_save): Use gen_rtx_INSN instead of
+       starting a sequence and emitting an INSN.
+
+2002-06-11  Jeffrey Law <law@redhat.com>
+
+       * caller-save.c (init_caller_save): Move creation of SAVEINSN
+       and RESTINSN into into the scope of the sequence.
+
+       * loop.c (loop_regs_scan): Avoid useless generation of REG objects.
+
+2002-06-10  Jeffrey Law  <law@redhat.com>
+
+       * alias.c (static_reg_base_value): New to hold RTL for
+       items allocated once per function for the aliasing code.
+       (init_alias_once_per_function): Initialize static_reg_base_value.
+       (init_alias_analysis): Avoid throw-away allocations of RTL by
+       using pre-computed values in static_reg_base_value.
+       * function.c (prepare_function_start): Call
+       init_alias_once_per_function appropriately.
+       * rtl.h (init_alias_once_per_function): Declare.
+       * caller-save (init_caller_save): Restructure slightly to
+       avoid lots of silly RTL generation.
+       * expr.c (init_expr_once): Likewise.
+       * reload1.c (reload_cse_regs_1): Allocate throw-away register
+       RTL object here.  Pass it into children.
+       (reload_cse_simplify_operands): Use passed-in register RTL
+       object.
+       (reload_cse_simplify): Pass through throw-away register
+       RTL object.
+
+2002-06-07  Jeff Law  <law@redhat.com>
+
+       * emit-rtl.c (init_emit): Add hard registers to regno_reg_rtx.
+       * combine.c (move_deaths): Use regno_reg_rtx for hard regs rather
+       than creating a new register.
+       (distribute_notes): Likewise.
+       * df.c (df_reg_use_gen): Likewise.
+       (df_reg_clobber_gen): Likewise.
+       (df_ref_record): Likewise.
+       * expr.c (use_regs): Likewise.
+       * flow.c (propagate_one_insn): Likewise.
+       (mark_set_1): Likewise.
+       (mark_used_reg): Likewise.
+       * reload.c (emit_reload_insns): Likewise.
+
+--- gcc/df.c.jj        Tue Apr  2 21:23:50 2002
++++ gcc/df.c   Thu Jun 20 14:12:05 2002
+@@ -633,8 +633,7 @@ static rtx df_reg_use_gen (regno)
+   rtx reg;
+   rtx use;
+-  reg = regno >= FIRST_PSEUDO_REGISTER
+-    ? regno_reg_rtx[regno] : gen_rtx_REG (reg_raw_mode[regno], regno);
++  reg = regno_reg_rtx[regno];
+   use = gen_rtx_USE (GET_MODE (reg), reg);
+   return use;
+@@ -648,8 +647,7 @@ static rtx df_reg_clobber_gen (regno)
+   rtx reg;
+   rtx use;
+-  reg = regno >= FIRST_PSEUDO_REGISTER
+-    ? regno_reg_rtx[regno] : gen_rtx_REG (reg_raw_mode[regno], regno);
++  reg = regno_reg_rtx[regno];
+   use = gen_rtx_CLOBBER (GET_MODE (reg), reg);
+   return use;
+@@ -905,7 +903,7 @@ df_ref_record (df, reg, loc, insn, ref_t
+       endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+       for (i = regno; i < endregno; i++)
+-      df_ref_record_1 (df, gen_rtx_REG (reg_raw_mode[i], i),
++      df_ref_record_1 (df, regno_reg_rtx[i],
+                        loc, insn, ref_type, ref_flags);
+     }
+   else
+--- gcc/config/rs6000/rs6000.c.jj      Sat May 25 00:01:52 2002
++++ gcc/config/rs6000/rs6000.c Thu Jun 20 18:23:59 2002
+@@ -8531,6 +8531,14 @@ rs6000_frame_related (insn, reg, val, re
+ {
+   rtx real, temp;
++  /* copy_rtx will not make unique copies of registers, so we need to
++     ensure we don't have unwanted sharing here.  */
++  if (reg == reg2)
++    reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
++
++  if (reg == rreg)
++    reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
++
+   real = copy_rtx (PATTERN (insn));
+   real = replace_rtx (real, reg, 
+--- gcc/combine.c.jj   Tue Jun  4 15:02:15 2002
++++ gcc/combine.c      Thu Jun 20 14:12:38 2002
+@@ -11908,7 +11908,7 @@ move_deaths (x, maybe_kill_insn, from_cu
+               if (i < regno || i >= ourend)
+                 REG_NOTES (where_dead)
+                   = gen_rtx_EXPR_LIST (REG_DEAD,
+-                                       gen_rtx_REG (reg_raw_mode[i], i),
++                                       regno_reg_rtx[i],
+                                        REG_NOTES (where_dead));
+           }
+@@ -11935,7 +11935,7 @@ move_deaths (x, maybe_kill_insn, from_cu
+               offset = 1;
+             for (i = regno + offset; i < ourend; i++)
+-              move_deaths (gen_rtx_REG (reg_raw_mode[i], i),
++              move_deaths (regno_reg_rtx[i],
+                            maybe_kill_insn, from_cuid, to_insn, &oldnotes);
+           }
+@@ -12557,7 +12557,7 @@ distribute_notes (notes, from_insn, i3, 
+                     for (i = regno; i < endregno;
+                          i += HARD_REGNO_NREGS (i, reg_raw_mode[i]))
+                       {
+-                        rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
++                        rtx piece = regno_reg_rtx[i];
+                         basic_block bb = BASIC_BLOCK (this_basic_block);
+                         if (! dead_or_set_p (place, piece)
+--- gcc/emit-rtl.c.jj  Thu May 23 10:28:12 2002
++++ gcc/emit-rtl.c     Thu Jun 20 18:38:08 2002
+@@ -92,6 +92,12 @@ static int no_line_numbers;
+ rtx global_rtl[GR_MAX];
++/* Commonly used RTL for hard registers.  These objects are not necessarily
++   unique, so we allocate them separately from global_rtl.  They are
++   initialized once per compilation unit, then copied into regno_reg_rtx
++   at the beginning of each function.  */
++static rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
++
+ /* We record floating-point CONST_DOUBLEs in each floating-point mode for
+    the values of 0, 1, and 2.  For the integer entries and VOIDmode, we
+    record a copy of const[012]_rtx.  */
+@@ -427,6 +433,15 @@ gen_rtx_REG (mode, regno)
+       return stack_pointer_rtx;
+     }
++  /* If the per-function register table has been set up, try to re-use
++     an existing entry in that table to avoid useless generation of RTL.  */
++  if (0 && cfun
++      && cfun->emit
++      && regno_reg_rtx
++      && regno >= 0 && regno < FIRST_PSEUDO_REGISTER
++      && reg_raw_mode[regno] == mode)
++    return regno_reg_rtx[regno];
++
+   return gen_raw_REG (mode, regno);
+ }
+@@ -4841,6 +4856,11 @@ init_emit ()
+   f->emit->regno_decl
+     = (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree));
++  /* Put copies of all the hard registers into regno_reg_rtx.  */
++  memcpy (regno_reg_rtx,
++        static_regno_reg_rtx,
++        FIRST_PSEUDO_REGISTER * sizeof (rtx));
++
+   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
+   init_virtual_regs (f->emit);
+@@ -5015,8 +5035,14 @@ init_emit_once (line_numbers)
+     gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
+   virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
++  /* Initialize RTL for commonly used hard registers.  These are
++     copied into regno_reg_rtx as we begin to compile each function.  */
++  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
++    static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
++
+   /* These rtx must be roots if GC is enabled.  */
+   ggc_add_rtx_root (global_rtl, GR_MAX);
++  ggc_add_rtx_root (static_regno_reg_rtx, (int) FIRST_PSEUDO_REGISTER);
+ #ifdef INIT_EXPANDERS
+   /* This is to initialize {init|mark|free}_machine_status before the first
+--- gcc/expr.c.jj      Tue May  7 12:45:49 2002
++++ gcc/expr.c Thu Jun 20 17:04:00 2002
+@@ -208,6 +208,7 @@ init_expr_once ()
+   enum machine_mode mode;
+   int num_clobbers;
+   rtx mem, mem1;
++  rtx reg;
+   start_sequence ();
+@@ -217,6 +218,10 @@ init_expr_once ()
+   mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
+   mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
++  /* A scratch register we can modify in-place below to avoid
++     useless RTL allocations.  */
++  reg = gen_raw_REG (VOIDmode, -1);
++
+   insn = emit_insn (gen_rtx_SET (0, NULL_RTX, NULL_RTX));
+   pat = PATTERN (insn);
+@@ -224,11 +229,11 @@ init_expr_once ()
+        mode = (enum machine_mode) ((int) mode + 1))
+     {
+       int regno;
+-      rtx reg;
+       direct_load[(int) mode] = direct_store[(int) mode] = 0;
+       PUT_MODE (mem, mode);
+       PUT_MODE (mem1, mode);
++      PUT_MODE (reg, mode);
+       /* See if there is some register that can be used in this mode and
+        directly loaded or stored from memory.  */
+@@ -241,7 +246,7 @@ init_expr_once ()
+           if (! HARD_REGNO_MODE_OK (regno, mode))
+             continue;
+-          reg = gen_rtx_REG (mode, regno);
++          REGNO (reg) = regno;
+           SET_SRC (pat) = mem;
+           SET_DEST (pat) = reg;
+@@ -2280,7 +2285,7 @@ use_regs (call_fusage, regno, nregs)
+     abort ();
+   for (i = 0; i < nregs; i++)
+-    use_reg (call_fusage, gen_rtx_REG (reg_raw_mode[regno + i], regno + i));
++    use_reg (call_fusage, regno_reg_rtx[regno + i]);
+ }
+ /* Add USE expressions to *CALL_FUSAGE for each REG contained in the
+--- gcc/flow.c.jj      Tue Apr 23 20:26:35 2002
++++ gcc/flow.c Thu Jun 20 14:12:05 2002
+@@ -1721,8 +1721,7 @@ propagate_one_insn (pbi, insn)
+           if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+             {
+               /* We do not want REG_UNUSED notes for these registers.  */
+-              mark_set_1 (pbi, CLOBBER, gen_rtx_REG (reg_raw_mode[i], i),
+-                          cond, insn,
++              mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
+                           pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
+             }
+       }
+@@ -1770,8 +1769,7 @@ propagate_one_insn (pbi, insn)
+            so they are made live.  */
+         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+           if (global_regs[i])
+-            mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
+-                           cond, insn);
++            mark_used_reg (pbi, regno_reg_rtx[i], cond, insn);
+       }
+     }
+@@ -2769,7 +2767,7 @@ mark_set_1 (pbi, code, reg, cond, insn, 
+                   if (! REGNO_REG_SET_P (pbi->reg_live, i))
+                     REG_NOTES (insn)
+                       = alloc_EXPR_LIST (REG_UNUSED,
+-                                         gen_rtx_REG (reg_raw_mode[i], i),
++                                         regno_reg_rtx[i],
+                                          REG_NOTES (insn));
+               }
+           }
+@@ -3577,7 +3575,7 @@ mark_used_reg (pbi, reg, cond, insn)
+               && ! dead_or_set_regno_p (insn, i))
+             REG_NOTES (insn)
+               = alloc_EXPR_LIST (REG_DEAD,
+-                                 gen_rtx_REG (reg_raw_mode[i], i),
++                                 regno_reg_rtx[i],
+                                  REG_NOTES (insn));
+       }
+     }
+--- gcc/reload1.c.jj   Wed May 22 14:17:55 2002
++++ gcc/reload1.c      Thu Jun 20 17:05:46 2002
+@@ -444,7 +444,7 @@ static int constraint_accepts_reg_p        PARA
+ static void reload_cse_regs_1         PARAMS ((rtx));
+ static int reload_cse_noop_set_p      PARAMS ((rtx));
+ static int reload_cse_simplify_set    PARAMS ((rtx, rtx));
+-static int reload_cse_simplify_operands       PARAMS ((rtx));
++static int reload_cse_simplify_operands       PARAMS ((rtx, rtx));
+ static void reload_combine            PARAMS ((void));
+ static void reload_combine_note_use   PARAMS ((rtx *, rtx));
+ static void reload_combine_note_store PARAMS ((rtx, rtx, void *));
+@@ -459,7 +459,7 @@ static HOST_WIDE_INT sext_for_mode PARAM
+ static void failed_reload             PARAMS ((rtx, int));
+ static int set_reload_reg             PARAMS ((int, int));
+ static void reload_cse_delete_noop_set        PARAMS ((rtx, rtx));
+-static void reload_cse_simplify               PARAMS ((rtx));
++static void reload_cse_simplify               PARAMS ((rtx, rtx));
+ void fixup_abnormal_edges             PARAMS ((void));
+ extern void dump_needs                        PARAMS ((struct insn_chain *));
\f
+@@ -7161,8 +7161,7 @@ emit_reload_insns (chain)
+                   for (k = 1; k < nnr; k++)
+                     reg_last_reload_reg[nregno + k]
+                       = (nr == nnr
+-                         ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
+-                                        REGNO (rld[r].reg_rtx) + k)
++                         ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
+                          : 0);
+                 /* Now do the inverse operation.  */
+@@ -7211,8 +7210,7 @@ emit_reload_insns (chain)
+                   for (k = 1; k < nnr; k++)
+                     reg_last_reload_reg[nregno + k]
+                       = (nr == nnr
+-                         ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
+-                                        REGNO (rld[r].reg_rtx) + k)
++                         ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
+                          : 0);
+                 /* Unless we inherited this reload, show we haven't
+@@ -8061,8 +8059,9 @@ reload_cse_noop_set_p (set)
+ /* Try to simplify INSN.  */
+ static void
+-reload_cse_simplify (insn)
++reload_cse_simplify (insn, testreg)
+      rtx insn;
++     rtx testreg;
+ {
+   rtx body = PATTERN (insn);
+@@ -8089,7 +8088,7 @@ reload_cse_simplify (insn)
+       if (count > 0)
+       apply_change_group ();
+       else
+-      reload_cse_simplify_operands (insn);
++      reload_cse_simplify_operands (insn, testreg);
+     }
+   else if (GET_CODE (body) == PARALLEL)
+     {
+@@ -8132,7 +8131,7 @@ reload_cse_simplify (insn)
+       if (count > 0)
+       apply_change_group ();
+       else
+-      reload_cse_simplify_operands (insn);
++      reload_cse_simplify_operands (insn, testreg);
+     }
+ }
+@@ -8158,6 +8157,7 @@ reload_cse_regs_1 (first)
+      rtx first;
+ {
+   rtx insn;
++  rtx testreg = gen_raw_REG (VOIDmode, -1);
+   cselib_init ();
+   init_alias_analysis ();
+@@ -8165,7 +8165,7 @@ reload_cse_regs_1 (first)
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (INSN_P (insn))
+-      reload_cse_simplify (insn);
++      reload_cse_simplify (insn, testreg);
+       cselib_process_insn (insn);
+     }
+@@ -8336,8 +8336,9 @@ reload_cse_simplify_set (set, insn)
+    hard registers.  */
+ static int
+-reload_cse_simplify_operands (insn)
++reload_cse_simplify_operands (insn, testreg)
+      rtx insn;
++     rtx testreg;
+ {
+   int i, j;
+@@ -8357,7 +8358,6 @@ reload_cse_simplify_operands (insn)
+   int *op_alt_regno[MAX_RECOG_OPERANDS];
+   /* Array of alternatives, sorted in order of decreasing desirability.  */
+   int *alternative_order;
+-  rtx reg = gen_rtx_REG (VOIDmode, -1);
+   extract_insn (insn);
+@@ -8441,8 +8441,8 @@ reload_cse_simplify_operands (insn)
+         if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
+           continue;
+-        REGNO (reg) = regno;
+-        PUT_MODE (reg, mode);
++        REGNO (testreg) = regno;
++        PUT_MODE (testreg, mode);
+         /* We found a register equal to this operand.  Now look for all
+            alternatives that can accept this register and have not been
+@@ -8484,10 +8484,10 @@ reload_cse_simplify_operands (insn)
+                    alternative yet and the operand being replaced is not
+                    a cheap CONST_INT.  */
+                 if (op_alt_regno[i][j] == -1
+-                    && reg_fits_class_p (reg, class, 0, mode)
++                    && reg_fits_class_p (testreg, class, 0, mode)
+                     && (GET_CODE (recog_data.operand[i]) != CONST_INT
+                         || (rtx_cost (recog_data.operand[i], SET)
+-                            > rtx_cost (reg, SET))))
++                            > rtx_cost (testreg, SET))))
+                   {
+                     alternative_nregs[j]++;
+                     op_alt_regno[i][j] = regno;
+--- gcc/alias.c.jj     Thu Jun 20 12:43:03 2002
++++ gcc/alias.c        Thu Jun 20 18:36:24 2002
+@@ -149,6 +149,10 @@ static rtx *reg_base_value;
+ static rtx *new_reg_base_value;
+ static unsigned int reg_base_value_size; /* size of reg_base_value array */
++/* Static hunks of RTL used by the aliasing code; these are initialized
++   once per function to avoid unnecessary RTL allocations.  */
++static rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
++
+ #define REG_BASE_VALUE(X) \
+   (REGNO (X) < reg_base_value_size \
+    ? reg_base_value[REGNO (X)] : 0)
+@@ -2429,8 +2433,6 @@ mark_constant_function ()
+ }
+-static HARD_REG_SET argument_registers;
+-
+ void
+ init_alias_once ()
+ {
+@@ -2439,13 +2441,26 @@ init_alias_once ()
+ #ifndef OUTGOING_REGNO
+ #define OUTGOING_REGNO(N) N
+ #endif
++  ggc_add_rtx_root (static_reg_base_value, (int) FIRST_PSEUDO_REGISTER);
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     /* Check whether this register can hold an incoming pointer
+        argument.  FUNCTION_ARG_REGNO_P tests outgoing register
+        numbers, so translate if necessary due to register windows.  */
+     if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
+       && HARD_REGNO_MODE_OK (i, Pmode))
+-      SET_HARD_REG_BIT (argument_registers, i);
++      static_reg_base_value[i]
++      = gen_rtx_ADDRESS (VOIDmode, gen_rtx_REG (Pmode, i));
++
++  static_reg_base_value[STACK_POINTER_REGNUM]
++    = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
++  static_reg_base_value[ARG_POINTER_REGNUM]
++    = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
++  static_reg_base_value[FRAME_POINTER_REGNUM]
++    = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
++#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
++  static_reg_base_value[HARD_FRAME_POINTER_REGNUM]
++    = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
++#endif
+   alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
+ }
+@@ -2535,21 +2550,8 @@ init_alias_analysis ()
+        The address expression is VOIDmode for an argument and
+        Pmode for other registers.  */
+-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+-      if (TEST_HARD_REG_BIT (argument_registers, i))
+-        new_reg_base_value[i] = gen_rtx_ADDRESS (VOIDmode,
+-                                                 gen_rtx_REG (Pmode, i));
+-
+-      new_reg_base_value[STACK_POINTER_REGNUM]
+-      = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
+-      new_reg_base_value[ARG_POINTER_REGNUM]
+-      = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
+-      new_reg_base_value[FRAME_POINTER_REGNUM]
+-      = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
+-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+-      new_reg_base_value[HARD_FRAME_POINTER_REGNUM]
+-      = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
+-#endif
++      memcpy (new_reg_base_value, static_reg_base_value,
++            FIRST_PSEUDO_REGISTER * sizeof (rtx));
+       /* Walk the insns adding values to the new_reg_base_value array.  */
+       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+--- gcc/caller-save.c.jj       Wed Jan  2 12:47:35 2002
++++ gcc/caller-save.c  Thu Jun 20 17:49:47 2002
+@@ -115,6 +115,9 @@ init_caller_save ()
+   rtx address;
+   int i, j;
+   enum machine_mode mode;
++  rtx savepat, restpat;
++  rtx test_reg, test_mem;
++  rtx saveinsn, restinsn;
+   /* First find all the registers that we need to deal with and all
+      the modes that they can have.  If we can't find a mode to use,
+@@ -179,22 +182,30 @@ init_caller_save ()
+     address = addr_reg;
+   /* Next we try to form an insn to save and restore the register.  We
+-     see if such an insn is recognized and meets its constraints.  */
++     see if such an insn is recognized and meets its constraints. 
+-  start_sequence ();
++     To avoid lots of unnecessary RTL allocation, we construct all the RTL
++     once, then modify the memory and register operands in-place.  */
++
++  test_reg = gen_rtx_REG (VOIDmode, 0);
++  test_mem = gen_rtx_MEM (VOIDmode, address);
++  savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);
++  restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);
++  saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, savepat, -1, 0, 0);
++  restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, restpat, -1, 0, 0);
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
+       if (HARD_REGNO_MODE_OK (i, mode))
+         {
+-        rtx mem = gen_rtx_MEM (mode, address);
+-        rtx reg = gen_rtx_REG (mode, i);
+-        rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
+-        rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
+-        rtx saveinsn = emit_insn (savepat);
+-        rtx restinsn = emit_insn (restpat);
+         int ok;
++        /* Update the register number and modes of the register
++           and memory operand.  */
++        REGNO (test_reg) = i;
++        PUT_MODE (test_reg, mode);
++        PUT_MODE (test_mem, mode);
++
+         reg_save_code[i][mode] = recog_memoized (saveinsn);
+         reg_restore_code[i][mode] = recog_memoized (restinsn);
+@@ -232,8 +243,6 @@ init_caller_save ()
+             SET_HARD_REG_BIT (call_fixed_reg_set, i);
+           }
+       }
+-
+-  end_sequence ();
+ }
\f
+ /* Initialize save areas by showing that we haven't allocated any yet.  */
+--- gcc/rtl.h.jj       Tue May 21 20:19:51 2002
++++ gcc/rtl.h  Thu Jun 20 18:01:01 2002
+@@ -1964,6 +1964,7 @@ extern int reg_classes_intersect_p       PARAM
+ extern int reg_class_subset_p         PARAMS ((enum reg_class, enum reg_class));
+ extern void globalize_reg             PARAMS ((int));
+ extern void init_regs                 PARAMS ((void));
++extern void init_fake_stack_mems      PARAMS ((void));
+ extern void init_reg_sets             PARAMS ((void));
+ extern void regset_release_memory     PARAMS ((void));
+ extern void regclass_init             PARAMS ((void));
+--- gcc/regclass.c.jj  Wed Jun 19 15:11:11 2002
++++ gcc/regclass.c     Thu Jun 20 18:01:01 2002
+@@ -605,11 +605,16 @@ init_regs ()
+   init_reg_sets_1 ();
+   init_reg_modes ();
++}
++/* Initialize some fake stack-frame MEM references for use in
++   memory_move_secondary_cost.  */
++
++void
++init_fake_stack_mems ()
++{
+ #ifdef HAVE_SECONDARY_RELOADS
+   {
+-    /* Make some fake stack-frame MEM references for use in
+-       memory_move_secondary_cost.  */
+     int i;
+     for (i = 0; i < MAX_MACHINE_MODE; i++)
+--- gcc/toplev.c.jj    Thu May 30 11:08:44 2002
++++ gcc/toplev.c       Thu Jun 20 18:01:01 2002
+@@ -5058,6 +5058,9 @@ lang_independent_init ()
+   init_stringpool ();
+   init_obstacks ();
++  /* init_emit_once uses reg_raw_mode and therefore must be called
++     after init_regs which initialized reg_raw_mode.  */
++  init_regs ();
+   init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
+                 || debug_info_level == DINFO_LEVEL_VERBOSE
+ #ifdef VMS_DEBUGGING_INFO
+@@ -5066,7 +5069,7 @@ lang_independent_init ()
+ #endif
+                   || flag_test_coverage
+                   || warn_notreached);
+-  init_regs ();
++  init_fake_stack_mems ();
+   init_alias_once ();
+   init_stmt ();
+   init_loop ();
+--- gcc/loop.c.jj      Wed Jun 19 15:10:51 2002
++++ gcc/loop.c Thu Jun 20 18:22:01 2002
+@@ -9541,7 +9541,7 @@ loop_regs_scan (loop, extra_size)
+   if (LOOP_INFO (loop)->has_call)
+     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
+-          && rtx_varies_p (gen_rtx_REG (Pmode, i), /*for_alias=*/1))
++          && rtx_varies_p (regno_reg_rtx[i], 1))
+         {
+           regs->array[i].may_not_optimize = 1;
+           regs->array[i].set_in_loop = 1;
diff --git a/gcc32-hard-reg-sharing2.patch b/gcc32-hard-reg-sharing2.patch
new file mode 100644 (file)
index 0000000..24a2a68
--- /dev/null
@@ -0,0 +1,17 @@
+2002-06-11  Richard Henderson  <rth@redhat.com>
+
+       * caller-save.c (init_caller_save): Clear INSN_CODE each iteration.
+
+--- gcc/caller-save.c.jj       Fri Jun 21 01:16:13 2002
++++ gcc/caller-save.c  Thu Jul 11 10:27:57 2002
+@@ -206,6 +206,10 @@ init_caller_save ()
+         PUT_MODE (test_reg, mode);
+         PUT_MODE (test_mem, mode);
++        /* Force re-recognition of the modified insns.  */
++        INSN_CODE (saveinsn) = -1;
++        INSN_CODE (restinsn) = -1;
++
+         reg_save_code[i][mode] = recog_memoized (saveinsn);
+         reg_restore_code[i][mode] = recog_memoized (restinsn);
diff --git a/gcc32-i386-default-momit-leaf-frame-pointer.patch b/gcc32-i386-default-momit-leaf-frame-pointer.patch
new file mode 100644 (file)
index 0000000..fb8e24b
--- /dev/null
@@ -0,0 +1,75 @@
+2002-05-29  Richard Henderson  <rth@redhat.com>
+
+       * config/i386/biarch64.h (TARGET_64BIT_DEFAULT): Define with value.
+       (TARGET_BI_ARCH): Likewise.
+       * config/i386/i386.h: Test TARGET_64BIT_DEFAULT by value.
+       (TARGET_SWITCHES): Combine target defaults here not in TARGET_DEFAULT.
+       (TARGET_64BIT_DEFAULT): Default to 0.
+       (TARGET_DEFAULT): Default to MASK_OMIT_LEAF_FRAME_POINTER.
+
+--- gcc/config/i386/biarch64.h.jj      Tue Oct  2 12:59:38 2001
++++ gcc/config/i386/biarch64.h Tue Jun  4 15:11:52 2002
+@@ -21,5 +21,5 @@ along with GNU CC; see the file COPYING.
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+-#define TARGET_64BIT_DEFAULT
+-#define TARGET_BI_ARCH
++#define TARGET_64BIT_DEFAULT MASK_64BIT
++#define TARGET_BI_ARCH 1
+--- gcc/config/i386/i386.h.jj  Thu Apr 18 19:02:03 2002
++++ gcc/config/i386/i386.h     Tue Jun  4 15:13:40 2002
+@@ -192,7 +192,7 @@ extern int target_flags;
+ #ifdef TARGET_BI_ARCH
+ #define TARGET_64BIT (target_flags & MASK_64BIT)
+ #else
+-#ifdef TARGET_64BIT_DEFAULT
++#if TARGET_64BIT_DEFAULT
+ #define TARGET_64BIT 1
+ #else
+ #define TARGET_64BIT 0
+@@ -381,14 +381,14 @@ extern int x86_prefetch_sse;
+   { "no-red-zone",            MASK_NO_RED_ZONE,                             \
+     N_("Do not use red-zone in the x86-64 code") },                         \
+   SUBTARGET_SWITCHES                                                        \
+-  { "", TARGET_DEFAULT, 0 }}
++  { "", TARGET_DEFAULT | TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_DEFAULT, 0 }}
+-#ifdef TARGET_64BIT_DEFAULT
+-#define TARGET_DEFAULT (MASK_64BIT | TARGET_SUBTARGET_DEFAULT)
+-#else
+-#define TARGET_DEFAULT TARGET_SUBTARGET_DEFAULT
++#ifndef TARGET_64BIT_DEFAULT
++#define TARGET_64BIT_DEFAULT 0
+ #endif
++#define TARGET_DEFAULT MASK_OMIT_LEAF_FRAME_POINTER
++
+ /* Which processor to schedule for. The cpu attribute defines a list that
+    mirrors this list, so changes to i386.md must be made at the same time.  */
+@@ -624,13 +624,13 @@ extern int ix86_arch;
+ #ifndef CPP_CPU_SPEC
+ #ifdef TARGET_BI_ARCH
+-#ifdef TARGET_64BIT_DEFAULT
++#if TARGET_64BIT_DEFAULT
+ #define CPP_CPU_SPEC "%{m32:%(cpp_cpu32)}%{!m32:%(cpp_cpu64)} %(cpp_cpucommon)"
+ #else
+ #define CPP_CPU_SPEC "%{m64:%(cpp_cpu64)}%{!m64:%(cpp_cpu32)} %(cpp_cpucommon)"
+ #endif
+ #else
+-#ifdef TARGET_64BIT_DEFAULT
++#if TARGET_64BIT_DEFAULT
+ #define CPP_CPU_SPEC "%(cpp_cpu64) %(cpp_cpucommon)"
+ #else
+ #define CPP_CPU_SPEC "%(cpp_cpu32) %(cpp_cpucommon)"
+@@ -695,7 +695,7 @@ extern int ix86_arch;
+ #define DOUBLE_TYPE_SIZE 64
+ #define LONG_LONG_TYPE_SIZE 64
+-#if defined (TARGET_BI_ARCH) || defined (TARGET_64BIT_DEFAULT)
++#if defined (TARGET_BI_ARCH) || TARGET_64BIT_DEFAULT
+ #define MAX_BITS_PER_WORD 64
+ #define MAX_LONG_TYPE_SIZE 64
+ #else
diff --git a/gcc32-i386-memtest-test.patch b/gcc32-i386-memtest-test.patch
new file mode 100644 (file)
index 0000000..93cded3
--- /dev/null
@@ -0,0 +1,31 @@
+2002-05-20  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/20020525-1.c: New test.
+
+--- gcc/testsuite/gcc.dg/20020525-1.c.jj       Thu Aug 30 22:30:55 2001
++++ gcc/testsuite/gcc.dg/20020525-1.c  Sat May 25 10:45:13 2002
+@@ -0,0 +1,24 @@
++/* PR optimization/6703
++   Origin: Glen Nakamura <glen@imodulo.com> */
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++
++extern void abort (void);
++extern void exit (int);
++
++void foo (int *x, int y)
++{
++  __builtin_memset (x, 0, y);
++}
++  
++int main ()
++{
++  int x[2] = { 0x5a5a5a5a, 0x5a5a5a5a };
++    
++  if (x[1] != 0x5a5a5a5a)
++    abort ();
++  foo (x, sizeof (int) + 1);
++  if (x[1] == 0x5a5a5a5a)
++    abort ();
++  exit (0);
++}
diff --git a/gcc32-i386-no-default-momit-leaf-frame-pointer.patch b/gcc32-i386-no-default-momit-leaf-frame-pointer.patch
new file mode 100644 (file)
index 0000000..94befa8
--- /dev/null
@@ -0,0 +1,13 @@
+Argh, GDB is not ready.
+
+--- gcc/config/i386/i386.h.jj  2002-08-28 11:20:27.000000000 +0200
++++ gcc/config/i386/i386.h     2002-08-28 22:01:26.000000000 +0200
+@@ -390,7 +390,7 @@ extern int x86_prefetch_sse;
+ #define TARGET_64BIT_DEFAULT 0
+ #endif
+-#define TARGET_DEFAULT MASK_OMIT_LEAF_FRAME_POINTER
++#define TARGET_DEFAULT 0
+ /* Which processor to schedule for. The cpu attribute defines a list that
+    mirrors this list, so changes to i386.md must be made at the same time.  */
diff --git a/gcc32-i386-pic-label-thunk.patch b/gcc32-i386-pic-label-thunk.patch
new file mode 100644 (file)
index 0000000..e0c11aa
--- /dev/null
@@ -0,0 +1,91 @@
+2002-06-04  Richard Henderson  <rth@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * config/i386/i386.c (USE_HIDDEN_LINKONCE): New.
+       (ix86_asm_file_end): If USE_HIDDEN_LINKONCE, emit get_pc thunks
+       into linkonce sections.
+       (load_pic_register): Set up pic_label_name for it.
+
+--- gcc/config/i386/i386.c.jj  Mon Jun  3 17:24:13 2002
++++ gcc/config/i386/i386.c     Tue Jun  4 15:49:17 2002
+@@ -3786,6 +3786,12 @@ ix86_setup_frame_addresses ()
+   cfun->machine->accesses_prev_frame = 1;
+ }
\f
++#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
++# define USE_HIDDEN_LINKONCE 1
++#else
++# define USE_HIDDEN_LINKONCE 0
++#endif
++
+ static char pic_label_name[32];
+ /* This function generates code for -fpic that loads %ebx with
+@@ -3800,10 +3806,6 @@ ix86_asm_file_end (file)
+   if (! TARGET_DEEP_BRANCH_PREDICTION || pic_label_name[0] == 0)
+     return;
+-  /* ??? Binutils 2.10 and earlier has a linkonce elimination bug related
+-     to updating relocations to a section being discarded such that this
+-     doesn't work.  Ought to detect this at configure time.  */
+-#if 0
+   /* The trick here is to create a linkonce section containing the
+      pic label thunk, but to refer to it with an internal label.
+      Because the label is internal, we don't have inter-dso name
+@@ -3811,28 +3813,27 @@ ix86_asm_file_end (file)
+      In order to use these macros, however, we must create a fake
+      function decl.  */
+-  if (targetm.have_named_sections)
++  if (USE_HIDDEN_LINKONCE && targetm.have_named_sections)
+     {
+       tree decl = build_decl (FUNCTION_DECL,
+-                            get_identifier ("i686.get_pc_thunk"),
++                            get_identifier (pic_label_name),
+                             error_mark_node);
++      TREE_PUBLIC (decl) = 1;
++      TREE_STATIC (decl) = 1;
+       DECL_ONE_ONLY (decl) = 1;
+       UNIQUE_SECTION (decl, 0);
+-      named_section (decl, NULL);
++      named_section (decl, NULL, 0);
++      ASM_GLOBALIZE_LABEL (file, pic_label_name);
++      fputs ("\t.hidden\t", file);
++      assemble_name (file, pic_label_name);
++      fputc ('\n', file);
++      ASM_DECLARE_FUNCTION_NAME (file, pic_label_name, decl);
+     }
+   else
+-#else
+-    text_section ();
+-#endif
+-
+-  /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
+-     internal (non-global) label that's being emitted, it didn't make
+-     sense to have .type information for local labels.   This caused
+-     the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
+-     me debug info for a label that you're declaring non-global?) this
+-     was changed to call ASM_OUTPUT_LABEL() instead.  */
+-
+-  ASM_OUTPUT_LABEL (file, pic_label_name);
++    {
++      text_section ();
++      ASM_OUTPUT_LABEL (file, pic_label_name);
++    }
+   xops[0] = pic_offset_table_rtx;
+   xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
+@@ -3853,7 +3854,12 @@ load_pic_register ()
+   if (TARGET_DEEP_BRANCH_PREDICTION)
+     {
+       if (! pic_label_name[0])
+-      ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
++      {
++        if (USE_HIDDEN_LINKONCE && targetm.have_named_sections)
++          strcpy (pic_label_name, "__i686.get_pc_thunk.bx");
++        else
++          ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
++      }
+       pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
+     }
+   else
diff --git a/gcc32-i386-pr7242.patch b/gcc32-i386-pr7242.patch
new file mode 100644 (file)
index 0000000..ebedafe
--- /dev/null
@@ -0,0 +1,16 @@
+2002-07-11  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/7242
+       * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Fix typo.
+
+--- gcc/config/i386/i386.h.jj  Wed Jul 10 16:56:41 2002
++++ gcc/config/i386/i386.h     Thu Jul 11 09:59:06 2002
+@@ -601,7 +601,7 @@ extern int ix86_arch;
+ %{m386|mcpu=i386:-D__tune_i386__ }\
+ %{m486|mcpu=i486:-D__tune_i486__ }\
+ %{mpentium|mcpu=pentium|mcpu=i586|mcpu=pentium-mmx:-D__tune_i586__ -D__tune_pentium__ }\
+-%{mpentiumpro|mcpu=pentiumpro|mcpu=i686|cpu=pentium2|cpu=pentium3:-D__tune_i686__ \
++%{mpentiumpro|mcpu=pentiumpro|mcpu=i686|mcpu=pentium2|mcpu=pentium3:-D__tune_i686__ \
+ -D__tune_pentiumpro__ }\
+ %{mcpu=k6|mcpu=k6-2|mcpu=k6-3:-D__tune_k6__ }\
+ %{mcpu=athlon|mcpu=athlon-tbird|mcpu=athlon-4|mcpu=athlon-xp|mcpu=athlon-mp:\
diff --git a/gcc32-i386-profile-olfp.patch b/gcc32-i386-profile-olfp.patch
new file mode 100644 (file)
index 0000000..7e234f8
--- /dev/null
@@ -0,0 +1,102 @@
+2002-05-30  Richard Henderson  <rth@redhat.com>
+
+       * defaults.h (TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER): Kill.
+       * toplev.c (process_options): Don't check it.
+       * doc/tm.texi: Don't document it.
+       * config/i386/linux.h (SUBTARGET_FRAME_POINTER_REQUIRED): New.
+       (TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER): Kill.
+       * config/i386/i386.c (ix86_frame_pointer_required): Suppress leaf
+       frame pointer optimization if current_function_profile.
+
+--- gcc/doc/tm.texi.jj Fri May  3 19:25:59 2002
++++ gcc/doc/tm.texi    Tue Jun  4 23:18:43 2002
+@@ -4077,22 +4077,6 @@ must not use the @var{labelno} argument 
+ @item PROFILE_BEFORE_PROLOGUE
+ Define this macro if the code for function profiling should come before
+ the function prologue.  Normally, the profiling code comes after.
+-
+-
+-@findex TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+-@item TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+-On some targets, it is impossible to use profiling when the frame
+-pointer has been omitted.  For example, on x86 GNU/Linux systems,
+-the @code{mcount} routine provided by the GNU C Library finds the
+-address of the routine that called the routine that called @code{mcount}
+-by looking in the immediate caller's stack frame.  If the immediate
+-caller has no frame pointer, this lookup will fail.
+-
+-By default, GCC assumes that the target does allow profiling when the
+-frame pointer is omitted.  This macro should be defined to a C
+-expression that evaluates to @code{false} if the target does not allow
+-profiling when the frame pointer is omitted.
+-
+ @end table
+ @node Tail Calls
+--- gcc/config/i386/i386.c.jj  Tue Jun  4 21:13:34 2002
++++ gcc/config/i386/i386.c     Tue Jun  4 23:18:43 2002
+@@ -3827,7 +3827,8 @@ ix86_frame_pointer_required ()
+   /* In override_options, TARGET_OMIT_LEAF_FRAME_POINTER turns off
+      the frame pointer by default.  Turn it back on now if we've not
+      got a leaf function.  */
+-  if (TARGET_OMIT_LEAF_FRAME_POINTER && ! leaf_function_p ())
++  if (TARGET_OMIT_LEAF_FRAME_POINTER
++      && (!current_function_is_leaf || current_function_profile))
+     return 1;
+   return 0;
+--- gcc/config/i386/linux.h.jj Tue Apr 16 08:15:02 2002
++++ gcc/config/i386/linux.h    Tue Jun  4 23:18:43 2002
+@@ -63,14 +63,11 @@ Boston, MA 02111-1307, USA.  */
+     fprintf (FILE, "\tcall\tmcount\n");                                       \
+ }
+-/* True if it is possible to profile code that does not have a frame
+-   pointer.  
+-
+-   The GLIBC version of mcount for the x86 assumes that there is a
++/* The GLIBC version of mcount for the x86 assumes that there is a
+    frame, so we cannot allow profiling without a frame pointer.  */
+-#undef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+-#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER false
++#undef SUBTARGET_FRAME_POINTER_REQUIRED
++#define SUBTARGET_FRAME_POINTER_REQUIRED current_function_profile
+ #undef SIZE_TYPE
+ #define SIZE_TYPE "unsigned int"
+--- gcc/defaults.h.jj  Fri May  3 19:24:51 2002
++++ gcc/defaults.h     Tue Jun  4 23:18:43 2002
+@@ -398,13 +398,6 @@ do {                                                              \
+    ? ptrmemfunc_vbit_in_pfn : ptrmemfunc_vbit_in_delta)
+ #endif
+-/* True if it is possible to profile code that does not have a frame
+-   pointer.  */
+-
+-#ifndef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+-#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER true
+-#endif
+-
+ #ifndef DEFAULT_GDB_EXTENSIONS
+ #define DEFAULT_GDB_EXTENSIONS 1
+ #endif
+--- gcc/toplev.c.jj    Thu May 30 11:08:44 2002
++++ gcc/toplev.c       Tue Jun  4 23:19:11 2002
+@@ -4908,16 +4908,6 @@ process_options ()
+     warning ("this target machine does not have delayed branches");
+ #endif
+-  /* Some operating systems do not allow profiling without a frame
+-     pointer.  */
+-  if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+-      && profile_flag
+-      && flag_omit_frame_pointer)
+-    {
+-      error ("profiling does not work without a frame pointer");
+-      flag_omit_frame_pointer = 0;
+-    }
+-    
+   user_label_prefix = USER_LABEL_PREFIX;
+   if (flag_leading_underscore != -1)
+     {
diff --git a/gcc32-inline-label.patch b/gcc32-inline-label.patch
new file mode 100644 (file)
index 0000000..f8a455f
--- /dev/null
@@ -0,0 +1,55 @@
+2002-08-07  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree-inline.c (remap_decl): Make sure DECL_TOO_LATE is clear for
+       remapped labels.
+
+       * gcc.c-torture/compile/20020807-1.c: New test.
+
+--- gcc/tree-inline.c.jj       2002-04-17 15:35:57.000000000 +0200
++++ gcc/tree-inline.c  2002-08-07 14:53:14.000000000 +0200
+@@ -145,6 +145,9 @@ remap_decl (decl, id)
+       t = copy_decl_for_inlining (decl, fn,
+                                 VARRAY_TREE (id->fns, 0));
++      if (TREE_CODE (t) == LABEL_DECL)
++      DECL_TOO_LATE (t) = 0;
++
+       /* The decl T could be a dynamic array or other variable size type,
+        in which case some fields need to be remapped because they may
+        contain SAVE_EXPRs.  */
+--- gcc/testsuite/gcc.c-torture/compile/20020807-1.c.jj        2002-08-07 14:55:26.000000000 +0200
++++ gcc/testsuite/gcc.c-torture/compile/20020807-1.c   2002-08-07 14:22:07.000000000 +0200
+@@ -0,0 +1,33 @@
++int x;
++
++static int
++__attribute__ ((noinline))
++foo (void)
++{
++  return 0;
++}
++
++static void
++__attribute__ ((noinline))
++bar (void)
++{
++}
++
++static inline void
++baz (void)
++{
++  char arr[x];
++
++lab:
++  if (foo () == -1)
++    {
++      bar ();
++      goto lab;
++    }
++}
++
++void
++test (void)
++{
++  baz ();
++}
diff --git a/gcc32-java-no-rpath.patch b/gcc32-java-no-rpath.patch
new file mode 100644 (file)
index 0000000..2c21dec
--- /dev/null
@@ -0,0 +1,93 @@
+--- libjava/Makefile.am.jj     Tue Jun  4 20:41:44 2002
++++ libjava/Makefile.am        Wed Jun  5 15:20:30 2002
+@@ -111,6 +111,8 @@ INCLUDES = -I$(top_srcdir) -Iinclude -I$
+ ## ################################################################
++rpath_def = $(shell if test "$(toolexeclibdir)" != /usr/lib; then echo -rpath $(toolexeclibdir); fi)
++
+ ##
+ ## How to build libgcj.a and libgcj.jar
+ ##
+@@ -410,7 +412,7 @@ EXTRA_jv_convert_SOURCES = $(convert_sou
+ ## need this because we are explicitly using libtool to link using the
+ ## `.la' file.
+ jv_convert_LDFLAGS = --main=gnu.gcj.convert.Convert \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ jv_convert_LINK = $(GCJLINK)
+ ## We don't explicitly link in the libraries we need; libgcj.la brings
+ ## in all dependencies.  We need the -L so that gcj can find libgcj
+@@ -429,7 +431,7 @@ gij_SOURCES = gij.cc
+ ## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'.  We
+ ## need this because we are explicitly using libtool to link using the
+ ## `.la' file.
+-gij_LDFLAGS = -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++gij_LDFLAGS = $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ gij_LINK = $(GCJLINK)
+ ## See jv_convert_LDADD.
+ gij_LDADD = -L$(here)/.libs libgcj.la
+@@ -441,7 +443,7 @@ rmic_SOURCES =
+ ## This is a dummy definition.
+ EXTRA_rmic_SOURCES = $(rmi_java_source_files)
+ rmic_LDFLAGS = --main=gnu.java.rmi.rmic.RMIC \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ rmic_LINK = $(GCJLINK)
+ ## See jv_convert_LDADD.
+ rmic_LDADD = -L$(here)/.libs libgcj.la
+@@ -453,7 +455,7 @@ rmiregistry_SOURCES =
+ ## This is a dummy definition.
+ EXTRA_rmiregistry_SOURCES = $(rmi_java_source_files)
+ rmiregistry_LDFLAGS = --main=gnu.java.rmi.registry.RegistryImpl \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ rmiregistry_LINK = $(GCJLINK)
+ ## See jv_convert_LDADD.
+ rmiregistry_LDADD = -L$(here)/.libs libgcj.la
+--- libjava/Makefile.in.jj     Tue Jun  4 23:25:56 2002
++++ libjava/Makefile.in        Wed Jun  5 15:21:59 2002
+@@ -184,6 +184,7 @@ INCLUDES = -I$(top_srcdir) -Iinclude -I$
+       $(GCINCS) $(THREADINCS) $(INCLTDL) \
+       $(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
++rpath_def = $(shell if test "$(toolexeclibdir)" != /usr/lib; then echo -rpath $(toolexeclibdir); fi)
+ nat_files = $(nat_source_files:.cc=.lo)
+ x_nat_files = $(x_nat_source_files:.cc=.lo)
+@@ -263,7 +264,7 @@ CONVERT_DIR = gnu/gcj/convert
+ jv_convert_SOURCES = 
+ EXTRA_jv_convert_SOURCES = $(convert_source_files)
+ jv_convert_LDFLAGS = --main=gnu.gcj.convert.Convert \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ jv_convert_LINK = $(GCJLINK)
+ jv_convert_LDADD = -L$(here)/.libs libgcj.la
+@@ -272,7 +273,7 @@ jv_convert_DEPENDENCIES = $(convert_sour
+ gij_SOURCES = gij.cc
+-gij_LDFLAGS = -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++gij_LDFLAGS = $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ gij_LINK = $(GCJLINK)
+ gij_LDADD = -L$(here)/.libs libgcj.la
+ gij_DEPENDENCIES = libgcj.la libgcj.spec
+@@ -280,7 +281,7 @@ gij_DEPENDENCIES = libgcj.la libgcj.spec
+ rmic_SOURCES = 
+ EXTRA_rmic_SOURCES = $(rmi_java_source_files)
+ rmic_LDFLAGS = --main=gnu.java.rmi.rmic.RMIC \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ rmic_LINK = $(GCJLINK)
+ rmic_LDADD = -L$(here)/.libs libgcj.la
+@@ -289,7 +290,7 @@ rmic_DEPENDENCIES = libgcj.la libgcj.spe
+ rmiregistry_SOURCES = 
+ EXTRA_rmiregistry_SOURCES = $(rmi_java_source_files)
+ rmiregistry_LDFLAGS = --main=gnu.java.rmi.registry.RegistryImpl \
+-      -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
++      $(rpath_def) -shared-libgcc $(THREADLDFLAGS)
+ rmiregistry_LINK = $(GCJLINK)
+ rmiregistry_LDADD = -L$(here)/.libs libgcj.la
diff --git a/gcc32-locale_in_ctype_members.patch b/gcc32-locale_in_ctype_members.patch
new file mode 100644 (file)
index 0000000..eb862df
--- /dev/null
@@ -0,0 +1,69 @@
+--- libstdc++-v3/config/locale/gnu/ctype_members.cc.jj 2002-08-30 12:09:12.000000000 +0200
++++ libstdc++-v3/config/locale/gnu/ctype_members.cc    2002-09-02 15:25:15.000000000 +0200
+@@ -166,15 +166,30 @@ namespace std
+   wchar_t
+   ctype<wchar_t>::
+   do_widen(char __c) const
+-  { return btowc(__c); }
+-  
++  {
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++    wchar_t __ret = btowc(__c);
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __uselocale(__old);
++#endif
++    return __ret;
++  }
++
+   const char* 
+   ctype<wchar_t>::
+   do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
+   {
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
+     mbstate_t __state;
+     memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t));
+     mbsrtowcs(__dest, &__lo, __hi - __lo, &__state);
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __uselocale(__old);
++#endif
+     return __hi;
+   }
+@@ -182,7 +197,13 @@ namespace std
+   ctype<wchar_t>::
+   do_narrow(wchar_t __wc, char __dfault) const
+   { 
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
+     int __c = wctob(__wc);
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __uselocale(__old);
++#endif
+     return (__c == EOF ? __dfault : static_cast<char>(__c)); 
+   }
+@@ -191,6 +212,9 @@ namespace std
+   do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 
+           char* __dest) const
+   {
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
+     size_t __offset = 0;
+     while (true)
+       {
+@@ -208,6 +232,9 @@ namespace std
+       else
+         break;
+       }
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++    __uselocale(__old);
++#endif
+     return __hi;
+   }
+ #endif //  _GLIBCPP_USE_WCHAR_T
diff --git a/gcc32-locale_in_monetary_members.patch b/gcc32-locale_in_monetary_members.patch
new file mode 100644 (file)
index 0000000..0d396dd
--- /dev/null
@@ -0,0 +1,59 @@
+--- libstdc++-v3/config/locale/gnu/monetary_members.cc.jj      2002-08-30 12:09:12.000000000 +0200
++++ libstdc++-v3/config/locale/gnu/monetary_members.cc 2002-08-31 23:41:51.000000000 +0200
+@@ -335,9 +335,13 @@ namespace std
+       else
+       {
+         // Named locale.
+-        // XXX Fix me. Switch to named locale so that mbsrtowcs will work.
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++        __c_locale __old = __uselocale(__cloc);
++#else
++        // Switch to named locale so that mbsrtowcs will work.
+         char* __old = strdup(setlocale(LC_ALL, NULL));
+         setlocale(LC_ALL, __name);
++#endif
+         _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w);
+@@ -400,9 +404,12 @@ namespace std
+         char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
+         _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
+-        // XXX
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++        __uselocale(__old);
++#else
+         setlocale(LC_ALL, __old);
+         free(__old);
++#endif
+       }
+     }
+@@ -427,9 +434,13 @@ namespace std
+       else
+       {
+         // Named locale.
+-        // XXX Fix me. Switch to named locale so that mbsrtowcs will work.
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++        __c_locale __old = __uselocale(__cloc);
++#else
++        // Switch to named locale so that mbsrtowcs will work.
+         char* __old = strdup(setlocale(LC_ALL, NULL));
+         setlocale(LC_ALL, __name);
++#endif
+         _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w);
+         _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w);
+@@ -491,9 +502,12 @@ namespace std
+         char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
+         _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn);
+-        // XXX
++#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
++        __uselocale(__old);
++#else
+         setlocale(LC_ALL, __old);
+         free(__old);
++#endif
+       }
+     }
diff --git a/gcc32-loop-prefetch.patch b/gcc32-loop-prefetch.patch
new file mode 100644 (file)
index 0000000..205090f
--- /dev/null
@@ -0,0 +1,25 @@
+Wed Jul 10 19:12:41 CEST 2002  Janis Johnson  <janis187@us.ibm.com>
+
+       * loop.c (emit_prefetch_instructions): Small fix.
+
+--- gcc/loop.c.jj      Fri Jun 14 21:12:04 2002
++++ gcc/loop.c Wed Aug 14 12:13:43 2002
+@@ -4090,11 +4090,17 @@ emit_prefetch_instructions (loop)
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+             rtx loop_start = loop->start;
++            rtx init_val = info[i].class->initial_value;
+             rtx add_val = simplify_gen_binary (PLUS, Pmode,
+                                                info[i].giv->add_val,
+                                                GEN_INT (y * PREFETCH_BLOCK));
+-            loop_iv_add_mult_emit_before (loop, info[i].class->initial_value,
++            /* Functions called by LOOP_IV_ADD_EMIT_BEFORE expect a
++               non-constant INIT_VAL to have the same mode as REG, which
++               in this case we know to be Pmode.  */
++            if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
++              init_val = convert_to_mode (Pmode, init_val, 0);
++            loop_iv_add_mult_emit_before (loop, init_val,
+                                           info[i].giv->mult_val,
+                                           add_val, reg, 0, loop_start);
+             emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
diff --git a/gcc32-pr6842.patch b/gcc32-pr6842.patch
new file mode 100644 (file)
index 0000000..905efaa
--- /dev/null
@@ -0,0 +1,48 @@
+2002-05-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR optimization/6842
+       * combine.c (combine_simplify_rtx) [SUBREG]: Don't ICE if VOIDmode
+       operand subreg cannot be simplified.
+
+       * gcc.dg/20020531-1.c: New test.
+
+--- gcc/testsuite/gcc.dg/20020531-1.c.jj       Fri May 31 17:15:15 2002
++++ gcc/testsuite/gcc.dg/20020531-1.c  Fri May 31 17:13:50 2002
+@@ -0,0 +1,21 @@
++/* PR optimization/6842
++   This testcase caused ICE when trying to optimize V8QI subreg of VOIDmode
++   CONST_DOUBLE.  */
++/* { dg-do compile { target i?86-*-* } } */
++/* { dg-options "-O2 -mmmx" } */
++
++typedef int __v8qi __attribute__ ((__mode__ (__V8QI__)));
++extern void abort (void);
++extern void exit (int);
++
++void foo (void)
++{
++  unsigned long long a = 0x0102030405060708LL;
++  unsigned long long b = 0x1020304050607080LL;
++  unsigned long long c;
++
++  c = (unsigned long long) __builtin_ia32_paddusb ((__v8qi) a, (__v8qi) b);
++  __builtin_ia32_emms ();
++  if (c != 0x1122334455667788)
++    abort ();
++}
+--- gcc/combine.c.jj   Thu May 23 10:22:59 2002
++++ gcc/combine.c      Fri May 31 17:05:09 2002
+@@ -3863,7 +3863,12 @@ combine_simplify_rtx (x, op0_mode, last,
+       /* simplify_subreg can't use gen_lowpart_for_combine.  */
+       if (CONSTANT_P (SUBREG_REG (x))
+-        && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x))
++        && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
++           /* Don't call gen_lowpart_for_combine if the inner mode
++              is VOIDmode and we cannot simplify it, as SUBREG without
++              inner mode is invalid.  */
++        && (GET_MODE (SUBREG_REG (x)) != VOIDmode
++            || gen_lowpart_common (mode, SUBREG_REG (x))))
+       return gen_lowpart_for_combine (mode, SUBREG_REG (x));
+       if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_CC)
diff --git a/gcc32-rh69989.patch b/gcc32-rh69989.patch
new file mode 100644 (file)
index 0000000..e1e9f38
--- /dev/null
@@ -0,0 +1,215 @@
+2002-07-29  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/20020729-1.c: New test.
+
+2002-05-17  Richard Sandiford  <rsandifo@redhat.com>
+
+       * expr.c (force_operand): Fix reversed move.
+
+Sat May  4 13:20:54 CEST 2002  Jan Hubicka  <jh@suse.cz>
+
+       * expr.c (force_operand): Use expand_simple_* to handle more
+       cases.
+
+--- gcc/expr.c.jj      2002-05-07 12:45:49.000000000 +0200
++++ gcc/expr.c 2002-08-03 01:08:28.000000000 +0200
+@@ -5434,16 +5434,13 @@ rtx
+ force_operand (value, target)
+      rtx value, target;
+ {
+-  optab binoptab = 0;
+-  /* Use a temporary to force order of execution of calls to
+-     `force_operand'.  */
+-  rtx tmp;
+-  rtx op2;
++  rtx op1, op2;
+   /* Use subtarget as the target for operand 0 of a binary operation.  */
+   rtx subtarget = get_subtarget (target);
++  enum rtx_code code = GET_CODE (value);
+   /* Check for a PIC address load.  */
+-  if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
++  if ((code == PLUS || code == MINUS)
+       && XEXP (value, 0) == pic_offset_table_rtx
+       && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
+         || GET_CODE (XEXP (value, 1)) == LABEL_REF
+@@ -5455,60 +5452,88 @@ force_operand (value, target)
+       return subtarget;
+     }
+-  if (GET_CODE (value) == PLUS)
+-    binoptab = add_optab;
+-  else if (GET_CODE (value) == MINUS)
+-    binoptab = sub_optab;
+-  else if (GET_CODE (value) == MULT)
++  if (code == ZERO_EXTEND || code == SIGN_EXTEND)
+     {
+-      op2 = XEXP (value, 1);
+-      if (!CONSTANT_P (op2)
+-        && !(GET_CODE (op2) == REG && op2 != subtarget))
+-      subtarget = 0;
+-      tmp = force_operand (XEXP (value, 0), subtarget);
+-      return expand_mult (GET_MODE (value), tmp,
+-                        force_operand (op2, NULL_RTX),
+-                        target, 1);
++      if (!target)
++      target = gen_reg_rtx (GET_MODE (value));
++      convert_move (target, force_operand (XEXP (value, 0), NULL),
++                  code == ZERO_EXTEND);
++      return target;
+     }
+-  if (binoptab)
++  if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
+     {
+       op2 = XEXP (value, 1);
+-      if (!CONSTANT_P (op2)
+-        && !(GET_CODE (op2) == REG && op2 != subtarget))
++      if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
+       subtarget = 0;
+-      if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
++      if (code == MINUS && GET_CODE (op2) == CONST_INT)
+       {
+-        binoptab = add_optab;
++        code = PLUS;
+         op2 = negate_rtx (GET_MODE (value), op2);
+       }
+       /* Check for an addition with OP2 a constant integer and our first
+-       operand a PLUS of a virtual register and something else.  In that
+-       case, we want to emit the sum of the virtual register and the
+-       constant first and then add the other value.  This allows virtual
+-       register instantiation to simply modify the constant rather than
+-       creating another one around this addition.  */
+-      if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
++         operand a PLUS of a virtual register and something else.  In that
++         case, we want to emit the sum of the virtual register and the
++         constant first and then add the other value.  This allows virtual
++         register instantiation to simply modify the constant rather than
++         creating another one around this addition.  */
++      if (code == PLUS && GET_CODE (op2) == CONST_INT
+         && GET_CODE (XEXP (value, 0)) == PLUS
+         && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
+         && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
+         && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
+       {
+-        rtx temp = expand_binop (GET_MODE (value), binoptab,
+-                                 XEXP (XEXP (value, 0), 0), op2,
+-                                 subtarget, 0, OPTAB_LIB_WIDEN);
+-        return expand_binop (GET_MODE (value), binoptab, temp,
+-                             force_operand (XEXP (XEXP (value, 0), 1), 0),
+-                             target, 0, OPTAB_LIB_WIDEN);
++        rtx temp = expand_simple_binop (GET_MODE (value), code,
++                                        XEXP (XEXP (value, 0), 0), op2,
++                                        subtarget, 0, OPTAB_LIB_WIDEN);
++        return expand_simple_binop (GET_MODE (value), code, temp,
++                                    force_operand (XEXP (XEXP (value,
++                                                               0), 1), 0),
++                                    target, 0, OPTAB_LIB_WIDEN);
++      }
++
++      op1 = force_operand (XEXP (value, 0), subtarget);
++      op2 = force_operand (op2, NULL_RTX);
++      switch (code)
++      {
++      case MULT:
++        return expand_mult (GET_MODE (value), op1, op2, target, 1);
++      case DIV:
++        if (!INTEGRAL_MODE_P (GET_MODE (value)))
++          return expand_simple_binop (GET_MODE (value), code, op1, op2,
++                                      target, 1, OPTAB_LIB_WIDEN);
++        else
++          return expand_divmod (0,
++                                FLOAT_MODE_P (GET_MODE (value))
++                                ? RDIV_EXPR : TRUNC_DIV_EXPR,
++                                GET_MODE (value), op1, op2, target, 0);
++        break;
++      case MOD:
++        return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
++                              target, 0);
++        break;
++      case UDIV:
++        return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
++                              target, 1);
++        break;
++      case UMOD:
++        return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
++                              target, 1);
++        break;
++      case ASHIFTRT:
++        return expand_simple_binop (GET_MODE (value), code, op1, op2,
++                                    target, 0, OPTAB_LIB_WIDEN);
++        break;
++      default:
++        return expand_simple_binop (GET_MODE (value), code, op1, op2,
++                                    target, 1, OPTAB_LIB_WIDEN);
+       }
+-
+-      tmp = force_operand (XEXP (value, 0), subtarget);
+-      return expand_binop (GET_MODE (value), binoptab, tmp,
+-                         force_operand (op2, NULL_RTX),
+-                         target, 0, OPTAB_LIB_WIDEN);
+-      /* We give UNSIGNEDP = 0 to expand_binop
+-       because the only operations we are expanding here are signed ones.  */
++    }
++  if (GET_RTX_CLASS (code) == '1')
++    {
++      op1 = force_operand (XEXP (value, 0), NULL_RTX);
++      return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
+     }
+ #ifdef INSN_SCHEDULING
+--- gcc/testsuite/gcc.dg/20020729-1.c.jj       2002-08-03 01:08:28.000000000 +0200
++++ gcc/testsuite/gcc.dg/20020729-1.c  2002-08-03 01:08:28.000000000 +0200
+@@ -0,0 +1,51 @@
++/* { dg-do compile { target i?86-*-* } } */
++/* { dg-options "-O2 -march=k6" } */
++
++static inline void *
++baz (void *s, unsigned long c, unsigned int count)
++{
++  int d0, d1;
++  __asm__ __volatile__ (""
++                      : "=&c" (d0), "=&D" (d1)
++                      :"a" (c), "q" (count), "0" (count / 4), "1" ((long) s)
++                      :"memory");
++  return s;
++}
++
++struct A
++{
++  unsigned long *a;
++};
++
++inline static void *
++bar (struct A *x, int y)
++{
++  char *ptr;
++
++  ptr = (void *) x->a[y >> 12];
++  ptr += y % (1UL << 12);
++  return (void *) ptr;
++}
++
++int
++foo (struct A *x, unsigned int *y, int z, int u)
++{
++  int a, b, c, d, e;
++
++  z += *y;
++  c = z + u;
++  a = (z >> 12) + 1;
++  do
++    {
++      b = (a << 12);
++      d = b - z;
++      e = c - z;
++      if (e < d)
++      d = e;
++      baz (bar (x, z), 0, d);
++      z = b;
++      a++;
++    }
++  while (z < c);
++  return 0;
++}
diff --git a/gcc32-sparc-sll1.patch b/gcc32-sparc-sll1.patch
new file mode 100644 (file)
index 0000000..e8e1104
--- /dev/null
@@ -0,0 +1,95 @@
+2002-05-05  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/sparc/sparc.md (ashlsi3): If shift count is const1_rtx,
+       use add instead of shift.
+       (ashldi3_sp64): Likewise.
+       (ashlsi3_const1, ashldi3_const1): Remove.
+       * config/sparc/sparc.h (PREDICATE_CODES): Add const1_operand.
+       * config/sparc/sparc.c (const1_operand): New.
+
+--- gcc/config/sparc/sparc.md.jj       Sun May  5 21:56:45 2002
++++ gcc/config/sparc/sparc.md  Sun May  5 23:33:31 2002
+@@ -7559,18 +7559,13 @@
+       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
+     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
++  if (operands[2] == const1_rtx)
++    return \"add\\t%1, %1, %0\";
+   return \"sll\\t%1, %2, %0\";
+ }"
+-  [(set_attr "type" "shift")])
+-
+-;; We special case multiplication by two, as add can be done
+-;; in both ALUs, while shift only in IEU0 on UltraSPARC.
+-(define_insn "*ashlsi3_const1"
+-  [(set (match_operand:SI 0 "register_operand" "=r")
+-        (ashift:SI (match_operand:SI 1 "register_operand" "r")
+-                   (const_int 1)))]
+-  ""
+-  "add\\t%1, %1, %0")
++  [(set (attr "type")
++      (if_then_else (match_operand 2 "const1_operand" "")
++                    (const_string "ialu") (const_string "shift")))])
+ (define_expand "ashldi3"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -7588,15 +7583,6 @@
+     }
+ }")
+-;; We special case multiplication by two, as add can be done
+-;; in both ALUs, while shift only in IEU0 on UltraSPARC.
+-(define_insn "*ashldi3_const1"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
+-      (ashift:DI (match_operand:DI 1 "register_operand" "r")
+-                 (const_int 1)))]
+-  "TARGET_ARCH64"
+-  "add\\t%1, %1, %0")
+-
+ (define_insn "*ashldi3_sp64"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+       (ashift:DI (match_operand:DI 1 "register_operand" "r")
+@@ -7608,9 +7594,13 @@
+       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
+     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
++  if (operands[2] == const1_rtx)
++    return \"add\\t%1, %1, %0\";
+   return \"sllx\\t%1, %2, %0\";
+ }"
+-  [(set_attr "type" "shift")])
++  [(set (attr "type")
++      (if_then_else (match_operand 2 "const1_operand" "")
++                    (const_string "ialu") (const_string "shift")))])
+ ;; XXX UGH!
+ (define_insn "ashldi3_v8plus"
+--- gcc/config/sparc/sparc.h.jj        Fri May  3 22:57:33 2002
++++ gcc/config/sparc/sparc.h   Sun May  5 23:20:48 2002
+@@ -3014,6 +3014,7 @@ do {                                                                     \
+ #define PREDICATE_CODES                                                       \
+ {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},         \
++{"const1_operand", {CONST_INT}},                                      \
+ {"fp_zero_operand", {CONST_DOUBLE}},                                  \
+ {"fp_register_operand", {SUBREG, REG}},                                       \
+ {"intreg_operand", {SUBREG, REG}},                                    \
+--- gcc/config/sparc/sparc.c.jj        Fri May  3 22:57:33 2002
++++ gcc/config/sparc/sparc.c   Sun May  5 23:24:18 2002
+@@ -478,6 +478,16 @@ reg_or_0_operand (op, mode)
+   return 0;
+ }
++/* Return non-zero only if OP is const1_rtx.  */
++
++int
++const1_operand (op, mode)
++     rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  return op == const1_rtx;
++}
++
+ /* Nonzero if OP is a floating point value with value 0.0.  */
+ int
diff --git a/gcc32-test-rh65771.patch b/gcc32-test-rh65771.patch
new file mode 100644 (file)
index 0000000..1bc801c
--- /dev/null
@@ -0,0 +1,93 @@
+2002-06-04  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.c-torture/compile/20020604-1.c: New test.
+
+--- gcc/testsuite/gcc.c-torture/compile/20020604-1.c.jj        Thu Apr 11 16:25:15 2002
++++ gcc/testsuite/gcc.c-torture/compile/20020604-1.c   Mon Jun  3 17:43:12 2002
+@@ -0,0 +1,86 @@
++/* This testcase ICEd at -O2 on IA-32, because
++   (insn 141 139 142 (set (subreg:SF (reg:QI 72) 0)
++         (plus:SF (reg:SF 73)
++             (reg:SF 76))) 525 {*fop_sf_comm_nosse} (insn_list 134 (nil))
++       (expr_list:REG_DEAD (reg:SF 73) (nil)))
++   couldn't be reloaded. */
++
++void
++foo (unsigned int n, int x, int y, unsigned char *z)
++{
++  int a, b;
++  float c[2048][4];
++
++  switch (x)
++    {
++    case 0x1906:
++      a = b = -1;
++      break;
++    case 0x190A:
++      a = b = -1;
++      break;
++    case 0x8049:
++      a = b = -1;
++      break;
++    case 0x1907:
++      a = 1;
++      b = 2;
++      break;
++    default:
++      return;
++    }
++
++  if (a >= 0)
++    {
++      unsigned char *d = z;
++      unsigned int i;
++      for (i = 0; i < n; i++)
++      {
++        do
++          {
++            union
++            {
++              float r;
++              unsigned int i;
++            }
++            e;
++            e.r = c[i][1];
++            d[a] =
++              ((e.i >= 0x3f7f0000) ? ((int) e.i <
++                                          0) ? (unsigned char) 0
++               : (unsigned char) 255 : (e.r =
++                                        e.r * (255.0F / 256.0F) +
++                                        32768.0F, (unsigned char) e.i));
++          }
++        while (0);
++        d += y;
++      }
++    }
++
++  if (b >= 0)
++    {
++      unsigned char *d = z;
++      unsigned int i;
++      for (i = 0; i < n; i++)
++      {
++        do
++          {
++            union
++            {
++              float r;
++              unsigned int i;
++            }
++            e;
++            e.r = c[i][2];
++            d[b] =
++              ((e.i >= 0x3f7f0000) ? ((int) e.i <
++                                          0) ? (unsigned char) 0
++               : (unsigned char) 255 : (e.r =
++                                        e.r * (255.0F / 256.0F) +
++                                        32768.0F, (unsigned char) e.i));
++          }
++        while (0);
++        d += y;
++      }
++    }
++}
diff --git a/gcc32-test-rotate.patch b/gcc32-test-rotate.patch
new file mode 100644 (file)
index 0000000..37e5f5c
--- /dev/null
@@ -0,0 +1,323 @@
+2002-05-08  Tom Rix  <trix@redhat.com>
+
+       * gcc.c-torture/execute/20020508-1.c: New test.
+       * gcc.c-torture/execute/20020508-2.c: New test.
+       * gcc.c-torture/execute/20020508-3.c: New test.
+
+--- gcc/testsuite/gcc.c-torture/execute/20020508-1.c.jj        Wed May 15 14:22:47 2002
++++ gcc/testsuite/gcc.c-torture/execute/20020508-1.c   Wed May 15 14:22:47 2002
+@@ -0,0 +1,104 @@
++/* This tests the rotate patterns that some machines support.  */
++
++#include <limits.h>
++
++#ifndef CHAR_BIT
++#define CHAR_BIT 8
++#endif
++
++#define ROR(a,b) (((a) >> (b)) | ((a) << ((sizeof (a) * CHAR_BIT) - (b))))
++#define ROL(a,b) (((a) << (b)) | ((a) >> ((sizeof (a) * CHAR_BIT) - (b))))
++
++#define CHAR_VALUE ((unsigned char)0xf234U)
++#define SHORT_VALUE ((unsigned short)0xf234U)
++#define INT_VALUE 0xf234U
++#define LONG_VALUE 0xf2345678LU
++#define LL_VALUE 0xf2345678abcdef0LLU
++
++#define SHIFT1 4
++#define SHIFT2 ((sizeof (long long) * CHAR_BIT) - SHIFT1)
++
++unsigned char uc = CHAR_VALUE;
++unsigned short us = SHORT_VALUE;
++unsigned int ui = INT_VALUE;
++unsigned long ul = LONG_VALUE;
++unsigned long long ull = LL_VALUE;
++int shift1 = SHIFT1;
++int shift2 = SHIFT2;
++
++main ()
++{
++  if (ROR (uc, shift1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (uc, SHIFT1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (us, shift1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (us, SHIFT1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ui, shift1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ui, SHIFT1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ul, shift1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ul, SHIFT1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ull, shift1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ull, SHIFT1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ull, shift2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROR (ull, SHIFT2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (uc, shift1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (uc, SHIFT1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (us, shift1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (us, SHIFT1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ui, shift1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ui, SHIFT1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ul, shift1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ul, SHIFT1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ull, shift1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ull, SHIFT1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ull, shift2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (ull, SHIFT2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  exit (0);
++}
+--- gcc/testsuite/gcc.c-torture/execute/20020508-2.c.jj        Wed May 15 14:22:47 2002
++++ gcc/testsuite/gcc.c-torture/execute/20020508-2.c   Wed May 15 14:22:47 2002
+@@ -0,0 +1,102 @@
++#include <limits.h>
++
++#ifndef CHAR_BIT
++#define CHAR_BIT 8
++#endif
++
++#define ROR(a,b) (((a) >> (b)) | ((a) << ((sizeof (a) * CHAR_BIT) - (b))))
++#define ROL(a,b) (((a) << (b)) | ((a) >> ((sizeof (a) * CHAR_BIT) - (b))))
++
++#define CHAR_VALUE ((char)0x1234)
++#define SHORT_VALUE ((short)0x1234)
++#define INT_VALUE ((int)0x1234)
++#define LONG_VALUE ((long)0x12345678L)
++#define LL_VALUE ((long long)0x12345678abcdef0LL)
++
++#define SHIFT1 4
++#define SHIFT2 ((sizeof (long long) * CHAR_BIT) - SHIFT1)
++
++char c = CHAR_VALUE;
++short s = SHORT_VALUE;
++int i = INT_VALUE;
++long l = LONG_VALUE;
++long long ll = LL_VALUE;
++int shift1 = SHIFT1;
++int shift2 = SHIFT2;
++
++main ()
++{
++  if (ROR (c, shift1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (c, SHIFT1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (s, shift1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (s, SHIFT1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (i, shift1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (i, SHIFT1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (l, shift1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (l, SHIFT1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, shift1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, SHIFT1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, shift2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROR (ll, SHIFT2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (c, shift1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (c, SHIFT1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (s, shift1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (s, SHIFT1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (i, shift1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (i, SHIFT1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (l, shift1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (l, SHIFT1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, shift1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, SHIFT1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, shift2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (ll, SHIFT2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  exit (0);
++}
+--- gcc/testsuite/gcc.c-torture/execute/20020508-3.c.jj        Wed May 15 14:22:47 2002
++++ gcc/testsuite/gcc.c-torture/execute/20020508-3.c   Wed May 15 14:22:47 2002
+@@ -0,0 +1,102 @@
++#include <limits.h>
++
++#ifndef CHAR_BIT
++#define CHAR_BIT 8
++#endif
++
++#define ROR(a,b) (((a) >> (b)) | ((a) << ((sizeof (a) * CHAR_BIT) - (b))))
++#define ROL(a,b) (((a) << (b)) | ((a) >> ((sizeof (a) * CHAR_BIT) - (b))))
++
++#define CHAR_VALUE ((char)0xf234)
++#define SHORT_VALUE ((short)0xf234)
++#define INT_VALUE ((int)0xf234)
++#define LONG_VALUE ((long)0xf2345678L)
++#define LL_VALUE ((long long)0xf2345678abcdef0LL)
++
++#define SHIFT1 4
++#define SHIFT2 ((sizeof (long long) * CHAR_BIT) - SHIFT1)
++
++char c = CHAR_VALUE;
++short s = SHORT_VALUE;
++int i = INT_VALUE;
++long l = LONG_VALUE;
++long long ll = LL_VALUE;
++int shift1 = SHIFT1;
++int shift2 = SHIFT2;
++
++main ()
++{
++  if (ROR (c, shift1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (c, SHIFT1) != ROR (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (s, shift1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (s, SHIFT1) != ROR (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (i, shift1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (i, SHIFT1) != ROR (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (l, shift1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (l, SHIFT1) != ROR (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, shift1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, SHIFT1) != ROR (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROR (ll, shift2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROR (ll, SHIFT2) != ROR (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (c, shift1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (c, SHIFT1) != ROL (CHAR_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (s, shift1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (s, SHIFT1) != ROL (SHORT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (i, shift1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (i, SHIFT1) != ROL (INT_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (l, shift1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (l, SHIFT1) != ROL (LONG_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, shift1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, SHIFT1) != ROL (LL_VALUE, SHIFT1))
++    abort ();
++
++  if (ROL (ll, shift2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  if (ROL (ll, SHIFT2) != ROL (LL_VALUE, SHIFT2))
++    abort ();
++
++  exit (0);
++}
diff --git a/gcc32-tls-dwarf2.patch b/gcc32-tls-dwarf2.patch
new file mode 100644 (file)
index 0000000..432f196
--- /dev/null
@@ -0,0 +1,337 @@
+2002-08-21  Richard Henderson  <rth@redhat.com>
+
+       * config/i386/i386-protos.h (i386_output_dwarf_dtprel): Add
+       prototype.
+       * config/i386/i386.c (i386_output_dwarf_dtprel): New.
+       * config/i386/i386.h (ASM_OUTPUT_DWARF_DTPREL): Define.
+       * dwarf2.h (DW_OP_GNU_push_tls_address): Add.
+       (DW_OP_lo_user): Define to 0xe0.
+       * dwarf2out.c (INTERNAL_DW_OP_tls_addr): Define.
+       (dwarf_stack_op_name, sizeof_loc_descr): Handle a few more OPs.
+       (output_loc_operands): Handle INTERNAL_DW_OP_tls_addr.
+       (loc_descriptor_from_tree): Handle DECL_THREAD_LOCAL variables.
+       (add_AT_location_description): Pass descr instead of rtl.
+       (add_location_or_const_value_attribute, add_bound_info,
+       gen_subprogram_die): Adjust its callers.
+       (rtl_for_decl_location): Avoid constant pool references.
+
+--- gcc/config/i386/i386-protos.h      20 Aug 2002 17:20:36 -0000      1.1.1.1
++++ gcc/config/i386/i386-protos.h      20 Aug 2002 22:35:02 -0000
+@@ -113,6 +113,7 @@ extern const char *output_fix_trunc PARA
+ extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
+ extern void i386_dwarf_output_addr_const PARAMS ((FILE*, rtx));
++extern void i386_output_dwarf_dtprel PARAMS ((FILE*, int, rtx));
+ extern rtx i386_simplify_dwarf_addr PARAMS ((rtx));
+ extern void ix86_expand_clear PARAMS ((rtx));
+--- gcc/config/i386/i386.c     20 Aug 2002 17:20:36 -0000      1.1.1.1
++++ gcc/config/i386/i386.c     20 Aug 2002 22:35:02 -0000
+@@ -5921,6 +5921,33 @@ i386_dwarf_output_addr_const (file, x)
+   fputc ('\n', file);
+ }
++/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
++   We need to emit DTP-relative relocations.  */
++
++void
++i386_output_dwarf_dtprel (file, size, x)
++     FILE *file;
++     int size;
++     rtx x;
++{
++  switch (size)
++    {
++    case 4:
++      fputs (ASM_LONG, file);
++      break;
++    case 8:
++#ifdef ASM_QUAD
++      fputs (ASM_QUAD, file);
++      break;
++#endif
++    default:
++      abort ();
++   }
++  
++  output_addr_const (file, x);
++  fputs ("@DTPOFF", file);
++}
++
+ /* In the name of slightly smaller debug output, and to cater to
+    general assembler losage, recognize PIC+GOTOFF and turn it back
+    into a direct symbol reference.  */
+--- gcc/config/i386/i386.h     20 Aug 2002 17:20:36 -0000      1.1.1.1
++++ gcc/config/i386/i386.h     20 Aug 2002 22:35:02 -0000
+@@ -2899,6 +2899,13 @@ extern int const svr4_dbx_register_map[F
+ #define ASM_SIMPLIFY_DWARF_ADDR(X) \
+   i386_simplify_dwarf_addr (X)
++/* Emit a dtp-relative reference to a TLS variable.  */
++
++#ifdef HAVE_AS_TLS
++#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
++  i386_output_dwarf_dtprel (FILE, SIZE, X)
++#endif
++
+ /* Switch to init or fini section via SECTION_OP, emit a call to FUNC,
+    and switch back.  For x86 we do this only to save a few bytes that
+    would otherwise be unused in the text section.  */
+--- gcc/dwarf2.h       20 Aug 2002 17:20:19 -0000      1.1.1.1
++++ gcc/dwarf2.h       20 Aug 2002 22:35:02 -0000
+@@ -399,10 +399,12 @@ enum dwarf_location_atom
+     DW_OP_push_object_address = 0x97,
+     DW_OP_call2 = 0x98,
+     DW_OP_call4 = 0x99,
+-    DW_OP_calli = 0x9a
++    DW_OP_call_ref = 0x9a,
++    /* GNU extensions.  */
++    DW_OP_GNU_push_tls_address = 0xe0
+   };
+-#define DW_OP_lo_user 0x80    /* Implementation-defined range start.  */
++#define DW_OP_lo_user 0xe0    /* Implementation-defined range start.  */
+ #define DW_OP_hi_user 0xff    /* Implementation-defined range end.  */
+ /* Type encodings.  */
+--- gcc/dwarf2out.c    20 Aug 2002 17:20:19 -0000      1.1.1.1
++++ gcc/dwarf2out.c    20 Aug 2002 22:40:42 -0000
+@@ -2169,6 +2169,11 @@ dwarf2out_frame_finish ()
+ /* And now, the subset of the debugging information support code necessary
+    for emitting location expressions.  */
++/* We need some way to distinguish DW_OP_addr with a direct symbol
++   relocation from DW_OP_addr with a dtp-relative symbol relocation.  */
++#define INTERNAL_DW_OP_tls_addr               (0x100 + DW_OP_addr)
++
++
+ typedef struct dw_val_struct *dw_val_ref;
+ typedef struct die_struct *dw_die_ref;
+ typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
+@@ -2294,6 +2299,7 @@ dwarf_stack_op_name (op)
+   switch (op)
+     {
+     case DW_OP_addr:
++    case INTERNAL_DW_OP_tls_addr:
+       return "DW_OP_addr";
+     case DW_OP_deref:
+       return "DW_OP_deref";
+@@ -2583,6 +2589,16 @@ dwarf_stack_op_name (op)
+       return "DW_OP_xderef_size";
+     case DW_OP_nop:
+       return "DW_OP_nop";
++    case DW_OP_push_object_address:
++      return "DW_OP_push_object_address";
++    case DW_OP_call2:
++      return "DW_OP_call2";
++    case DW_OP_call4:
++      return "DW_OP_call4";
++    case DW_OP_call_ref:
++      return "DW_OP_call_ref";
++    case DW_OP_GNU_push_tls_address:
++      return "DW_OP_GNU_push_tls_address";
+     default:
+       return "OP_<unknown>";
+     }
+@@ -2640,6 +2656,7 @@ size_of_loc_descr (loc)
+   switch (loc->dw_loc_opc)
+     {
+     case DW_OP_addr:
++    case INTERNAL_DW_OP_tls_addr:
+       size += DWARF2_ADDR_SIZE;
+       break;
+     case DW_OP_const1u:
+@@ -2725,6 +2742,15 @@ size_of_loc_descr (loc)
+     case DW_OP_xderef_size:
+       size += 1;
+       break;
++    case DW_OP_call2:
++      size += 2;
++      break;
++    case DW_OP_call4:
++      size += 4;
++      break;
++    case DW_OP_call_ref:
++      size += DWARF2_ADDR_SIZE;
++      break;
+     default:
+       break;
+     }
+@@ -2874,6 +2900,17 @@ output_loc_operands (loc)
+     case DW_OP_xderef_size:
+       dw2_asm_output_data (1, val1->v.val_int, NULL);
+       break;
++
++    case INTERNAL_DW_OP_tls_addr:
++#ifdef ASM_OUTPUT_DWARF_DTPREL
++      ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE,
++                             val1->v.val_addr);
++      fputc ('\n', asm_out_file);
++#else
++      abort ();
++#endif
++      break;
++
+     default:
+       /* Other codes have no operands.  */
+       break;
+@@ -3598,7 +3635,8 @@ static unsigned int simple_field_decl_al
+ static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
+ static HOST_WIDE_INT field_byte_offset        PARAMS ((tree));
+ static void add_AT_location_description       PARAMS ((dw_die_ref,
+-                                               enum dwarf_attribute, rtx));
++                                               enum dwarf_attribute,
++                                               dw_loc_descr_ref));
+ static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
+ static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
+ static rtx rtl_for_decl_location      PARAMS ((tree));
+@@ -8031,6 +8069,41 @@ loc_descriptor_from_tree (loc, addressp)
+              : 0);
+     case VAR_DECL:
++      if (DECL_THREAD_LOCAL (loc))
++      {
++        rtx rtl;
++
++#ifndef ASM_OUTPUT_DWARF_DTPREL
++        /* If this is not defined, we have no way to emit the data.  */
++        return 0;
++#endif
++        /* The way DW_OP_GNU_push_tls_address is specified, we can only
++           look up addresses of objects in the current module.  */
++        if (DECL_P (loc) && TREE_PUBLIC (loc) && !MODULE_LOCAL_P (loc))
++          return 0;
++
++        rtl = rtl_for_decl_location (loc);
++        if (rtl == NULL_RTX)
++          return 0;
++
++        if (GET_CODE (rtl) != MEM)
++          return 0;
++        rtl = XEXP (rtl, 0);
++        if (! CONSTANT_P (rtl))
++          return 0;
++
++        ret = new_loc_descr (INTERNAL_DW_OP_tls_addr, 0, 0);
++        ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
++        ret->dw_loc_oprnd1.v.val_addr = rtl;
++
++        ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
++        add_loc_descr (&ret, ret1);
++
++        indirect_p = 1;
++        break;
++      }
++      /* FALLTHRU */
++
+     case PARM_DECL:
+       {
+       rtx rtl = rtl_for_decl_location (loc);
+@@ -8531,14 +8604,12 @@ field_byte_offset (decl)
+    whole parameters.  Note that the location attributes for struct fields are
+    generated by the routine `data_member_location_attribute' below.  */
+-static void
+-add_AT_location_description (die, attr_kind, rtl)
++static inline void
++add_AT_location_description (die, attr_kind, descr)
+      dw_die_ref die;
+      enum dwarf_attribute attr_kind;
+-     rtx rtl;
++     dw_loc_descr_ref descr;
+ {
+-  dw_loc_descr_ref descr = loc_descriptor (rtl);
+-
+   if (descr != 0)
+     add_AT_loc (die, attr_kind, descr);
+ }
+@@ -8963,6 +9034,13 @@ rtl_for_decl_location (decl)
+   if (rtl)
+     rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+ #endif
++
++  /* If we don't look past the constant pool, we risk emitting a
++     reference to a constant pool entry that isn't referenced from
++     code, and thus is not emitted.  */
++  if (rtl)
++    rtl = avoid_constant_pool_reference (rtl);
++
+   return rtl;
+ }
+@@ -8983,6 +9061,7 @@ add_location_or_const_value_attribute (d
+      tree decl;
+ {
+   rtx rtl;
++  dw_loc_descr_ref descr;
+   if (TREE_CODE (decl) == ERROR_MARK)
+     return;
+@@ -8993,16 +9072,11 @@ add_location_or_const_value_attribute (d
+   if (rtl == NULL_RTX)
+     return;
+-  /* If we don't look past the constant pool, we risk emitting a
+-     reference to a constant pool entry that isn't referenced from
+-     code, and thus is not emitted.  */
+-  rtl = avoid_constant_pool_reference (rtl);
+-
+   switch (GET_CODE (rtl))
+     {
+     case ADDRESSOF:
+-      /* The address of a variable that was optimized away; don't emit
+-       anything.  */
++      /* The address of a variable that was optimized away;
++       don't emit anything.  */
+       break;
+     case CONST_INT:
+@@ -9017,12 +9091,24 @@ add_location_or_const_value_attribute (d
+       break;
+     case MEM:
+-    case REG:
+-    case SUBREG:
+-    case CONCAT:
+-      add_AT_location_description (die, DW_AT_location, rtl);
++      if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
++      {
++        /* Need loc_descriptor_from_tree since that's where we know
++           how to handle TLS variables.  Want the object's address
++           since the top-level DW_AT_location assumes such.  See
++           the confusion in loc_descriptor for reference.  */
++        descr = loc_descriptor_from_tree (decl, 1);
++      }
++      else
++      {
++      case REG:
++      case SUBREG:
++      case CONCAT:
++        descr = loc_descriptor (rtl);
++      }
++      add_AT_location_description (die, DW_AT_location, descr);
+       break;
+-
++      
+     default:
+       abort ();
+     }
+@@ -9154,7 +9240,8 @@ add_bound_info (subrange_die, bound_attr
+         add_AT_flag (decl_die, DW_AT_artificial, 1);
+         add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
+-        add_AT_location_description (decl_die, DW_AT_location, loc);
++        add_AT_location_description (decl_die, DW_AT_location,
++                                     loc_descriptor (loc));
+         add_AT_die_ref (subrange_die, bound_attr, decl_die);
+       }
+@@ -10359,7 +10446,7 @@ gen_subprogram_die (decl, context_die)
+        is not part of the state saved/restored for inline functions.  */
+       if (current_function_needs_context)
+       add_AT_location_description (subr_die, DW_AT_static_link,
+-                                   lookup_static_chain (decl));
++                           loc_descriptor (lookup_static_chain (decl)));
+ #endif
+     }
diff --git a/gcc32-tls.patch b/gcc32-tls.patch
new file mode 100644 (file)
index 0000000..0f3a413
--- /dev/null
@@ -0,0 +1,4294 @@
+--- gcc/cp/lex.c.jj    Sat May 25 00:02:23 2002
++++ gcc/cp/lex.c       Wed Jun 19 19:33:51 2002
+@@ -396,6 +396,7 @@ static const struct resword reswords[] =
+   { "__restrict__",   RID_RESTRICT,   0 },
+   { "__signed",               RID_SIGNED,     0 },
+   { "__signed__",     RID_SIGNED,     0 },
++  { "__thread",               RID_THREAD,     0 },
+   { "__typeof",               RID_TYPEOF,     0 },
+   { "__typeof__",     RID_TYPEOF,     0 },
+   { "__volatile",     RID_VOLATILE,   0 },
+@@ -502,6 +503,7 @@ const short rid_to_yy[RID_MAX] =
+   /* RID_BOUNDED */   0,
+   /* RID_UNBOUNDED */ 0,
+   /* RID_COMPLEX */   TYPESPEC,
++  /* RID_THREAD */    SCSPEC,
+   /* C++ */
+   /* RID_FRIEND */    SCSPEC,
+--- gcc/cp/decl.c.jj   Wed Jun 19 19:33:51 2002
++++ gcc/cp/decl.c      Wed Jun 19 19:33:51 2002
+@@ -7122,7 +7122,8 @@ check_tag_decl (declspecs)
+              || value == ridpointers[(int) RID_VIRTUAL]
+              || value == ridpointers[(int) RID_CONST]
+              || value == ridpointers[(int) RID_VOLATILE]
+-             || value == ridpointers[(int) RID_EXPLICIT])
++             || value == ridpointers[(int) RID_EXPLICIT]
++             || value == ridpointers[(int) RID_THREAD])
+       ob_modifier = value;
+     }
+@@ -7596,6 +7597,12 @@ static tree
+ obscure_complex_init (decl, init)
+      tree decl, init;
+ {
++  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
++    {
++      error ("run-time initialization of thread-local storage");
++      return NULL_TREE;
++    }
++
+   if (! flag_no_inline && TREE_STATIC (decl))
+     {
+       if (extract_init (decl, init))
+@@ -9290,6 +9297,16 @@ grokvardecl (type, declarator, specbits_
+       TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
+     }
++  if (RIDBIT_SETP (RID_THREAD, specbits))
++    {
++      if (targetm.have_tls)
++      DECL_THREAD_LOCAL (decl) = 1;
++      else
++      /* A mere warning is sure to result in improper semantics
++         at runtime.  Don't bother to allow this to compile.  */
++      error ("thread-local storage not supported for this target");
++    }
++
+   if (TREE_PUBLIC (decl))
+     {
+       /* [basic.link]: A name with no linkage (notably, the name of a class
+@@ -10192,10 +10209,22 @@ grokdeclarator (declarator, declspecs, d
+                   }
+                 else if (RIDBIT_SETP (i, specbits))
+                   pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
++
++                /* Diagnose "__thread extern".  Recall that this list
++                   is in the reverse order seen in the text.  */
++                if (i == (int)RID_THREAD)
++                  {
++                    if (RIDBIT_SETP (RID_EXTERN, specbits))
++                      error ("`__thread' before `extern'");
++                    if (RIDBIT_SETP (RID_STATIC, specbits))
++                      error ("`__thread' before `static'");
++                  }
++
+                 if (i == (int)RID_EXTERN
+                     && TREE_PURPOSE (spec) == error_mark_node)
+                   /* This extern was part of a language linkage.  */
+                   extern_langp = 1;
++
+                 RIDBIT_SET (i, specbits);
+                 goto found;
+               }
+@@ -10492,6 +10521,7 @@ grokdeclarator (declarator, declspecs, d
+     {
+       if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
+       if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
++      if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
+       if (decl_context == PARM && nclasses > 0)
+       error ("storage class specifiers invalid in parameter declarations");
+       if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+@@ -10523,6 +10553,13 @@ grokdeclarator (declarator, declspecs, d
+   /* Warn about storage classes that are invalid for certain
+      kinds of declarations (parameters, typenames, etc.).  */
++  /* "static __thread" and "extern __thread" are allowed.  */
++  if (nclasses == 2
++      && RIDBIT_SETP (RID_THREAD, specbits)
++      && (RIDBIT_SETP (RID_EXTERN, specbits)
++        || RIDBIT_SETP (RID_STATIC, specbits)))
++    nclasses = 1;
++    
+   if (nclasses > 1)
+     error ("multiple storage classes in declaration of `%s'", name);
+   else if (decl_context != NORMAL && nclasses > 0)
+@@ -10578,6 +10615,7 @@ grokdeclarator (declarator, declspecs, d
+         RIDBIT_RESET (RID_REGISTER, specbits);
+         RIDBIT_RESET (RID_AUTO, specbits);
+         RIDBIT_RESET (RID_EXTERN, specbits);
++        RIDBIT_RESET (RID_THREAD, specbits);
+       }
+     }
+   else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
+@@ -10600,6 +10638,14 @@ grokdeclarator (declarator, declspecs, d
+       if (RIDBIT_SETP (RID_AUTO, specbits))
+       error ("top-level declaration of `%s' specifies `auto'", name);
+     }
++  else if (RIDBIT_SETP (RID_THREAD, specbits)
++         && !RIDBIT_SETP (RID_EXTERN, specbits)
++         && !RIDBIT_SETP (RID_STATIC, specbits))
++    {
++      error ("function-scope `%s' implicitly auto and declared `__thread'",
++           name);
++      RIDBIT_RESET (RID_THREAD, specbits);
++    }
+   if (nclasses > 0 && friendp)
+     error ("storage class specifiers invalid in friend function declarations");
+@@ -11800,6 +11846,8 @@ friend declaration requires class-key, i
+         error ("storage class `auto' invalid for function `%s'", name);
+       else if (RIDBIT_SETP (RID_REGISTER, specbits))
+         error ("storage class `register' invalid for function `%s'", name);
++      else if (RIDBIT_SETP (RID_THREAD, specbits))
++        error ("storage class `__thread' invalid for function `%s'", name);
+       /* Function declaration not at top level.
+          Storage classes other than `extern' are not allowed
+--- gcc/doc/extend.texi.jj     Wed Jun 19 19:33:51 2002
++++ gcc/doc/extend.texi        Wed Jun 19 19:33:51 2002
+@@ -432,6 +432,7 @@ extensions, accepted by GCC in C89 mode 
+ * Target Builtins::     Built-in functions specific to particular targets.
+ * Pragmas::             Pragmas accepted by GCC.
+ * Unnamed Fields::      Unnamed struct/union fields within structs/unions.
++* Thread-Local::        Per-thread variables.
+ @end menu
+ @node Statement Exprs
+@@ -6119,6 +6120,265 @@ It is ambiguous which @code{a} is being 
+ Such constructs are not supported and must be avoided.  In the future,
+ such constructs may be detected and treated as compilation errors.
++@node Thread-Local
++@section Thread-Local Storage
++@cindex Thread-Local Storage
++@cindex TLS
++@cindex __thread
++
++Thread-local storage (@acronym{TLS}) is a mechanism by which variables
++are allocated such that there is one instance of the variable per extant
++thread.  The run-time model GCC uses to implement this originates
++in the IA-64 processor-specific ABI, but has since been migrated
++to other processors as well.  It requires significant support from
++the linker (@command{ld}), dynamic linker (@command{ld.so}), and
++system libraries (@file{libc.so} and @file{libpthread.so}), so it
++is not available everywhere.
++
++At the user level, the extension is visible with a new storage
++class keyword: @code{__thread}.  For example:
++
++@example
++__thread int i;
++extern __thread struct state s;
++static __thread char *p;
++@end example
++
++The @code{__thread} specifier may be used alone, with the @code{extern}
++or @code{static} specifiers, but with no other storage class specifier.
++When used with @code{extern} or @code{static}, @code{__thread} must appear
++immediately after the other storage class specifier.
++
++The @code{__thread} specifier may be applied to any global, file-scoped
++static, function-scoped static, or static data member of a class.  It may
++not be applied to block-scoped automatic or non-static data member.
++
++When the address-of operator is applied to a thread-local variable, it is
++evaluated at run-time and returns the address of the current thread's
++instance of that variable.  An address so obtained may be used by any
++thread.  When a thread terminates, any pointers to thread-local variables
++in that thread become invalid.
++
++No static initialization may refer to the address of a thread-local variable.
++
++In C++, if an initializer is present for a thread-local variable, it must
++be a @var{constant-expression}, as defined in 5.19.2 of the ANSI/ISO C++
++standard.
++
++See @uref{http://people.redhat.com/drepper/tls.pdf,
++ELF Handling For Thread-Local Storage} for a detailed explanation of
++the four thread-local storage addressing models, and how the run-time
++is expected to function.
++
++@menu
++* C99 Thread-Local Edits::
++* C++98 Thread-Local Edits::
++@end menu
++
++@node C99 Thread-Local Edits
++@subsection ISO/IEC 9899:1999 Edits for Thread-Local Storage
++
++The following are a set of changes to ISO/IEC 9899:1999 (aka C99)
++that document the exact semantics of the language extension.
++
++@itemize @bullet
++@item
++@cite{5.1.2  Execution environments}
++
++Add new text after paragraph 1
++
++@quotation
++Within either execution environment, a @dfn{thread} is a flow of
++control within a program.  It is implementation defined whether
++or not there may be more than one thread associated with a program.
++It is implementation defined how threads beyond the first are
++created, the name and type of the function called at thread
++startup, and how threads may be terminated.  However, objects
++with thread storage duration shall be initialized before thread
++startup.
++@end quotation
++
++@item
++@cite{6.2.4  Storage durations of objects}
++
++Add new text before paragraph 3
++
++@quotation
++An object whose identifier is declared with the storage-class
++specifier @w{@code{__thread}} has @dfn{thread storage duration}.
++Its lifetime is the entire execution of the thread, and its
++stored value is initialized only once, prior to thread startup.
++@end quotation
++
++@item
++@cite{6.4.1  Keywords}
++
++Add @code{__thread}.
++
++@item
++@cite{6.7.1  Storage-class specifiers}
++
++Add @code{__thread} to the list of storage class specifiers in
++paragraph 1.
++
++Change paragraph 2 to
++
++@quotation
++With the exception of @code{__thread}, at most one storage-class
++specifier may be given [@dots{}].  The @code{__thread} specifier may
++be used alone, or immediately following @code{extern} or
++@code{static}.
++@end quotation
++
++Add new text after paragraph 6
++
++@quotation
++The declaration of an identifier for a variable that has
++block scope that specifies @code{__thread} shall also
++specify either @code{extern} or @code{static}.
++
++The @code{__thread} specifier shall be used only with
++variables.
++@end quotation
++@end itemize
++
++@node C++98 Thread-Local Edits
++@subsection ISO/IEC 14882:1998 Edits for Thread-Local Storage
++
++The following are a set of changes to ISO/IEC 14882:1998 (aka C++98)
++that document the exact semantics of the language extension.
++
++@itemize @bullet
++@b{[intro.execution]}
++
++New text after paragraph 4
++
++@quotation
++A @dfn{thread} is a flow of control within the abstract machine.
++It is implementation defined whether or not there may be more than
++one thread.
++@end quotation
++
++New text after paragraph 7
++
++@quotation
++It is unspecified whether additional action must be taken to 
++ensure when and whether side effects are visible to other threads.
++@end quotation
++
++@item
++@b{[lex.key]}
++
++Add @code{__thread}.
++
++@item
++@b{[basic.start.main]}
++
++Add after paragraph 5
++
++@quotation
++The thread that begins execution at the @code{main} function is called
++the @dfn{main thread}.  It is implementation defined how functions 
++beginning threads other than the main thread are designated or typed.
++A function so designated, as well as the @code{main} function, is called
++a @dfn{thread startup function}.  It is implementation defined what
++happens if a thread startup function returns.  It is implementation
++defined what happens to other threads when any thread calls @code{exit}.
++@end quotation
++
++@item
++@b{[basic.start.init]}
++
++Add after paragraph 4
++
++@quotation
++The storage for an object of thread storage duration shall be
++staticly initialized before the first statement of the thread startup
++function.  An object of thread storage duration shall not require
++dynamic initialization.
++@end quotation
++
++@item
++@b{[basic.start.term]}
++
++Add after paragraph 3
++
++@quotation
++The type of an object with thread storage duration shall not have a
++non-trivial destructor, nor shall it be an array type whose elements
++(directly or indirectly) have non-trivial destructors.
++@end quotation
++
++@item
++@b{[basic.stc]}
++
++Add ``thread storage duration'' to the list in paragraph 1.
++
++Change paragraph 2
++
++@quotation
++Thread, static, and automatic storage durations are associated with
++objects introduced by declarations [@dots{}].
++@end quotation
++
++Add @code{__thread} to the list of specifiers in paragraph 3.
++
++@item
++@b{[basic.stc.thread]}
++
++New section before @b{[basic.stc.static]}
++
++@quotation
++The keyword @code{__thread} applied to an non-local object gives the
++object thread storage duration.
++
++A local variable or class data member declared both @code{static}
++and @code{__thread} gives the variable or member thread storage
++duration.
++@end quotation
++
++@item
++@b{[basic.stc.static]}
++
++Change paragraph 1
++
++@quotation
++All objects which have neither thread storage duration, dynamic
++storage duration nor are local [@dots{}].
++@end quotation
++
++@item
++@b{[dcl.stc]}
++
++Add @code{__thread} to the list in paragraph 1.
++
++Change paragraph 1
++
++@quotation
++With the exception of @code{__thread}, at most one
++@var{storage-class-specifier} shall appear in a given
++@var{decl-specifier-seq}.  The @code{__thread} specifier may
++be used alone, or immediately following the @code{extern} or
++@code{static} specifiers.  [@dots{}]
++@end quotation
++
++Add after paragraph 5
++
++@quotation
++The @code{__thread} specifier can be applied only to the names of objects
++and to anonymous unions.
++@end quotation
++
++@item
++@b{[class.mem]}
++
++Add after paragraph 6
++
++@quotation
++Non-@code{static} members shall not be @code{__thread}.
++@end quotation
++@end itemize
++
+ @node C++ Extensions
+ @chapter Extensions to the C++ Language
+ @cindex extensions, C++ language
+--- gcc/doc/invoke.texi.jj     Tue May 21 20:27:44 2002
++++ gcc/doc/invoke.texi        Wed Jun 19 19:33:52 2002
+@@ -674,7 +674,7 @@ in the following sections.
+ -fverbose-asm  -fpack-struct  -fstack-check @gol
+ -fstack-limit-register=@var{reg}  -fstack-limit-symbol=@var{sym} @gol
+ -fargument-alias  -fargument-noalias @gol
+--fargument-noalias-global  -fleading-underscore}
++-fargument-noalias-global  -fleading-underscore -ftls-model=@var{model}}
+ @end table
+ @menu
+@@ -9910,6 +9910,14 @@ is to help link with legacy assembly cod
+ Be warned that you should know what you are doing when invoking this
+ option, and that not all targets provide complete support for it.
++
++@item -ftls-model=@var{model}
++Alter the thread-local storage model to be used (@pxref{Thread-Local}).
++The @var{model} argument should be one of @code{global-dynamic},
++@code{local-dynamic}, @code{initial-exec} or @code{local-exec}.
++
++The default without @option{-fpic} is @code{initial-exec}; with
++@option{-fpic} the default is @code{global-dynamic}.
+ @end table
+ @c man end
+--- gcc/config/i386/i386.c.jj  Wed Jun 19 19:33:51 2002
++++ gcc/config/i386/i386.c     Wed Jun 19 23:18:18 2002
+@@ -536,6 +536,10 @@ int const svr4_dbx_register_map[FIRST_PS
+ rtx ix86_compare_op0 = NULL_RTX;
+ rtx ix86_compare_op1 = NULL_RTX;
++/* The encoding characters for the four TLS models present in ELF.  */
++
++static char const tls_model_chars[] = " GLil";
++
+ #define MAX_386_STACK_LOCALS 3
+ /* Size of the register save area.  */
+ #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
+@@ -544,6 +548,7 @@ rtx ix86_compare_op1 = NULL_RTX;
+ struct machine_function
+ {
+   rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
++  const char *some_ld_name;
+   int save_varrargs_registers;
+   int accesses_prev_frame;
+ };
+@@ -596,6 +601,9 @@ enum cmodel ix86_cmodel;
+ /* Asm dialect.  */
+ const char *ix86_asm_string;
+ enum asm_dialect ix86_asm_dialect = ASM_ATT;
++/* TLS dialext.  */
++const char *ix86_tls_dialect_string;
++enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
+ /* which cpu are we scheduling for */
+ enum processor_type ix86_cpu;
+@@ -646,12 +654,17 @@ static char internal_label_prefix[16];
+ static int internal_label_prefix_len;
\f
+ static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
++static int tls_symbolic_operand_1 PARAMS ((rtx, enum tls_model));
+ static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
+ static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
+                                      int, int, FILE *));
++static const char *get_some_local_dynamic_name PARAMS ((void));
++static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
++static rtx maybe_get_pool_constant PARAMS ((rtx));
+ static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
+ static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
+                                                          rtx *, rtx *));
++static rtx get_thread_pointer PARAMS ((void));
+ static rtx gen_push PARAMS ((rtx));
+ static int memory_address_length PARAMS ((rtx addr));
+ static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
+@@ -820,6 +833,11 @@ static enum x86_64_reg_class merge_class
+ #undef TARGET_SCHED_REORDER
+ #define TARGET_SCHED_REORDER ix86_sched_reorder
++#ifdef HAVE_AS_TLS
++#undef TARGET_HAVE_TLS
++#define TARGET_HAVE_TLS true
++#endif
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
\f
+ /* Sometimes certain combinations of command options do not make
+@@ -1109,6 +1127,17 @@ override_options ()
+       ix86_branch_cost = i;
+     }
++  if (ix86_tls_dialect_string)
++    {
++      if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
++      ix86_tls_dialect = TLS_DIALECT_GNU;
++      else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
++      ix86_tls_dialect = TLS_DIALECT_SUN;
++      else
++      error ("bad value (%s) for -mtls-dialect= switch",
++             ix86_tls_dialect_string);
++    }
++
+   /* Keep nonleaf frame pointers.  */
+   if (TARGET_OMIT_LEAF_FRAME_POINTER)
+     flag_omit_frame_pointer = 1;
+@@ -3007,6 +3036,70 @@ local_symbolic_operand (op, mode)
+   return 0;
+ }
++/* Test for various thread-local symbols.  See ix86_encode_section_info. */
++
++int
++tls_symbolic_operand (op, mode)
++     register rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  const char *symbol_str;
++
++  if (GET_CODE (op) != SYMBOL_REF)
++    return 0;
++  symbol_str = XSTR (op, 0);
++
++  if (symbol_str[0] != '%')
++    return 0;
++  return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;
++}
++
++static int
++tls_symbolic_operand_1 (op, kind)
++     rtx op;
++     enum tls_model kind;
++{
++  const char *symbol_str;
++
++  if (GET_CODE (op) != SYMBOL_REF)
++    return 0;
++  symbol_str = XSTR (op, 0);
++
++  return symbol_str[0] == '%' && symbol_str[1] == tls_model_chars[kind];
++}
++
++int
++global_dynamic_symbolic_operand (op, mode)
++     register rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  return tls_symbolic_operand_1 (op, TLS_MODEL_GLOBAL_DYNAMIC);
++}
++
++int
++local_dynamic_symbolic_operand (op, mode)
++     register rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_DYNAMIC);
++}
++
++int
++initial_exec_symbolic_operand (op, mode)
++     register rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  return tls_symbolic_operand_1 (op, TLS_MODEL_INITIAL_EXEC);
++}
++
++int
++local_exec_symbolic_operand (op, mode)
++     register rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_EXEC);
++}
++
+ /* Test for a valid operand for a call instruction.  Don't allow the
+    arg pointer register or virtual regs since they may decay into
+    reg + const, which the patterns can't handle.  */
+@@ -3858,7 +3951,7 @@ ix86_asm_file_end (file)
+ {
+   rtx xops[2];
+-  if (! TARGET_DEEP_BRANCH_PREDICTION || pic_label_name[0] == 0)
++  if (pic_label_name[0] == 0)
+     return;
+   /* The trick here is to create a linkonce section containing the
+@@ -3896,17 +3989,33 @@ ix86_asm_file_end (file)
+   output_asm_insn ("ret", xops);
+ }
+-void
+-load_pic_register ()
++/* Emit code for the SET_GOT patterns.  */
++
++const char *
++output_set_got (dest)
++     rtx dest;
+ {
+-  rtx gotsym, pclab;
++  rtx xops[3];
+-  if (TARGET_64BIT)
+-    abort ();
++  xops[0] = dest;
++  xops[1] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
++
++  if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
++    {
++      xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
++
++      if (!flag_pic)
++      output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
++      else
++      output_asm_insn ("call\t%a2", xops);
+-  gotsym = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
++      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
++                               CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
+-  if (TARGET_DEEP_BRANCH_PREDICTION)
++      if (flag_pic)
++      output_asm_insn ("pop{l}\t%0", xops);
++    }
++  else
+     {
+       if (! pic_label_name[0])
+       {
+@@ -3915,16 +4024,17 @@ load_pic_register ()
+         else
+           ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
+       }
+-      pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
+-    }
++      xops[2] = gen_rtx_SYMBOL_REF (Pmode, pic_label_name);
++      xops[2] = gen_rtx_MEM (QImode, xops[2]);
++      output_asm_insn ("call\t%X2", xops);
++    }
++  
++  if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
++    output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
+   else
+-    {
+-      pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+-    }
+-
+-  emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
+-
+-  emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
++    output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %a1+(.-%a2)}", xops);
++  
++  return "";
+ }
+ /* Generate an "push" pattern for input ARG.  */
+@@ -4253,7 +4363,15 @@ ix86_expand_prologue ()
+ #endif
+   if (pic_reg_used)
+-    load_pic_register ();
++    {
++      insn = emit_insn (gen_set_got (pic_offset_table_rtx));
++
++      /* ??? The current_function_uses_pic_offset_table flag is woefully
++       inaccurate, as it isn't updated as code gets deleted.  Allow the
++       thing to be removed.  A better solution would be to actually get
++       proper liveness for ebx, as then we won't save/restore it too.  */
++      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
++    }
+   /* If we are profiling, make sure no instructions are scheduled before
+      the call to mcount.  However, if -fpic, the above call will have
+@@ -4694,6 +4812,114 @@ ix86_find_base_term (x)
+   return term;
+ }
\f
++/* Determine if a given RTX is a valid constant.  We already know this
++   satisfies CONSTANT_P.  */
++
++bool
++legitimate_constant_p (x)
++     rtx x;
++{
++  rtx inner;
++
++  switch (GET_CODE (x))
++    {
++    case SYMBOL_REF:
++      /* TLS symbols are not constant.  */
++      if (tls_symbolic_operand (x, Pmode))
++      return false;
++      break;
++
++    case CONST:
++      inner = XEXP (x, 0);
++
++      /* Offsets of TLS symbols are never valid.
++       Discourage CSE from creating them.  */
++      if (GET_CODE (inner) == PLUS
++        && tls_symbolic_operand (XEXP (inner, 0), Pmode))
++      return false;
++
++      /* Only some unspecs are valid as "constants".  */
++      if (GET_CODE (inner) == UNSPEC)
++      switch (XINT (inner, 1))
++        {
++        case UNSPEC_TPOFF:
++          return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
++        case UNSPEC_TP:
++          return true;
++        default:
++          return false;
++        }
++      break;
++
++    default:
++      break;
++    }
++
++  /* Otherwise we handle everything else in the move patterns.  */
++  return true;
++}
++
++/* Determine if a given RTX is a valid constant address.  */
++
++bool
++constant_address_p (x)
++     rtx x;
++{
++  switch (GET_CODE (x))
++    {
++    case LABEL_REF:
++    case CONST_INT:
++      return true;
++
++    case CONST_DOUBLE:
++      return TARGET_64BIT;
++
++    case CONST:
++    case SYMBOL_REF:
++      return !flag_pic && legitimate_constant_p (x);
++
++    default:
++      return false;
++    }
++}
++
++/* Nonzero if the constant value X is a legitimate general operand
++   when generating PIC code.  It is given that flag_pic is on and 
++   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
++
++bool
++legitimate_pic_operand_p (x)
++     rtx x;
++{
++  rtx inner;
++
++  switch (GET_CODE (x))
++    {
++    case CONST:
++      inner = XEXP (x, 0);
++
++      /* Only some unspecs are valid as "constants".  */
++      if (GET_CODE (inner) == UNSPEC)
++      switch (XINT (inner, 1))
++        {
++        case UNSPEC_TPOFF:
++          return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
++        case UNSPEC_TP:
++          return true;
++        default:
++          return false;
++        }
++      /* FALLTHRU */
++
++    case SYMBOL_REF:
++    case LABEL_REF:
++      return legitimate_pic_address_disp_p (x);
++
++    default:
++      return true;
++    }
++}
++
+ /* Determine if a given CONST RTX is a valid memory displacement
+    in PIC mode.  */
+@@ -4701,6 +4927,8 @@ int
+ legitimate_pic_address_disp_p (disp)
+      register rtx disp;
+ {
++  bool saw_plus;
++
+   /* In 64bit mode we can allow direct addresses of symbols and labels
+      when they are not dynamic symbols.  */
+   if (TARGET_64BIT)
+@@ -4737,25 +4965,39 @@ legitimate_pic_address_disp_p (disp)
+       return 1;
+     }
++  saw_plus = false;
+   if (GET_CODE (disp) == PLUS)
+     {
+       if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
+       return 0;
+       disp = XEXP (disp, 0);
++      saw_plus = true;
+     }
+   if (GET_CODE (disp) != UNSPEC
+       || XVECLEN (disp, 0) != 1)
+     return 0;
+-  /* Must be @GOT or @GOTOFF.  */
+   switch (XINT (disp, 1))
+     {
+-    case 6: /* @GOT */
++    case UNSPEC_GOT:
++      if (saw_plus)
++      return false;
+       return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF;
+-
+-    case 7: /* @GOTOFF */
++    case UNSPEC_GOTOFF:
+       return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
++    case UNSPEC_GOTTPOFF:
++      if (saw_plus)
++      return false;
++      return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
++    case UNSPEC_NTPOFF:
++      if (saw_plus)
++      return false;
++      return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
++    case UNSPEC_DTPOFF:
++      if (saw_plus)
++      return false;
++      return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
+     }
+     
+   return 0;
+@@ -4882,12 +5124,6 @@ legitimate_address_p (mode, addr, strict
+     {
+       reason_rtx = disp;
+-      if (!CONSTANT_ADDRESS_P (disp))
+-      {
+-        reason = "displacement is not constant";
+-        goto report_error;
+-      }
+-
+       if (TARGET_64BIT)
+       {
+         if (!x86_64_sign_extended_value (disp))
+@@ -4905,8 +5141,30 @@ legitimate_address_p (mode, addr, strict
+           }
+       }
+-      if (flag_pic && SYMBOLIC_CONST (disp))
++      if (GET_CODE (disp) == CONST
++        && GET_CODE (XEXP (disp, 0)) == UNSPEC)
++      switch (XINT (XEXP (disp, 0), 1))
++        {
++        case UNSPEC_GOT:
++        case UNSPEC_GOTOFF:
++        case UNSPEC_GOTPCREL:
++          if (!flag_pic)
++            abort ();
++          goto is_legitimate_pic;
++
++        case UNSPEC_GOTTPOFF:
++        case UNSPEC_NTPOFF:
++        case UNSPEC_DTPOFF:
++          break;
++
++        default:
++          reason = "invalid address unspec";
++          goto report_error;
++        }
++
++      else if (flag_pic && SYMBOLIC_CONST (disp))
+       {
++      is_legitimate_pic:
+         if (TARGET_64BIT && (index || base))
+           {
+             reason = "non-constant pic memory reference";
+@@ -4949,6 +5207,11 @@ legitimate_address_p (mode, addr, strict
+             goto report_error;
+           }
+       }
++      else if (!CONSTANT_ADDRESS_P (disp))
++      {
++        reason = "displacement is not constant";
++        goto report_error;
++      }
+     }
+   /* Everything looks valid.  */
+@@ -5129,7 +5392,102 @@ legitimize_pic_address (orig, reg)
+     }
+   return new;
+ }
++
++void
++ix86_encode_section_info (decl)
++     tree decl;
++{
++  bool local_p;
++  rtx rtl, symbol;
++
++  rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
++  if (GET_CODE (rtl) != MEM)
++    return;
++  symbol = XEXP (rtl, 0);
++  if (GET_CODE (symbol) != SYMBOL_REF)
++    return;
++
++  local_p = !DECL_P (decl) || !TREE_PUBLIC (decl) || MODULE_LOCAL_P (decl);
++
++  /* For basic x86, if using PIC, mark a SYMBOL_REF for a non-global
++     symbol so that we may access it directly in the GOT.  */
++
++  if (flag_pic)
++    SYMBOL_REF_FLAG (symbol) = local_p;
++
++  /* For ELF, encode thread-local data with %[GLil] for "global dynamic",
++     "local dynamic", "initial exec" or "local exec" TLS models
++     respectively.  */
++
++  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
++    {
++      const char *symbol_str;
++      char *newstr;
++      size_t len;
++      enum tls_model kind;
++
++      if (!flag_pic)
++      {
++        if (local_p)
++          kind = TLS_MODEL_LOCAL_EXEC;
++        else
++          kind = TLS_MODEL_INITIAL_EXEC;
++      }
++      /* Local dynamic is inefficient when we're not combining the
++       parts of the address.  */
++      else if (optimize && local_p)
++      kind = TLS_MODEL_LOCAL_DYNAMIC;
++      else
++      kind = TLS_MODEL_GLOBAL_DYNAMIC;
++      if (kind < flag_tls_default)
++      kind = flag_tls_default;
++
++      symbol_str = XSTR (symbol, 0);
++
++      if (symbol_str[0] == '%')
++      {
++        if (symbol_str[1] == tls_model_chars[kind])
++          return;
++        symbol_str += 2;
++      }
++      len = strlen (symbol_str) + 1;
++      newstr = alloca (len + 2);
++
++      newstr[0] = '%';
++      newstr[1] = tls_model_chars[kind];
++      memcpy (newstr + 2, symbol_str, len);
++
++      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
++    }
++}
++
++/* Undo the above when printing symbol names.  */
++
++const char *
++ix86_strip_name_encoding (str)
++     const char *str;
++{
++  if (str[0] == '%')
++    str += 2;
++  if (str [0] == '*')
++    str += 1;
++  return str;
++}
\f
++/* Load the thread pointer into a register.  */
++
++static rtx
++get_thread_pointer ()
++{
++  rtx tp;
++
++  tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
++  tp = gen_rtx_CONST (Pmode, tp);
++  tp = force_reg (Pmode, tp);
++
++  return tp;
++}
++
+ /* Try machine-dependent ways of modifying an illegitimate address
+    to be legitimate.  If we find one, return the new, valid address.
+    This macro is used in only one place: `memory_address' in explow.c.
+@@ -5167,6 +5525,84 @@ legitimize_address (x, oldx, mode)
+       debug_rtx (x);
+     }
++  log = tls_symbolic_operand (x, mode);
++  if (log)
++    {
++      rtx dest, base, off, pic;
++
++      switch (log)
++        {
++        case TLS_MODEL_GLOBAL_DYNAMIC:
++        dest = gen_reg_rtx (Pmode);
++          emit_insn (gen_tls_global_dynamic (dest, x));
++        break;
++
++        case TLS_MODEL_LOCAL_DYNAMIC:
++        base = gen_reg_rtx (Pmode);
++        emit_insn (gen_tls_local_dynamic_base (base));
++
++        off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
++        off = gen_rtx_CONST (Pmode, off);
++
++        return gen_rtx_PLUS (Pmode, base, off);
++
++        case TLS_MODEL_INITIAL_EXEC:
++        if (flag_pic)
++          {
++            current_function_uses_pic_offset_table = 1;
++            pic = pic_offset_table_rtx;
++          }
++        else
++          {
++            pic = gen_reg_rtx (Pmode);
++            emit_insn (gen_set_got (pic));
++          }
++
++        base = get_thread_pointer ();
++
++        off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_GOTTPOFF);
++        off = gen_rtx_CONST (Pmode, off);
++        off = gen_rtx_PLUS (Pmode, pic, off);
++        off = gen_rtx_MEM (Pmode, off);
++        RTX_UNCHANGING_P (off) = 1;
++        set_mem_alias_set (off, ix86_GOT_alias_set ());
++
++        /* Damn Sun for specifing a set of dynamic relocations without
++           considering the two-operand nature of the architecture!
++           We'd be much better off with a "GOTNTPOFF" relocation that
++           already contained the negated constant.  */
++        /* ??? Using negl and reg+reg addressing appears to be a lose
++           size-wise.  The negl is two bytes, just like the extra movl
++           incurred by the two-operand subl, but reg+reg addressing
++           uses the two-byte modrm form, unlike plain reg.  */
++
++        dest = gen_reg_rtx (Pmode);
++        emit_insn (gen_subsi3 (dest, base, off));
++        break;
++
++        case TLS_MODEL_LOCAL_EXEC:
++        base = get_thread_pointer ();
++
++        off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
++                              TARGET_GNU_TLS ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
++        off = gen_rtx_CONST (Pmode, off);
++
++        if (TARGET_GNU_TLS)
++          return gen_rtx_PLUS (Pmode, base, off);
++        else
++          {
++            dest = gen_reg_rtx (Pmode);
++            emit_insn (gen_subsi3 (dest, base, off));
++          }
++        break;
++
++      default:
++        abort ();
++        }
++
++      return dest;
++    }
++
+   if (flag_pic && SYMBOLIC_CONST (x))
+     return legitimize_pic_address (x, 0);
+@@ -5410,18 +5846,30 @@ output_pic_addr_const (file, x, code)
+        output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
+        switch (XINT (x, 1))
+       {
+-      case 6:
++      case UNSPEC_GOT:
+         fputs ("@GOT", file);
+         break;
+-      case 7:
++      case UNSPEC_GOTOFF:
+         fputs ("@GOTOFF", file);
+         break;
+-      case 8:
++      case UNSPEC_PLT:
+         fputs ("@PLT", file);
+         break;
+-      case 15:
++      case UNSPEC_GOTPCREL:
+         fputs ("@GOTPCREL(%RIP)", file);
+         break;
++      case UNSPEC_GOTTPOFF:
++        fputs ("@GOTTPOFF", file);
++        break;
++      case UNSPEC_TPOFF:
++        fputs ("@TPOFF", file);
++        break;
++      case UNSPEC_NTPOFF:
++        fputs ("@NTPOFF", file);
++        break;
++      case UNSPEC_DTPOFF:
++        fputs ("@DTPOFF", file);
++        break;
+       default:
+         output_operand_lossage ("invalid UNSPEC as operand");
+         break;
+@@ -5710,6 +6158,43 @@ print_reg (x, code, file)
+     }
+ }
++/* Locate some local-dynamic symbol still in use by this function
++   so that we can print its name in some tls_local_dynamic_base
++   pattern.  */
++
++static const char *
++get_some_local_dynamic_name ()
++{
++  rtx insn;
++
++  if (cfun->machine->some_ld_name)
++    return cfun->machine->some_ld_name;
++
++  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
++    if (INSN_P (insn)
++      && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
++      return cfun->machine->some_ld_name;
++
++  abort ();
++}
++
++static int
++get_some_local_dynamic_name_1 (px, data)
++     rtx *px;
++     void *data ATTRIBUTE_UNUSED;
++{
++  rtx x = *px;
++
++  if (GET_CODE (x) == SYMBOL_REF
++      && local_dynamic_symbolic_operand (x, Pmode))
++    {
++      cfun->machine->some_ld_name = XSTR (x, 0);
++      return 1;
++    }
++
++  return 0;
++}
++
+ /* Meaning of CODE:
+    L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
+    C -- print opcode suffix for set/cmov insn.
+@@ -5734,6 +6219,7 @@ print_reg (x, code, file)
+    D -- print condition for SSE cmp instruction.
+    P -- if PIC, print an @PLT suffix.
+    X -- don't print any sort of PIC '@' suffix for a symbol.
++   & -- print some in-use local-dynamic symbol name.
+  */
+ void
+@@ -5751,6 +6237,10 @@ print_operand (file, x, code)
+           putc ('*', file);
+         return;
++      case '&':
++        assemble_name (file, get_some_local_dynamic_name ());
++        return;
++
+       case 'A':
+         if (ASSEMBLER_DIALECT == ASM_ATT)
+           putc ('*', file);
+@@ -6078,6 +6568,18 @@ print_operand (file, x, code)
+       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
+       fprintf (file, "%s", dstr);
+     }
++
++  else if (GET_CODE (x) == CONST
++         && GET_CODE (XEXP (x, 0)) == UNSPEC
++         && XINT (XEXP (x, 0), 1) == UNSPEC_TP)
++    {
++      if (ASSEMBLER_DIALECT == ASM_INTEL)
++      fputs ("DWORD PTR ", file);
++      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
++      putc ('%', file);
++      fputs ("gs:0", file);
++    }
++
+   else
+     {
+       if (code != 'P')
+@@ -6226,6 +6728,43 @@ print_operand_address (file, addr)
+       }
+     }
+ }
++
++bool
++output_addr_const_extra (file, x)
++     FILE *file;
++     rtx x;
++{
++  rtx op;
++
++  if (GET_CODE (x) != UNSPEC)
++    return false;
++
++  op = XVECEXP (x, 0, 0);
++  switch (XINT (x, 1))
++    {
++    case UNSPEC_GOTTPOFF:
++      output_addr_const (file, op);
++      fputs ("@GOTTPOFF", file);
++      break;
++    case UNSPEC_TPOFF:
++      output_addr_const (file, op);
++      fputs ("@TPOFF", file);
++      break;
++    case UNSPEC_NTPOFF:
++      output_addr_const (file, op);
++      fputs ("@NTPOFF", file);
++      break;
++    case UNSPEC_DTPOFF:
++      output_addr_const (file, op);
++      fputs ("@DTPOFF", file);
++      break;
++
++    default:
++      return false;
++    }
++
++  return true;
++}
\f
+ /* Split one or more DImode RTL references into pairs of SImode
+    references.  The RTL can be REG, offsettable MEM, integer constant, or
+@@ -6763,51 +7302,117 @@ ix86_expand_clear (dest)
+   emit_insn (tmp);
+ }
++/* X is an unchanging MEM.  If it is a constant pool reference, return
++   the constant pool rtx, else NULL.  */
++
++static rtx
++maybe_get_pool_constant (x)
++     rtx x;
++{
++  x = XEXP (x, 0);
++
++  if (flag_pic)
++    {
++      if (GET_CODE (x) != PLUS)
++      return NULL_RTX;
++      if (XEXP (x, 0) != pic_offset_table_rtx)
++      return NULL_RTX;
++      x = XEXP (x, 1);
++      if (GET_CODE (x) != CONST)
++      return NULL_RTX;
++      x = XEXP (x, 0);
++      if (GET_CODE (x) != UNSPEC)
++      return NULL_RTX;
++      if (XINT (x, 1) != UNSPEC_GOTOFF)
++      return NULL_RTX;
++      x = XVECEXP (x, 0, 0);
++    }
++
++  if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
++    return get_pool_constant (x);
++
++  return NULL_RTX;
++}
++
+ void
+ ix86_expand_move (mode, operands)
+      enum machine_mode mode;
+      rtx operands[];
+ {
+   int strict = (reload_in_progress || reload_completed);
+-  rtx insn;
++  rtx insn, op0, op1, tmp;
++
++  op0 = operands[0];
++  op1 = operands[1];
+-  if (flag_pic && mode == Pmode && symbolic_operand (operands[1], Pmode))
++  /* ??? We have a slight problem.  We need to say that tls symbols are
++     not legitimate constants so that reload does not helpfully reload
++     these constants from a REG_EQUIV, which we cannot handle.  (Recall
++     that general- and local-dynamic address resolution requires a
++     function call.)
++
++     However, if we say that tls symbols are not legitimate constants,
++     then emit_move_insn helpfully drop them into the constant pool.
++
++     It is far easier to work around emit_move_insn than reload.  Recognize
++     the MEM that we would have created and extract the symbol_ref.  */
++
++  if (mode == Pmode
++      && GET_CODE (op1) == MEM
++      && RTX_UNCHANGING_P (op1))
+     {
+-      /* Emit insns to move operands[1] into operands[0].  */
++      tmp = maybe_get_pool_constant (op1);
++      /* Note that we only care about symbolic constants here, which
++       unlike CONST_INT will always have a proper mode.  */
++      if (tmp && GET_MODE (tmp) == Pmode)
++      op1 = tmp;
++    }
+-      if (GET_CODE (operands[0]) == MEM)
+-      operands[1] = force_reg (Pmode, operands[1]);
++  if (tls_symbolic_operand (op1, Pmode))
++    {
++      op1 = legitimize_address (op1, op1, VOIDmode);
++      if (GET_CODE (op0) == MEM)
++      {
++        tmp = gen_reg_rtx (mode);
++        emit_insn (gen_rtx_SET (VOIDmode, tmp, op1));
++        op1 = tmp;
++      }
++    }
++  else if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
++    {
++      if (GET_CODE (op0) == MEM)
++      op1 = force_reg (Pmode, op1);
+       else
+       {
+-        rtx temp = operands[0];
++        rtx temp = op0;
+         if (GET_CODE (temp) != REG)
+           temp = gen_reg_rtx (Pmode);
+-        temp = legitimize_pic_address (operands[1], temp);
+-        if (temp == operands[0])
++        temp = legitimize_pic_address (op1, temp);
++        if (temp == op0)
+           return;
+-        operands[1] = temp;
++        op1 = temp;
+       }
+     }
+   else
+     {
+-      if (GET_CODE (operands[0]) == MEM
++      if (GET_CODE (op0) == MEM
+         && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
+-            || !push_operand (operands[0], mode))
+-        && GET_CODE (operands[1]) == MEM)
+-      operands[1] = force_reg (mode, operands[1]);
+-
+-      if (push_operand (operands[0], mode)
+-        && ! general_no_elim_operand (operands[1], mode))
+-      operands[1] = copy_to_mode_reg (mode, operands[1]);
++            || !push_operand (op0, mode))
++        && GET_CODE (op1) == MEM)
++      op1 = force_reg (mode, op1);
++
++      if (push_operand (op0, mode)
++        && ! general_no_elim_operand (op1, mode))
++      op1 = copy_to_mode_reg (mode, op1);
+       /* Force large constants in 64bit compilation into register
+        to get them CSEed.  */
+       if (TARGET_64BIT && mode == DImode
+-        && immediate_operand (operands[1], mode)
+-        && !x86_64_zero_extended_value (operands[1])
+-        && !register_operand (operands[0], mode)
++        && immediate_operand (op1, mode)
++        && !x86_64_zero_extended_value (op1)
++        && !register_operand (op0, mode)
+         && optimize && !reload_completed && !reload_in_progress)
+-      operands[1] = copy_to_mode_reg (mode, operands[1]);
++      op1 = copy_to_mode_reg (mode, op1);
+       if (FLOAT_MODE_P (mode))
+       {
+@@ -6817,13 +7422,13 @@ ix86_expand_move (mode, operands)
+         if (strict)
+           ;
+-        else if (GET_CODE (operands[1]) == CONST_DOUBLE
+-                 && register_operand (operands[0], mode))
+-          operands[1] = validize_mem (force_const_mem (mode, operands[1]));
++        else if (GET_CODE (op1) == CONST_DOUBLE
++                 && register_operand (op0, mode))
++          op1 = validize_mem (force_const_mem (mode, op1));
+       }
+     }
+-  insn = gen_rtx_SET (VOIDmode, operands[0], operands[1]);
++  insn = gen_rtx_SET (VOIDmode, op0, op1);
+   emit_insn (insn);
+ }
+@@ -8588,13 +9193,14 @@ ix86_split_to_parts (operand, parts, mod
+   if (size < 2 || size > 3)
+     abort ();
+-  /* Optimize constant pool reference to immediates.  This is used by fp moves,
+-     that force all constants to memory to allow combining.  */
+-
+-  if (GET_CODE (operand) == MEM
+-      && GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
+-      && CONSTANT_POOL_ADDRESS_P (XEXP (operand, 0)))
+-    operand = get_pool_constant (XEXP (operand, 0));
++  /* Optimize constant pool reference to immediates.  This is used by fp
++     moves, that force all constants to memory to allow combining.  */
++  if (GET_CODE (operand) == MEM && RTX_UNCHANGING_P (operand))
++    {
++      rtx tmp = maybe_get_pool_constant (operand);
++      if (tmp)
++      operand = tmp;
++    }
+   if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
+     {
+@@ -9790,6 +10396,55 @@ ix86_expand_strlensi_unroll_1 (out, alig
+   emit_label (end_0_label);
+ }
++
++void
++ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
++     rtx retval, fnaddr, callarg1, callarg2, pop;
++{
++  rtx use = NULL, call;
++
++  if (pop == const0_rtx)
++    pop = NULL;
++  if (TARGET_64BIT && pop)
++    abort ();
++
++  /* Static functions and indirect calls don't need the pic register.  */
++  if (! TARGET_64BIT && flag_pic
++      && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
++      && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
++    {
++      current_function_uses_pic_offset_table = 1;
++      use_reg (&use, pic_offset_table_rtx);
++    }
++
++  if (TARGET_64BIT && INTVAL (callarg2) >= 0)
++    {
++      rtx al = gen_rtx_REG (QImode, 0);
++      emit_move_insn (al, callarg2);
++      use_reg (&use, al);
++    }
++
++  if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
++    {
++      fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
++      fnaddr = gen_rtx_MEM (QImode, fnaddr);
++    }
++
++  call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
++  if (retval)
++    call = gen_rtx_SET (VOIDmode, retval, call);
++  if (pop)
++    {
++      pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
++      pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
++      call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
++    }
++
++  call = emit_call_insn (call);
++  if (use)
++    CALL_INSN_FUNCTION_USAGE (call) = use;
++}
++  
\f
+ /* Clear stack slot assignments remembered from previous functions.
+    This is called from INIT_EXPANDERS once before RTL is emitted for each
+@@ -9849,6 +10504,24 @@ assign_386_stack_local (mode, n)
+   return ix86_stack_locals[(int) mode][n];
+ }
++
++/* Construct the SYMBOL_REF for the tls_get_addr function.  */
++
++rtx
++ix86_tls_get_addr ()
++{
++  static rtx symbol;
++
++  if (!symbol)
++    {
++      symbol = gen_rtx_SYMBOL_REF (Pmode, (TARGET_GNU_TLS
++                                         ? "___tls_get_addr"
++                                         : "__tls_get_addr"));
++      ggc_add_rtx_root (&symbol, 1);
++    }
++
++  return symbol;
++}
\f
+ /* Calculate the length of the memory address in the instruction
+    encoding.  Does not include the one-byte modrm, opcode, or prefix.  */
+--- gcc/config/i386/i386-protos.h.jj   Wed Jun 19 15:18:02 2002
++++ gcc/config/i386/i386-protos.h      Wed Jun 19 19:33:52 2002
+@@ -28,7 +28,6 @@ extern int ix86_frame_pointer_required P
+ extern void ix86_setup_frame_addresses PARAMS ((void));
+ extern void ix86_asm_file_end PARAMS ((FILE *));
+-extern void load_pic_register PARAMS ((void));
+ extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
+ extern void ix86_expand_prologue PARAMS ((void));
+ extern void ix86_expand_epilogue PARAMS ((int));
+@@ -36,6 +35,9 @@ extern void ix86_expand_epilogue PARAMS 
+ extern void ix86_output_addr_vec_elt PARAMS ((FILE *, int));
+ extern void ix86_output_addr_diff_elt PARAMS ((FILE *, int, int));
++extern void ix86_encode_section_info PARAMS ((tree));
++extern const char *ix86_strip_name_encoding PARAMS ((const char *));
++
+ #ifdef RTX_CODE
+ extern int ix86_aligned_p PARAMS ((rtx));
+@@ -51,6 +53,11 @@ extern int x86_64_immediate_operand PARA
+ extern int x86_64_zext_immediate_operand PARAMS ((rtx, enum machine_mode));
+ extern int const_int_1_operand PARAMS ((rtx, enum machine_mode));
+ extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
++extern int tls_symbolic_operand PARAMS ((rtx, enum machine_mode));
++extern int global_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
++extern int local_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
++extern int initial_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
++extern int local_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
+ extern int constant_call_address_operand PARAMS ((rtx, enum machine_mode));
+@@ -84,6 +91,9 @@ extern int ix86_expand_movstr PARAMS ((r
+ extern int ix86_expand_clrstr PARAMS ((rtx, rtx, rtx));
+ extern int ix86_expand_strlen PARAMS ((rtx, rtx, rtx, rtx));
++extern bool legitimate_constant_p PARAMS ((rtx));
++extern bool constant_address_p PARAMS ((rtx));
++extern bool legitimate_pic_operand_p PARAMS ((rtx));
+ extern int legitimate_pic_address_disp_p PARAMS ((rtx));
+ extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
+ extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
+@@ -92,10 +102,12 @@ extern rtx legitimize_address PARAMS ((r
+ extern void print_reg PARAMS ((rtx, int, FILE*));
+ extern void print_operand PARAMS ((FILE*, rtx, int));
+ extern void print_operand_address PARAMS ((FILE*, rtx));
++extern bool output_addr_const_extra PARAMS ((FILE*, rtx));
+ extern void split_di PARAMS ((rtx[], int, rtx[], rtx[]));
+ extern void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
++extern const char *output_set_got PARAMS ((rtx));
+ extern const char *output_387_binary_op PARAMS ((rtx, rtx*));
+ extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
+ extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
+@@ -121,6 +133,7 @@ extern void ix86_expand_branch PARAMS ((
+ extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
+ extern int ix86_expand_int_movcc PARAMS ((rtx[]));
+ extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
++extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx));
+ extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
+ extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
+ extern void ix86_split_long_move PARAMS ((rtx[]));
+@@ -181,6 +194,8 @@ extern rtx ix86_expand_builtin PARAMS ((
+ #endif
++extern rtx ix86_tls_get_addr PARAMS ((void));
++
+ #ifdef TREE_CODE
+ extern int ix86_return_pops_args PARAMS ((tree, tree, int));
+ extern tree ix86_build_va_list PARAMS ((void));
+--- gcc/config/i386/i386.h.jj  Wed Jun 19 19:33:51 2002
++++ gcc/config/i386/i386.h     Wed Jun 19 20:20:56 2002
+@@ -282,6 +282,9 @@ extern int x86_prefetch_sse;
+ #define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
++#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
++#define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN)
++
+ /* WARNING: Do not mark empty strings for translation, as calling
+             gettext on an empty string does NOT return an empty
+             string. */
+@@ -451,6 +454,8 @@ extern int ix86_arch;
+     "" /* Undocumented. */ },                                 \
+   { "asm=", &ix86_asm_string,                                 \
+     N_("Use given assembler dialect") },                      \
++  { "tls-dialect=", &ix86_tls_dialect_string,                 \
++    N_("Use given thread-local storage dialect") },           \
+   SUBTARGET_OPTIONS                                           \
+ }
+@@ -1934,15 +1939,12 @@ do {                                                                   \
+ #define MAX_REGS_PER_ADDRESS 2
+-#define CONSTANT_ADDRESS_P(X)                                 \
+-  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF    \
+-   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST      \
+-   || GET_CODE (X) == CONST_DOUBLE)
++#define CONSTANT_ADDRESS_P(X)  constant_address_p (X)
+ /* Nonzero if the constant value X is a legitimate general operand.
+    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
+-#define LEGITIMATE_CONSTANT_P(X) 1
++#define LEGITIMATE_CONSTANT_P(X)  legitimate_constant_p (X)
+ #ifdef REG_OK_STRICT
+ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                               \
+@@ -2005,9 +2007,7 @@ do {                                                                     \
+    when generating PIC code.  It is given that flag_pic is on and 
+    that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
+-#define LEGITIMATE_PIC_OPERAND_P(X)           \
+-  (! SYMBOLIC_CONST (X)                               \
+-   || legitimate_pic_address_disp_p (X))
++#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
+ #define SYMBOLIC_CONST(X)     \
+   (GET_CODE (X) == SYMBOL_REF                                         \
+@@ -2251,33 +2251,23 @@ enum ix86_builtins
+    On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
+    so that we may access it directly in the GOT.  */
+-#define ENCODE_SECTION_INFO(DECL)                             \
+-do {                                                          \
+-    if (flag_pic)                                             \
+-      {                                                               \
+-      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'    \
+-                 ? TREE_CST_RTL (DECL) : DECL_RTL (DECL));    \
+-                                                              \
+-      if (GET_CODE (rtl) == MEM)                              \
+-        {                                                     \
+-          if (TARGET_DEBUG_ADDR                               \
+-              && TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd')   \
+-            {                                                 \
+-              fprintf (stderr, "Encode %s, public = %d\n",    \
+-                       IDENTIFIER_POINTER (DECL_NAME (DECL)), \
+-                       TREE_PUBLIC (DECL));                   \
+-            }                                                 \
+-                                                              \
+-          SYMBOL_REF_FLAG (XEXP (rtl, 0))                     \
+-            = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'      \
+-               || ! TREE_PUBLIC (DECL)                        \
+-               || MODULE_LOCAL_P (DECL));                     \
+-        }                                                     \
+-      }                                                               \
+-} while (0)
+-
++#define ENCODE_SECTION_INFO(DECL)  ix86_encode_section_info(DECL)
+ #define REDO_SECTION_INFO_P(DECL) 1
++#define STRIP_NAME_ENCODING(VAR,STR)  ((VAR) = ix86_strip_name_encoding (STR))
++
++#define ASM_OUTPUT_LABELREF(FILE,NAME)                \
++  do {                                                \
++    const char *xname = (NAME);                       \
++    if (xname[0] == '%')                      \
++      xname += 2;                             \
++    if (xname[0] == '*')                      \
++      xname += 1;                             \
++    else                                      \
++      fputs (user_label_prefix, FILE);                \
++    fputs (xname, FILE);                      \
++  } while (0)
++
+ /* The `FINALIZE_PIC' macro serves as a hook to emit these special
+    codes once the function is being compiled into assembly code, but
+    not before.  (It is not done before, because in the case of
+@@ -2923,7 +2913,7 @@ extern int const svr4_dbx_register_map[F
+    print_operand function.  */
+ #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+-  ((CODE) == '*' || (CODE) == '+')
++  ((CODE) == '*' || (CODE) == '+' || (CODE) == '&')
+ /* Print the name of a register based on its machine mode and number.
+    If CODE is 'w', pretend the mode is HImode.
+@@ -2942,6 +2932,12 @@ extern int const svr4_dbx_register_map[F
+ #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
+   print_operand_address ((FILE), (ADDR))
++#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL)        \
++do {                                          \
++  if (! output_addr_const_extra (FILE, (X)))  \
++    goto FAIL;                                        \
++} while (0);
++
+ /* Print the name of a register for based on its machine mode and number.
+    This macro is used to print debugging output.
+    This macro is different from PRINT_REG in that it may be used in
+@@ -3071,7 +3067,12 @@ extern int const svr4_dbx_register_map[F
+   {"memory_displacement_operand", {MEM}},                             \
+   {"cmpsi_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,      \
+                    LABEL_REF, SUBREG, REG, MEM, AND}},                \
+-  {"long_memory_operand", {MEM}},
++  {"long_memory_operand", {MEM}},                                     \
++  {"tls_symbolic_operand", {SYMBOL_REF}},                             \
++  {"global_dynamic_symbolic_operand", {SYMBOL_REF}},                  \
++  {"local_dynamic_symbolic_operand", {SYMBOL_REF}},                   \
++  {"initial_exec_symbolic_operand", {SYMBOL_REF}},                    \
++  {"local_exec_symbolic_operand", {SYMBOL_REF}},
+ /* A list of predicates that do special things with modes, and so
+    should not elicit warnings for VOIDmode match_operand.  */
+@@ -3112,6 +3113,16 @@ enum asm_dialect {
+ };
+ extern const char *ix86_asm_string;
+ extern enum asm_dialect ix86_asm_dialect;
++
++enum tls_dialect
++{
++  TLS_DIALECT_GNU,
++  TLS_DIALECT_SUN
++};
++
++extern enum tls_dialect ix86_tls_dialect;
++extern const char *ix86_tls_dialect_string;
++  
+ /* Value of -mcmodel specified by user.  */
+ extern const char *ix86_cmodel_string;
+ extern enum cmodel ix86_cmodel;
+--- gcc/config/i386/i386.md.jj Tue Jun  4 20:28:36 2002
++++ gcc/config/i386/i386.md    Wed Jun 19 19:33:52 2002
+@@ -49,55 +49,59 @@
+ ;; 'k' Likewise, print the SImode name of the register.
+ ;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
+ ;; 'y' Print "st(0)" instead of "st" as a register.
+-;;
++
+ ;; UNSPEC usage:
+-;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
+-;;    operand 0 is the memory address to scan.
+-;;    operand 1 is a register containing the value to scan for.  The mode
+-;;       of the scas opcode will be the same as the mode of this operand.
+-;;    operand 2 is the known alignment of operand 0.
+-;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
+-;;    operand 0 is the argument for `sin'.
+-;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
+-;;    operand 0 is the argument for `cos'.
+-;; 3  This is part of a `stack probe' operation.  The mode of the UNSPEC is 
+-;;    always SImode.  operand 0 is the size of the stack allocation.
+-;; 4  This is the source of a fake SET of the frame pointer which is used to
+-;;    prevent insns referencing it being scheduled across the initial
+-;;    decrement of the stack pointer.
+-;; 5  This is a `bsf' operation.
+-;; 6  This is the @GOT offset of a PIC address.
+-;; 7  This is the @GOTOFF offset of a PIC address.
+-;; 8  This is a reference to a symbol's @PLT address.
+-;; 9  This is an `fnstsw' operation.
+-;; 10 This is a `sahf' operation.
+-;; 11 This is a `fstcw' operation
+-;; 12 This is behaviour of add when setting carry flag.
+-;; 13 This is a `eh_return' placeholder.
+-
+-;; For SSE/MMX support:
+-;; 30 This is `fix', guaranteed to be truncating.
+-;; 31 This is a `emms' operation.
+-;; 32 This is a `maskmov' operation.
+-;; 33 This is a `movmsk' operation.
+-;; 34 This is a `non-temporal' move.
+-;; 36 This is used to distinguish COMISS from UCOMISS.
+-;; 37 This is a `ldmxcsr' operation.
+-;; 38 This is a forced `movaps' instruction (rather than whatever movti does)
+-;; 39 This is a forced `movups' instruction (rather than whatever movti does)
+-;; 40 This is a `stmxcsr' operation.
+-;; 41 This is a `shuffle' operation.
+-;; 42 This is a `rcp' operation.
+-;; 43 This is a `rsqsrt' operation.
+-;; 44 This is a `sfence' operation.
+-;; 45 This is a noop to prevent excessive combiner cleverness.
+-;; 46 This is a `femms' operation.
+-;; 49 This is a 'pavgusb' operation.
+-;; 50 This is a `pfrcp' operation.
+-;; 51 This is a `pfrcpit1' operation.
+-;; 52 This is a `pfrcpit2' operation.
+-;; 53 This is a `pfrsqrt' operation.
+-;; 54 This is a `pfrsqrit1' operation.
++;; ??? Note that the 3.1 branch, unlike mainline, has not had all
++;; of the uses of UNSPEC replaced with their symbolic constants.
++;; Thus you cannot change these arbitrarily without pain.
++
++(define_constants
++  [(UNSPEC_SCAS                       0)
++   (UNSPEC_SIN                        1)
++   (UNSPEC_COS                        2)
++   (UNSPEC_STACK_PROBE                3)
++   (UNSPEC_STACK_ALLOC                4)
++   (UNSPEC_BSF                        5)
++   (UNSPEC_GOT                        6)
++   (UNSPEC_GOTOFF             7)
++   (UNSPEC_PLT                        8)
++   (UNSPEC_FNSTSW             9)
++   (UNSPEC_SAHF                       10)
++   (UNSPEC_FSTCW              11)
++   (UNSPEC_FLDCW              12)
++   (UNSPEC_ADD_CARRY          12)
++   (UNSPEC_EH_RETURN          13)
++   (UNSPEC_GOTPCREL           15)
++   (UNSPEC_SET_GOT            16)
++
++   ; For TLS support:
++   (UNSPEC_GOTTPOFF             20)
++   (UNSPEC_TPOFF                21)
++   (UNSPEC_NTPOFF               22)
++   (UNSPEC_DTPOFF               23)
++   (UNSPEC_TP                   24)
++   (UNSPEC_TLS_GD               25)
++   (UNSPEC_TLS_LD_BASE          26)
++
++   ; For SSE/MMX support:
++   (UNSPEC_FIX                  30)
++   (UNSPEC_MASKMOV              32)
++   (UNSPEC_MOVMSK               33)
++   (UNSPEC_MOVNT                34)
++   (UNSPEC_MOVA                 38)
++   (UNSPEC_MOVU                 39)
++   (UNSPEC_SHUFFLE              41)
++   (UNSPEC_RCP                  42)
++   (UNSPEC_RSQRT                43)
++   (UNSPEC_SFENCE               44)
++   (UNSPEC_NOP                  45)     ; prevents combiner cleverness
++   (UNSPEC_PAVGUSB              49)
++   (UNSPEC_PFRCP                50)
++   (UNSPEC_PFRCPIT1             51)
++   (UNSPEC_PFRCPIT2             52)
++   (UNSPEC_PFRSQRT              53)
++   (UNSPEC_PFRSQIT1             54)
++  ])
+ ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
+ ;; from i386.c.
+@@ -1759,7 +1763,7 @@
+       return "lea{l}\t{%1, %0|%0, %1}";
+     default:
+-      if (flag_pic && SYMBOLIC_CONST (operands[1]))
++      if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
+       abort();
+       return "mov{l}\t{%1, %0|%0, %1}";
+     }
+@@ -2525,7 +2529,7 @@
+     case TYPE_LEA:
+       return "lea{q}\t{%a1, %0|%0, %a1}";
+     default:
+-      if (flag_pic && SYMBOLIC_CONST (operands[1]))
++      if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
+       abort ();
+       if (get_attr_mode (insn) == MODE_SI)
+       return "mov{l}\t{%k1, %k0|%k0, %k1}";
+@@ -13474,21 +13478,8 @@
+                           (match_operand:SI 3 "" "")))])]
+   "!TARGET_64BIT"
+ {
+-  if (operands[3] == const0_rtx)
+-    {
+-      emit_insn (gen_call (operands[0], operands[1], constm1_rtx));
+-      DONE;
+-    }
+-  /* Static functions and indirect calls don't need
+-     current_function_uses_pic_offset_table.  */
+-  if (flag_pic
+-      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+-      && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+-    current_function_uses_pic_offset_table = 1;
+-  if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
+-    XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+-  if (TARGET_64BIT)
+-    abort();
++  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]);
++  DONE;
+ })
+ (define_insn "*call_pop_0"
+@@ -13530,37 +13521,12 @@
+   [(call (match_operand:QI 0 "" "")
+        (match_operand 1 "" ""))
+    (use (match_operand 2 "" ""))]
+-  ;; Operand 1 not used on the i386.
+   ""
+ {
+-  rtx insn;
+-  /* Static functions and indirect calls don't need
+-     current_function_uses_pic_offset_table.  */
+-  if (flag_pic
+-      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+-      && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+-    current_function_uses_pic_offset_table = 1;
+-
+-  if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
+-    XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+-  if (TARGET_64BIT && INTVAL (operands[2]) >= 0)
+-    {
+-      rtx reg = gen_rtx_REG (QImode, 0);
+-      emit_move_insn (reg, operands[2]);
+-      insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
+-      use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
+-      DONE;
+-    }
+-   insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
+-   DONE;
++  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL);
++  DONE;
+ })
+-(define_expand "call_exp"
+-  [(call (match_operand:QI 0 "" "")
+-       (match_operand 1 "" ""))]
+-  ""
+-  "")
+-
+ (define_insn "*call_0"
+   [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
+        (match_operand 1 "" ""))]
+@@ -13612,7 +13578,6 @@
+   [(set_attr "type" "call")])
+ ;; Call subroutine, returning value in operand 0
+-;; (which must be a hard register).
+ (define_expand "call_value_pop"
+   [(parallel [(set (match_operand 0 "" "")
+@@ -13623,20 +13588,9 @@
+                           (match_operand:SI 4 "" "")))])]
+   "!TARGET_64BIT"
+ {
+-  if (operands[4] == const0_rtx)
+-    {
+-      emit_insn (gen_call_value (operands[0], operands[1], operands[2],
+-                               constm1_rtx));
+-      DONE;
+-    }
+-  /* Static functions and indirect calls don't need
+-     current_function_uses_pic_offset_table.  */
+-  if (flag_pic
+-      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+-      && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+-    current_function_uses_pic_offset_table = 1;
+-  if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
+-    XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
++  ix86_expand_call (operands[0], operands[1], operands[2],
++                  operands[3], operands[4]);
++  DONE;
+ })
+ (define_expand "call_value"
+@@ -13647,36 +13601,10 @@
+   ;; Operand 2 not used on the i386.
+   ""
+ {
+-  rtx insn;
+-  /* Static functions and indirect calls don't need
+-     current_function_uses_pic_offset_table.  */
+-  if (flag_pic
+-      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+-      && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+-    current_function_uses_pic_offset_table = 1;
+-  if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
+-    XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+-  if (TARGET_64BIT && INTVAL (operands[3]) >= 0)
+-    {
+-      rtx reg = gen_rtx_REG (QImode, 0);
+-      emit_move_insn (reg, operands[3]);
+-      insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
+-                                               operands[2]));
+-      use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
+-      DONE;
+-    }
+-  insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
+-                                           operands[2]));
++  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL);
+   DONE;
+ })
+-(define_expand "call_value_exp"
+-  [(set (match_operand 0 "" "")
+-      (call (match_operand:QI 1 "" "")
+-            (match_operand:SI 2 "" "")))]
+-  ""
+-  "")
+-
+ ;; Call subroutine returning any type.
+ (define_expand "untyped_call"
+@@ -13693,12 +13621,10 @@
+      simply pretend the untyped call returns a complex long double
+      value.  */
+-  emit_call_insn (TARGET_FLOAT_RETURNS_IN_80387
+-                  ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
+-                                  operands[0], const0_rtx,
+-                                  GEN_INT (SSE_REGPARM_MAX - 1))
+-                  : gen_call (operands[0], const0_rtx,
+-                            GEN_INT (SSE_REGPARM_MAX - 1)));
++  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
++                   ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
++                  operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
++                  NULL);
+   for (i = 0; i < XVECLEN (operands[2], 0); i++)
+     {
+@@ -13781,45 +13707,39 @@
+   ""
+   "ix86_expand_prologue (); DONE;")
+-(define_insn "prologue_set_got"
++(define_expand "set_got"
++  [(parallel [(set (match_operand:SI 0 "register_operand" "")
++                 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
++            (clobber (reg:CC 17))])]
++  "!TARGET_64BIT"
++  "")
++
++(define_insn "*set_got_nopic"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+-      (unspec_volatile:SI
+-       [(plus:SI (match_dup 0)
+-                 (plus:SI (match_operand:SI 1 "symbolic_operand" "")
+-                          (minus:SI (pc) (match_operand 2 "" ""))))] 1))
++      (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+    (clobber (reg:CC 17))]
+-  "!TARGET_64BIT"
+-{
+-  if (GET_CODE (operands[2]) == LABEL_REF)
+-     operands[2] = XEXP (operands[2], 0);
+-  if (TARGET_DEEP_BRANCH_PREDICTION) 
+-    return "add{l}\t{%1, %0|%0, %1}";
+-  else  
+-    return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}";
+-}
+-  [(set_attr "type" "alu")
+-   ; Since this insn may have two constant operands, we must set the
+-   ; length manually.
+-   (set_attr "length_immediate" "4")
+-   (set_attr "mode" "SI")])
++  "!TARGET_64BIT && !flag_pic"
++  { return output_set_got (operands[0]); }
++  [(set_attr "type" "multi")
++   (set_attr "length" "11")])
++  
++(define_insn "*set_got_deep"
++  [(set (match_operand:SI 0 "register_operand" "=b")
++      (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
++   (clobber (reg:CC 17))]
++  "!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
++  { return output_set_got (operands[0]); }
++  [(set_attr "type" "multi")
++   (set_attr "length" "11")])
+-(define_insn "prologue_get_pc"
++(define_insn "*set_got_nodeep"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+-    (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
++      (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
++   (clobber (reg:CC 17))]
+   "!TARGET_64BIT"
+-{
+-  if (GET_CODE (operands[1]) == LABEL_REF)
+-    operands[1] = XEXP (operands[1], 0);
+-  output_asm_insn ("call\t%X1", operands);
+-  if (! TARGET_DEEP_BRANCH_PREDICTION)
+-    {
+-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+-                               CODE_LABEL_NUMBER (operands[1]));
+-      return "pop{l}\t%0";
+-    }
+-  RET;
+-}
+-  [(set_attr "type" "multi")])
++  { return output_set_got (operands[0]); }
++  [(set_attr "type" "multi")
++   (set_attr "length" "12")])
+ (define_expand "epilogue"
+   [(const_int 1)]
+@@ -13996,6 +13916,127 @@
+ ;; ffshi2 is not useful -- 4 word prefix ops are needed, which is larger
+ ;; and slower than the two-byte movzx insn needed to do the work in SImode.
\f
++;; Thread-local storage patterns for ELF.
++;;
++;; Note that these code sequences must appear exactly as shown
++;; in order to allow linker relaxation.
++
++(define_insn "*tls_global_dynamic_gnu"
++  [(set (match_operand:SI 0 "register_operand" "=a")
++      (unspec:SI [(match_operand:SI 1 "register_operand" "b")
++                  (match_operand:SI 2 "tls_symbolic_operand" "")
++                  (match_operand:SI 3 "call_insn_operand" "")]
++                  UNSPEC_TLS_GD))
++   (clobber (match_scratch:SI 4 "=d"))
++   (clobber (match_scratch:SI 5 "=c"))
++   (clobber (reg:CC 17))]
++  "TARGET_GNU_TLS"
++  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
++  [(set_attr "type" "multi")
++   (set_attr "length" "12")])
++
++(define_insn "*tls_global_dynamic_sun"
++  [(set (match_operand:SI 0 "register_operand" "=a")
++      (unspec:SI [(match_operand:SI 1 "register_operand" "b")
++                  (match_operand:SI 2 "tls_symbolic_operand" "")
++                  (match_operand:SI 3 "call_insn_operand" "")]
++                  UNSPEC_TLS_GD))
++   (clobber (match_scratch:SI 4 "=d"))
++   (clobber (match_scratch:SI 5 "=c"))
++   (clobber (reg:CC 17))]
++  "TARGET_SUN_TLS"
++  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
++      push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
++  [(set_attr "type" "multi")
++   (set_attr "length" "14")])
++
++(define_expand "tls_global_dynamic"
++  [(parallel [(set (match_operand:SI 0 "register_operand" "")
++                 (unspec:SI
++                  [(match_dup 2)
++                   (match_operand:SI 1 "tls_symbolic_operand" "")
++                   (match_dup 3)]
++                  UNSPEC_TLS_GD))
++            (clobber (match_scratch:SI 4 ""))
++            (clobber (match_scratch:SI 5 ""))
++            (clobber (reg:CC 17))])]
++  ""
++{
++  if (!flag_pic)
++    abort ();
++  current_function_uses_pic_offset_table = 1;
++  operands[2] = pic_offset_table_rtx;
++  operands[3] = ix86_tls_get_addr ();
++})
++
++(define_insn "*tls_local_dynamic_base_gnu"
++  [(set (match_operand:SI 0 "register_operand" "=a")
++      (unspec:SI [(match_operand:SI 1 "register_operand" "b")
++                    (match_operand:SI 2 "call_insn_operand" "")]
++                 UNSPEC_TLS_LD_BASE))
++   (clobber (match_scratch:SI 3 "=d"))
++   (clobber (match_scratch:SI 4 "=c"))
++   (clobber (reg:CC 17))]
++  "TARGET_GNU_TLS"
++  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
++  [(set_attr "type" "multi")
++   (set_attr "length" "11")])
++
++(define_insn "*tls_local_dynamic_base_sun"
++  [(set (match_operand:SI 0 "register_operand" "=a")
++      (unspec:SI [(match_operand:SI 1 "register_operand" "b")
++                    (match_operand:SI 2 "call_insn_operand" "")]
++                 UNSPEC_TLS_LD_BASE))
++   (clobber (match_scratch:SI 3 "=d"))
++   (clobber (match_scratch:SI 4 "=c"))
++   (clobber (reg:CC 17))]
++  "TARGET_SUN_TLS"
++  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
++      push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
++  [(set_attr "type" "multi")
++   (set_attr "length" "13")])
++
++(define_expand "tls_local_dynamic_base"
++  [(parallel [(set (match_operand:SI 0 "register_operand" "")
++                 (unspec:SI [(match_dup 1) (match_dup 2)]
++                            UNSPEC_TLS_LD_BASE))
++            (clobber (match_scratch:SI 3 ""))
++            (clobber (match_scratch:SI 4 ""))
++            (clobber (reg:CC 17))])]
++  ""
++{
++  if (!flag_pic)
++    abort ();
++  current_function_uses_pic_offset_table = 1;
++  operands[1] = pic_offset_table_rtx;
++  operands[2] = ix86_tls_get_addr ();
++})
++
++;; Local dynamic of a single variable is a lose.  Show combine how
++;; to convert that back to global dynamic.
++
++(define_insn_and_split "*tls_local_dynamic_once"
++  [(set (match_operand:SI 0 "register_operand" "=a")
++      (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
++                           (match_operand:SI 2 "call_insn_operand" "")]
++                          UNSPEC_TLS_LD_BASE)
++               (const:SI (unspec:SI
++                          [(match_operand:SI 3 "tls_symbolic_operand" "")]
++                          UNSPEC_DTPOFF))))
++   (clobber (match_scratch:SI 4 "=d"))
++   (clobber (match_scratch:SI 5 "=c"))
++   (clobber (reg:CC 17))]
++  ""
++  "#"
++  ""
++  [(parallel [(set (match_dup 0)
++                 (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
++                            UNSPEC_TLS_GD))
++            (clobber (match_dup 4))
++            (clobber (match_dup 5))
++            (clobber (reg:CC 17))])]
++  "")
++\f
+ ;; These patterns match the binary 387 instructions for addM3, subM3,
+ ;; mulM3 and divM3.  There are three patterns for each of DFmode and
+ ;; SFmode.  The first is the normal insn, the second the same insn but
+@@ -16835,7 +16876,7 @@
+   [(label_ref (match_operand 0 "" ""))]
+   "!TARGET_64BIT && flag_pic"
+ {
+-  load_pic_register ();
++  emit_insn (gen_set_got (pic_offset_table_rtx));
+   DONE;
+ })
\f
+--- gcc/config/ia64/ia64-protos.h.jj   Tue Apr 23 20:28:20 2002
++++ gcc/config/ia64/ia64-protos.h      Wed Jun 19 19:33:52 2002
+@@ -31,6 +31,7 @@ extern int call_operand PARAMS((rtx, enu
+ extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode));
+ extern int got_symbolic_operand PARAMS((rtx, enum machine_mode));
+ extern int symbolic_operand PARAMS((rtx, enum machine_mode));
++extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode));
+ extern int function_operand PARAMS((rtx, enum machine_mode));
+ extern int setjmp_operand PARAMS((rtx, enum machine_mode));
+ extern int move_operand PARAMS((rtx, enum machine_mode));
+@@ -67,6 +68,7 @@ extern int general_tfmode_operand PARAMS
+ extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
+ extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
++extern rtx ia64_expand_move PARAMS ((rtx, rtx));
+ extern int ia64_move_ok PARAMS((rtx, rtx));
+ extern int ia64_depz_field_mask PARAMS((rtx, rtx));
+ extern rtx ia64_gp_save_reg PARAMS((int));
+--- gcc/config/ia64/ia64.c.jj  Wed Jun 19 22:36:54 2002
++++ gcc/config/ia64/ia64.c     Wed Jun 19 22:46:07 2002
+@@ -95,6 +95,13 @@ static const char * const ia64_output_re
+ /* String used with the -mfixed-range= option.  */
+ const char *ia64_fixed_range_string;
++/* Determines whether we use adds, addl, or movl to generate our
++   TLS immediate offsets.  */
++int ia64_tls_size = 22;
++
++/* String used with the -mtls-size= option.  */
++const char *ia64_tls_size_string;
++
+ /* Determines whether we run our final scheduling pass or not.  We always
+    avoid the normal second scheduling pass.  */
+ static int ia64_flag_schedule_insns2;
+@@ -104,6 +111,8 @@ static int ia64_flag_schedule_insns2;
+ unsigned int ia64_section_threshold;
\f
++static rtx gen_tls_get_addr PARAMS ((void));
++static rtx gen_thread_pointer PARAMS ((void));
+ static int find_gr_spill PARAMS ((int));
+ static int next_scratch_gr_reg PARAMS ((void));
+ static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
+@@ -214,6 +223,11 @@ static const struct attribute_spec ia64_
+ #undef TARGET_SCHED_CYCLE_DISPLAY
+ #define TARGET_SCHED_CYCLE_DISPLAY ia64_cycle_display
++#ifdef HAVE_AS_TLS
++#undef TARGET_HAVE_TLS
++#define TARGET_HAVE_TLS true
++#endif
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
\f
+ /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
+@@ -250,7 +264,10 @@ sdata_symbolic_operand (op, mode)
+       if (CONSTANT_POOL_ADDRESS_P (op))
+       return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
+       else
+-        return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR;
++      {
++        const char *str = XSTR (op, 0);
++          return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
++      }
+     default:
+       break;
+@@ -324,6 +341,35 @@ symbolic_operand (op, mode)
+   return 0;
+ }
++/* Return tls_model if OP refers to a TLS symbol.  */
++
++int
++tls_symbolic_operand (op, mode)
++     rtx op;
++     enum machine_mode mode ATTRIBUTE_UNUSED;
++{
++  const char *str;
++
++  if (GET_CODE (op) != SYMBOL_REF)
++    return 0;
++  str = XSTR (op, 0);
++  if (str[0] != ENCODE_SECTION_INFO_CHAR)
++    return 0;
++  switch (str[1])
++    {
++    case 'G':
++      return TLS_MODEL_GLOBAL_DYNAMIC;
++    case 'L':
++      return TLS_MODEL_LOCAL_DYNAMIC;
++    case 'i':
++      return TLS_MODEL_INITIAL_EXEC;
++    case 'l':
++      return TLS_MODEL_LOCAL_EXEC;
++    }
++  return 0;
++}
++
++
+ /* Return 1 if OP refers to a function.  */
+ int
+@@ -922,6 +968,9 @@ ia64_expand_load_address (dest, src, scr
+   else
+     temp = dest;
++  if (tls_symbolic_operand (src, Pmode))
++    abort ();
++
+   if (TARGET_AUTO_PIC)
+     emit_insn (gen_load_gprel64 (temp, src));
+   else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
+@@ -964,6 +1013,185 @@ ia64_expand_load_address (dest, src, scr
+     emit_move_insn (dest, temp);
+ }
++static rtx
++gen_tls_get_addr ()
++{
++  static rtx tga;
++  if (!tga)
++    {
++      tga = init_one_libfunc ("__tls_get_addr");
++      ggc_add_rtx_root (&tga, 1);
++    }
++  return tga;
++}
++
++static rtx
++gen_thread_pointer ()
++{
++  static rtx tp;
++  if (!tp)
++    {
++      tp = gen_rtx_REG (Pmode, 13);
++      RTX_UNCHANGING_P (tp) = 1;
++      ggc_add_rtx_root (&tp, 1);
++    }
++  return tp;
++}
++
++rtx
++ia64_expand_move (op0, op1)
++     rtx op0, op1;
++{
++  enum machine_mode mode = GET_MODE (op0);
++
++  if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
++    op1 = force_reg (mode, op1);
++
++  if (mode == Pmode)
++    {
++      enum tls_model tls_kind;
++      if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
++      {
++        rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
++
++        switch (tls_kind)
++          {
++          case TLS_MODEL_GLOBAL_DYNAMIC:
++            start_sequence ();
++
++            tga_op1 = gen_reg_rtx (Pmode);
++            emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
++            tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
++            RTX_UNCHANGING_P (tga_op1) = 1;
++
++            tga_op2 = gen_reg_rtx (Pmode);
++            emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
++            tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
++            RTX_UNCHANGING_P (tga_op2) = 1;
++            
++            tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
++                                               LCT_CONST, Pmode, 2, tga_op1,
++                                               Pmode, tga_op2, Pmode);
++
++            insns = get_insns ();
++            end_sequence ();
++
++            emit_libcall_block (insns, op0, tga_ret, op1);
++            return NULL_RTX;
++
++          case TLS_MODEL_LOCAL_DYNAMIC:
++            /* ??? This isn't the completely proper way to do local-dynamic
++               If the call to __tls_get_addr is used only by a single symbol,
++               then we should (somehow) move the dtprel to the second arg
++               to avoid the extra add.  */
++            start_sequence ();
++
++            tga_op1 = gen_reg_rtx (Pmode);
++            emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
++            tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
++            RTX_UNCHANGING_P (tga_op1) = 1;
++
++            tga_op2 = const0_rtx;
++
++            tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
++                                               LCT_CONST, Pmode, 2, tga_op1,
++                                               Pmode, tga_op2, Pmode);
++
++            insns = get_insns ();
++            end_sequence ();
++
++            tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
++                                      UNSPEC_LD_BASE);
++            tmp = gen_reg_rtx (Pmode);
++            emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
++
++            if (register_operand (op0, Pmode))
++              tga_ret = op0;
++            else
++              tga_ret = gen_reg_rtx (Pmode);
++            if (TARGET_TLS64)
++              {
++                emit_insn (gen_load_dtprel (tga_ret, op1));
++                emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
++              }
++            else
++              emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
++            if (tga_ret == op0)
++              return NULL_RTX;
++            op1 = tga_ret;
++            break;
++
++          case TLS_MODEL_INITIAL_EXEC:
++            tmp = gen_reg_rtx (Pmode);
++            emit_insn (gen_load_ltoff_tprel (tmp, op1));
++            tmp = gen_rtx_MEM (Pmode, tmp);
++            RTX_UNCHANGING_P (tmp) = 1;
++            tmp = force_reg (Pmode, tmp);
++
++            if (register_operand (op0, Pmode))
++              op1 = op0;
++            else
++              op1 = gen_reg_rtx (Pmode);
++            emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
++            if (op1 == op0)
++              return NULL_RTX;
++            break;
++
++          case TLS_MODEL_LOCAL_EXEC:
++            if (register_operand (op0, Pmode))
++              tmp = op0;
++            else
++              tmp = gen_reg_rtx (Pmode);
++            if (TARGET_TLS64)
++              {
++                emit_insn (gen_load_tprel (tmp, op1));
++                emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
++              }
++            else
++              emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
++            if (tmp == op0)
++              return NULL_RTX;
++            op1 = tmp;
++            break;
++
++          default:
++            abort ();
++          }
++      }
++      else if (!TARGET_NO_PIC && symbolic_operand (op1, DImode))
++      {
++        /* Before optimization starts, delay committing to any particular
++           type of PIC address load.  If this function gets deferred, we
++           may acquire information that changes the value of the
++           sdata_symbolic_operand predicate.
++
++           But don't delay for function pointers.  Loading a function address
++           actually loads the address of the descriptor not the function.
++           If we represent these as SYMBOL_REFs, then they get cse'd with
++           calls, and we end up with calls to the descriptor address instead
++           of calls to the function address.  Functions are not candidates
++           for sdata anyways.
++
++           Don't delay for LABEL_REF because the splitter loses REG_LABEL
++           notes.  Don't delay for pool addresses on general principals;
++           they'll never become non-local behind our back.  */
++
++        if (rtx_equal_function_value_matters
++            && GET_CODE (op1) != LABEL_REF
++            && ! (GET_CODE (op1) == SYMBOL_REF
++                  && (SYMBOL_REF_FLAG (op1)
++                      || CONSTANT_POOL_ADDRESS_P (op1)
++                      || STRING_POOL_ADDRESS_P (op1))))
++          emit_insn (gen_movdi_symbolic (op0, op1));
++        else
++          ia64_expand_load_address (op0, op1, NULL_RTX);
++        return NULL_RTX;
++      }
++    }
++
++  return op1;
++}
++
+ rtx
+ ia64_gp_save_reg (setjmp_p)
+      int setjmp_p;
+@@ -3944,6 +4172,16 @@ ia64_override_options ()
+   if (ia64_fixed_range_string)
+     fix_range (ia64_fixed_range_string);
++  if (ia64_tls_size_string)
++    {
++      char *end;
++      unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
++      if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
++      error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
++      else
++      ia64_tls_size = tmp;
++    }
++
+   ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
+   flag_schedule_insns_after_reload = 0;
+@@ -4607,6 +4845,13 @@ rtx_needs_barrier (x, flags, pred)
+         need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
+         break;
++      case UNSPEC_LTOFF_DTPMOD:
++      case UNSPEC_LTOFF_DTPREL:
++      case UNSPEC_DTPREL:
++      case UNSPEC_LTOFF_TPREL:
++      case UNSPEC_TPREL:
++          break;
++
+       default:
+         abort ();
+       }
+@@ -6872,6 +7117,9 @@ ia64_encode_section_info (decl)
+      tree decl;
+ {
+   const char *symbol_str;
++  bool is_local, is_small;
++  rtx symbol;
++  char encoding = 0;
+   if (TREE_CODE (decl) == FUNCTION_DECL)
+     {
+@@ -6885,75 +7133,111 @@ ia64_encode_section_info (decl)
+       || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
+     return;
+     
+-  symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
++  symbol = XEXP (DECL_RTL (decl), 0);
++  symbol_str = XSTR (symbol, 0);
++
++  /* A non-decl is an entry in the constant pool.  */
++  if (!DECL_P (decl))
++    is_local = true;
++  /* Static variables are always local.  */
++  else if (! TREE_PUBLIC (decl))
++    is_local = true;
++  /* A variable is local if the user tells us so.  */
++  else if (MODULE_LOCAL_P (decl))
++    is_local = true;
++  /* Otherwise, variables defined outside this object may not be local.  */
++  else if (DECL_EXTERNAL (decl))
++    is_local = false;
++  /* Linkonce and weak data are never local.  */
++  else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
++    is_local = false;
++  /* If PIC, then assume that any global name can be overridden by
++     symbols resolved from other modules.  */
++  else if (flag_pic)
++    is_local = false;
++  /* Uninitialized COMMON variable may be unified with symbols
++     resolved from other modules.  */
++  else if (DECL_COMMON (decl)
++         && (DECL_INITIAL (decl) == NULL
++             || DECL_INITIAL (decl) == error_mark_node))
++    is_local = false;
++  /* Otherwise we're left with initialized (or non-common) global data
++     which is of necessity defined locally.  */
++  else
++    is_local = true;
+-  /* We assume that -fpic is used only to create a shared library (dso).
+-     With -fpic, no global data can ever be sdata.
+-     Without -fpic, global common uninitialized data can never be sdata, since
+-     it can unify with a real definition in a dso.  */
+-  /* ??? Actually, we can put globals in sdata, as long as we don't use gprel
+-     to access them.  The linker may then be able to do linker relaxation to
+-     optimize references to them.  Currently sdata implies use of gprel.  */
+-  /* We need the DECL_EXTERNAL check for C++.  static class data members get
+-     both TREE_STATIC and DECL_EXTERNAL set, to indicate that they are
+-     statically allocated, but the space is allocated somewhere else.  Such
+-     decls can not be own data.  */
+-  if (! TARGET_NO_SDATA
+-      && ((TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
+-         && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
+-         && ! (TREE_PUBLIC (decl)
+-               && (flag_pic
+-                   || (DECL_COMMON (decl)
+-                       && (DECL_INITIAL (decl) == 0
+-                           || DECL_INITIAL (decl) == error_mark_node)))))
+-        || MODULE_LOCAL_P (decl))
+-      /* Either the variable must be declared without a section attribute,
+-       or the section must be sdata or sbss.  */
+-      && (DECL_SECTION_NAME (decl) == 0
+-        || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
+-                     ".sdata")
+-        || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
+-                     ".sbss")))
++  is_small = false;
++  if (TARGET_NO_SDATA)
++    ;
++  else if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
++    {
++      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
++      if (strcmp (section, ".sdata") == 0
++        || strcmp (section, ".sbss") == 0)
++      is_small = true;
++    }
++  else
+     {
+       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
+-      /* If the variable has already been defined in the output file, then it
+-       is too late to put it in sdata if it wasn't put there in the first
+-       place.  The test is here rather than above, because if it is already
+-       in sdata, then it can stay there.  */
+-
+-      if (TREE_ASM_WRITTEN (decl))
+-      ;
+-
+-      /* If this is an incomplete type with size 0, then we can't put it in
+-       sdata because it might be too big when completed.
+-       Objects bigger than threshold should have SDATA_NAME_FLAG_CHAR
+-       added if they are in .sdata or .sbss explicitely.  */
+-      else if (((size > 0
+-               && size <= (HOST_WIDE_INT) ia64_section_threshold)
+-              || DECL_SECTION_NAME (decl))
+-             && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
+-      {
+-        size_t len = strlen (symbol_str);
+-        char *newstr = alloca (len + 1);
+-        const char *string;
++      /* If this is an incomplete type with size 0, then we can't put it
++       in sdata because it might be too big when completed.  */
++      if (size > 0 && size <= ia64_section_threshold)
++      is_small = true;
++    }
+-        *newstr = SDATA_NAME_FLAG_CHAR;
+-        memcpy (newstr + 1, symbol_str, len + 1);
+-        
+-        string = ggc_alloc_string (newstr, len + 1);
+-        XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
++  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
++    {
++      enum tls_model kind;
++      if (!flag_pic)
++      {
++        if (is_local)
++          kind = TLS_MODEL_LOCAL_EXEC;
++        else
++          kind = TLS_MODEL_INITIAL_EXEC;
+       }
+-    }
+-  /* This decl is marked as being in small data/bss but it shouldn't
+-     be; one likely explanation for this is that the decl has been
+-     moved into a different section from the one it was in when
+-     ENCODE_SECTION_INFO was first called.  Remove the '@'.  */
+-  else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
++      else if (is_local)
++      kind = TLS_MODEL_LOCAL_DYNAMIC;
++      else
++      kind = TLS_MODEL_GLOBAL_DYNAMIC;
++      if (kind < flag_tls_default)
++      kind = flag_tls_default;
++
++      encoding = " GLil"[kind];
++    }
++  /* Determine if DECL will wind up in .sdata/.sbss.  */
++  else if (is_local && is_small)
++    encoding = 's';
++  
++  /* Finally, encode this into the symbol string.  */
++  if (encoding)
+     {
+-      XSTR (XEXP (DECL_RTL (decl), 0), 0)
+-      = ggc_strdup (symbol_str + 1);
++      char *newstr;
++      size_t len;
++  
++      if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
++      {
++        if (encoding == symbol_str[1])
++          return;
++        /* ??? Sdata became thread or thread becaome not thread.  Lose.  */
++        abort ();
++      }
++
++      len = strlen (symbol_str);
++      newstr = alloca (len + 3);
++      newstr[0] = ENCODE_SECTION_INFO_CHAR;
++      newstr[1] = encoding;
++      memcpy (newstr + 2, symbol_str, len + 1);
++
++      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
+     }
++  
++  /* This decl is marked as being in small data/bss but it shouldn't be;
++     one likely explanation for this is that the decl has been moved into
++     a different section from the one it was in when encode_section_info
++     was first called.  Remove the encoding.  */
++  else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
++    XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
+ }
\f
+ /* Output assembly directives for prologue regions.  */
+--- gcc/config/ia64/ia64.h.jj  Tue Apr 23 20:28:21 2002
++++ gcc/config/ia64/ia64.h     Wed Jun 19 19:33:52 2002
+@@ -109,6 +109,11 @@ extern int target_flags;
+ #define TARGET_DWARF2_ASM     (target_flags & MASK_DWARF2_ASM)
++extern int ia64_tls_size;
++#define TARGET_TLS14          (ia64_tls_size == 14)
++#define TARGET_TLS22          (ia64_tls_size == 22)
++#define TARGET_TLS64          (ia64_tls_size == 64)
++
+ /* This macro defines names of command options to set and clear bits in
+    `target_flags'.  Its definition is an initializer with a subgrouping for
+    each command option.  */
+@@ -177,10 +182,13 @@ extern int target_flags;
+    subgrouping for each command option.  */
+ extern const char *ia64_fixed_range_string;
++extern const char *ia64_tls_size_string;
+ #define TARGET_OPTIONS \
+ {                                                                     \
+   { "fixed-range=",   &ia64_fixed_range_string,                       \
+       N_("Specify range of registers to make fixed")},                        \
++  { "tls-size=",      &ia64_tls_size_string,                          \
++      N_("Specify bit size of immediate TLS offsets")},                       \
+ }
+ /* Sometimes certain combinations of command options do not make sense on a
+@@ -1801,7 +1809,7 @@ do {                                                                     \
+     && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL)        \
+       || DECL_SECTION_NAME (DECL) != 0))
+-#define SDATA_NAME_FLAG_CHAR '@'
++#define ENCODE_SECTION_INFO_CHAR '@'
+ #define IA64_DEFAULT_GVALUE 8
+@@ -1811,8 +1819,8 @@ do {                                                                     \
+ #define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
+ do {                                          \
+   (VAR) = (SYMBOL_NAME);                      \
+-  if ((VAR)[0] == SDATA_NAME_FLAG_CHAR)               \
+-    (VAR)++;                                  \
++  if ((VAR)[0] == ENCODE_SECTION_INFO_CHAR)   \
++    (VAR) += 2;                                       \
+   if ((VAR)[0] == '*')                                \
+     (VAR)++;                                  \
+ } while (0)
+--- gcc/config/ia64/ia64.md.jj Tue Apr 23 20:28:21 2002
++++ gcc/config/ia64/ia64.md    Wed Jun 19 19:33:52 2002
+@@ -68,7 +68,19 @@
+ ;;    23      cycle display
+ ;;      24      addp4
+ ;;    25      prologue_use
+-;;
++
++;; More unspec:
++
++(define_constants
++  [; Relocations
++   (UNSPEC_LTOFF_DTPMOD               14)
++   (UNSPEC_LTOFF_DTPREL               15)
++   (UNSPEC_DTPREL             16)
++   (UNSPEC_LTOFF_TPREL                17)
++   (UNSPEC_TPREL              18)
++   (UNSPEC_LD_BASE            26)
++  ])
++
+ ;; unspec_volatile:
+ ;;    0       alloc
+ ;;    1       blockage
+@@ -272,12 +284,12 @@
+   [(set (match_operand:QI 0 "general_operand" "")
+       (match_operand:QI 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (QImode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn "*movqi_internal"
+   [(set (match_operand:QI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
+@@ -297,12 +309,12 @@
+   [(set (match_operand:HI 0 "general_operand" "")
+       (match_operand:HI 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (HImode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn "*movhi_internal"
+   [(set (match_operand:HI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
+@@ -322,12 +334,12 @@
+   [(set (match_operand:SI 0 "general_operand" "")
+       (match_operand:SI 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (SImode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn "*movsi_internal"
+   [(set (match_operand:SI 0 "destination_operand" "=r,r,r,r, m, r,*f,*f, r,*d")
+@@ -351,32 +363,12 @@
+   [(set (match_operand:DI 0 "general_operand" "")
+       (match_operand:DI 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (DImode, operands[1]);
+-  if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode))
+-    {
+-      /* Before optimization starts, delay committing to any particular
+-       type of PIC address load.  If this function gets deferred, we
+-       may acquire information that changes the value of the
+-       sdata_symbolic_operand predicate.  */
+-      /* But don't delay for function pointers.  Loading a function address
+-       actually loads the address of the descriptor not the function.
+-       If we represent these as SYMBOL_REFs, then they get cse'd with
+-       calls, and we end up with calls to the descriptor address instead of
+-       calls to the function address.  Functions are not candidates for
+-       sdata anyways.  */
+-      if (rtx_equal_function_value_matters
+-        && ! (GET_CODE (operands[1]) == SYMBOL_REF
+-              && SYMBOL_REF_FLAG (operands[1])))
+-      emit_insn (gen_movdi_symbolic (operands[0], operands[1], gen_reg_rtx (DImode)));
+-      else
+-        ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
+-      DONE;
+-    }
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ ;; This is used during early compilation to delay the decision on
+ ;; how to refer to a variable as long as possible.  This is especially
+@@ -384,19 +376,22 @@
+ ;; deferred functions, since we may acquire additional information
+ ;; on the variables used in the meantime.
+-;; ??? This causes us to lose REG_LABEL notes, because the insn splitter
+-;; does not attempt to preserve any REG_NOTES on the input instruction.
+-
+ (define_insn_and_split "movdi_symbolic"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+       (match_operand:DI 1 "symbolic_operand" "s"))
+-   (clobber (match_operand:DI  2 "register_operand" "+r"))
++   (clobber (match_scratch:DI 2 "=r"))
+    (use (reg:DI 1))]
+   ""
+   "* abort ();"
+-  ""
++  "!no_new_pseudos || reload_completed"
+   [(const_int 0)]
+-  "ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE;")
++{
++  rtx scratch = operands[2];
++  if (!reload_completed)
++    gen_reg_rtx (Pmode);
++  ia64_expand_load_address (operands[0], operands[1], scratch); 
++  DONE;
++})
+ (define_insn "*movdi_internal"
+   [(set (match_operand:DI 0 "destination_operand"
+@@ -510,6 +505,131 @@
+   "addl %0 = @ltoff(%1), gp"
+   [(set_attr "itanium_class" "ialu")])
++(define_insn "load_ltoff_dtpmod"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (reg:DI 1)
++               (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                          UNSPEC_LTOFF_DTPMOD)))]
++  ""
++  "addl %0 = @ltoff(@dtpmod(%1)), gp"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_insn "load_ltoff_dtprel"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (reg:DI 1)
++               (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                          UNSPEC_LTOFF_DTPREL)))]
++  ""
++  "addl %0 = @ltoff(@dtprel(%1)), gp"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_expand "load_dtprel"
++  [(set (match_operand:DI 0 "register_operand" "")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_DTPREL))]
++  ""
++  "")
++
++(define_insn "*load_dtprel64"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_DTPREL))]
++  "TARGET_TLS64"
++  "movl %0 = @dtprel(%1)"
++  [(set_attr "itanium_class" "long_i")])
++
++(define_insn "*load_dtprel22"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_DTPREL))]
++  ""
++  "addl %0 = @dtprel(%1), r0"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_expand "add_dtprel"
++  [(set (match_operand:DI 0 "register_operand" "")
++      (plus:DI (match_operand:DI 1 "register_operand" "")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_DTPREL)))]
++  "!TARGET_TLS64"
++  "")
++
++(define_insn "*add_dtprel14"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (match_operand:DI 1 "register_operand" "r")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_DTPREL)))]
++  "TARGET_TLS14"
++  "adds %0 = @dtprel(%2), %1"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_insn "*add_dtprel22"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (match_operand:DI 1 "register_operand" "a")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_DTPREL)))]
++  "TARGET_TLS22"
++  "addl %0 = @dtprel(%2), %1"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_insn "load_ltoff_tprel"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (reg:DI 1)
++               (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                          UNSPEC_LTOFF_TPREL)))]
++  ""
++  "addl %0 = @ltoff(@tprel(%1)), gp"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_expand "load_tprel"
++  [(set (match_operand:DI 0 "register_operand" "")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_TPREL))]
++  ""
++  "")
++
++(define_insn "*load_tprel64"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_TPREL))]
++  "TARGET_TLS64"
++  "movl %0 = @tprel(%1)"
++  [(set_attr "itanium_class" "long_i")])
++
++(define_insn "*load_tprel22"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
++                 UNSPEC_TPREL))]
++  ""
++  "addl %0 = @tprel(%1), r0"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_expand "add_tprel"
++  [(set (match_operand:DI 0 "register_operand" "")
++      (plus:DI (match_operand:DI 1 "register_operand" "")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_TPREL)))]
++  "!TARGET_TLS64"
++  "")
++
++(define_insn "*add_tprel14"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (match_operand:DI 1 "register_operand" "r")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_TPREL)))]
++  "TARGET_TLS14"
++  "adds %0 = @tprel(%2), %1"
++  [(set_attr "itanium_class" "ialu")])
++
++(define_insn "*add_tprel22"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++      (plus:DI (match_operand:DI 1 "register_operand" "a")
++               (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
++                          UNSPEC_TPREL)))]
++  "TARGET_TLS22"
++  "addl %0 = @tprel(%2), %1"
++  [(set_attr "itanium_class" "ialu")])
++
+ ;; With no offsettable memory references, we've got to have a scratch
+ ;; around to play with the second word.
+ (define_expand "movti"
+@@ -517,12 +637,12 @@
+                  (match_operand:TI 1 "general_operand" ""))
+             (clobber (match_scratch:DI 2 ""))])]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (TImode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn_and_split "*movti_internal"
+   [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
+@@ -639,12 +759,12 @@
+   [(set (match_operand:SF 0 "general_operand" "")
+       (match_operand:SF 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (SFmode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn "*movsf_internal"
+   [(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
+@@ -665,12 +785,12 @@
+   [(set (match_operand:DF 0 "general_operand" "")
+       (match_operand:DF 1 "general_operand" ""))]
+   ""
+-  "
+ {
+-  if (! reload_in_progress && ! reload_completed
+-      && ! ia64_move_ok (operands[0], operands[1]))
+-    operands[1] = force_reg (DFmode, operands[1]);
+-}")
++  rtx op1 = ia64_expand_move (operands[0], operands[1]);
++  if (!op1)
++    DONE;
++  operands[1] = op1;
++})
+ (define_insn "*movdf_internal"
+   [(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
+--- gcc/config/ia64/sysv4.h.jj Mon Jun  3 17:24:18 2002
++++ gcc/config/ia64/sysv4.h    Wed Jun 19 19:33:52 2002
+@@ -42,8 +42,7 @@ extern int size_directive_output;
+ #undef ASM_OUTPUT_ALIGNED_LOCAL
+ #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+ do {                                                                  \
+-  if ((DECL)                                                          \
+-      && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \
++  if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
+     sbss_section ();                                                  \
+   else                                                                        \
+     bss_section ();                                                   \
+@@ -62,8 +61,8 @@ do {                                                                 \
+ #define ASM_OUTPUT_LABELREF(STREAM, NAME)     \
+ do {                                          \
+   const char *name_ = NAME;                   \
+-  if (*name_ == SDATA_NAME_FLAG_CHAR)         \
+-    name_++;                                  \
++  if (*name_ == ENCODE_SECTION_INFO_CHAR)     \
++    name_ += 2;                                       \
+   if (*name_ == '*')                          \
+     name_++;                                  \
+   else                                                \
+@@ -149,9 +148,11 @@ do {                                                                      \
+       0       .text
+       1       .rodata
+       2       .data
+-      3       .sdata
+-      4       .bss
++      3       .bss
++      4       .sdata
+       5       .sbss
++      6       .tdata
++      7       .tbss
+ */
+ #define DO_SELECT_SECTION(SECNUM, DECL, RELOC)                                \
+   do                                                                  \
+@@ -167,9 +168,10 @@ do {                                                                      \
+       }                                                               \
+       else if (TREE_CODE (DECL) == VAR_DECL)                          \
+       {                                                               \
+-        if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0]                    \
+-            == SDATA_NAME_FLAG_CHAR)                                  \
+-          SECNUM = 3;                                                 \
++        if (DECL_THREAD_LOCAL (DECL))                                 \
++          SECNUM = 6;                                                 \
++        else if (sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode))\
++          SECNUM = 4;                                                 \
+         /* ??? We need the extra RELOC check, because the default     \
+            is to only check RELOC if flag_pic is set, and we don't    \
+            set flag_pic (yet?).  */                                   \
+@@ -184,13 +186,18 @@ do {                                                                     \
+           SECNUM = 0x201;                                             \
+         else                                                          \
+           SECNUM = 0x301;                                             \
++                                                                      \
++        if (SECNUM >= 2                                               \
++            && (!DECL_INITIAL (DECL)                                  \
++                || DECL_INITIAL (DECL) == error_mark_node))           \
++          SECNUM++;                                                   \
+       }                                                               \
+       /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
+        in which case we can't put it in a shared library rodata.  */  \
+       else if (flag_pic && (RELOC))                                   \
+-      SECNUM = 3;                                                     \
+-      else                                                            \
+       SECNUM = 2;                                                     \
++      else                                                            \
++      SECNUM = 1;                                                     \
+     }                                                                 \
+   while (0)
+@@ -206,8 +213,8 @@ do {                                                                       \
+       text_section,                                                   \
+       const_section,                                                  \
+       data_section,                                                   \
+-      sdata_section,                                                  \
+       bss_section,                                                    \
++      sdata_section,                                                  \
+       sbss_section                                                    \
+       };                                                              \
+                                                                       \
+@@ -217,6 +224,12 @@ do {                                                                      \
+                                                                       \
+       switch (sec)                                                    \
+       {                                                               \
++      case 6:                                                         \
++        named_section (NULL_TREE, ".tdata", RELOC);                   \
++        break;                                                        \
++      case 7:                                                         \
++        named_section (NULL_TREE, ".tbss", RELOC);                    \
++        break;                                                        \
+       case 0x101:                                                     \
+         mergeable_string_section (DECL, ALIGN, 0);                    \
+         break;                                                        \
+@@ -244,9 +257,11 @@ do {                                                                      \
+       { ".text.",   ".gnu.linkonce.t." },                             \
+       { ".rodata.", ".gnu.linkonce.r." },                             \
+       { ".data.",   ".gnu.linkonce.d." },                             \
+-      { ".sdata.",  ".gnu.linkonce.s." },                             \
+       { ".bss.",    ".gnu.linkonce.b." },                             \
+-      { ".sbss.",   ".gnu.linkonce.sb." }                             \
++      { ".sdata.",  ".gnu.linkonce.s." },                             \
++      { ".sbss.",   ".gnu.linkonce.sb." },                            \
++      { ".tdata.",  ".gnu.linkonce.td." },                            \
++      { ".tbss.",   ".gnu.linkonce.tb." }                             \
+       };                                                              \
+                                                                       \
+       int nlen, plen, sec;                                            \
+--- gcc/config/elfos.h.jj      Tue Dec 18 01:30:48 2001
++++ gcc/config/elfos.h Wed Jun 19 19:33:52 2002
+@@ -288,24 +288,28 @@ const_section ()                                         \
+       const char *name;                                               \
+       char *string;                                           \
+       const char *prefix;                                     \
+-      static const char *const prefixes[4][2] =                       \
++      static const char *const prefixes[][2] =                        \
+       {                                                               \
+       { ".text.",   ".gnu.linkonce.t." },                     \
+       { ".rodata.", ".gnu.linkonce.r." },                     \
+       { ".data.",   ".gnu.linkonce.d." },                     \
+-      { ".bss.",    ".gnu.linkonce.b." }                      \
++      { ".bss.",    ".gnu.linkonce.b." },                     \
++      { ".tdata",   ".gnu.linkonce.td." },                    \
++      { ".tbss",    ".gnu.linkonce.tb." },                    \
+       };                                                      \
+                                                                       \
+       if (TREE_CODE (DECL) == FUNCTION_DECL)                  \
+       sec = 0;                                                \
+       else if (DECL_INITIAL (DECL) == 0                               \
+              || DECL_INITIAL (DECL) == error_mark_node)       \
+-        sec =  3;                                             \
++        sec = 3;                                              \
+       else if (DECL_READONLY_SECTION (DECL, RELOC))           \
+       sec = 1;                                                \
+       else                                                    \
+       sec = 2;                                                \
+-                                                                      \
++      if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) \
++      sec = (sec == 3 ? 5 : 4);                               \
++                                                              \
+       name   = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL));       \
+       /* Strip off any encoding in name.  */                  \
+       STRIP_NAME_ENCODING (name, name);                               \
+@@ -367,10 +371,18 @@ const_section ()                                         \
+     }                                                         \
+   else if (TREE_CODE (DECL) == VAR_DECL)                      \
+     {                                                         \
+-      if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL)   \
+-        || !DECL_INITIAL (DECL)                               \
+-        || (DECL_INITIAL (DECL) != error_mark_node            \
+-            && !TREE_CONSTANT (DECL_INITIAL (DECL))))         \
++      if (DECL_THREAD_LOCAL (DECL))                           \
++      {                                                       \
++        if (!DECL_INITIAL (DECL)                              \
++            || DECL_INITIAL (DECL) == error_mark_node)        \
++          named_section (NULL_TREE, ".tbss", RELOC);          \
++        else                                                  \
++          named_section (NULL_TREE, ".tdata", RELOC);         \
++      }                                                       \
++      else if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
++             || !DECL_INITIAL (DECL)                          \
++             || (DECL_INITIAL (DECL) != error_mark_node       \
++                 && !TREE_CONSTANT (DECL_INITIAL (DECL))))    \
+       {                                                       \
+         if (flag_pic && ((RELOC) & 2))                        \
+           named_section (NULL_TREE, ".data.rel", RELOC);      \
+--- gcc/fixinc/fixincl.x.jj    Thu May  2 12:15:15 2002
++++ gcc/fixinc/fixincl.x       Wed Jun 19 19:33:52 2002
+@@ -5,7 +5,7 @@
+  * files which are fixed to work correctly with ANSI C and placed in a
+  * directory that GNU C will search.
+  *
+- * This file contains 142 fixup descriptions.
++ * This file contains 143 fixup descriptions.
+  *
+  * See README for more information.
+  *
+@@ -4568,6 +4568,41 @@ static const char* apzSysz_Stdlib_For_Su
+ /* * * * * * * * * * * * * * * * * * * * * * * * * *
+  *
++ *  Description of Thread_Keyword fix
++ */
++tSCC zThread_KeywordName[] =
++     "thread_keyword";
++
++/*
++ *  File name selection pattern
++ */
++tSCC zThread_KeywordList[] =
++  "|pthread.h|bits/sigthread.h|";
++/*
++ *  Machine/OS name selection pattern
++ */
++#define apzThread_KeywordMachs (const char**)NULL
++
++/*
++ *  content selection pattern - do fix if pattern found
++ */
++tSCC zThread_KeywordSelect0[] =
++       " __thread([,)])";
++
++#define    THREAD_KEYWORD_TEST_CT  1
++static tTestDesc aThread_KeywordTests[] = {
++  { TT_EGREP,    zThread_KeywordSelect0, (regex_t*)NULL }, };
++
++/*
++ *  Fix Command Arguments for Thread_Keyword
++ */
++static const char* apzThread_KeywordPatch[] = {
++    "format",
++    " __thr%1",
++    (char*)NULL };
++
++/* * * * * * * * * * * * * * * * * * * * * * * * * *
++ *
+  *  Description of Tinfo_Cplusplus fix
+  */
+ tSCC zTinfo_CplusplusName[] =
+@@ -5581,9 +5616,9 @@ static const char* apzX11_SprintfPatch[]
+  *
+  *  List of all fixes
+  */
+-#define REGEX_COUNT          151
++#define REGEX_COUNT          152
+ #define MACH_LIST_SIZE_LIMIT 279
+-#define FIX_COUNT            142
++#define FIX_COUNT            143
+ /*
+  *  Enumerate the fixes
+@@ -5705,6 +5740,7 @@ typedef enum {
+     SVR4_PROFIL_FIXIDX,
+     SYSV68_STRING_FIXIDX,
+     SYSZ_STDLIB_FOR_SUN_FIXIDX,
++    THREAD_KEYWORD_FIXIDX,
+     TINFO_CPLUSPLUS_FIXIDX,
+     ULTRIX_ATEXIT_PARAM_FIXIDX,
+     ULTRIX_ATOF_PARAM_FIXIDX,
+@@ -6314,6 +6350,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
+      SYSZ_STDLIB_FOR_SUN_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+      aSysz_Stdlib_For_SunTests,   apzSysz_Stdlib_For_SunPatch, 0 },
++  {  zThread_KeywordName,    zThread_KeywordList,
++     apzThread_KeywordMachs,
++     THREAD_KEYWORD_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
++     aThread_KeywordTests,   apzThread_KeywordPatch, 0 },
++
+   {  zTinfo_CplusplusName,    zTinfo_CplusplusList,
+      apzTinfo_CplusplusMachs,
+      TINFO_CPLUSPLUS_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+--- gcc/fixinc/inclhack.def.jj Thu May  2 12:15:17 2002
++++ gcc/fixinc/inclhack.def    Wed Jun 19 19:33:52 2002
+@@ -1,4 +1,3 @@
+-
+ /* -*- Mode: C -*-  */
+ autogen definitions fixincl;
+@@ -2886,6 +2885,24 @@ fix = {
+ };
++/*
++ * __thread is now a keyword.
++ */
++fix = {
++    hackname  = thread_keyword;
++    files     = "pthread.h";
++    files     = "bits/sigthread.h";
++    select    = " __thread([,)])";
++    c_fix     = format;
++    c_fix_arg = " __thr%1";
++
++    test_text =
++        "extern int pthread_create (pthread_t *__restrict __thread,\n"
++        "extern int pthread_kill (pthread_t __thread, int __signo);\n"
++        "extern int pthread_cancel (pthread_t __thread);";
++};
++
++
+ /*
+  *  if the #if says _cplusplus, not the double underscore __cplusplus
+  *  that it should be
+--- gcc/testsuite/g++.dg/dg.exp.jj     Thu Feb 14 13:26:12 2002
++++ gcc/testsuite/g++.dg/dg.exp        Wed Jun 19 19:33:52 2002
+@@ -28,10 +28,12 @@ if ![info exists DEFAULT_CXXFLAGS] then 
+ # Initialize `dg'.
+ dg-init
+-# Gather a list of all tests, excluding those in special/; those are handled
+-# well, specially.
+-set all [lsort [find $srcdir/$subdir *.C]]
+-set tests [prune [prune $all $srcdir/$subdir/special/*] $srcdir/$subdir/debug/*]
++# Gather a list of all tests, with the exception of those in directories
++# that are handled specially.
++set tests [lsort [find $srcdir/$subdir *.C]]
++set tests [prune $tests $srcdir/$subdir/debug/*]
++set tests [prune $tests $srcdir/$subdir/special/*]
++set tests [prune $tests $srcdir/$subdir/tls/*]
+ # Main loop.
+ dg-runtest $tests "" $DEFAULT_CXXFLAGS
+--- gcc/testsuite/g++.dg/tls/diag-1.C.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/diag-1.C  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,30 @@
++/* Valid __thread specifiers.  */
++
++__thread int g1;
++extern __thread int g2;
++static __thread int g3;
++
++void foo()
++{
++  extern __thread int l1;
++  static __thread int l2;
++}
++
++struct A {
++  static __thread int i;
++};
++
++__thread int A::i = 42;
++
++template <typename T> struct B {
++  static __thread T t;
++};
++
++template <typename T>
++__thread T B<T>::t = 42;
++
++void bar ()
++{
++  int j = B<int>::t;
++  int k = B<const int>::t;
++}
+--- gcc/testsuite/g++.dg/tls/diag-2.C.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/diag-2.C  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,25 @@
++/* Invalid __thread specifiers.  */
++
++__thread extern int g1;               /* { dg-error "`__thread' before `extern'" } */
++__thread static int g2;               /* { dg-error "`__thread' before `static'" } */
++__thread __thread int g3;     /* { dg-error "duplicate `__thread'" } */
++typedef __thread int g4;      /* { dg-error "multiple storage classes" } */
++
++void foo()
++{
++  __thread int l1;            /* { dg-error "implicitly auto and declared `__thread'" } */
++  auto __thread int l2;               /* { dg-error "multiple storage classes" } */
++  __thread extern int l3;     /* { dg-error "`__thread' before `extern'" } */
++  register __thread int l4;   /* { dg-error "multiple storage classes" } */
++}
++
++__thread void f1 ();          /* { dg-error "invalid for function" } */
++extern __thread void f2 ();   /* { dg-error "invalid for function" } */
++static __thread void f3 ();   /* { dg-error "invalid for function" } */
++__thread void f4 () { }               /* { dg-error "invalid for function" } */
++
++void bar(__thread int p1);    /* { dg-error "(invalid in parameter)|(specified for parameter)" } */
++
++struct A {
++  __thread int i;             /* { dg-error "specified for field" } */
++};
+--- gcc/testsuite/g++.dg/tls/init-1.C.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/init-1.C  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,13 @@
++/* Valid initializations.  */
++
++__thread int i = 42;
++
++static int j;
++__thread int *p = &j;
++
++/* Note that this is valid in C++ (unlike C) as a run-time initialization.  */
++int *q = &i;
++
++/* Valid because "const int k" is an integral constant expression in C++.  */
++__thread const int k = 42;
++__thread const int l = k;
+--- gcc/testsuite/g++.dg/tls/init-2.C.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/init-2.C  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,13 @@
++/* Invalid initializations.  */
++
++extern __thread int i;
++__thread int *p = &i; /* { dg-error "run-time initialization" } */
++
++extern int f();
++__thread int j = f(); /* { dg-error "run-time initialization" } */
++
++struct S
++{
++  S();
++};
++__thread S s;         /* { dg-error "run-time initialization" } */
+--- gcc/testsuite/g++.dg/tls/tls.exp.jj        Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/tls.exp   Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,44 @@
++#   Copyright (C) 2002 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Load support procs.
++load_lib g++-dg.exp
++
++# Test for thread-local data supported by the platform.  If it
++# isn't, everything will fail with the "not supported" message.
++
++set comp_output [g++_target_compile \
++              "$srcdir/$subdir/trivial.C" "trivial.S" assembly ""]
++if { [string match "*not supported*" $comp_output] } {
++  return 0
++}
++
++# If a testcase doesn't have special options, use these.
++global DEFAULT_CXXFLAGS
++if ![info exists DEFAULT_CXXFLAGS] then {
++    set DEFAULT_CXXFLAGS " -ansi -pedantic-errors -Wno-long-long"
++}
++
++# Initialize `dg'.
++dg-init
++
++# Main loop.
++dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" $DEFAULT_CXXFLAGS
++
++# All done.
++dg-finish
+--- gcc/testsuite/g++.dg/tls/trivial.C.jj      Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/g++.dg/tls/trivial.C Wed Jun 19 19:33:52 2002
+@@ -0,0 +1 @@
++__thread int i;
+--- gcc/testsuite/gcc.dg/tls/diag-1.c.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/gcc.dg/tls/diag-1.c  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,11 @@
++/* Valid __thread specifiers.  */
++
++__thread int g1;
++extern __thread int g2;
++static __thread int g3;
++
++void foo()
++{
++  extern __thread int l1;
++  static __thread int l2;
++}
+--- gcc/testsuite/gcc.dg/tls/diag-2.c.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/gcc.dg/tls/diag-2.c  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,21 @@
++/* Invalid __thread specifiers.  */
++
++__thread extern int g1;               /* { dg-error "`__thread' before `extern'" } */
++__thread static int g2;               /* { dg-error "`__thread' before `static'" } */
++__thread __thread int g3;     /* { dg-error "duplicate `__thread'" } */
++typedef __thread int g4;      /* { dg-error "multiple storage classes" } */
++
++void foo()
++{
++  __thread int l1;            /* { dg-error "implicitly auto and declared `__thread'" } */
++  auto __thread int l2;               /* { dg-error "multiple storage classes" } */
++  __thread extern int l3;     /* { dg-error "`__thread' before `extern'" } */
++  register __thread int l4;   /* { dg-error "multiple storage classes" } */
++}
++
++__thread void f1 ();          /* { dg-error "invalid storage class for function" } */
++extern __thread void f2 ();   /* { dg-error "invalid storage class for function" } */
++static __thread void f3 ();   /* { dg-error "invalid storage class for function" } */
++__thread void f4 () { }               /* { dg-error "function definition declared `__thread'" } */
++
++void bar(__thread int p1);    /* { dg-error "storage class specified for parameter" } */
+--- gcc/testsuite/gcc.dg/tls/init-1.c.jj       Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/gcc.dg/tls/init-1.c  Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,4 @@
++/* Invalid initializations.  */
++
++extern __thread int i;
++int *p = &i;  /* { dg-error "initializer element is not constant" } */
+--- gcc/testsuite/gcc.dg/tls/tls.exp.jj        Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/gcc.dg/tls/tls.exp   Wed Jun 19 19:33:52 2002
+@@ -0,0 +1,45 @@
++#   Copyright (C) 2002 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Load support procs.
++load_lib gcc-dg.exp
++
++# Test for thread-local data supported by the platform.  If it
++# isn't, everything will fail with the "not supported" message.
++
++set comp_output [gcc_target_compile \
++              "$srcdir/$subdir/trivial.c" "trivial.S" assembly ""]
++if { [string match "*not supported*" $comp_output] } {
++  return 0
++}
++
++# If a testcase doesn't have special options, use these.
++global DEFAULT_CFLAGS
++if ![info exists DEFAULT_CFLAGS] then {
++    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
++}
++
++# Initialize `dg'.
++dg-init
++
++# Main loop.
++dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
++        "" $DEFAULT_CFLAGS
++
++# All done.
++dg-finish
+--- gcc/testsuite/gcc.dg/tls/trivial.c.jj      Wed Jun 19 19:33:52 2002
++++ gcc/testsuite/gcc.dg/tls/trivial.c Wed Jun 19 19:33:52 2002
+@@ -0,0 +1 @@
++__thread int i;
+--- gcc/c-common.h.jj  Wed Apr 17 15:34:36 2002
++++ gcc/c-common.h     Wed Jun 19 19:33:52 2002
+@@ -58,7 +58,7 @@ enum rid
+   RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
+   /* C extensions */
+-  RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX,
++  RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX, RID_THREAD,
+   /* C++ */
+   RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
+--- gcc/c-decl.c.jj    Wed Jun 19 19:33:50 2002
++++ gcc/c-decl.c       Wed Jun 19 19:33:52 2002
+@@ -3571,9 +3571,19 @@ start_decl (declarator, declspecs, initi
+   /* ANSI specifies that a tentative definition which is not merged with
+      a non-tentative definition behaves exactly like a definition with an
+      initializer equal to zero.  (Section 3.7.2)
+-     -fno-common gives strict ANSI behavior.  Usually you don't want it.
+-     This matters only for variables with external linkage.  */
+-  if (! flag_no_common || ! TREE_PUBLIC (decl))
++
++     -fno-common gives strict ANSI behavior, though this tends to break
++     a large body of code that grew up without this rule.
++
++     Thread-local variables are never common, since there's no entrenched
++     body of code to break, and it allows more efficient variable references
++     in the presense of dynamic linking.  */
++
++  if (TREE_CODE (decl) == VAR_DECL
++      && !initialized
++      && TREE_PUBLIC (decl)
++      && !DECL_THREAD_LOCAL (decl)
++      && !flag_no_common)
+     DECL_COMMON (decl) = 1;
+   /* Set attributes here so if duplicate decl, will have proper attributes.  */
+@@ -4172,7 +4182,7 @@ grokdeclarator (declarator, declspecs, d
+         enum rid i = C_RID_CODE (id);
+         if ((int) i <= (int) RID_LAST_MODIFIER)
+           {
+-            if (i == RID_LONG && (specbits & (1 << (int) i)))
++            if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
+               {
+                 if (longlong)
+                   error ("`long long long' is too long for GCC");
+@@ -4186,6 +4196,19 @@ grokdeclarator (declarator, declspecs, d
+               }
+             else if (specbits & (1 << (int) i))
+               pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
++
++            /* Diagnose "__thread extern".  Recall that this list
++               is in the reverse order seen in the text.  */
++            if (i == RID_THREAD
++                && (specbits & (1 << (int) RID_EXTERN
++                                | 1 << (int) RID_STATIC)))
++              {
++                if (specbits & 1 << (int) RID_EXTERN)
++                  error ("`__thread' before `extern'");
++                else
++                  error ("`__thread' before `static'");
++              }
++
+             specbits |= 1 << (int) i;
+             goto found;
+           }
+@@ -4438,6 +4461,12 @@ grokdeclarator (declarator, declspecs, d
+     if (specbits & 1 << (int) RID_REGISTER) nclasses++;
+     if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
++    /* "static __thread" and "extern __thread" are allowed.  */
++    if ((specbits & (1 << (int) RID_THREAD
++                   | 1 << (int) RID_STATIC
++                   | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
++      nclasses++;
++
+     /* Warn about storage classes that are invalid for certain
+        kinds of declarations (parameters, typenames, etc.).  */
+@@ -4447,7 +4476,8 @@ grokdeclarator (declarator, declspecs, d
+            && (specbits
+                & ((1 << (int) RID_REGISTER)
+                   | (1 << (int) RID_AUTO)
+-                  | (1 << (int) RID_TYPEDEF))))
++                  | (1 << (int) RID_TYPEDEF)
++                  | (1 << (int) RID_THREAD))))
+       {
+       if (specbits & 1 << (int) RID_AUTO
+           && (pedantic || current_binding_level == global_binding_level))
+@@ -4456,8 +4486,10 @@ grokdeclarator (declarator, declspecs, d
+         error ("function definition declared `register'");
+       if (specbits & 1 << (int) RID_TYPEDEF)
+         error ("function definition declared `typedef'");
++      if (specbits & 1 << (int) RID_THREAD)
++        error ("function definition declared `__thread'");
+       specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+-                    | (1 << (int) RID_AUTO));
++                    | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
+       }
+     else if (decl_context != NORMAL && nclasses > 0)
+       {
+@@ -4480,7 +4512,7 @@ grokdeclarator (declarator, declspecs, d
+             }
+           specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+                         | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
+-                        | (1 << (int) RID_EXTERN));
++                        | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
+         }
+       }
+     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
+@@ -4491,12 +4523,25 @@ grokdeclarator (declarator, declspecs, d
+       else
+         error ("`%s' has both `extern' and initializer", name);
+       }
+-    else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
+-           && current_binding_level != global_binding_level)
+-      error ("nested function `%s' declared `extern'", name);
+-    else if (current_binding_level == global_binding_level
+-           && specbits & (1 << (int) RID_AUTO))
+-      error ("top-level declaration of `%s' specifies `auto'", name);
++    else if (current_binding_level == global_binding_level)
++      {
++      if (specbits & 1 << (int) RID_AUTO)
++        error ("top-level declaration of `%s' specifies `auto'", name);
++      }
++    else
++      {
++      if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
++        error ("nested function `%s' declared `extern'", name);
++      else if ((specbits & (1 << (int) RID_THREAD
++                             | 1 << (int) RID_EXTERN
++                             | 1 << (int) RID_STATIC))
++               == (1 << (int) RID_THREAD))
++        {
++          error ("function-scope `%s' implicitly auto and declared `__thread'",
++                 name);
++          specbits &= ~(1 << (int) RID_THREAD);
++        }
++      }
+   }
+   /* Now figure out the structure of the declarator proper.
+@@ -5095,6 +5140,8 @@ grokdeclarator (declarator, declspecs, d
+         pedwarn ("invalid storage class for function `%s'", name);
+       if (specbits & (1 << (int) RID_REGISTER))
+         error ("invalid storage class for function `%s'", name);
++      if (specbits & (1 << (int) RID_THREAD))
++        error ("invalid storage class for function `%s'", name);
+       /* Function declaration not at top level.
+          Storage classes other than `extern' are not allowed
+          and `extern' makes no difference.  */
+@@ -5187,22 +5234,32 @@ grokdeclarator (declarator, declspecs, d
+         pedwarn_with_decl (decl, "variable `%s' declared `inline'");
+       DECL_EXTERNAL (decl) = extern_ref;
++
+       /* At top level, the presence of a `static' or `register' storage
+          class specifier, or the absence of all storage class specifiers
+          makes this declaration a definition (perhaps tentative).  Also,
+          the absence of both `static' and `register' makes it public.  */
+       if (current_binding_level == global_binding_level)
+         {
+-          TREE_PUBLIC (decl)
+-            = !(specbits
+-                & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
+-          TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
++          TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
++                                             | (1 << (int) RID_REGISTER)));
++          TREE_STATIC (decl) = !extern_ref;
+         }
+       /* Not at top level, only `static' makes a static definition.  */
+       else
+         {
+           TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
+-          TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
++          TREE_PUBLIC (decl) = extern_ref;
++        }
++
++      if (specbits & 1 << (int) RID_THREAD)
++        {
++          if (targetm.have_tls)
++            DECL_THREAD_LOCAL (decl) = 1;
++          else
++            /* A mere warning is sure to result in improper semantics
++               at runtime.  Don't bother to allow this to compile.  */
++            error ("thread-local storage not supported for this target");
+         }
+       }
+--- gcc/c-parse.in.jj  Wed Apr 17 15:34:46 2002
++++ gcc/c-parse.in     Wed Jun 19 19:33:52 2002
+@@ -3329,6 +3329,7 @@ static const struct resword reswords[] =
+   { "__restrict__",   RID_RESTRICT,   0 },
+   { "__signed",               RID_SIGNED,     0 },
+   { "__signed__",     RID_SIGNED,     0 },
++  { "__thread",               RID_THREAD,     0 },
+   { "__typeof",               RID_TYPEOF,     0 },
+   { "__typeof__",     RID_TYPEOF,     0 },
+   { "__unbounded",    RID_UNBOUNDED,  0 },
+@@ -3424,6 +3425,7 @@ static const short rid_to_yy[RID_MAX] =
+   /* RID_BOUNDED */   TYPE_QUAL,
+   /* RID_UNBOUNDED */ TYPE_QUAL,
+   /* RID_COMPLEX */   TYPESPEC,
++  /* RID_THREAD */    SCSPEC,
+   /* C++ */
+   /* RID_FRIEND */    0,
+--- gcc/config.in.jj   Sat Jun  8 00:38:25 2002
++++ gcc/config.in      Wed Jun 19 19:33:52 2002
+@@ -523,6 +523,9 @@
+ /* Define if your assembler supports marking sections with SHF_MERGE flag. */
+ #undef HAVE_GAS_SHF_MERGE
++/* Define if your assembler supports thread-local storage. */
++#undef HAVE_AS_TLS
++
+ /* Define if your assembler supports explicit relocations. */
+ #undef HAVE_AS_EXPLICIT_RELOCS
+--- gcc/flags.h.jj     Sat Mar 23 12:02:51 2002
++++ gcc/flags.h        Wed Jun 19 19:33:52 2002
+@@ -450,11 +450,22 @@ extern int flag_pretend_float;
+ extern int flag_pedantic_errors;
+-/* Nonzero means generate position-independent code.
+-   This is not fully implemented yet.  */
++/* Nonzero means generate position-independent code.  1 vs 2 for a 
++   target-dependent "small" or "large" mode.  */
+ extern int flag_pic;
++/* Set to the default thread-local storage (tls) model to use.  */
++
++enum tls_model {
++  TLS_MODEL_GLOBAL_DYNAMIC = 1,
++  TLS_MODEL_LOCAL_DYNAMIC,
++  TLS_MODEL_INITIAL_EXEC,
++  TLS_MODEL_LOCAL_EXEC
++};
++
++extern enum tls_model flag_tls_default;
++
+ /* Nonzero means generate extra code for exception handling and enable
+    exception handling.  */
+--- gcc/configure.in.jj        Sat Jun  8 00:38:27 2002
++++ gcc/configure.in   Wed Jun 19 19:33:52 2002
+@@ -1715,6 +1715,72 @@ if test x"$gcc_cv_as_shf_merge" = xyes; 
+ fi
+ AC_MSG_RESULT($gcc_cv_as_shf_merge)
++AC_MSG_CHECKING(assembler thread-local storage support)
++gcc_cv_as_tls=no
++conftest_s=
++tls_first_major=
++tls_first_minor=
++case "$target" in
++changequote(,)dnl
++  i[34567]86-*-*)
++changequote([,])dnl
++    conftest_s='
++      .section ".tdata","awT",@progbits
++foo:  .long   25
++      .text
++      movl    %gs:0, %eax
++      leal    foo@TLSGD(,%ebx,1), %eax
++      leal    foo@TLSLDM(%ebx), %eax
++      leal    foo@DTPOFF(%eax), %edx
++      movl    foo@GOTTPOFF(%ebx), %eax
++      subl    foo@GOTTPOFF(%ebx), %eax
++      movl    $foo@TPOFF, %eax
++      subl    $foo@TPOFF, %eax
++      leal    foo@NTPOFF(%ecx), %eax'
++      tls_first_major=2
++      tls_first_minor=13
++      ;;
++  ia64-*-*)
++    conftest_s='
++      .section ".tdata","awT",@progbits
++foo:  data8   25
++      .text
++      addl    r16 = @ltoff(@dtpmod(foo#)), gp
++      addl    r17 = @ltoff(@dtprel(foo#)), gp
++      addl    r18 = @ltoff(@tprel(foo#)), gp
++      addl    r19 = @dtprel(foo#), gp
++      adds    r21 = @dtprel(foo#), r13
++      movl    r23 = @dtprel(foo#)
++      addl    r20 = @tprel(foo#), gp
++      adds    r22 = @tprel(foo#), r13
++      movl    r24 = @tprel(foo#)'
++      tls_first_major=2
++      tls_first_minor=13
++      ;;
++esac
++if test -z "$tls_first_major"; then
++  :
++elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
++then
++  if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
++        -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
++        -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
++    gcc_cv_as_tls=yes
++  fi
++elif test x$gcc_cv_as != x; then
++  echo "$conftest_s" > conftest.s
++  if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
++  then
++    gcc_cv_as_tls=yes
++  fi
++  rm -f conftest.s conftest.o
++fi
++if test "$gcc_cv_as_tls" = yes; then
++  AC_DEFINE(HAVE_AS_TLS, 1,
++          [Define if your assembler supports thread-local storage.])
++fi
++AC_MSG_RESULT($gcc_cv_as_tls)
++
+ case "$target" in
+   # All TARGET_ABI_OSF targets.
+   alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
+--- gcc/configure.jj   Sat Jun  8 00:38:27 2002
++++ gcc/configure      Wed Jun 19 22:28:09 2002
+@@ -7391,6 +7391,73 @@ EOF
+ fi
+ echo "$ac_t""$gcc_cv_as_shf_merge" 1>&6
++echo $ac_n "checking assembler thread-local storage support""... $ac_c" 1>&6
++echo "configure:7399: checking assembler thread-local storage support" >&5
++gcc_cv_as_tls=no
++conftest_s=
++tls_first_major=
++tls_first_minor=
++case "$target" in
++  i[34567]86-*-*)
++    conftest_s='
++      .section ".tdata","awT",@progbits
++foo:  .long   25
++      .text
++      movl    %gs:0, %eax
++      leal    foo@TLSGD(,%ebx,1), %eax
++      leal    foo@TLSLDM(%ebx), %eax
++      leal    foo@DTPOFF(%eax), %edx
++      movl    foo@GOTTPOFF(%ebx), %eax
++      subl    foo@GOTTPOFF(%ebx), %eax
++      movl    $foo@TPOFF, %eax
++      subl    $foo@TPOFF, %eax
++      leal    foo@NTPOFF(%ecx), %eax'
++      tls_first_major=2
++      tls_first_minor=13
++      ;;
++  ia64-*-*)
++    conftest_s='
++      .section ".tdata","awT",@progbits
++foo:  data8   25
++      .text
++      addl    r16 = @ltoff(@dtpmod(foo#)), gp
++      addl    r17 = @ltoff(@dtprel(foo#)), gp
++      addl    r18 = @ltoff(@tprel(foo#)), gp
++      addl    r19 = @dtprel(foo#), gp
++      adds    r21 = @dtprel(foo#), r13
++      movl    r23 = @dtprel(foo#)
++      addl    r20 = @tprel(foo#), gp
++      adds    r22 = @tprel(foo#), r13
++      movl    r24 = @tprel(foo#)'
++      tls_first_major=2
++      tls_first_minor=13
++      ;;
++esac
++if test -z "$tls_first_major"; then
++  :
++elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
++then
++  if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
++        -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
++        -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
++    gcc_cv_as_tls=yes
++  fi
++elif test x$gcc_cv_as != x; then
++  echo "$conftest_s" > conftest.s
++  if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
++  then
++    gcc_cv_as_tls=yes
++  fi
++  rm -f conftest.s conftest.o
++fi
++if test "$gcc_cv_as_tls" = yes; then
++  cat >> confdefs.h <<\EOF
++#define HAVE_AS_TLS 1
++EOF
++
++fi
++echo "$ac_t""$gcc_cv_as_tls" 1>&6
++
+ case "$target" in
+   # All TARGET_ABI_OSF targets.
+   alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
+--- gcc/output.h.jj    Wed Jun 19 19:33:50 2002
++++ gcc/output.h       Wed Jun 19 19:33:52 2002
+@@ -514,7 +514,8 @@ extern void no_asm_to_stream PARAMS ((FI
+ #define SECTION_STRINGS  0x10000      /* contains zero terminated strings without
+                                          embedded zeros */
+ #define SECTION_OVERRIDE 0x20000      /* allow override of default flags */
+-#define SECTION_MACH_DEP 0x40000      /* subsequent bits reserved for target */
++#define SECTION_TLS    0x40000        /* contains thread-local storage */
++#define SECTION_MACH_DEP 0x80000      /* subsequent bits reserved for target */
+ extern unsigned int get_named_section_flags PARAMS ((const char *));
+ extern bool set_named_section_flags   PARAMS ((const char *, unsigned int));
+--- gcc/print-tree.c.jj        Mon Mar 18 23:19:57 2002
++++ gcc/print-tree.c   Wed Jun 19 19:33:52 2002
+@@ -363,6 +363,8 @@ print_node (file, prefix, node, indent)
+       if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
+       fputs (" in-text-section", file);
++      if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))
++      fputs (" thread-local", file);
+       if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
+       fputs (" transparent-union", file);
+--- gcc/target-def.h.jj        Tue Feb 12 16:19:14 2002
++++ gcc/target-def.h   Wed Jun 19 19:33:52 2002
+@@ -98,6 +98,10 @@ Foundation, 59 Temple Place - Suite 330,
+ #define TARGET_HAVE_NAMED_SECTIONS false
+ #endif
++#ifndef TARGET_HAVE_TLS
++#define TARGET_HAVE_TLS false
++#endif
++
+ #ifndef TARGET_ASM_EXCEPTION_SECTION
+ #define TARGET_ASM_EXCEPTION_SECTION default_exception_section
+ #endif
+@@ -194,9 +198,10 @@ Foundation, 59 Temple Place - Suite 330,
+   TARGET_INIT_BUILTINS,                               \
+   TARGET_EXPAND_BUILTIN,                      \
+   TARGET_SECTION_TYPE_FLAGS,                  \
++  TARGET_CANNOT_MODIFY_JUMPS_P,                       \
+   TARGET_HAVE_NAMED_SECTIONS,                 \
+   TARGET_HAVE_CTORS_DTORS,                    \
+-  TARGET_CANNOT_MODIFY_JUMPS_P                        \
++  TARGET_HAVE_TLS                             \
+ }
+ #include "hooks.h"
+--- gcc/target.h.jj    Tue Feb 12 16:19:14 2002
++++ gcc/target.h       Wed Jun 19 19:33:52 2002
+@@ -178,6 +178,10 @@ struct gcc_target
+   /* ??? Should be merged with SELECT_SECTION and UNIQUE_SECTION.  */
+   unsigned int (* section_type_flags) PARAMS ((tree, const char *, int));
++  /* True if new jumps cannot be created, to replace existing ones or
++     not, at the current point in the compilation.  */
++  bool (* cannot_modify_jumps_p) PARAMS ((void));
++
+   /* True if arbitrary sections are supported.  */
+   bool have_named_sections;
+@@ -185,9 +189,8 @@ struct gcc_target
+      false if we're using collect2 for the job.  */
+   bool have_ctors_dtors;
+-  /* True if new jumps cannot be created, to replace existing ones or
+-     not, at the current point in the compilation.  */
+-  bool (* cannot_modify_jumps_p) PARAMS ((void));
++  /* True if thread-local storage is supported.  */
++  bool have_tls;
+ };
+ extern struct gcc_target targetm;
+--- gcc/toplev.c.jj    Thu May 30 11:08:44 2002
++++ gcc/toplev.c       Wed Jun 19 19:33:52 2002
+@@ -682,12 +682,15 @@ int flag_shared_data;
+ int flag_delayed_branch;
+ /* Nonzero if we are compiling pure (sharable) code.
+-   Value is 1 if we are doing reasonable (i.e. simple
+-   offset into offset table) pic.  Value is 2 if we can
+-   only perform register offsets.  */
++   Value is 1 if we are doing "small" pic; value is 2 if we're doing
++   "large" pic.  */
+ int flag_pic;
++/* Set to the default thread-local storage (tls) model to use.  */
++
++enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
++
+ /* Nonzero means generate extra code for exception handling and enable
+    exception handling.  */
+@@ -3609,6 +3612,7 @@ display_help ()
+   printf (_("  -finline-limit=<number> Limits the size of inlined functions to <number>\n"));
+   printf (_("  -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line.  0 suppresses line-wrapping\n"));
+   printf (_("  -fdiagnostics-show-location=[once | every-line] Indicates how often source location information should be emitted, as prefix, at the beginning of diagnostics when line-wrapping\n"));
++  printf (_("  -ftls-model=[global-dynamic | local-dynamic | initial-exec | local-exec] Indicates the default thread-local storage code generation model\n"));
+   for (i = ARRAY_SIZE (f_options); i--;)
+     {
+@@ -3887,6 +3891,19 @@ decode_f_option (arg)
+                                MAX_INLINE_INSNS);
+       set_param_value ("max-inline-insns", val);
+     }
++  else if ((option_value = skip_leading_substring (arg, "tls-model=")))
++    {
++      if (strcmp (option_value, "global-dynamic") == 0)
++      flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
++      else if (strcmp (option_value, "local-dynamic") == 0)
++      flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
++      else if (strcmp (option_value, "initial-exec") == 0)
++      flag_tls_default = TLS_MODEL_INITIAL_EXEC;
++      else if (strcmp (option_value, "local-exec") == 0)
++      flag_tls_default = TLS_MODEL_LOCAL_EXEC;
++      else
++      warning ("`%s': unknown tls-model option", arg - 2);
++    }
+ #ifdef INSN_SCHEDULING
+   else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
+     fix_sched_param ("verbose", option_value);
+--- gcc/tree.c.jj      Sun Apr 28 23:20:20 2002
++++ gcc/tree.c Wed Jun 19 19:33:52 2002
+@@ -1510,12 +1510,13 @@ staticp (arg)
+     case FUNCTION_DECL:
+       /* Nested functions aren't static, since taking their address
+        involves a trampoline.  */
+-      return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
+-      && ! DECL_NON_ADDR_CONST_P (arg);
++      return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
++            && ! DECL_NON_ADDR_CONST_P (arg));
+     case VAR_DECL:
+-      return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+-      && ! DECL_NON_ADDR_CONST_P (arg);
++      return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
++            && ! DECL_THREAD_LOCAL (arg)
++            && ! DECL_NON_ADDR_CONST_P (arg));
+     case CONSTRUCTOR:
+       return TREE_STATIC (arg);
+--- gcc/tree.h.jj      Wed Jun 19 19:33:50 2002
++++ gcc/tree.h Wed Jun 19 19:33:52 2002
+@@ -1614,6 +1614,10 @@ struct tree_type
+ /* In a FUNCTION_DECL, nonzero if the function cannot be inlined.  */
+ #define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
++/* In a VAR_DECL, nonzero if the data should be allocated from 
++   thread-local storage.  */
++#define DECL_THREAD_LOCAL(NODE) (VAR_DECL_CHECK (NODE)->decl.thread_local_flag)
++
+ /* In a FUNCTION_DECL, the saved representation of the body of the
+    entire function.  Usually a COMPOUND_STMT, but in C++ this may also
+    be a RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK.  */
+@@ -1792,7 +1796,8 @@ struct tree_decl
+   unsigned non_addressable : 1;
+   unsigned user_align : 1;
+   unsigned uninlinable : 1;
+-  /* Three unused bits.  */
++  unsigned thread_local_flag : 1;
++  /* Two unused bits.  */
+   unsigned lang_flag_0 : 1;
+   unsigned lang_flag_1 : 1;
+--- gcc/varasm.c.jj    Wed Jun 19 19:33:51 2002
++++ gcc/varasm.c       Wed Jun 19 19:33:52 2002
+@@ -1599,14 +1599,24 @@ assemble_variable (decl, top_level, at_e
+   /* Handle uninitialized definitions.  */
+-  if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
+-      /* If the target can't output uninitialized but not common global data
+-       in .bss, then we have to use .data.  */
+-#if ! defined ASM_EMIT_BSS
+-      && DECL_COMMON (decl)
++  /* If the decl has been given an explicit section name, then it
++     isn't common, and shouldn't be handled as such.  */
++  if (DECL_SECTION_NAME (decl) || dont_output_data)
++    ;
++  /* We don't implement common thread-local data at present.  */
++  else if (DECL_THREAD_LOCAL (decl))
++    {
++      if (DECL_COMMON (decl))
++      sorry ("thread-local COMMON data not implemented");
++    }
++#ifndef ASM_EMIT_BSS
++  /* If the target can't output uninitialized but not common global data
++     in .bss, then we have to use .data.  */
++  else if (!DECL_COMMON (decl))
++    ;
+ #endif
+-      && DECL_SECTION_NAME (decl) == NULL_TREE
+-      && ! dont_output_data)
++  else if (DECL_INITIAL (decl) == 0
++         || DECL_INITIAL (decl) == error_mark_node)
+     {
+       unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+       unsigned HOST_WIDE_INT rounded = size;
+@@ -5324,14 +5334,22 @@ default_section_type_flags (decl, name, 
+   if (decl && DECL_ONE_ONLY (decl))
+     flags |= SECTION_LINKONCE;
++  if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
++    flags |= SECTION_TLS | SECTION_WRITE;
++
+   if (strcmp (name, ".bss") == 0
+       || strncmp (name, ".bss.", 5) == 0
+       || strncmp (name, ".gnu.linkonce.b.", 16) == 0
+       || strcmp (name, ".sbss") == 0
+       || strncmp (name, ".sbss.", 6) == 0
+-      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
++      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
++      || strcmp (name, ".tbss") == 0)
+     flags |= SECTION_BSS;
++  if (strcmp (name, ".tdata") == 0
++      || strcmp (name, ".tbss") == 0)
++    flags |= SECTION_TLS;
++
+   return flags;
+ }
+@@ -5374,6 +5392,8 @@ default_elf_asm_named_section (name, fla
+     *f++ = 'M';
+   if (flags & SECTION_STRINGS)
+     *f++ = 'S';
++  if (flags & SECTION_TLS)
++    *f++ = 'T';
+   *f = '\0';
+   if (flags & SECTION_BSS)
diff --git a/gcc32-tls2.patch b/gcc32-tls2.patch
new file mode 100644 (file)
index 0000000..65eea64
--- /dev/null
@@ -0,0 +1,54 @@
+2002-07-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * expr.c (expand_expr) [ADDR_EXPR]: Force addresses of thread-local
+       variables into pseudo.
+
+       * gcc.dg/tls/opt-1.c: New test.
+
+--- gcc/testsuite/gcc.dg/tls/opt-1.c.jj        2002-07-30 13:57:33.000000000 +0200
++++ gcc/testsuite/gcc.dg/tls/opt-1.c   2002-07-30 13:56:40.000000000 +0200
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fPIC" } */
++/* { dg-options "-O2 -fPIC -mcpu=i686" { target i?86-*-* } } */
++
++extern __thread int thr;
++
++static int x;
++
++static void
++bar (void)
++{
++  x = 1;
++}
++
++static void
++#ifdef __i386__
++__attribute__ ((regparm (3)))
++#endif
++foo (const char *x, void *y, int *z)
++{
++  bar ();
++}
++
++void
++test (const char *x, void *y)
++{
++  foo (x, y, &thr);
++}
+--- gcc/expr.c.jj      2002-07-30 12:49:43.000000000 +0200
++++ gcc/expr.c 2002-07-30 20:18:36.000000000 +0200
+@@ -8833,7 +8833,12 @@ expand_expr (exp, target, tmode, modifie
+         op0 = force_operand (XEXP (op0, 0), target);
+       }
+-      if (flag_force_addr
++      if ((flag_force_addr
++         || (TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
++             && DECL_THREAD_LOCAL (TREE_OPERAND (exp, 0))
++             && ! memory_address_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
++                                                                        0))),
++                                    op0)))
+         && GET_CODE (op0) != REG
+         && modifier != EXPAND_CONST_ADDRESS
+         && modifier != EXPAND_INITIALIZER
diff --git a/gcc32-tls3.patch b/gcc32-tls3.patch
new file mode 100644 (file)
index 0000000..aec74c9
--- /dev/null
@@ -0,0 +1,48 @@
+2002-08-06  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-decl.c (duplicate_decls): Error out for incompatible TLS
+       declarations.
+
+       * testsuite/gcc.dg/tls/diag-3.c: New.
+
+*** gcc/c-decl.c       1 Aug 2002 06:20:30 -0000       1.344
+--- gcc/c-decl.c       7 Aug 2002 01:01:55 -0000
+*************** duplicate_decls (newdecl, olddecl, diffe
+*** 1400,1405 ****
+--- 1400,1419 ----
+       }
+        error_with_decl (olddecl, "previous declaration of `%s'");
+      }
++   /* TLS cannot follow non-TLS declaration.  */
++   else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
++         && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
++     {
++       error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
++       error_with_decl (olddecl, "previous declaration of `%s'");
++     }
++   /* non-TLS declaration cannot follow TLS declaration.  */
++   else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
++         && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
++     {
++       error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
++       error_with_decl (olddecl, "previous declaration of `%s'");
++     }
+    else
+      {
+        errmsg = redeclaration_error_message (newdecl, olddecl);
+*** gcc/testsuite/gcc.dg/tls/diag-3.c  1 Jan 1970 00:00:00 -0000
+--- gcc/testsuite/gcc.dg/tls/diag-3.c  7 Aug 2002 01:01:55 -0000
+***************
+*** 0 ****
+--- 1,10 ----
++ /* Report invalid extern and __thread combinations.  */
++ 
++ extern int j;                /* { dg-error "previous declaration" } */
++ __thread int j;              /* { dg-error "thread-local declaration" } */
++ 
++ extern __thread int i;       /* { dg-error "previous declaration" } */
++ int i;                       /* { dg-error "non thread-local" } */
++ 
++ extern __thread int k;       /* This is fine.  */
++ __thread int k;
+
diff --git a/gcc32-tls4.patch b/gcc32-tls4.patch
new file mode 100644 (file)
index 0000000..7595e6b
--- /dev/null
@@ -0,0 +1,74 @@
+2002-05-22  Richard Henderson  <rth@redhat.com>
+
+       * varasm.c (default_section_type_flags): Handle tls data and
+       default sections.
+
+       * gcc.dg/tls/section-1.c: New test.
+
+2002-03-15  Jason Merrill  <jason@redhat.com>
+
+       * varasm.c (assemble_variable): Call resolve_unique_section before
+       checking DECL_SECTION_NAME.
+
+--- gcc/testsuite/gcc.dg/tls/section-1.c.jj    2002-08-08 16:11:55.000000000 +0200
++++ gcc/testsuite/gcc.dg/tls/section-1.c       2002-08-08 16:19:08.000000000 +0200
+@@ -0,0 +1,11 @@
++/* Verify that we get errors for trying to put TLS data in 
++   sections which can't work.  */
++
++#define A(X)  __attribute__((section(X)))
++
++__thread int i A("foo");              /* Ok */
++
++__thread int j A(".data");  /* { dg-error "causes a section type conflict" "conflict with .data section" { xfail *-*-* } } */
++
++int k A("bar");
++__thread int l A("bar");  /* { dg-error "causes a section type conflict" "conflict with user-defined section" } */
+--- gcc/varasm.c.jj    2002-08-01 20:58:53.000000000 +0200
++++ gcc/varasm.c       2002-08-08 16:10:15.000000000 +0200
+@@ -1597,6 +1597,13 @@ assemble_variable (decl, top_level, at_e
+   if (TREE_PUBLIC (decl))
+     maybe_assemble_visibility (decl);
++  /* Output any data that we will need to use the address of.  */
++  if (DECL_INITIAL (decl) == error_mark_node)
++    reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
++  else if (DECL_INITIAL (decl))
++    reloc = output_addressed_constants (DECL_INITIAL (decl));
++  resolve_unique_section (decl, reloc, flag_data_sections);
++
+   /* Handle uninitialized definitions.  */
+   /* If the decl has been given an explicit section name, then it
+@@ -1652,14 +1659,7 @@ assemble_variable (decl, top_level, at_e
+   if (TREE_PUBLIC (decl) && DECL_NAME (decl))
+     globalize_decl (decl);
+-  /* Output any data that we will need to use the address of.  */
+-  if (DECL_INITIAL (decl) == error_mark_node)
+-    reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
+-  else if (DECL_INITIAL (decl))
+-    reloc = output_addressed_constants (DECL_INITIAL (decl));
+-
+   /* Switch to the appropriate section.  */
+-  resolve_unique_section (decl, reloc, flag_data_sections);
+   variable_section (decl, reloc);
+   /* dbxout.c needs to know this.  */
+@@ -5343,11 +5343,14 @@ default_section_type_flags (decl, name, 
+       || strcmp (name, ".sbss") == 0
+       || strncmp (name, ".sbss.", 6) == 0
+       || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
+-      || strcmp (name, ".tbss") == 0)
++      || strcmp (name, ".tbss") == 0
++      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
+     flags |= SECTION_BSS;
+   if (strcmp (name, ".tdata") == 0
+-      || strcmp (name, ".tbss") == 0)
++      || strcmp (name, ".tbss") == 0
++      || strncmp (name, ".gnu.linkonce.td.", 17) == 0
++      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
+     flags |= SECTION_TLS;
+   return flags;
diff --git a/gcc32-tls5.patch b/gcc32-tls5.patch
new file mode 100644 (file)
index 0000000..c3b5ab7
--- /dev/null
@@ -0,0 +1,149 @@
+2002-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/i386/i386.c (legitimate_constant_p): UNSPEC_TP is not
+       legitimate constant.
+       (legitimate_pic_operand_p): Neither pic operand.
+       (legitimate_address_p): But legitimate address.
+       (get_thread_pointer): Generate MEM/u instead of CONST around
+       UNSPEC_TP.
+       (print_operand): Remove printing of UNSPEC_TP.
+       (print_operand_address): And print it here.
+
+       * gcc.dg/tls/opt-2.c: New test.
+
+--- gcc/config/i386/i386.c.jj  2002-08-07 22:18:39.000000000 +0200
++++ gcc/config/i386/i386.c     2002-08-08 18:18:18.000000000 +0200
+@@ -4850,8 +4850,6 @@ legitimate_constant_p (x)
+         {
+         case UNSPEC_TPOFF:
+           return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+-        case UNSPEC_TP:
+-          return true;
+         default:
+           return false;
+         }
+@@ -4914,8 +4912,6 @@ legitimate_pic_operand_p (x)
+         {
+         case UNSPEC_TPOFF:
+           return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+-        case UNSPEC_TP:
+-          return true;
+         default:
+           return false;
+         }
+@@ -5054,6 +5050,13 @@ legitimate_address_p (mode, addr, strict
+       debug_rtx (addr);
+     }
++  if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
++    {
++      if (TARGET_DEBUG_ADDR)
++      fprintf (stderr, "Success.\n");
++      return TRUE;
++    }
++
+   if (ix86_decompose_address (addr, &parts) <= 0)
+     {
+       reason = "decomposition failed";
+@@ -5521,7 +5524,9 @@ get_thread_pointer ()
+   rtx tp;
+   tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
+-  tp = gen_rtx_CONST (Pmode, tp);
++  tp = gen_rtx_MEM (Pmode, tp);
++  RTX_UNCHANGING_P (tp) = 1;
++  set_mem_alias_set (tp, ix86_GOT_alias_set ());
+   tp = force_reg (Pmode, tp);
+   return tp;
+@@ -6611,17 +6615,6 @@ print_operand (file, x, code)
+       fprintf (file, "%s", dstr);
+     }
+-  else if (GET_CODE (x) == CONST
+-         && GET_CODE (XEXP (x, 0)) == UNSPEC
+-         && XINT (XEXP (x, 0), 1) == UNSPEC_TP)
+-    {
+-      if (ASSEMBLER_DIALECT == ASM_INTEL)
+-      fputs ("DWORD PTR ", file);
+-      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
+-      putc ('%', file);
+-      fputs ("gs:0", file);
+-    }
+-
+   else
+     {
+       if (code != 'P')
+@@ -6660,6 +6653,16 @@ print_operand_address (file, addr)
+   rtx base, index, disp;
+   int scale;
++  if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
++    {
++      if (ASSEMBLER_DIALECT == ASM_INTEL)
++      fputs ("DWORD PTR ", file);
++      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
++      putc ('%', file);
++      fputs ("gs:0", file);
++      return;
++    }
++
+   if (! ix86_decompose_address (addr, &parts))
+     abort ();
+--- gcc/testsuite/gcc.dg/tls/opt-2.c.jj        2002-08-08 18:36:32.000000000 +0200
++++ gcc/testsuite/gcc.dg/tls/opt-2.c   2002-08-08 18:34:44.000000000 +0200
+@@ -0,0 +1,53 @@
++/* This testcase generated invalid assembly on IA-32,
++   since %gs:0 memory load was not exposed to the compiler
++   as memory load and mem to mem moves are not possible
++   on IA-32.  */
++/* { dg-do link } */
++/* { dg-options "-O2 -ftls-model=initial-exec" } */
++/* { dg-options "-O2 -ftls-model=initial-exec -march=i686" { target i?86-*-* } } */
++
++__thread int thr;
++
++struct A
++{
++  unsigned int a, b, c, d, e;
++};
++
++int bar (int x, unsigned long y, void *z)
++{
++  return 0;
++}
++
++int
++foo (int x, int y, const struct A *z)
++{
++  struct A b;
++  int d;
++
++  b = *z;
++  d = bar (x, y, &b);
++  if (d == 0 && y == 0x5402)
++    {
++      int e = thr;
++      d = bar (x, 0x5401, &b);
++      if (d)
++      {
++        thr = e;
++        d = 0;
++      }
++      else if ((z->c & 0600) != (b.c & 0600)
++             || ((z->c & 060) && ((z->c & 060) != (b.c & 060))))
++      {
++        thr = 22;
++        d = -1;
++      }
++    }
++
++  return d;
++}
++
++int main (void)
++{
++  foo (1, 2, 0);
++  return 0;
++}
diff --git a/gcc32-typeof-asm.patch b/gcc32-typeof-asm.patch
new file mode 100644 (file)
index 0000000..ab0db75
--- /dev/null
@@ -0,0 +1,100 @@
+2002-08-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/ext/typeof2.C: New test.
+       * gcc.dg/typeof-1.c: New test.
+       * gcc.dg/typeof-2.c: New test.
+
+--- gcc/testsuite/g++.dg/ext/typeof2.C.jj      2002-08-08 14:24:56.000000000 +0200
++++ gcc/testsuite/g++.dg/ext/typeof2.C 2002-08-08 14:24:39.000000000 +0200
+@@ -0,0 +1,29 @@
++// Test typeof with __asm redirection
++// { dg-do compile }
++// { dg-options "-O2" }
++
++extern "C" {
++  extern int foo1;
++  extern int foo1 __asm ("bar1");
++  int foo1 = 1;
++
++  extern int foo2 (int);
++  extern int foo2 (int) __asm ("bar2");
++  int foo2 (int x)
++  {
++    return x;
++  }
++
++  extern int foo3;
++  extern __typeof (foo3) foo3 __asm ("bar3");
++  int foo3 = 1;
++
++  extern int foo4 (int);
++  extern __typeof (foo4) foo4 __asm ("bar4");
++  int foo4 (int x)
++  {
++    return x;
++  }
++}
++
++// { dg-final { scan-assembler-not "foo" } }
+--- gcc/testsuite/gcc.dg/typeof-1.c.jj 2002-08-08 14:26:18.000000000 +0200
++++ gcc/testsuite/gcc.dg/typeof-1.c    2002-08-08 14:26:06.000000000 +0200
+@@ -0,0 +1,27 @@
++/* Test typeof with __asm redirection. */
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++extern int foo1;
++extern int foo1 __asm ("bar1");
++int foo1 = 1;
++
++extern int foo2 (int);
++extern int foo2 (int) __asm ("bar2");
++int foo2 (int x)
++{
++  return x;
++}
++
++extern int foo3;
++extern __typeof (foo3) foo3 __asm ("bar3");
++int foo3 = 1;
++
++extern int foo4 (int);
++extern __typeof (foo4) foo4 __asm ("bar4");
++int foo4 (int x)
++{
++  return x;
++}
++
++// { dg-final { scan-assembler-not "foo" } }
+--- gcc/testsuite/gcc.dg/typeof-2.c.jj 2002-08-08 20:42:33.000000000 +0200
++++ gcc/testsuite/gcc.dg/typeof-2.c    2002-08-08 20:47:53.000000000 +0200
+@@ -0,0 +1,29 @@
++/* Test typeof with __asm redirection. */
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++
++extern int foo1 (int x) __asm ("baz1");
++int bar1 (int x) { return x; }
++extern __typeof (bar1) foo1 __attribute ((weak, alias ("bar1")));
++
++extern int foo2 (int x) __attribute__ ((const));
++extern __typeof (foo2) foo2 __asm ("baz2");
++int bar2 (int x)
++{
++  return foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x);
++}
++
++extern int foo3 (int x);
++extern __typeof (foo3) foo3 __asm ("baz3");
++int bar3 (int x)
++{
++  return foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x);
++}
++
++// { dg-final { scan-assembler-not "foo1" } }
++// { dg-final { scan-assembler "baz1" } }
++// { dg-final { scan-assembler-not "foo2" } }
++// { dg-final { scan-assembler "baz2" } }
++// { dg-final { scan-assembler-not "baz2.*baz2.*baz2.*baz2.*baz2.*baz2" } }
++// { dg-final { scan-assembler-not "foo3" } }
++// { dg-final { scan-assembler "baz3.*baz3.*baz3.*baz3.*baz3.*baz3" } }
diff --git a/gcc32-typeof-skip-eval.patch b/gcc32-typeof-skip-eval.patch
new file mode 100644 (file)
index 0000000..ffbe65a
--- /dev/null
@@ -0,0 +1,160 @@
+2002-08-12  Alexandre Oliva  <aoliva@redhat.com>
+
+       * c-tree.h (skip_evaluation): Move declaration...
+       * c-common.h: ... here.
+       * c-typeck.c (build_external_ref): Don't assemble_external nor
+       mark a tree as used if skip_evaluation is set.
+       * c-parse.in (typeof): New non-terminal to set skip_evaluation
+       around TYPEOF.
+       (typespec_nonreserved_nonattr): Use it.
+
+--- gcc/cp/parse.y.jj  2002-05-02 12:14:49.000000000 +0200
++++ gcc/cp/parse.y     2002-08-22 23:28:34.000000000 +0200
+@@ -1255,16 +1255,20 @@ unary_expr:
+       /* Refer to the address of a label as a pointer.  */
+       | ANDAND identifier
+               { $$ = finish_label_address_expr ($2); }
+-      | SIZEOF unary_expr  %prec UNARY
+-              { $$ = finish_sizeof ($2); }
+-      | SIZEOF '(' type_id ')'  %prec HYPERUNARY
++      | sizeof unary_expr  %prec UNARY
++              { $$ = finish_sizeof ($2);
++                skip_evaluation--; }
++      | sizeof '(' type_id ')'  %prec HYPERUNARY
+               { $$ = finish_sizeof (groktypename ($3.t));
+-                check_for_new_type ("sizeof", $3); }
+-      | ALIGNOF unary_expr  %prec UNARY
+-              { $$ = finish_alignof ($2); }
+-      | ALIGNOF '(' type_id ')'  %prec HYPERUNARY
+-              { $$ = finish_alignof (groktypename ($3.t)); 
+-                check_for_new_type ("alignof", $3); }
++                check_for_new_type ("sizeof", $3);
++                skip_evaluation--; }
++      | alignof unary_expr  %prec UNARY
++              { $$ = finish_alignof ($2);
++                skip_evaluation--; }
++      | alignof '(' type_id ')'  %prec HYPERUNARY
++              { $$ = finish_alignof (groktypename ($3.t));
++                check_for_new_type ("alignof", $3);
++                skip_evaluation--; }
+       /* The %prec EMPTY's here are required by the = init initializer
+          syntax extension; see below.  */
+@@ -1989,6 +1993,18 @@ reserved_typespecquals:
+               { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+       ;
++sizeof:
++      SIZEOF { skip_evaluation++; }
++      ;
++
++alignof:
++      ALIGNOF { skip_evaluation++; }
++      ;
++
++typeof:
++      TYPEOF { skip_evaluation++; }
++      ;
++
+ /* A typespec (but not a type qualifier).
+    Once we have seen one of these in a declaration,
+    if a typedef name appears then it is being redeclared.  */
+@@ -2000,12 +2016,14 @@ typespec:
+               { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
+       | complete_type_name
+               { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
+-      | TYPEOF '(' expr ')'
++      | typeof '(' expr ')'
+               { $$.t = finish_typeof ($3);
+-                $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
+-      | TYPEOF '(' type_id ')'
++                $$.new_type_flag = 0; $$.lookups = NULL_TREE;
++                skip_evaluation--; }
++      | typeof '(' type_id ')'
+               { $$.t = groktypename ($3.t);
+-                $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
++                $$.new_type_flag = 0; $$.lookups = NULL_TREE;
++                skip_evaluation--; }
+       | SIGOF '(' expr ')'
+               { tree type = TREE_TYPE ($3);
+--- gcc/cp/decl2.c.jj  2002-07-27 01:31:05.000000000 +0200
++++ gcc/cp/decl2.c     2002-08-22 23:24:11.000000000 +0200
+@@ -5179,7 +5179,8 @@ mark_used (decl)
+   TREE_USED (decl) = 1;
+   if (processing_template_decl)
+     return;
+-  assemble_external (decl);
++  if (!skip_evaluation)
++    assemble_external (decl);
+   /* Is it a synthesized method that needs to be synthesized?  */
+   if (TREE_CODE (decl) == FUNCTION_DECL
+--- gcc/c-tree.h.jj    2002-04-02 23:17:23.000000000 +0200
++++ gcc/c-tree.h       2002-08-22 23:24:34.000000000 +0200
+@@ -287,11 +287,6 @@ extern int current_function_returns_null
+ extern int current_function_returns_abnormally;
+-/* Nonzero means the expression being parsed will never be evaluated.
+-   This is a count, since unevaluated expressions can nest.  */
+-
+-extern int skip_evaluation;
+-
+ /* Nonzero means `$' can be in an identifier.  */
+ extern int dollars_in_ident;
+--- gcc/c-common.h.jj  2002-04-17 15:34:36.000000000 +0200
++++ gcc/c-common.h     2002-08-22 23:24:11.000000000 +0200
+@@ -464,6 +464,11 @@ extern int warn_conversion;
+ extern int warn_long_long;
++/* Nonzero means the expression being parsed will never be evaluated.
++   This is a count, since unevaluated expressions can nest.  */
++
++extern int skip_evaluation;
++
+ /* C types are partitioned into three subsets: object, function, and
+    incomplete types.  */
+ #define C_TYPE_OBJECT_P(type) \
+--- gcc/c-typeck.c.jj  2002-03-23 12:02:51.000000000 +0100
++++ gcc/c-typeck.c     2002-08-22 23:24:11.000000000 +0200
+@@ -1493,7 +1493,8 @@ build_external_ref (id, fun)
+   if (TREE_TYPE (ref) == error_mark_node)
+     return error_mark_node;
+-  assemble_external (ref);
++  if (!skip_evaluation)
++    assemble_external (ref);
+   TREE_USED (ref) = 1;
+   if (TREE_CODE (ref) == CONST_DECL)
+--- gcc/c-parse.in.jj  2002-04-17 15:34:46.000000000 +0200
++++ gcc/c-parse.in     2002-08-22 23:24:11.000000000 +0200
+@@ -534,6 +534,10 @@ alignof:
+       ALIGNOF { skip_evaluation++; }
+       ;
++typeof:
++      TYPEOF { skip_evaluation++; }
++      ;
++
+ cast_expr:
+       unary_expr
+       | '(' typename ')' cast_expr  %prec UNARY
+@@ -1376,10 +1380,10 @@ ifobjc
+         | non_empty_protocolrefs
+                 { $$ = get_object_reference ($1); }
+ end ifobjc
+-      | TYPEOF '(' expr ')'
+-              { $$ = TREE_TYPE ($3); }
+-      | TYPEOF '(' typename ')'
+-              { $$ = groktypename ($3); }
++      | typeof '(' expr ')'
++              { skip_evaluation--; $$ = TREE_TYPE ($3); }
++      | typeof '(' typename ')'
++              { skip_evaluation--; $$ = groktypename ($3); }
+       ;
+ /* typespec_nonreserved_attr does not exist.  */
This page took 0.414916 seconds and 4 git commands to generate.