]> git.pld-linux.org Git - packages/gcc.git/blob - gcc32-tls.patch
- massive attack: adding Source-md5
[packages/gcc.git] / gcc32-tls.patch
1 --- gcc/cp/lex.c.jj     Sat May 25 00:02:23 2002
2 +++ gcc/cp/lex.c        Wed Jun 19 19:33:51 2002
3 @@ -396,6 +396,7 @@ static const struct resword reswords[] =
4    { "__restrict__",    RID_RESTRICT,   0 },
5    { "__signed",                RID_SIGNED,     0 },
6    { "__signed__",      RID_SIGNED,     0 },
7 +  { "__thread",                RID_THREAD,     0 },
8    { "__typeof",                RID_TYPEOF,     0 },
9    { "__typeof__",      RID_TYPEOF,     0 },
10    { "__volatile",      RID_VOLATILE,   0 },
11 @@ -502,6 +503,7 @@ const short rid_to_yy[RID_MAX] =
12    /* RID_BOUNDED */    0,
13    /* RID_UNBOUNDED */  0,
14    /* RID_COMPLEX */    TYPESPEC,
15 +  /* RID_THREAD */     SCSPEC,
16  
17    /* C++ */
18    /* RID_FRIEND */     SCSPEC,
19 --- gcc/cp/decl.c.jj    Wed Jun 19 19:33:51 2002
20 +++ gcc/cp/decl.c       Wed Jun 19 19:33:51 2002
21 @@ -7122,7 +7122,8 @@ check_tag_decl (declspecs)
22                || value == ridpointers[(int) RID_VIRTUAL]
23                || value == ridpointers[(int) RID_CONST]
24                || value == ridpointers[(int) RID_VOLATILE]
25 -              || value == ridpointers[(int) RID_EXPLICIT])
26 +              || value == ridpointers[(int) RID_EXPLICIT]
27 +              || value == ridpointers[(int) RID_THREAD])
28         ob_modifier = value;
29      }
30  
31 @@ -7596,6 +7597,12 @@ static tree
32  obscure_complex_init (decl, init)
33       tree decl, init;
34  {
35 +  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
36 +    {
37 +      error ("run-time initialization of thread-local storage");
38 +      return NULL_TREE;
39 +    }
40 +
41    if (! flag_no_inline && TREE_STATIC (decl))
42      {
43        if (extract_init (decl, init))
44 @@ -9290,6 +9297,16 @@ grokvardecl (type, declarator, specbits_
45        TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
46      }
47  
48 +  if (RIDBIT_SETP (RID_THREAD, specbits))
49 +    {
50 +      if (targetm.have_tls)
51 +       DECL_THREAD_LOCAL (decl) = 1;
52 +      else
53 +       /* A mere warning is sure to result in improper semantics
54 +          at runtime.  Don't bother to allow this to compile.  */
55 +       error ("thread-local storage not supported for this target");
56 +    }
57 +
58    if (TREE_PUBLIC (decl))
59      {
60        /* [basic.link]: A name with no linkage (notably, the name of a class
61 @@ -10192,10 +10209,22 @@ grokdeclarator (declarator, declspecs, d
62                     }
63                   else if (RIDBIT_SETP (i, specbits))
64                     pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
65 +
66 +                 /* Diagnose "__thread extern".  Recall that this list
67 +                    is in the reverse order seen in the text.  */
68 +                 if (i == (int)RID_THREAD)
69 +                   {
70 +                     if (RIDBIT_SETP (RID_EXTERN, specbits))
71 +                       error ("`__thread' before `extern'");
72 +                     if (RIDBIT_SETP (RID_STATIC, specbits))
73 +                       error ("`__thread' before `static'");
74 +                   }
75 +
76                   if (i == (int)RID_EXTERN
77                       && TREE_PURPOSE (spec) == error_mark_node)
78                     /* This extern was part of a language linkage.  */
79                     extern_langp = 1;
80 +
81                   RIDBIT_SET (i, specbits);
82                   goto found;
83                 }
84 @@ -10492,6 +10521,7 @@ grokdeclarator (declarator, declspecs, d
85      {
86        if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
87        if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
88 +      if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
89        if (decl_context == PARM && nclasses > 0)
90         error ("storage class specifiers invalid in parameter declarations");
91        if (RIDBIT_SETP (RID_TYPEDEF, specbits))
92 @@ -10523,6 +10553,13 @@ grokdeclarator (declarator, declspecs, d
93    /* Warn about storage classes that are invalid for certain
94       kinds of declarations (parameters, typenames, etc.).  */
95  
96 +  /* "static __thread" and "extern __thread" are allowed.  */
97 +  if (nclasses == 2
98 +      && RIDBIT_SETP (RID_THREAD, specbits)
99 +      && (RIDBIT_SETP (RID_EXTERN, specbits)
100 +         || RIDBIT_SETP (RID_STATIC, specbits)))
101 +    nclasses = 1;
102 +    
103    if (nclasses > 1)
104      error ("multiple storage classes in declaration of `%s'", name);
105    else if (decl_context != NORMAL && nclasses > 0)
106 @@ -10578,6 +10615,7 @@ grokdeclarator (declarator, declspecs, d
107           RIDBIT_RESET (RID_REGISTER, specbits);
108           RIDBIT_RESET (RID_AUTO, specbits);
109           RIDBIT_RESET (RID_EXTERN, specbits);
110 +         RIDBIT_RESET (RID_THREAD, specbits);
111         }
112      }
113    else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
114 @@ -10600,6 +10638,14 @@ grokdeclarator (declarator, declspecs, d
115        if (RIDBIT_SETP (RID_AUTO, specbits))
116         error ("top-level declaration of `%s' specifies `auto'", name);
117      }
118 +  else if (RIDBIT_SETP (RID_THREAD, specbits)
119 +          && !RIDBIT_SETP (RID_EXTERN, specbits)
120 +          && !RIDBIT_SETP (RID_STATIC, specbits))
121 +    {
122 +      error ("function-scope `%s' implicitly auto and declared `__thread'",
123 +            name);
124 +      RIDBIT_RESET (RID_THREAD, specbits);
125 +    }
126  
127    if (nclasses > 0 && friendp)
128      error ("storage class specifiers invalid in friend function declarations");
129 @@ -11800,6 +11846,8 @@ friend declaration requires class-key, i
130           error ("storage class `auto' invalid for function `%s'", name);
131         else if (RIDBIT_SETP (RID_REGISTER, specbits))
132           error ("storage class `register' invalid for function `%s'", name);
133 +       else if (RIDBIT_SETP (RID_THREAD, specbits))
134 +         error ("storage class `__thread' invalid for function `%s'", name);
135  
136         /* Function declaration not at top level.
137            Storage classes other than `extern' are not allowed
138 --- gcc/doc/extend.texi.jj      Wed Jun 19 19:33:51 2002
139 +++ gcc/doc/extend.texi Wed Jun 19 19:33:51 2002
140 @@ -432,6 +432,7 @@ extensions, accepted by GCC in C89 mode 
141  * Target Builtins::     Built-in functions specific to particular targets.
142  * Pragmas::             Pragmas accepted by GCC.
143  * Unnamed Fields::      Unnamed struct/union fields within structs/unions.
144 +* Thread-Local::        Per-thread variables.
145  @end menu
146  
147  @node Statement Exprs
148 @@ -6119,6 +6120,265 @@ It is ambiguous which @code{a} is being 
149  Such constructs are not supported and must be avoided.  In the future,
150  such constructs may be detected and treated as compilation errors.
151  
152 +@node Thread-Local
153 +@section Thread-Local Storage
154 +@cindex Thread-Local Storage
155 +@cindex TLS
156 +@cindex __thread
157 +
158 +Thread-local storage (@acronym{TLS}) is a mechanism by which variables
159 +are allocated such that there is one instance of the variable per extant
160 +thread.  The run-time model GCC uses to implement this originates
161 +in the IA-64 processor-specific ABI, but has since been migrated
162 +to other processors as well.  It requires significant support from
163 +the linker (@command{ld}), dynamic linker (@command{ld.so}), and
164 +system libraries (@file{libc.so} and @file{libpthread.so}), so it
165 +is not available everywhere.
166 +
167 +At the user level, the extension is visible with a new storage
168 +class keyword: @code{__thread}.  For example:
169 +
170 +@example
171 +__thread int i;
172 +extern __thread struct state s;
173 +static __thread char *p;
174 +@end example
175 +
176 +The @code{__thread} specifier may be used alone, with the @code{extern}
177 +or @code{static} specifiers, but with no other storage class specifier.
178 +When used with @code{extern} or @code{static}, @code{__thread} must appear
179 +immediately after the other storage class specifier.
180 +
181 +The @code{__thread} specifier may be applied to any global, file-scoped
182 +static, function-scoped static, or static data member of a class.  It may
183 +not be applied to block-scoped automatic or non-static data member.
184 +
185 +When the address-of operator is applied to a thread-local variable, it is
186 +evaluated at run-time and returns the address of the current thread's
187 +instance of that variable.  An address so obtained may be used by any
188 +thread.  When a thread terminates, any pointers to thread-local variables
189 +in that thread become invalid.
190 +
191 +No static initialization may refer to the address of a thread-local variable.
192 +
193 +In C++, if an initializer is present for a thread-local variable, it must
194 +be a @var{constant-expression}, as defined in 5.19.2 of the ANSI/ISO C++
195 +standard.
196 +
197 +See @uref{http://people.redhat.com/drepper/tls.pdf,
198 +ELF Handling For Thread-Local Storage} for a detailed explanation of
199 +the four thread-local storage addressing models, and how the run-time
200 +is expected to function.
201 +
202 +@menu
203 +* C99 Thread-Local Edits::
204 +* C++98 Thread-Local Edits::
205 +@end menu
206 +
207 +@node C99 Thread-Local Edits
208 +@subsection ISO/IEC 9899:1999 Edits for Thread-Local Storage
209 +
210 +The following are a set of changes to ISO/IEC 9899:1999 (aka C99)
211 +that document the exact semantics of the language extension.
212 +
213 +@itemize @bullet
214 +@item
215 +@cite{5.1.2  Execution environments}
216 +
217 +Add new text after paragraph 1
218 +
219 +@quotation
220 +Within either execution environment, a @dfn{thread} is a flow of
221 +control within a program.  It is implementation defined whether
222 +or not there may be more than one thread associated with a program.
223 +It is implementation defined how threads beyond the first are
224 +created, the name and type of the function called at thread
225 +startup, and how threads may be terminated.  However, objects
226 +with thread storage duration shall be initialized before thread
227 +startup.
228 +@end quotation
229 +
230 +@item
231 +@cite{6.2.4  Storage durations of objects}
232 +
233 +Add new text before paragraph 3
234 +
235 +@quotation
236 +An object whose identifier is declared with the storage-class
237 +specifier @w{@code{__thread}} has @dfn{thread storage duration}.
238 +Its lifetime is the entire execution of the thread, and its
239 +stored value is initialized only once, prior to thread startup.
240 +@end quotation
241 +
242 +@item
243 +@cite{6.4.1  Keywords}
244 +
245 +Add @code{__thread}.
246 +
247 +@item
248 +@cite{6.7.1  Storage-class specifiers}
249 +
250 +Add @code{__thread} to the list of storage class specifiers in
251 +paragraph 1.
252 +
253 +Change paragraph 2 to
254 +
255 +@quotation
256 +With the exception of @code{__thread}, at most one storage-class
257 +specifier may be given [@dots{}].  The @code{__thread} specifier may
258 +be used alone, or immediately following @code{extern} or
259 +@code{static}.
260 +@end quotation
261 +
262 +Add new text after paragraph 6
263 +
264 +@quotation
265 +The declaration of an identifier for a variable that has
266 +block scope that specifies @code{__thread} shall also
267 +specify either @code{extern} or @code{static}.
268 +
269 +The @code{__thread} specifier shall be used only with
270 +variables.
271 +@end quotation
272 +@end itemize
273 +
274 +@node C++98 Thread-Local Edits
275 +@subsection ISO/IEC 14882:1998 Edits for Thread-Local Storage
276 +
277 +The following are a set of changes to ISO/IEC 14882:1998 (aka C++98)
278 +that document the exact semantics of the language extension.
279 +
280 +@itemize @bullet
281 +@b{[intro.execution]}
282 +
283 +New text after paragraph 4
284 +
285 +@quotation
286 +A @dfn{thread} is a flow of control within the abstract machine.
287 +It is implementation defined whether or not there may be more than
288 +one thread.
289 +@end quotation
290 +
291 +New text after paragraph 7
292 +
293 +@quotation
294 +It is unspecified whether additional action must be taken to 
295 +ensure when and whether side effects are visible to other threads.
296 +@end quotation
297 +
298 +@item
299 +@b{[lex.key]}
300 +
301 +Add @code{__thread}.
302 +
303 +@item
304 +@b{[basic.start.main]}
305 +
306 +Add after paragraph 5
307 +
308 +@quotation
309 +The thread that begins execution at the @code{main} function is called
310 +the @dfn{main thread}.  It is implementation defined how functions 
311 +beginning threads other than the main thread are designated or typed.
312 +A function so designated, as well as the @code{main} function, is called
313 +a @dfn{thread startup function}.  It is implementation defined what
314 +happens if a thread startup function returns.  It is implementation
315 +defined what happens to other threads when any thread calls @code{exit}.
316 +@end quotation
317 +
318 +@item
319 +@b{[basic.start.init]}
320 +
321 +Add after paragraph 4
322 +
323 +@quotation
324 +The storage for an object of thread storage duration shall be
325 +staticly initialized before the first statement of the thread startup
326 +function.  An object of thread storage duration shall not require
327 +dynamic initialization.
328 +@end quotation
329 +
330 +@item
331 +@b{[basic.start.term]}
332 +
333 +Add after paragraph 3
334 +
335 +@quotation
336 +The type of an object with thread storage duration shall not have a
337 +non-trivial destructor, nor shall it be an array type whose elements
338 +(directly or indirectly) have non-trivial destructors.
339 +@end quotation
340 +
341 +@item
342 +@b{[basic.stc]}
343 +
344 +Add ``thread storage duration'' to the list in paragraph 1.
345 +
346 +Change paragraph 2
347 +
348 +@quotation
349 +Thread, static, and automatic storage durations are associated with
350 +objects introduced by declarations [@dots{}].
351 +@end quotation
352 +
353 +Add @code{__thread} to the list of specifiers in paragraph 3.
354 +
355 +@item
356 +@b{[basic.stc.thread]}
357 +
358 +New section before @b{[basic.stc.static]}
359 +
360 +@quotation
361 +The keyword @code{__thread} applied to an non-local object gives the
362 +object thread storage duration.
363 +
364 +A local variable or class data member declared both @code{static}
365 +and @code{__thread} gives the variable or member thread storage
366 +duration.
367 +@end quotation
368 +
369 +@item
370 +@b{[basic.stc.static]}
371 +
372 +Change paragraph 1
373 +
374 +@quotation
375 +All objects which have neither thread storage duration, dynamic
376 +storage duration nor are local [@dots{}].
377 +@end quotation
378 +
379 +@item
380 +@b{[dcl.stc]}
381 +
382 +Add @code{__thread} to the list in paragraph 1.
383 +
384 +Change paragraph 1
385 +
386 +@quotation
387 +With the exception of @code{__thread}, at most one
388 +@var{storage-class-specifier} shall appear in a given
389 +@var{decl-specifier-seq}.  The @code{__thread} specifier may
390 +be used alone, or immediately following the @code{extern} or
391 +@code{static} specifiers.  [@dots{}]
392 +@end quotation
393 +
394 +Add after paragraph 5
395 +
396 +@quotation
397 +The @code{__thread} specifier can be applied only to the names of objects
398 +and to anonymous unions.
399 +@end quotation
400 +
401 +@item
402 +@b{[class.mem]}
403 +
404 +Add after paragraph 6
405 +
406 +@quotation
407 +Non-@code{static} members shall not be @code{__thread}.
408 +@end quotation
409 +@end itemize
410 +
411  @node C++ Extensions
412  @chapter Extensions to the C++ Language
413  @cindex extensions, C++ language
414 --- gcc/doc/invoke.texi.jj      Tue May 21 20:27:44 2002
415 +++ gcc/doc/invoke.texi Wed Jun 19 19:33:52 2002
416 @@ -674,7 +674,7 @@ in the following sections.
417  -fverbose-asm  -fpack-struct  -fstack-check @gol
418  -fstack-limit-register=@var{reg}  -fstack-limit-symbol=@var{sym} @gol
419  -fargument-alias  -fargument-noalias @gol
420 --fargument-noalias-global  -fleading-underscore}
421 +-fargument-noalias-global  -fleading-underscore -ftls-model=@var{model}}
422  @end table
423  
424  @menu
425 @@ -9988,6 +9988,14 @@
426  generate code that is not binary compatible with code generated without that
427  switch.  Use it to conform to a non-default application binary interface.
428  Not all targets provide complete support for this switch.
429 +
430 +@item -ftls-model=@var{model}
431 +Alter the thread-local storage model to be used (@pxref{Thread-Local}).
432 +The @var{model} argument should be one of @code{global-dynamic},
433 +@code{local-dynamic}, @code{initial-exec} or @code{local-exec}.
434
435 +The default without @option{-fpic} is @code{initial-exec}; with
436 +@option{-fpic} the default is @code{global-dynamic}.
437  @end table
438  
439  @c man end
440 --- gcc/config/i386/i386.c.jj   Wed Jun 19 19:33:51 2002
441 +++ gcc/config/i386/i386.c      Wed Jun 19 23:18:18 2002
442 @@ -536,6 +536,10 @@ int const svr4_dbx_register_map[FIRST_PS
443  rtx ix86_compare_op0 = NULL_RTX;
444  rtx ix86_compare_op1 = NULL_RTX;
445  
446 +/* The encoding characters for the four TLS models present in ELF.  */
447 +
448 +static char const tls_model_chars[] = " GLil";
449 +
450  #define MAX_386_STACK_LOCALS 3
451  /* Size of the register save area.  */
452  #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
453 @@ -544,6 +548,7 @@ rtx ix86_compare_op1 = NULL_RTX;
454  struct machine_function
455  {
456    rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
457 +  const char *some_ld_name;
458    int save_varrargs_registers;
459    int accesses_prev_frame;
460  };
461 @@ -596,6 +601,9 @@ enum cmodel ix86_cmodel;
462  /* Asm dialect.  */
463  const char *ix86_asm_string;
464  enum asm_dialect ix86_asm_dialect = ASM_ATT;
465 +/* TLS dialext.  */
466 +const char *ix86_tls_dialect_string;
467 +enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
468  
469  /* which cpu are we scheduling for */
470  enum processor_type ix86_cpu;
471 @@ -646,12 +654,17 @@ static char internal_label_prefix[16];
472  static int internal_label_prefix_len;
473  \f
474  static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
475 +static int tls_symbolic_operand_1 PARAMS ((rtx, enum tls_model));
476  static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
477  static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
478                                        int, int, FILE *));
479 +static const char *get_some_local_dynamic_name PARAMS ((void));
480 +static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
481 +static rtx maybe_get_pool_constant PARAMS ((rtx));
482  static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
483  static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
484                                                            rtx *, rtx *));
485 +static rtx get_thread_pointer PARAMS ((void));
486  static rtx gen_push PARAMS ((rtx));
487  static int memory_address_length PARAMS ((rtx addr));
488  static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
489 @@ -820,6 +833,11 @@ static enum x86_64_reg_class merge_class
490  #undef TARGET_SCHED_REORDER
491  #define TARGET_SCHED_REORDER ix86_sched_reorder
492  
493 +#ifdef HAVE_AS_TLS
494 +#undef TARGET_HAVE_TLS
495 +#define TARGET_HAVE_TLS true
496 +#endif
497 +
498  struct gcc_target targetm = TARGET_INITIALIZER;
499  \f
500  /* Sometimes certain combinations of command options do not make
501 @@ -1109,6 +1127,17 @@ override_options ()
502         ix86_branch_cost = i;
503      }
504  
505 +  if (ix86_tls_dialect_string)
506 +    {
507 +      if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
508 +       ix86_tls_dialect = TLS_DIALECT_GNU;
509 +      else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
510 +       ix86_tls_dialect = TLS_DIALECT_SUN;
511 +      else
512 +       error ("bad value (%s) for -mtls-dialect= switch",
513 +              ix86_tls_dialect_string);
514 +    }
515 +
516    /* Keep nonleaf frame pointers.  */
517    if (TARGET_OMIT_LEAF_FRAME_POINTER)
518      flag_omit_frame_pointer = 1;
519 @@ -3007,6 +3036,70 @@ local_symbolic_operand (op, mode)
520    return 0;
521  }
522  
523 +/* Test for various thread-local symbols.  See ix86_encode_section_info. */
524 +
525 +int
526 +tls_symbolic_operand (op, mode)
527 +     register rtx op;
528 +     enum machine_mode mode ATTRIBUTE_UNUSED;
529 +{
530 +  const char *symbol_str;
531 +
532 +  if (GET_CODE (op) != SYMBOL_REF)
533 +    return 0;
534 +  symbol_str = XSTR (op, 0);
535 +
536 +  if (symbol_str[0] != '%')
537 +    return 0;
538 +  return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;
539 +}
540 +
541 +static int
542 +tls_symbolic_operand_1 (op, kind)
543 +     rtx op;
544 +     enum tls_model kind;
545 +{
546 +  const char *symbol_str;
547 +
548 +  if (GET_CODE (op) != SYMBOL_REF)
549 +    return 0;
550 +  symbol_str = XSTR (op, 0);
551 +
552 +  return symbol_str[0] == '%' && symbol_str[1] == tls_model_chars[kind];
553 +}
554 +
555 +int
556 +global_dynamic_symbolic_operand (op, mode)
557 +     register rtx op;
558 +     enum machine_mode mode ATTRIBUTE_UNUSED;
559 +{
560 +  return tls_symbolic_operand_1 (op, TLS_MODEL_GLOBAL_DYNAMIC);
561 +}
562 +
563 +int
564 +local_dynamic_symbolic_operand (op, mode)
565 +     register rtx op;
566 +     enum machine_mode mode ATTRIBUTE_UNUSED;
567 +{
568 +  return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_DYNAMIC);
569 +}
570 +
571 +int
572 +initial_exec_symbolic_operand (op, mode)
573 +     register rtx op;
574 +     enum machine_mode mode ATTRIBUTE_UNUSED;
575 +{
576 +  return tls_symbolic_operand_1 (op, TLS_MODEL_INITIAL_EXEC);
577 +}
578 +
579 +int
580 +local_exec_symbolic_operand (op, mode)
581 +     register rtx op;
582 +     enum machine_mode mode ATTRIBUTE_UNUSED;
583 +{
584 +  return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_EXEC);
585 +}
586 +
587  /* Test for a valid operand for a call instruction.  Don't allow the
588     arg pointer register or virtual regs since they may decay into
589     reg + const, which the patterns can't handle.  */
590 @@ -3858,7 +3951,7 @@ ix86_asm_file_end (file)
591  {
592    rtx xops[2];
593  
594 -  if (! TARGET_DEEP_BRANCH_PREDICTION || pic_label_name[0] == 0)
595 +  if (pic_label_name[0] == 0)
596      return;
597  
598    /* The trick here is to create a linkonce section containing the
599 @@ -3896,17 +3989,33 @@ ix86_asm_file_end (file)
600    output_asm_insn ("ret", xops);
601  }
602  
603 -void
604 -load_pic_register ()
605 +/* Emit code for the SET_GOT patterns.  */
606 +
607 +const char *
608 +output_set_got (dest)
609 +     rtx dest;
610  {
611 -  rtx gotsym, pclab;
612 +  rtx xops[3];
613  
614 -  if (TARGET_64BIT)
615 -    abort ();
616 +  xops[0] = dest;
617 +  xops[1] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
618 +
619 +  if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
620 +    {
621 +      xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
622 +
623 +      if (!flag_pic)
624 +       output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
625 +      else
626 +       output_asm_insn ("call\t%a2", xops);
627  
628 -  gotsym = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
629 +      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
630 +                                CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
631  
632 -  if (TARGET_DEEP_BRANCH_PREDICTION)
633 +      if (flag_pic)
634 +       output_asm_insn ("pop{l}\t%0", xops);
635 +    }
636 +  else
637      {
638        if (! pic_label_name[0])
639         {
640 @@ -3915,16 +4024,17 @@ load_pic_register ()
641           else
642             ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
643         }
644 -      pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
645 -    }
646 +      xops[2] = gen_rtx_SYMBOL_REF (Pmode, pic_label_name);
647 +      xops[2] = gen_rtx_MEM (QImode, xops[2]);
648 +      output_asm_insn ("call\t%X2", xops);
649 +    }
650 +  
651 +  if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
652 +    output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
653    else
654 -    {
655 -      pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
656 -    }
657 -
658 -  emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
659 -
660 -  emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
661 +    output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %a1+(.-%a2)}", xops);
662 +  
663 +  return "";
664  }
665  
666  /* Generate an "push" pattern for input ARG.  */
667 @@ -4253,7 +4363,15 @@ ix86_expand_prologue ()
668  #endif
669  
670    if (pic_reg_used)
671 -    load_pic_register ();
672 +    {
673 +      insn = emit_insn (gen_set_got (pic_offset_table_rtx));
674 +
675 +      /* ??? The current_function_uses_pic_offset_table flag is woefully
676 +        inaccurate, as it isn't updated as code gets deleted.  Allow the
677 +        thing to be removed.  A better solution would be to actually get
678 +        proper liveness for ebx, as then we won't save/restore it too.  */
679 +      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
680 +    }
681  
682    /* If we are profiling, make sure no instructions are scheduled before
683       the call to mcount.  However, if -fpic, the above call will have
684 @@ -4694,6 +4812,114 @@ ix86_find_base_term (x)
685    return term;
686  }
687  \f
688 +/* Determine if a given RTX is a valid constant.  We already know this
689 +   satisfies CONSTANT_P.  */
690 +
691 +bool
692 +legitimate_constant_p (x)
693 +     rtx x;
694 +{
695 +  rtx inner;
696 +
697 +  switch (GET_CODE (x))
698 +    {
699 +    case SYMBOL_REF:
700 +      /* TLS symbols are not constant.  */
701 +      if (tls_symbolic_operand (x, Pmode))
702 +       return false;
703 +      break;
704 +
705 +    case CONST:
706 +      inner = XEXP (x, 0);
707 +
708 +      /* Offsets of TLS symbols are never valid.
709 +        Discourage CSE from creating them.  */
710 +      if (GET_CODE (inner) == PLUS
711 +         && tls_symbolic_operand (XEXP (inner, 0), Pmode))
712 +       return false;
713 +
714 +      /* Only some unspecs are valid as "constants".  */
715 +      if (GET_CODE (inner) == UNSPEC)
716 +       switch (XINT (inner, 1))
717 +         {
718 +         case UNSPEC_TPOFF:
719 +           return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
720 +         case UNSPEC_TP:
721 +           return true;
722 +         default:
723 +           return false;
724 +         }
725 +      break;
726 +
727 +    default:
728 +      break;
729 +    }
730 +
731 +  /* Otherwise we handle everything else in the move patterns.  */
732 +  return true;
733 +}
734 +
735 +/* Determine if a given RTX is a valid constant address.  */
736 +
737 +bool
738 +constant_address_p (x)
739 +     rtx x;
740 +{
741 +  switch (GET_CODE (x))
742 +    {
743 +    case LABEL_REF:
744 +    case CONST_INT:
745 +      return true;
746 +
747 +    case CONST_DOUBLE:
748 +      return TARGET_64BIT;
749 +
750 +    case CONST:
751 +    case SYMBOL_REF:
752 +      return !flag_pic && legitimate_constant_p (x);
753 +
754 +    default:
755 +      return false;
756 +    }
757 +}
758 +
759 +/* Nonzero if the constant value X is a legitimate general operand
760 +   when generating PIC code.  It is given that flag_pic is on and 
761 +   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
762 +
763 +bool
764 +legitimate_pic_operand_p (x)
765 +     rtx x;
766 +{
767 +  rtx inner;
768 +
769 +  switch (GET_CODE (x))
770 +    {
771 +    case CONST:
772 +      inner = XEXP (x, 0);
773 +
774 +      /* Only some unspecs are valid as "constants".  */
775 +      if (GET_CODE (inner) == UNSPEC)
776 +       switch (XINT (inner, 1))
777 +         {
778 +         case UNSPEC_TPOFF:
779 +           return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
780 +         case UNSPEC_TP:
781 +           return true;
782 +         default:
783 +           return false;
784 +         }
785 +      /* FALLTHRU */
786 +
787 +    case SYMBOL_REF:
788 +    case LABEL_REF:
789 +      return legitimate_pic_address_disp_p (x);
790 +
791 +    default:
792 +      return true;
793 +    }
794 +}
795 +
796  /* Determine if a given CONST RTX is a valid memory displacement
797     in PIC mode.  */
798  
799 @@ -4701,6 +4927,8 @@ int
800  legitimate_pic_address_disp_p (disp)
801       register rtx disp;
802  {
803 +  bool saw_plus;
804 +
805    /* In 64bit mode we can allow direct addresses of symbols and labels
806       when they are not dynamic symbols.  */
807    if (TARGET_64BIT)
808 @@ -4737,25 +4965,39 @@ legitimate_pic_address_disp_p (disp)
809        return 1;
810      }
811  
812 +  saw_plus = false;
813    if (GET_CODE (disp) == PLUS)
814      {
815        if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
816         return 0;
817        disp = XEXP (disp, 0);
818 +      saw_plus = true;
819      }
820  
821    if (GET_CODE (disp) != UNSPEC
822        || XVECLEN (disp, 0) != 1)
823      return 0;
824  
825 -  /* Must be @GOT or @GOTOFF.  */
826    switch (XINT (disp, 1))
827      {
828 -    case 6: /* @GOT */
829 +    case UNSPEC_GOT:
830 +      if (saw_plus)
831 +       return false;
832        return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF;
833 -
834 -    case 7: /* @GOTOFF */
835 +    case UNSPEC_GOTOFF:
836        return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
837 +    case UNSPEC_GOTTPOFF:
838 +      if (saw_plus)
839 +       return false;
840 +      return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
841 +    case UNSPEC_NTPOFF:
842 +      if (saw_plus)
843 +       return false;
844 +      return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
845 +    case UNSPEC_DTPOFF:
846 +      if (saw_plus)
847 +       return false;
848 +      return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
849      }
850      
851    return 0;
852 @@ -4882,12 +5124,6 @@ legitimate_address_p (mode, addr, strict
853      {
854        reason_rtx = disp;
855  
856 -      if (!CONSTANT_ADDRESS_P (disp))
857 -       {
858 -         reason = "displacement is not constant";
859 -         goto report_error;
860 -       }
861 -
862        if (TARGET_64BIT)
863         {
864           if (!x86_64_sign_extended_value (disp))
865 @@ -4905,8 +5141,30 @@ legitimate_address_p (mode, addr, strict
866             }
867         }
868  
869 -      if (flag_pic && SYMBOLIC_CONST (disp))
870 +      if (GET_CODE (disp) == CONST
871 +         && GET_CODE (XEXP (disp, 0)) == UNSPEC)
872 +       switch (XINT (XEXP (disp, 0), 1))
873 +         {
874 +         case UNSPEC_GOT:
875 +         case UNSPEC_GOTOFF:
876 +         case UNSPEC_GOTPCREL:
877 +           if (!flag_pic)
878 +             abort ();
879 +           goto is_legitimate_pic;
880 +
881 +         case UNSPEC_GOTTPOFF:
882 +         case UNSPEC_NTPOFF:
883 +         case UNSPEC_DTPOFF:
884 +           break;
885 +
886 +         default:
887 +           reason = "invalid address unspec";
888 +           goto report_error;
889 +         }
890 +
891 +      else if (flag_pic && SYMBOLIC_CONST (disp))
892         {
893 +       is_legitimate_pic:
894           if (TARGET_64BIT && (index || base))
895             {
896               reason = "non-constant pic memory reference";
897 @@ -4949,6 +5207,11 @@ legitimate_address_p (mode, addr, strict
898               goto report_error;
899             }
900         }
901 +      else if (!CONSTANT_ADDRESS_P (disp))
902 +       {
903 +         reason = "displacement is not constant";
904 +         goto report_error;
905 +       }
906      }
907  
908    /* Everything looks valid.  */
909 @@ -5129,7 +5392,102 @@ legitimize_pic_address (orig, reg)
910      }
911    return new;
912  }
913 +
914 +void
915 +ix86_encode_section_info (decl)
916 +     tree decl;
917 +{
918 +  bool local_p;
919 +  rtx rtl, symbol;
920 +
921 +  rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
922 +  if (GET_CODE (rtl) != MEM)
923 +    return;
924 +  symbol = XEXP (rtl, 0);
925 +  if (GET_CODE (symbol) != SYMBOL_REF)
926 +    return;
927 +
928 +  local_p = !DECL_P (decl) || !TREE_PUBLIC (decl) || MODULE_LOCAL_P (decl);
929 +
930 +  /* For basic x86, if using PIC, mark a SYMBOL_REF for a non-global
931 +     symbol so that we may access it directly in the GOT.  */
932 +
933 +  if (flag_pic)
934 +    SYMBOL_REF_FLAG (symbol) = local_p;
935 +
936 +  /* For ELF, encode thread-local data with %[GLil] for "global dynamic",
937 +     "local dynamic", "initial exec" or "local exec" TLS models
938 +     respectively.  */
939 +
940 +  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
941 +    {
942 +      const char *symbol_str;
943 +      char *newstr;
944 +      size_t len;
945 +      enum tls_model kind;
946 +
947 +      if (!flag_pic)
948 +       {
949 +         if (local_p)
950 +           kind = TLS_MODEL_LOCAL_EXEC;
951 +         else
952 +           kind = TLS_MODEL_INITIAL_EXEC;
953 +       }
954 +      /* Local dynamic is inefficient when we're not combining the
955 +        parts of the address.  */
956 +      else if (optimize && local_p)
957 +       kind = TLS_MODEL_LOCAL_DYNAMIC;
958 +      else
959 +       kind = TLS_MODEL_GLOBAL_DYNAMIC;
960 +      if (kind < flag_tls_default)
961 +       kind = flag_tls_default;
962 +
963 +      symbol_str = XSTR (symbol, 0);
964 +
965 +      if (symbol_str[0] == '%')
966 +       {
967 +         if (symbol_str[1] == tls_model_chars[kind])
968 +           return;
969 +         symbol_str += 2;
970 +       }
971 +      len = strlen (symbol_str) + 1;
972 +      newstr = alloca (len + 2);
973 +
974 +      newstr[0] = '%';
975 +      newstr[1] = tls_model_chars[kind];
976 +      memcpy (newstr + 2, symbol_str, len);
977 +
978 +      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
979 +    }
980 +}
981 +
982 +/* Undo the above when printing symbol names.  */
983 +
984 +const char *
985 +ix86_strip_name_encoding (str)
986 +     const char *str;
987 +{
988 +  if (str[0] == '%')
989 +    str += 2;
990 +  if (str [0] == '*')
991 +    str += 1;
992 +  return str;
993 +}
994  \f
995 +/* Load the thread pointer into a register.  */
996 +
997 +static rtx
998 +get_thread_pointer ()
999 +{
1000 +  rtx tp;
1001 +
1002 +  tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
1003 +  tp = gen_rtx_CONST (Pmode, tp);
1004 +  tp = force_reg (Pmode, tp);
1005 +
1006 +  return tp;
1007 +}
1008 +
1009  /* Try machine-dependent ways of modifying an illegitimate address
1010     to be legitimate.  If we find one, return the new, valid address.
1011     This macro is used in only one place: `memory_address' in explow.c.
1012 @@ -5167,6 +5525,84 @@ legitimize_address (x, oldx, mode)
1013        debug_rtx (x);
1014      }
1015  
1016 +  log = tls_symbolic_operand (x, mode);
1017 +  if (log)
1018 +    {
1019 +      rtx dest, base, off, pic;
1020 +
1021 +      switch (log)
1022 +        {
1023 +        case TLS_MODEL_GLOBAL_DYNAMIC:
1024 +         dest = gen_reg_rtx (Pmode);
1025 +          emit_insn (gen_tls_global_dynamic (dest, x));
1026 +         break;
1027 +
1028 +        case TLS_MODEL_LOCAL_DYNAMIC:
1029 +         base = gen_reg_rtx (Pmode);
1030 +         emit_insn (gen_tls_local_dynamic_base (base));
1031 +
1032 +         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
1033 +         off = gen_rtx_CONST (Pmode, off);
1034 +
1035 +         return gen_rtx_PLUS (Pmode, base, off);
1036 +
1037 +        case TLS_MODEL_INITIAL_EXEC:
1038 +         if (flag_pic)
1039 +           {
1040 +             current_function_uses_pic_offset_table = 1;
1041 +             pic = pic_offset_table_rtx;
1042 +           }
1043 +         else
1044 +           {
1045 +             pic = gen_reg_rtx (Pmode);
1046 +             emit_insn (gen_set_got (pic));
1047 +           }
1048 +
1049 +         base = get_thread_pointer ();
1050 +
1051 +         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_GOTTPOFF);
1052 +         off = gen_rtx_CONST (Pmode, off);
1053 +         off = gen_rtx_PLUS (Pmode, pic, off);
1054 +         off = gen_rtx_MEM (Pmode, off);
1055 +         RTX_UNCHANGING_P (off) = 1;
1056 +         set_mem_alias_set (off, ix86_GOT_alias_set ());
1057 +
1058 +         /* Damn Sun for specifing a set of dynamic relocations without
1059 +            considering the two-operand nature of the architecture!
1060 +            We'd be much better off with a "GOTNTPOFF" relocation that
1061 +            already contained the negated constant.  */
1062 +         /* ??? Using negl and reg+reg addressing appears to be a lose
1063 +            size-wise.  The negl is two bytes, just like the extra movl
1064 +            incurred by the two-operand subl, but reg+reg addressing
1065 +            uses the two-byte modrm form, unlike plain reg.  */
1066 +
1067 +         dest = gen_reg_rtx (Pmode);
1068 +         emit_insn (gen_subsi3 (dest, base, off));
1069 +         break;
1070 +
1071 +        case TLS_MODEL_LOCAL_EXEC:
1072 +         base = get_thread_pointer ();
1073 +
1074 +         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
1075 +                               TARGET_GNU_TLS ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
1076 +         off = gen_rtx_CONST (Pmode, off);
1077 +
1078 +         if (TARGET_GNU_TLS)
1079 +           return gen_rtx_PLUS (Pmode, base, off);
1080 +         else
1081 +           {
1082 +             dest = gen_reg_rtx (Pmode);
1083 +             emit_insn (gen_subsi3 (dest, base, off));
1084 +           }
1085 +         break;
1086 +
1087 +       default:
1088 +         abort ();
1089 +        }
1090 +
1091 +      return dest;
1092 +    }
1093 +
1094    if (flag_pic && SYMBOLIC_CONST (x))
1095      return legitimize_pic_address (x, 0);
1096  
1097 @@ -5410,18 +5846,30 @@ output_pic_addr_const (file, x, code)
1098         output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
1099         switch (XINT (x, 1))
1100         {
1101 -       case 6:
1102 +       case UNSPEC_GOT:
1103           fputs ("@GOT", file);
1104           break;
1105 -       case 7:
1106 +       case UNSPEC_GOTOFF:
1107           fputs ("@GOTOFF", file);
1108           break;
1109 -       case 8:
1110 +       case UNSPEC_PLT:
1111           fputs ("@PLT", file);
1112           break;
1113 -       case 15:
1114 +       case UNSPEC_GOTPCREL:
1115           fputs ("@GOTPCREL(%RIP)", file);
1116           break;
1117 +       case UNSPEC_GOTTPOFF:
1118 +         fputs ("@GOTTPOFF", file);
1119 +         break;
1120 +       case UNSPEC_TPOFF:
1121 +         fputs ("@TPOFF", file);
1122 +         break;
1123 +       case UNSPEC_NTPOFF:
1124 +         fputs ("@NTPOFF", file);
1125 +         break;
1126 +       case UNSPEC_DTPOFF:
1127 +         fputs ("@DTPOFF", file);
1128 +         break;
1129         default:
1130           output_operand_lossage ("invalid UNSPEC as operand");
1131           break;
1132 @@ -5710,6 +6158,43 @@ print_reg (x, code, file)
1133      }
1134  }
1135  
1136 +/* Locate some local-dynamic symbol still in use by this function
1137 +   so that we can print its name in some tls_local_dynamic_base
1138 +   pattern.  */
1139 +
1140 +static const char *
1141 +get_some_local_dynamic_name ()
1142 +{
1143 +  rtx insn;
1144 +
1145 +  if (cfun->machine->some_ld_name)
1146 +    return cfun->machine->some_ld_name;
1147 +
1148 +  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
1149 +    if (INSN_P (insn)
1150 +       && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
1151 +      return cfun->machine->some_ld_name;
1152 +
1153 +  abort ();
1154 +}
1155 +
1156 +static int
1157 +get_some_local_dynamic_name_1 (px, data)
1158 +     rtx *px;
1159 +     void *data ATTRIBUTE_UNUSED;
1160 +{
1161 +  rtx x = *px;
1162 +
1163 +  if (GET_CODE (x) == SYMBOL_REF
1164 +      && local_dynamic_symbolic_operand (x, Pmode))
1165 +    {
1166 +      cfun->machine->some_ld_name = XSTR (x, 0);
1167 +      return 1;
1168 +    }
1169 +
1170 +  return 0;
1171 +}
1172 +
1173  /* Meaning of CODE:
1174     L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
1175     C -- print opcode suffix for set/cmov insn.
1176 @@ -5734,6 +6219,7 @@ print_reg (x, code, file)
1177     D -- print condition for SSE cmp instruction.
1178     P -- if PIC, print an @PLT suffix.
1179     X -- don't print any sort of PIC '@' suffix for a symbol.
1180 +   & -- print some in-use local-dynamic symbol name.
1181   */
1182  
1183  void
1184 @@ -5751,6 +6237,10 @@ print_operand (file, x, code)
1185             putc ('*', file);
1186           return;
1187  
1188 +       case '&':
1189 +         assemble_name (file, get_some_local_dynamic_name ());
1190 +         return;
1191 +
1192         case 'A':
1193           if (ASSEMBLER_DIALECT == ASM_ATT)
1194             putc ('*', file);
1195 @@ -6078,6 +6568,18 @@ print_operand (file, x, code)
1196        REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
1197        fprintf (file, "%s", dstr);
1198      }
1199 +
1200 +  else if (GET_CODE (x) == CONST
1201 +          && GET_CODE (XEXP (x, 0)) == UNSPEC
1202 +          && XINT (XEXP (x, 0), 1) == UNSPEC_TP)
1203 +    {
1204 +      if (ASSEMBLER_DIALECT == ASM_INTEL)
1205 +       fputs ("DWORD PTR ", file);
1206 +      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
1207 +       putc ('%', file);
1208 +      fputs ("gs:0", file);
1209 +    }
1210 +
1211    else
1212      {
1213        if (code != 'P')
1214 @@ -6226,6 +6728,43 @@ print_operand_address (file, addr)
1215         }
1216      }
1217  }
1218 +
1219 +bool
1220 +output_addr_const_extra (file, x)
1221 +     FILE *file;
1222 +     rtx x;
1223 +{
1224 +  rtx op;
1225 +
1226 +  if (GET_CODE (x) != UNSPEC)
1227 +    return false;
1228 +
1229 +  op = XVECEXP (x, 0, 0);
1230 +  switch (XINT (x, 1))
1231 +    {
1232 +    case UNSPEC_GOTTPOFF:
1233 +      output_addr_const (file, op);
1234 +      fputs ("@GOTTPOFF", file);
1235 +      break;
1236 +    case UNSPEC_TPOFF:
1237 +      output_addr_const (file, op);
1238 +      fputs ("@TPOFF", file);
1239 +      break;
1240 +    case UNSPEC_NTPOFF:
1241 +      output_addr_const (file, op);
1242 +      fputs ("@NTPOFF", file);
1243 +      break;
1244 +    case UNSPEC_DTPOFF:
1245 +      output_addr_const (file, op);
1246 +      fputs ("@DTPOFF", file);
1247 +      break;
1248 +
1249 +    default:
1250 +      return false;
1251 +    }
1252 +
1253 +  return true;
1254 +}
1255  \f
1256  /* Split one or more DImode RTL references into pairs of SImode
1257     references.  The RTL can be REG, offsettable MEM, integer constant, or
1258 @@ -6763,51 +7302,117 @@ ix86_expand_clear (dest)
1259    emit_insn (tmp);
1260  }
1261  
1262 +/* X is an unchanging MEM.  If it is a constant pool reference, return
1263 +   the constant pool rtx, else NULL.  */
1264 +
1265 +static rtx
1266 +maybe_get_pool_constant (x)
1267 +     rtx x;
1268 +{
1269 +  x = XEXP (x, 0);
1270 +
1271 +  if (flag_pic)
1272 +    {
1273 +      if (GET_CODE (x) != PLUS)
1274 +       return NULL_RTX;
1275 +      if (XEXP (x, 0) != pic_offset_table_rtx)
1276 +       return NULL_RTX;
1277 +      x = XEXP (x, 1);
1278 +      if (GET_CODE (x) != CONST)
1279 +       return NULL_RTX;
1280 +      x = XEXP (x, 0);
1281 +      if (GET_CODE (x) != UNSPEC)
1282 +       return NULL_RTX;
1283 +      if (XINT (x, 1) != UNSPEC_GOTOFF)
1284 +       return NULL_RTX;
1285 +      x = XVECEXP (x, 0, 0);
1286 +    }
1287 +
1288 +  if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
1289 +    return get_pool_constant (x);
1290 +
1291 +  return NULL_RTX;
1292 +}
1293 +
1294  void
1295  ix86_expand_move (mode, operands)
1296       enum machine_mode mode;
1297       rtx operands[];
1298  {
1299    int strict = (reload_in_progress || reload_completed);
1300 -  rtx insn;
1301 +  rtx insn, op0, op1, tmp;
1302 +
1303 +  op0 = operands[0];
1304 +  op1 = operands[1];
1305  
1306 -  if (flag_pic && mode == Pmode && symbolic_operand (operands[1], Pmode))
1307 +  /* ??? We have a slight problem.  We need to say that tls symbols are
1308 +     not legitimate constants so that reload does not helpfully reload
1309 +     these constants from a REG_EQUIV, which we cannot handle.  (Recall
1310 +     that general- and local-dynamic address resolution requires a
1311 +     function call.)
1312 +
1313 +     However, if we say that tls symbols are not legitimate constants,
1314 +     then emit_move_insn helpfully drop them into the constant pool.
1315 +
1316 +     It is far easier to work around emit_move_insn than reload.  Recognize
1317 +     the MEM that we would have created and extract the symbol_ref.  */
1318 +
1319 +  if (mode == Pmode
1320 +      && GET_CODE (op1) == MEM
1321 +      && RTX_UNCHANGING_P (op1))
1322      {
1323 -      /* Emit insns to move operands[1] into operands[0].  */
1324 +      tmp = maybe_get_pool_constant (op1);
1325 +      /* Note that we only care about symbolic constants here, which
1326 +        unlike CONST_INT will always have a proper mode.  */
1327 +      if (tmp && GET_MODE (tmp) == Pmode)
1328 +       op1 = tmp;
1329 +    }
1330  
1331 -      if (GET_CODE (operands[0]) == MEM)
1332 -       operands[1] = force_reg (Pmode, operands[1]);
1333 +  if (tls_symbolic_operand (op1, Pmode))
1334 +    {
1335 +      op1 = legitimize_address (op1, op1, VOIDmode);
1336 +      if (GET_CODE (op0) == MEM)
1337 +       {
1338 +         tmp = gen_reg_rtx (mode);
1339 +         emit_insn (gen_rtx_SET (VOIDmode, tmp, op1));
1340 +         op1 = tmp;
1341 +       }
1342 +    }
1343 +  else if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
1344 +    {
1345 +      if (GET_CODE (op0) == MEM)
1346 +       op1 = force_reg (Pmode, op1);
1347        else
1348         {
1349 -         rtx temp = operands[0];
1350 +         rtx temp = op0;
1351           if (GET_CODE (temp) != REG)
1352             temp = gen_reg_rtx (Pmode);
1353 -         temp = legitimize_pic_address (operands[1], temp);
1354 -         if (temp == operands[0])
1355 +         temp = legitimize_pic_address (op1, temp);
1356 +         if (temp == op0)
1357             return;
1358 -         operands[1] = temp;
1359 +         op1 = temp;
1360         }
1361      }
1362    else
1363      {
1364 -      if (GET_CODE (operands[0]) == MEM
1365 +      if (GET_CODE (op0) == MEM
1366           && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
1367 -             || !push_operand (operands[0], mode))
1368 -         && GET_CODE (operands[1]) == MEM)
1369 -       operands[1] = force_reg (mode, operands[1]);
1370 -
1371 -      if (push_operand (operands[0], mode)
1372 -         && ! general_no_elim_operand (operands[1], mode))
1373 -       operands[1] = copy_to_mode_reg (mode, operands[1]);
1374 +             || !push_operand (op0, mode))
1375 +         && GET_CODE (op1) == MEM)
1376 +       op1 = force_reg (mode, op1);
1377 +
1378 +      if (push_operand (op0, mode)
1379 +         && ! general_no_elim_operand (op1, mode))
1380 +       op1 = copy_to_mode_reg (mode, op1);
1381  
1382        /* Force large constants in 64bit compilation into register
1383          to get them CSEed.  */
1384        if (TARGET_64BIT && mode == DImode
1385 -         && immediate_operand (operands[1], mode)
1386 -         && !x86_64_zero_extended_value (operands[1])
1387 -         && !register_operand (operands[0], mode)
1388 +         && immediate_operand (op1, mode)
1389 +         && !x86_64_zero_extended_value (op1)
1390 +         && !register_operand (op0, mode)
1391           && optimize && !reload_completed && !reload_in_progress)
1392 -       operands[1] = copy_to_mode_reg (mode, operands[1]);
1393 +       op1 = copy_to_mode_reg (mode, op1);
1394  
1395        if (FLOAT_MODE_P (mode))
1396         {
1397 @@ -6817,13 +7422,13 @@ ix86_expand_move (mode, operands)
1398  
1399           if (strict)
1400             ;
1401 -         else if (GET_CODE (operands[1]) == CONST_DOUBLE
1402 -                  && register_operand (operands[0], mode))
1403 -           operands[1] = validize_mem (force_const_mem (mode, operands[1]));
1404 +         else if (GET_CODE (op1) == CONST_DOUBLE
1405 +                  && register_operand (op0, mode))
1406 +           op1 = validize_mem (force_const_mem (mode, op1));
1407         }
1408      }
1409  
1410 -  insn = gen_rtx_SET (VOIDmode, operands[0], operands[1]);
1411 +  insn = gen_rtx_SET (VOIDmode, op0, op1);
1412  
1413    emit_insn (insn);
1414  }
1415 @@ -8588,13 +9193,14 @@ ix86_split_to_parts (operand, parts, mod
1416    if (size < 2 || size > 3)
1417      abort ();
1418  
1419 -  /* Optimize constant pool reference to immediates.  This is used by fp moves,
1420 -     that force all constants to memory to allow combining.  */
1421 -
1422 -  if (GET_CODE (operand) == MEM
1423 -      && GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
1424 -      && CONSTANT_POOL_ADDRESS_P (XEXP (operand, 0)))
1425 -    operand = get_pool_constant (XEXP (operand, 0));
1426 +  /* Optimize constant pool reference to immediates.  This is used by fp
1427 +     moves, that force all constants to memory to allow combining.  */
1428 +  if (GET_CODE (operand) == MEM && RTX_UNCHANGING_P (operand))
1429 +    {
1430 +      rtx tmp = maybe_get_pool_constant (operand);
1431 +      if (tmp)
1432 +       operand = tmp;
1433 +    }
1434  
1435    if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
1436      {
1437 @@ -9790,6 +10396,55 @@ ix86_expand_strlensi_unroll_1 (out, alig
1438  
1439    emit_label (end_0_label);
1440  }
1441 +
1442 +void
1443 +ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
1444 +     rtx retval, fnaddr, callarg1, callarg2, pop;
1445 +{
1446 +  rtx use = NULL, call;
1447 +
1448 +  if (pop == const0_rtx)
1449 +    pop = NULL;
1450 +  if (TARGET_64BIT && pop)
1451 +    abort ();
1452 +
1453 +  /* Static functions and indirect calls don't need the pic register.  */
1454 +  if (! TARGET_64BIT && flag_pic
1455 +      && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
1456 +      && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
1457 +    {
1458 +      current_function_uses_pic_offset_table = 1;
1459 +      use_reg (&use, pic_offset_table_rtx);
1460 +    }
1461 +
1462 +  if (TARGET_64BIT && INTVAL (callarg2) >= 0)
1463 +    {
1464 +      rtx al = gen_rtx_REG (QImode, 0);
1465 +      emit_move_insn (al, callarg2);
1466 +      use_reg (&use, al);
1467 +    }
1468 +
1469 +  if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
1470 +    {
1471 +      fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
1472 +      fnaddr = gen_rtx_MEM (QImode, fnaddr);
1473 +    }
1474 +
1475 +  call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1476 +  if (retval)
1477 +    call = gen_rtx_SET (VOIDmode, retval, call);
1478 +  if (pop)
1479 +    {
1480 +      pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
1481 +      pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
1482 +      call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
1483 +    }
1484 +
1485 +  call = emit_call_insn (call);
1486 +  if (use)
1487 +    CALL_INSN_FUNCTION_USAGE (call) = use;
1488 +}
1489 +  
1490  \f
1491  /* Clear stack slot assignments remembered from previous functions.
1492     This is called from INIT_EXPANDERS once before RTL is emitted for each
1493 @@ -9849,6 +10504,24 @@ assign_386_stack_local (mode, n)
1494  
1495    return ix86_stack_locals[(int) mode][n];
1496  }
1497 +
1498 +/* Construct the SYMBOL_REF for the tls_get_addr function.  */
1499 +
1500 +rtx
1501 +ix86_tls_get_addr ()
1502 +{
1503 +  static rtx symbol;
1504 +
1505 +  if (!symbol)
1506 +    {
1507 +      symbol = gen_rtx_SYMBOL_REF (Pmode, (TARGET_GNU_TLS
1508 +                                          ? "___tls_get_addr"
1509 +                                          : "__tls_get_addr"));
1510 +      ggc_add_rtx_root (&symbol, 1);
1511 +    }
1512 +
1513 +  return symbol;
1514 +}
1515  \f
1516  /* Calculate the length of the memory address in the instruction
1517     encoding.  Does not include the one-byte modrm, opcode, or prefix.  */
1518 --- gcc/config/i386/i386-protos.h.jj    Wed Jun 19 15:18:02 2002
1519 +++ gcc/config/i386/i386-protos.h       Wed Jun 19 19:33:52 2002
1520 @@ -28,7 +28,6 @@ extern int ix86_frame_pointer_required P
1521  extern void ix86_setup_frame_addresses PARAMS ((void));
1522  
1523  extern void ix86_asm_file_end PARAMS ((FILE *));
1524 -extern void load_pic_register PARAMS ((void));
1525  extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
1526  extern void ix86_expand_prologue PARAMS ((void));
1527  extern void ix86_expand_epilogue PARAMS ((int));
1528 @@ -36,6 +35,9 @@ extern void ix86_expand_epilogue PARAMS 
1529  extern void ix86_output_addr_vec_elt PARAMS ((FILE *, int));
1530  extern void ix86_output_addr_diff_elt PARAMS ((FILE *, int, int));
1531  
1532 +extern void ix86_encode_section_info PARAMS ((tree));
1533 +extern const char *ix86_strip_name_encoding PARAMS ((const char *));
1534 +
1535  #ifdef RTX_CODE
1536  extern int ix86_aligned_p PARAMS ((rtx));
1537  
1538 @@ -51,6 +53,11 @@ extern int x86_64_immediate_operand PARA
1539  extern int x86_64_zext_immediate_operand PARAMS ((rtx, enum machine_mode));
1540  extern int const_int_1_operand PARAMS ((rtx, enum machine_mode));
1541  extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
1542 +extern int tls_symbolic_operand PARAMS ((rtx, enum machine_mode));
1543 +extern int global_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
1544 +extern int local_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
1545 +extern int initial_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
1546 +extern int local_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
1547  extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
1548  extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
1549  extern int constant_call_address_operand PARAMS ((rtx, enum machine_mode));
1550 @@ -84,6 +91,9 @@ extern int ix86_expand_movstr PARAMS ((r
1551  extern int ix86_expand_clrstr PARAMS ((rtx, rtx, rtx));
1552  extern int ix86_expand_strlen PARAMS ((rtx, rtx, rtx, rtx));
1553  
1554 +extern bool legitimate_constant_p PARAMS ((rtx));
1555 +extern bool constant_address_p PARAMS ((rtx));
1556 +extern bool legitimate_pic_operand_p PARAMS ((rtx));
1557  extern int legitimate_pic_address_disp_p PARAMS ((rtx));
1558  extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
1559  extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
1560 @@ -92,10 +102,12 @@ extern rtx legitimize_address PARAMS ((r
1561  extern void print_reg PARAMS ((rtx, int, FILE*));
1562  extern void print_operand PARAMS ((FILE*, rtx, int));
1563  extern void print_operand_address PARAMS ((FILE*, rtx));
1564 +extern bool output_addr_const_extra PARAMS ((FILE*, rtx));
1565  
1566  extern void split_di PARAMS ((rtx[], int, rtx[], rtx[]));
1567  extern void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
1568  
1569 +extern const char *output_set_got PARAMS ((rtx));
1570  extern const char *output_387_binary_op PARAMS ((rtx, rtx*));
1571  extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
1572  extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
1573 @@ -121,6 +133,7 @@ extern void ix86_expand_branch PARAMS ((
1574  extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
1575  extern int ix86_expand_int_movcc PARAMS ((rtx[]));
1576  extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
1577 +extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx));
1578  extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
1579  extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
1580  extern void ix86_split_long_move PARAMS ((rtx[]));
1581 @@ -181,6 +194,8 @@ extern rtx ix86_expand_builtin PARAMS ((
1582  
1583  #endif
1584  
1585 +extern rtx ix86_tls_get_addr PARAMS ((void));
1586 +
1587  #ifdef TREE_CODE
1588  extern int ix86_return_pops_args PARAMS ((tree, tree, int));
1589  extern tree ix86_build_va_list PARAMS ((void));
1590 --- gcc/config/i386/i386.h.jj   Wed Jun 19 19:33:51 2002
1591 +++ gcc/config/i386/i386.h      Wed Jun 19 20:20:56 2002
1592 @@ -282,6 +282,9 @@ extern int x86_prefetch_sse;
1593  
1594  #define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
1595  
1596 +#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
1597 +#define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN)
1598 +
1599  /* WARNING: Do not mark empty strings for translation, as calling
1600              gettext on an empty string does NOT return an empty
1601              string. */
1602 @@ -451,6 +454,8 @@ extern int ix86_arch;
1603      "" /* Undocumented. */ },                                  \
1604    { "asm=", &ix86_asm_string,                                  \
1605      N_("Use given assembler dialect") },                       \
1606 +  { "tls-dialect=", &ix86_tls_dialect_string,                  \
1607 +    N_("Use given thread-local storage dialect") },            \
1608    SUBTARGET_OPTIONS                                            \
1609  }
1610  
1611 @@ -1934,15 +1939,12 @@ do {                                                                    \
1612  
1613  #define MAX_REGS_PER_ADDRESS 2
1614  
1615 -#define CONSTANT_ADDRESS_P(X)                                  \
1616 -  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF     \
1617 -   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST       \
1618 -   || GET_CODE (X) == CONST_DOUBLE)
1619 +#define CONSTANT_ADDRESS_P(X)  constant_address_p (X)
1620  
1621  /* Nonzero if the constant value X is a legitimate general operand.
1622     It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
1623  
1624 -#define LEGITIMATE_CONSTANT_P(X) 1
1625 +#define LEGITIMATE_CONSTANT_P(X)  legitimate_constant_p (X)
1626  
1627  #ifdef REG_OK_STRICT
1628  #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                                \
1629 @@ -2005,9 +2007,7 @@ do {                                                                      \
1630     when generating PIC code.  It is given that flag_pic is on and 
1631     that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
1632  
1633 -#define LEGITIMATE_PIC_OPERAND_P(X)            \
1634 -  (! SYMBOLIC_CONST (X)                                \
1635 -   || legitimate_pic_address_disp_p (X))
1636 +#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
1637  
1638  #define SYMBOLIC_CONST(X)      \
1639    (GET_CODE (X) == SYMBOL_REF                                          \
1640 @@ -2251,33 +2251,23 @@ enum ix86_builtins
1641     On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
1642     so that we may access it directly in the GOT.  */
1643  
1644 -#define ENCODE_SECTION_INFO(DECL)                              \
1645 -do {                                                           \
1646 -    if (flag_pic)                                              \
1647 -      {                                                                \
1648 -       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'    \
1649 -                  ? TREE_CST_RTL (DECL) : DECL_RTL (DECL));    \
1650 -                                                               \
1651 -       if (GET_CODE (rtl) == MEM)                              \
1652 -         {                                                     \
1653 -           if (TARGET_DEBUG_ADDR                               \
1654 -               && TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd')   \
1655 -             {                                                 \
1656 -               fprintf (stderr, "Encode %s, public = %d\n",    \
1657 -                        IDENTIFIER_POINTER (DECL_NAME (DECL)), \
1658 -                        TREE_PUBLIC (DECL));                   \
1659 -             }                                                 \
1660 -                                                               \
1661 -           SYMBOL_REF_FLAG (XEXP (rtl, 0))                     \
1662 -             = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'      \
1663 -                || ! TREE_PUBLIC (DECL)                        \
1664 -                || MODULE_LOCAL_P (DECL));                     \
1665 -         }                                                     \
1666 -      }                                                                \
1667 -} while (0)
1668 -
1669 +#define ENCODE_SECTION_INFO(DECL)  ix86_encode_section_info(DECL)
1670  #define REDO_SECTION_INFO_P(DECL) 1
1671  
1672 +#define STRIP_NAME_ENCODING(VAR,STR)  ((VAR) = ix86_strip_name_encoding (STR))
1673 +
1674 +#define ASM_OUTPUT_LABELREF(FILE,NAME)         \
1675 +  do {                                         \
1676 +    const char *xname = (NAME);                        \
1677 +    if (xname[0] == '%')                       \
1678 +      xname += 2;                              \
1679 +    if (xname[0] == '*')                       \
1680 +      xname += 1;                              \
1681 +    else                                       \
1682 +      fputs (user_label_prefix, FILE);         \
1683 +    fputs (xname, FILE);                       \
1684 +  } while (0)
1685 +
1686  /* The `FINALIZE_PIC' macro serves as a hook to emit these special
1687     codes once the function is being compiled into assembly code, but
1688     not before.  (It is not done before, because in the case of
1689 @@ -2923,7 +2913,7 @@ extern int const svr4_dbx_register_map[F
1690     print_operand function.  */
1691  
1692  #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
1693 -  ((CODE) == '*' || (CODE) == '+')
1694 +  ((CODE) == '*' || (CODE) == '+' || (CODE) == '&')
1695  
1696  /* Print the name of a register based on its machine mode and number.
1697     If CODE is 'w', pretend the mode is HImode.
1698 @@ -2942,6 +2932,12 @@ extern int const svr4_dbx_register_map[F
1699  #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
1700    print_operand_address ((FILE), (ADDR))
1701  
1702 +#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
1703 +do {                                           \
1704 +  if (! output_addr_const_extra (FILE, (X)))   \
1705 +    goto FAIL;                                 \
1706 +} while (0);
1707 +
1708  /* Print the name of a register for based on its machine mode and number.
1709     This macro is used to print debugging output.
1710     This macro is different from PRINT_REG in that it may be used in
1711 @@ -3071,7 +3067,12 @@ extern int const svr4_dbx_register_map[F
1712    {"memory_displacement_operand", {MEM}},                              \
1713    {"cmpsi_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,       \
1714                      LABEL_REF, SUBREG, REG, MEM, AND}},                \
1715 -  {"long_memory_operand", {MEM}},
1716 +  {"long_memory_operand", {MEM}},                                      \
1717 +  {"tls_symbolic_operand", {SYMBOL_REF}},                              \
1718 +  {"global_dynamic_symbolic_operand", {SYMBOL_REF}},                   \
1719 +  {"local_dynamic_symbolic_operand", {SYMBOL_REF}},                    \
1720 +  {"initial_exec_symbolic_operand", {SYMBOL_REF}},                     \
1721 +  {"local_exec_symbolic_operand", {SYMBOL_REF}},
1722  
1723  /* A list of predicates that do special things with modes, and so
1724     should not elicit warnings for VOIDmode match_operand.  */
1725 @@ -3112,6 +3113,16 @@ enum asm_dialect {
1726  };
1727  extern const char *ix86_asm_string;
1728  extern enum asm_dialect ix86_asm_dialect;
1729 +
1730 +enum tls_dialect
1731 +{
1732 +  TLS_DIALECT_GNU,
1733 +  TLS_DIALECT_SUN
1734 +};
1735 +
1736 +extern enum tls_dialect ix86_tls_dialect;
1737 +extern const char *ix86_tls_dialect_string;
1738 +  
1739  /* Value of -mcmodel specified by user.  */
1740  extern const char *ix86_cmodel_string;
1741  extern enum cmodel ix86_cmodel;
1742 --- gcc/config/i386/i386.md.jj  Tue Jun  4 20:28:36 2002
1743 +++ gcc/config/i386/i386.md     Wed Jun 19 19:33:52 2002
1744 @@ -49,55 +49,59 @@
1745  ;; 'k' Likewise, print the SImode name of the register.
1746  ;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
1747  ;; 'y' Print "st(0)" instead of "st" as a register.
1748 -;;
1749 +
1750  ;; UNSPEC usage:
1751 -;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
1752 -;;    operand 0 is the memory address to scan.
1753 -;;    operand 1 is a register containing the value to scan for.  The mode
1754 -;;       of the scas opcode will be the same as the mode of this operand.
1755 -;;    operand 2 is the known alignment of operand 0.
1756 -;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
1757 -;;    operand 0 is the argument for `sin'.
1758 -;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
1759 -;;    operand 0 is the argument for `cos'.
1760 -;; 3  This is part of a `stack probe' operation.  The mode of the UNSPEC is 
1761 -;;    always SImode.  operand 0 is the size of the stack allocation.
1762 -;; 4  This is the source of a fake SET of the frame pointer which is used to
1763 -;;    prevent insns referencing it being scheduled across the initial
1764 -;;    decrement of the stack pointer.
1765 -;; 5  This is a `bsf' operation.
1766 -;; 6  This is the @GOT offset of a PIC address.
1767 -;; 7  This is the @GOTOFF offset of a PIC address.
1768 -;; 8  This is a reference to a symbol's @PLT address.
1769 -;; 9  This is an `fnstsw' operation.
1770 -;; 10 This is a `sahf' operation.
1771 -;; 11 This is a `fstcw' operation
1772 -;; 12 This is behaviour of add when setting carry flag.
1773 -;; 13 This is a `eh_return' placeholder.
1774 -
1775 -;; For SSE/MMX support:
1776 -;; 30 This is `fix', guaranteed to be truncating.
1777 -;; 31 This is a `emms' operation.
1778 -;; 32 This is a `maskmov' operation.
1779 -;; 33 This is a `movmsk' operation.
1780 -;; 34 This is a `non-temporal' move.
1781 -;; 36 This is used to distinguish COMISS from UCOMISS.
1782 -;; 37 This is a `ldmxcsr' operation.
1783 -;; 38 This is a forced `movaps' instruction (rather than whatever movti does)
1784 -;; 39 This is a forced `movups' instruction (rather than whatever movti does)
1785 -;; 40 This is a `stmxcsr' operation.
1786 -;; 41 This is a `shuffle' operation.
1787 -;; 42 This is a `rcp' operation.
1788 -;; 43 This is a `rsqsrt' operation.
1789 -;; 44 This is a `sfence' operation.
1790 -;; 45 This is a noop to prevent excessive combiner cleverness.
1791 -;; 46 This is a `femms' operation.
1792 -;; 49 This is a 'pavgusb' operation.
1793 -;; 50 This is a `pfrcp' operation.
1794 -;; 51 This is a `pfrcpit1' operation.
1795 -;; 52 This is a `pfrcpit2' operation.
1796 -;; 53 This is a `pfrsqrt' operation.
1797 -;; 54 This is a `pfrsqrit1' operation.
1798 +;; ??? Note that the 3.1 branch, unlike mainline, has not had all
1799 +;; of the uses of UNSPEC replaced with their symbolic constants.
1800 +;; Thus you cannot change these arbitrarily without pain.
1801 +
1802 +(define_constants
1803 +  [(UNSPEC_SCAS                        0)
1804 +   (UNSPEC_SIN                 1)
1805 +   (UNSPEC_COS                 2)
1806 +   (UNSPEC_STACK_PROBE         3)
1807 +   (UNSPEC_STACK_ALLOC         4)
1808 +   (UNSPEC_BSF                 5)
1809 +   (UNSPEC_GOT                 6)
1810 +   (UNSPEC_GOTOFF              7)
1811 +   (UNSPEC_PLT                 8)
1812 +   (UNSPEC_FNSTSW              9)
1813 +   (UNSPEC_SAHF                        10)
1814 +   (UNSPEC_FSTCW               11)
1815 +   (UNSPEC_FLDCW               12)
1816 +   (UNSPEC_ADD_CARRY           12)
1817 +   (UNSPEC_EH_RETURN           13)
1818 +   (UNSPEC_GOTPCREL            15)
1819 +   (UNSPEC_SET_GOT             16)
1820 +
1821 +   ; For TLS support:
1822 +   (UNSPEC_GOTTPOFF             20)
1823 +   (UNSPEC_TPOFF                21)
1824 +   (UNSPEC_NTPOFF               22)
1825 +   (UNSPEC_DTPOFF               23)
1826 +   (UNSPEC_TP                   24)
1827 +   (UNSPEC_TLS_GD               25)
1828 +   (UNSPEC_TLS_LD_BASE          26)
1829 +
1830 +   ; For SSE/MMX support:
1831 +   (UNSPEC_FIX                  30)
1832 +   (UNSPEC_MASKMOV              32)
1833 +   (UNSPEC_MOVMSK               33)
1834 +   (UNSPEC_MOVNT                34)
1835 +   (UNSPEC_MOVA                 38)
1836 +   (UNSPEC_MOVU                 39)
1837 +   (UNSPEC_SHUFFLE              41)
1838 +   (UNSPEC_RCP                  42)
1839 +   (UNSPEC_RSQRT                43)
1840 +   (UNSPEC_SFENCE               44)
1841 +   (UNSPEC_NOP                  45)     ; prevents combiner cleverness
1842 +   (UNSPEC_PAVGUSB              49)
1843 +   (UNSPEC_PFRCP                50)
1844 +   (UNSPEC_PFRCPIT1             51)
1845 +   (UNSPEC_PFRCPIT2             52)
1846 +   (UNSPEC_PFRSQRT              53)
1847 +   (UNSPEC_PFRSQIT1             54)
1848 +  ])
1849  
1850  ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
1851  ;; from i386.c.
1852 @@ -1759,7 +1763,7 @@
1853        return "lea{l}\t{%1, %0|%0, %1}";
1854  
1855      default:
1856 -      if (flag_pic && SYMBOLIC_CONST (operands[1]))
1857 +      if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
1858         abort();
1859        return "mov{l}\t{%1, %0|%0, %1}";
1860      }
1861 @@ -2525,7 +2529,7 @@
1862      case TYPE_LEA:
1863        return "lea{q}\t{%a1, %0|%0, %a1}";
1864      default:
1865 -      if (flag_pic && SYMBOLIC_CONST (operands[1]))
1866 +      if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
1867         abort ();
1868        if (get_attr_mode (insn) == MODE_SI)
1869         return "mov{l}\t{%k1, %k0|%k0, %k1}";
1870 @@ -13474,21 +13478,8 @@
1871                             (match_operand:SI 3 "" "")))])]
1872    "!TARGET_64BIT"
1873  {
1874 -  if (operands[3] == const0_rtx)
1875 -    {
1876 -      emit_insn (gen_call (operands[0], operands[1], constm1_rtx));
1877 -      DONE;
1878 -    }
1879 -  /* Static functions and indirect calls don't need
1880 -     current_function_uses_pic_offset_table.  */
1881 -  if (flag_pic
1882 -      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
1883 -      && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
1884 -    current_function_uses_pic_offset_table = 1;
1885 -  if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
1886 -    XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1887 -  if (TARGET_64BIT)
1888 -    abort();
1889 +  ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]);
1890 +  DONE;
1891  })
1892  
1893  (define_insn "*call_pop_0"
1894 @@ -13530,37 +13521,12 @@
1895    [(call (match_operand:QI 0 "" "")
1896          (match_operand 1 "" ""))
1897     (use (match_operand 2 "" ""))]
1898 -  ;; Operand 1 not used on the i386.
1899    ""
1900  {
1901 -  rtx insn;
1902 -  /* Static functions and indirect calls don't need
1903 -     current_function_uses_pic_offset_table.  */
1904 -  if (flag_pic
1905 -      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
1906 -      && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
1907 -    current_function_uses_pic_offset_table = 1;
1908 -
1909 -  if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
1910 -    XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1911 -  if (TARGET_64BIT && INTVAL (operands[2]) >= 0)
1912 -    {
1913 -      rtx reg = gen_rtx_REG (QImode, 0);
1914 -      emit_move_insn (reg, operands[2]);
1915 -      insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
1916 -      use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
1917 -      DONE;
1918 -    }
1919 -   insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
1920 -   DONE;
1921 +  ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL);
1922 +  DONE;
1923  })
1924  
1925 -(define_expand "call_exp"
1926 -  [(call (match_operand:QI 0 "" "")
1927 -        (match_operand 1 "" ""))]
1928 -  ""
1929 -  "")
1930 -
1931  (define_insn "*call_0"
1932    [(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
1933          (match_operand 1 "" ""))]
1934 @@ -13612,7 +13578,6 @@
1935    [(set_attr "type" "call")])
1936  
1937  ;; Call subroutine, returning value in operand 0
1938 -;; (which must be a hard register).
1939  
1940  (define_expand "call_value_pop"
1941    [(parallel [(set (match_operand 0 "" "")
1942 @@ -13623,20 +13588,9 @@
1943                             (match_operand:SI 4 "" "")))])]
1944    "!TARGET_64BIT"
1945  {
1946 -  if (operands[4] == const0_rtx)
1947 -    {
1948 -      emit_insn (gen_call_value (operands[0], operands[1], operands[2],
1949 -                                constm1_rtx));
1950 -      DONE;
1951 -    }
1952 -  /* Static functions and indirect calls don't need
1953 -     current_function_uses_pic_offset_table.  */
1954 -  if (flag_pic
1955 -      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
1956 -      && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
1957 -    current_function_uses_pic_offset_table = 1;
1958 -  if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
1959 -    XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1960 +  ix86_expand_call (operands[0], operands[1], operands[2],
1961 +                   operands[3], operands[4]);
1962 +  DONE;
1963  })
1964  
1965  (define_expand "call_value"
1966 @@ -13647,36 +13601,10 @@
1967    ;; Operand 2 not used on the i386.
1968    ""
1969  {
1970 -  rtx insn;
1971 -  /* Static functions and indirect calls don't need
1972 -     current_function_uses_pic_offset_table.  */
1973 -  if (flag_pic
1974 -      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
1975 -      && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
1976 -    current_function_uses_pic_offset_table = 1;
1977 -  if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
1978 -    XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1979 -  if (TARGET_64BIT && INTVAL (operands[3]) >= 0)
1980 -    {
1981 -      rtx reg = gen_rtx_REG (QImode, 0);
1982 -      emit_move_insn (reg, operands[3]);
1983 -      insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
1984 -                                                operands[2]));
1985 -      use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
1986 -      DONE;
1987 -    }
1988 -  insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
1989 -                                            operands[2]));
1990 +  ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL);
1991    DONE;
1992  })
1993  
1994 -(define_expand "call_value_exp"
1995 -  [(set (match_operand 0 "" "")
1996 -       (call (match_operand:QI 1 "" "")
1997 -             (match_operand:SI 2 "" "")))]
1998 -  ""
1999 -  "")
2000 -
2001  ;; Call subroutine returning any type.
2002  
2003  (define_expand "untyped_call"
2004 @@ -13693,12 +13621,10 @@
2005       simply pretend the untyped call returns a complex long double
2006       value.  */
2007  
2008 -  emit_call_insn (TARGET_FLOAT_RETURNS_IN_80387
2009 -                  ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
2010 -                                   operands[0], const0_rtx,
2011 -                                   GEN_INT (SSE_REGPARM_MAX - 1))
2012 -                  : gen_call (operands[0], const0_rtx,
2013 -                             GEN_INT (SSE_REGPARM_MAX - 1)));
2014 +  ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
2015 +                    ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
2016 +                   operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
2017 +                   NULL);
2018  
2019    for (i = 0; i < XVECLEN (operands[2], 0); i++)
2020      {
2021 @@ -13781,45 +13707,39 @@
2022    ""
2023    "ix86_expand_prologue (); DONE;")
2024  
2025 -(define_insn "prologue_set_got"
2026 +(define_expand "set_got"
2027 +  [(parallel [(set (match_operand:SI 0 "register_operand" "")
2028 +                  (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
2029 +             (clobber (reg:CC 17))])]
2030 +  "!TARGET_64BIT"
2031 +  "")
2032 +
2033 +(define_insn "*set_got_nopic"
2034    [(set (match_operand:SI 0 "register_operand" "=r")
2035 -       (unspec_volatile:SI
2036 -        [(plus:SI (match_dup 0)
2037 -                  (plus:SI (match_operand:SI 1 "symbolic_operand" "")
2038 -                           (minus:SI (pc) (match_operand 2 "" ""))))] 1))
2039 +       (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
2040     (clobber (reg:CC 17))]
2041 -  "!TARGET_64BIT"
2042 -{
2043 -  if (GET_CODE (operands[2]) == LABEL_REF)
2044 -     operands[2] = XEXP (operands[2], 0);
2045 -  if (TARGET_DEEP_BRANCH_PREDICTION) 
2046 -    return "add{l}\t{%1, %0|%0, %1}";
2047 -  else  
2048 -    return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}";
2049 -}
2050 -  [(set_attr "type" "alu")
2051 -   ; Since this insn may have two constant operands, we must set the
2052 -   ; length manually.
2053 -   (set_attr "length_immediate" "4")
2054 -   (set_attr "mode" "SI")])
2055 +  "!TARGET_64BIT && !flag_pic"
2056 +  { return output_set_got (operands[0]); }
2057 +  [(set_attr "type" "multi")
2058 +   (set_attr "length" "11")])
2059 +  
2060 +(define_insn "*set_got_deep"
2061 +  [(set (match_operand:SI 0 "register_operand" "=b")
2062 +       (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
2063 +   (clobber (reg:CC 17))]
2064 +  "!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
2065 +  { return output_set_got (operands[0]); }
2066 +  [(set_attr "type" "multi")
2067 +   (set_attr "length" "11")])
2068  
2069 -(define_insn "prologue_get_pc"
2070 +(define_insn "*set_got_nodeep"
2071    [(set (match_operand:SI 0 "register_operand" "=r")
2072 -    (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
2073 +       (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
2074 +   (clobber (reg:CC 17))]
2075    "!TARGET_64BIT"
2076 -{
2077 -  if (GET_CODE (operands[1]) == LABEL_REF)
2078 -    operands[1] = XEXP (operands[1], 0);
2079 -  output_asm_insn ("call\t%X1", operands);
2080 -  if (! TARGET_DEEP_BRANCH_PREDICTION)
2081 -    {
2082 -      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
2083 -                                CODE_LABEL_NUMBER (operands[1]));
2084 -      return "pop{l}\t%0";
2085 -    }
2086 -  RET;
2087 -}
2088 -  [(set_attr "type" "multi")])
2089 +  { return output_set_got (operands[0]); }
2090 +  [(set_attr "type" "multi")
2091 +   (set_attr "length" "12")])
2092  
2093  (define_expand "epilogue"
2094    [(const_int 1)]
2095 @@ -13996,6 +13916,127 @@
2096  ;; ffshi2 is not useful -- 4 word prefix ops are needed, which is larger
2097  ;; and slower than the two-byte movzx insn needed to do the work in SImode.
2098  \f
2099 +;; Thread-local storage patterns for ELF.
2100 +;;
2101 +;; Note that these code sequences must appear exactly as shown
2102 +;; in order to allow linker relaxation.
2103 +
2104 +(define_insn "*tls_global_dynamic_gnu"
2105 +  [(set (match_operand:SI 0 "register_operand" "=a")
2106 +       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
2107 +                   (match_operand:SI 2 "tls_symbolic_operand" "")
2108 +                   (match_operand:SI 3 "call_insn_operand" "")]
2109 +                   UNSPEC_TLS_GD))
2110 +   (clobber (match_scratch:SI 4 "=d"))
2111 +   (clobber (match_scratch:SI 5 "=c"))
2112 +   (clobber (reg:CC 17))]
2113 +  "TARGET_GNU_TLS"
2114 +  "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
2115 +  [(set_attr "type" "multi")
2116 +   (set_attr "length" "12")])
2117 +
2118 +(define_insn "*tls_global_dynamic_sun"
2119 +  [(set (match_operand:SI 0 "register_operand" "=a")
2120 +       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
2121 +                   (match_operand:SI 2 "tls_symbolic_operand" "")
2122 +                   (match_operand:SI 3 "call_insn_operand" "")]
2123 +                   UNSPEC_TLS_GD))
2124 +   (clobber (match_scratch:SI 4 "=d"))
2125 +   (clobber (match_scratch:SI 5 "=c"))
2126 +   (clobber (reg:CC 17))]
2127 +  "TARGET_SUN_TLS"
2128 +  "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
2129 +       push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
2130 +  [(set_attr "type" "multi")
2131 +   (set_attr "length" "14")])
2132 +
2133 +(define_expand "tls_global_dynamic"
2134 +  [(parallel [(set (match_operand:SI 0 "register_operand" "")
2135 +                  (unspec:SI
2136 +                   [(match_dup 2)
2137 +                    (match_operand:SI 1 "tls_symbolic_operand" "")
2138 +                    (match_dup 3)]
2139 +                   UNSPEC_TLS_GD))
2140 +             (clobber (match_scratch:SI 4 ""))
2141 +             (clobber (match_scratch:SI 5 ""))
2142 +             (clobber (reg:CC 17))])]
2143 +  ""
2144 +{
2145 +  if (!flag_pic)
2146 +    abort ();
2147 +  current_function_uses_pic_offset_table = 1;
2148 +  operands[2] = pic_offset_table_rtx;
2149 +  operands[3] = ix86_tls_get_addr ();
2150 +})
2151 +
2152 +(define_insn "*tls_local_dynamic_base_gnu"
2153 +  [(set (match_operand:SI 0 "register_operand" "=a")
2154 +       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
2155 +                    (match_operand:SI 2 "call_insn_operand" "")]
2156 +                  UNSPEC_TLS_LD_BASE))
2157 +   (clobber (match_scratch:SI 3 "=d"))
2158 +   (clobber (match_scratch:SI 4 "=c"))
2159 +   (clobber (reg:CC 17))]
2160 +  "TARGET_GNU_TLS"
2161 +  "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
2162 +  [(set_attr "type" "multi")
2163 +   (set_attr "length" "11")])
2164 +
2165 +(define_insn "*tls_local_dynamic_base_sun"
2166 +  [(set (match_operand:SI 0 "register_operand" "=a")
2167 +       (unspec:SI [(match_operand:SI 1 "register_operand" "b")
2168 +                    (match_operand:SI 2 "call_insn_operand" "")]
2169 +                  UNSPEC_TLS_LD_BASE))
2170 +   (clobber (match_scratch:SI 3 "=d"))
2171 +   (clobber (match_scratch:SI 4 "=c"))
2172 +   (clobber (reg:CC 17))]
2173 +  "TARGET_SUN_TLS"
2174 +  "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
2175 +       push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
2176 +  [(set_attr "type" "multi")
2177 +   (set_attr "length" "13")])
2178 +
2179 +(define_expand "tls_local_dynamic_base"
2180 +  [(parallel [(set (match_operand:SI 0 "register_operand" "")
2181 +                  (unspec:SI [(match_dup 1) (match_dup 2)]
2182 +                             UNSPEC_TLS_LD_BASE))
2183 +             (clobber (match_scratch:SI 3 ""))
2184 +             (clobber (match_scratch:SI 4 ""))
2185 +             (clobber (reg:CC 17))])]
2186 +  ""
2187 +{
2188 +  if (!flag_pic)
2189 +    abort ();
2190 +  current_function_uses_pic_offset_table = 1;
2191 +  operands[1] = pic_offset_table_rtx;
2192 +  operands[2] = ix86_tls_get_addr ();
2193 +})
2194 +
2195 +;; Local dynamic of a single variable is a lose.  Show combine how
2196 +;; to convert that back to global dynamic.
2197 +
2198 +(define_insn_and_split "*tls_local_dynamic_once"
2199 +  [(set (match_operand:SI 0 "register_operand" "=a")
2200 +       (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
2201 +                            (match_operand:SI 2 "call_insn_operand" "")]
2202 +                           UNSPEC_TLS_LD_BASE)
2203 +                (const:SI (unspec:SI
2204 +                           [(match_operand:SI 3 "tls_symbolic_operand" "")]
2205 +                           UNSPEC_DTPOFF))))
2206 +   (clobber (match_scratch:SI 4 "=d"))
2207 +   (clobber (match_scratch:SI 5 "=c"))
2208 +   (clobber (reg:CC 17))]
2209 +  ""
2210 +  "#"
2211 +  ""
2212 +  [(parallel [(set (match_dup 0)
2213 +                  (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
2214 +                             UNSPEC_TLS_GD))
2215 +             (clobber (match_dup 4))
2216 +             (clobber (match_dup 5))
2217 +             (clobber (reg:CC 17))])]
2218 +  "")
2219 +\f
2220  ;; These patterns match the binary 387 instructions for addM3, subM3,
2221  ;; mulM3 and divM3.  There are three patterns for each of DFmode and
2222  ;; SFmode.  The first is the normal insn, the second the same insn but
2223 @@ -16835,7 +16876,7 @@
2224    [(label_ref (match_operand 0 "" ""))]
2225    "!TARGET_64BIT && flag_pic"
2226  {
2227 -  load_pic_register ();
2228 +  emit_insn (gen_set_got (pic_offset_table_rtx));
2229    DONE;
2230  })
2231  \f
2232 --- gcc/config/ia64/ia64-protos.h.jj    Tue Apr 23 20:28:20 2002
2233 +++ gcc/config/ia64/ia64-protos.h       Wed Jun 19 19:33:52 2002
2234 @@ -31,6 +31,7 @@ extern int call_operand PARAMS((rtx, enu
2235  extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode));
2236  extern int got_symbolic_operand PARAMS((rtx, enum machine_mode));
2237  extern int symbolic_operand PARAMS((rtx, enum machine_mode));
2238 +extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode));
2239  extern int function_operand PARAMS((rtx, enum machine_mode));
2240  extern int setjmp_operand PARAMS((rtx, enum machine_mode));
2241  extern int move_operand PARAMS((rtx, enum machine_mode));
2242 @@ -67,6 +68,7 @@ extern int general_tfmode_operand PARAMS
2243  extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
2244  extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
2245  
2246 +extern rtx ia64_expand_move PARAMS ((rtx, rtx));
2247  extern int ia64_move_ok PARAMS((rtx, rtx));
2248  extern int ia64_depz_field_mask PARAMS((rtx, rtx));
2249  extern rtx ia64_gp_save_reg PARAMS((int));
2250 --- gcc/config/ia64/ia64.c.jj   Wed Jun 19 22:36:54 2002
2251 +++ gcc/config/ia64/ia64.c      Wed Jun 19 22:46:07 2002
2252 @@ -95,6 +95,13 @@ static const char * const ia64_output_re
2253  /* String used with the -mfixed-range= option.  */
2254  const char *ia64_fixed_range_string;
2255  
2256 +/* Determines whether we use adds, addl, or movl to generate our
2257 +   TLS immediate offsets.  */
2258 +int ia64_tls_size = 22;
2259 +
2260 +/* String used with the -mtls-size= option.  */
2261 +const char *ia64_tls_size_string;
2262 +
2263  /* Determines whether we run our final scheduling pass or not.  We always
2264     avoid the normal second scheduling pass.  */
2265  static int ia64_flag_schedule_insns2;
2266 @@ -104,6 +111,8 @@ static int ia64_flag_schedule_insns2;
2267  
2268  unsigned int ia64_section_threshold;
2269  \f
2270 +static rtx gen_tls_get_addr PARAMS ((void));
2271 +static rtx gen_thread_pointer PARAMS ((void));
2272  static int find_gr_spill PARAMS ((int));
2273  static int next_scratch_gr_reg PARAMS ((void));
2274  static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
2275 @@ -214,6 +223,11 @@ static const struct attribute_spec ia64_
2276  #undef TARGET_SCHED_CYCLE_DISPLAY
2277  #define TARGET_SCHED_CYCLE_DISPLAY ia64_cycle_display
2278  
2279 +#ifdef HAVE_AS_TLS
2280 +#undef TARGET_HAVE_TLS
2281 +#define TARGET_HAVE_TLS true
2282 +#endif
2283 +
2284  struct gcc_target targetm = TARGET_INITIALIZER;
2285  \f
2286  /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
2287 @@ -250,7 +264,10 @@ sdata_symbolic_operand (op, mode)
2288        if (CONSTANT_POOL_ADDRESS_P (op))
2289         return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
2290        else
2291 -        return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR;
2292 +       {
2293 +         const char *str = XSTR (op, 0);
2294 +          return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
2295 +       }
2296  
2297      default:
2298        break;
2299 @@ -324,6 +341,35 @@ symbolic_operand (op, mode)
2300    return 0;
2301  }
2302  
2303 +/* Return tls_model if OP refers to a TLS symbol.  */
2304 +
2305 +int
2306 +tls_symbolic_operand (op, mode)
2307 +     rtx op;
2308 +     enum machine_mode mode ATTRIBUTE_UNUSED;
2309 +{
2310 +  const char *str;
2311 +
2312 +  if (GET_CODE (op) != SYMBOL_REF)
2313 +    return 0;
2314 +  str = XSTR (op, 0);
2315 +  if (str[0] != ENCODE_SECTION_INFO_CHAR)
2316 +    return 0;
2317 +  switch (str[1])
2318 +    {
2319 +    case 'G':
2320 +      return TLS_MODEL_GLOBAL_DYNAMIC;
2321 +    case 'L':
2322 +      return TLS_MODEL_LOCAL_DYNAMIC;
2323 +    case 'i':
2324 +      return TLS_MODEL_INITIAL_EXEC;
2325 +    case 'l':
2326 +      return TLS_MODEL_LOCAL_EXEC;
2327 +    }
2328 +  return 0;
2329 +}
2330 +
2331 +
2332  /* Return 1 if OP refers to a function.  */
2333  
2334  int
2335 @@ -922,6 +968,9 @@ ia64_expand_load_address (dest, src, scr
2336    else
2337      temp = dest;
2338  
2339 +  if (tls_symbolic_operand (src, Pmode))
2340 +    abort ();
2341 +
2342    if (TARGET_AUTO_PIC)
2343      emit_insn (gen_load_gprel64 (temp, src));
2344    else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
2345 @@ -964,6 +1013,185 @@ ia64_expand_load_address (dest, src, scr
2346      emit_move_insn (dest, temp);
2347  }
2348  
2349 +static rtx
2350 +gen_tls_get_addr ()
2351 +{
2352 +  static rtx tga;
2353 +  if (!tga)
2354 +    {
2355 +      tga = init_one_libfunc ("__tls_get_addr");
2356 +      ggc_add_rtx_root (&tga, 1);
2357 +    }
2358 +  return tga;
2359 +}
2360 +
2361 +static rtx
2362 +gen_thread_pointer ()
2363 +{
2364 +  static rtx tp;
2365 +  if (!tp)
2366 +    {
2367 +      tp = gen_rtx_REG (Pmode, 13);
2368 +      RTX_UNCHANGING_P (tp) = 1;
2369 +      ggc_add_rtx_root (&tp, 1);
2370 +    }
2371 +  return tp;
2372 +}
2373 +
2374 +rtx
2375 +ia64_expand_move (op0, op1)
2376 +     rtx op0, op1;
2377 +{
2378 +  enum machine_mode mode = GET_MODE (op0);
2379 +
2380 +  if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
2381 +    op1 = force_reg (mode, op1);
2382 +
2383 +  if (mode == Pmode)
2384 +    {
2385 +      enum tls_model tls_kind;
2386 +      if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
2387 +       {
2388 +         rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
2389 +
2390 +         switch (tls_kind)
2391 +           {
2392 +           case TLS_MODEL_GLOBAL_DYNAMIC:
2393 +             start_sequence ();
2394 +
2395 +             tga_op1 = gen_reg_rtx (Pmode);
2396 +             emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
2397 +             tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
2398 +             RTX_UNCHANGING_P (tga_op1) = 1;
2399 +
2400 +             tga_op2 = gen_reg_rtx (Pmode);
2401 +             emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
2402 +             tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
2403 +             RTX_UNCHANGING_P (tga_op2) = 1;
2404 +             
2405 +             tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
2406 +                                                LCT_CONST, Pmode, 2, tga_op1,
2407 +                                                Pmode, tga_op2, Pmode);
2408 +
2409 +             insns = get_insns ();
2410 +             end_sequence ();
2411 +
2412 +             emit_libcall_block (insns, op0, tga_ret, op1);
2413 +             return NULL_RTX;
2414 +
2415 +           case TLS_MODEL_LOCAL_DYNAMIC:
2416 +             /* ??? This isn't the completely proper way to do local-dynamic
2417 +                If the call to __tls_get_addr is used only by a single symbol,
2418 +                then we should (somehow) move the dtprel to the second arg
2419 +                to avoid the extra add.  */
2420 +             start_sequence ();
2421 +
2422 +             tga_op1 = gen_reg_rtx (Pmode);
2423 +             emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
2424 +             tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
2425 +             RTX_UNCHANGING_P (tga_op1) = 1;
2426 +
2427 +             tga_op2 = const0_rtx;
2428 +
2429 +             tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
2430 +                                                LCT_CONST, Pmode, 2, tga_op1,
2431 +                                                Pmode, tga_op2, Pmode);
2432 +
2433 +             insns = get_insns ();
2434 +             end_sequence ();
2435 +
2436 +             tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
2437 +                                       UNSPEC_LD_BASE);
2438 +             tmp = gen_reg_rtx (Pmode);
2439 +             emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
2440 +
2441 +             if (register_operand (op0, Pmode))
2442 +               tga_ret = op0;
2443 +             else
2444 +               tga_ret = gen_reg_rtx (Pmode);
2445 +             if (TARGET_TLS64)
2446 +               {
2447 +                 emit_insn (gen_load_dtprel (tga_ret, op1));
2448 +                 emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
2449 +               }
2450 +             else
2451 +               emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
2452 +             if (tga_ret == op0)
2453 +               return NULL_RTX;
2454 +             op1 = tga_ret;
2455 +             break;
2456 +
2457 +           case TLS_MODEL_INITIAL_EXEC:
2458 +             tmp = gen_reg_rtx (Pmode);
2459 +             emit_insn (gen_load_ltoff_tprel (tmp, op1));
2460 +             tmp = gen_rtx_MEM (Pmode, tmp);
2461 +             RTX_UNCHANGING_P (tmp) = 1;
2462 +             tmp = force_reg (Pmode, tmp);
2463 +
2464 +             if (register_operand (op0, Pmode))
2465 +               op1 = op0;
2466 +             else
2467 +               op1 = gen_reg_rtx (Pmode);
2468 +             emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
2469 +             if (op1 == op0)
2470 +               return NULL_RTX;
2471 +             break;
2472 +
2473 +           case TLS_MODEL_LOCAL_EXEC:
2474 +             if (register_operand (op0, Pmode))
2475 +               tmp = op0;
2476 +             else
2477 +               tmp = gen_reg_rtx (Pmode);
2478 +             if (TARGET_TLS64)
2479 +               {
2480 +                 emit_insn (gen_load_tprel (tmp, op1));
2481 +                 emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
2482 +               }
2483 +             else
2484 +               emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
2485 +             if (tmp == op0)
2486 +               return NULL_RTX;
2487 +             op1 = tmp;
2488 +             break;
2489 +
2490 +           default:
2491 +             abort ();
2492 +           }
2493 +       }
2494 +      else if (!TARGET_NO_PIC && symbolic_operand (op1, DImode))
2495 +       {
2496 +         /* Before optimization starts, delay committing to any particular
2497 +            type of PIC address load.  If this function gets deferred, we
2498 +            may acquire information that changes the value of the
2499 +            sdata_symbolic_operand predicate.
2500 +
2501 +            But don't delay for function pointers.  Loading a function address
2502 +            actually loads the address of the descriptor not the function.
2503 +            If we represent these as SYMBOL_REFs, then they get cse'd with
2504 +            calls, and we end up with calls to the descriptor address instead
2505 +            of calls to the function address.  Functions are not candidates
2506 +            for sdata anyways.
2507 +
2508 +            Don't delay for LABEL_REF because the splitter loses REG_LABEL
2509 +            notes.  Don't delay for pool addresses on general principals;
2510 +            they'll never become non-local behind our back.  */
2511 +
2512 +         if (rtx_equal_function_value_matters
2513 +             && GET_CODE (op1) != LABEL_REF
2514 +             && ! (GET_CODE (op1) == SYMBOL_REF
2515 +                   && (SYMBOL_REF_FLAG (op1)
2516 +                       || CONSTANT_POOL_ADDRESS_P (op1)
2517 +                       || STRING_POOL_ADDRESS_P (op1))))
2518 +           emit_insn (gen_movdi_symbolic (op0, op1));
2519 +         else
2520 +           ia64_expand_load_address (op0, op1, NULL_RTX);
2521 +         return NULL_RTX;
2522 +       }
2523 +    }
2524 +
2525 +  return op1;
2526 +}
2527 +
2528  rtx
2529  ia64_gp_save_reg (setjmp_p)
2530       int setjmp_p;
2531 @@ -3944,6 +4172,16 @@ ia64_override_options ()
2532    if (ia64_fixed_range_string)
2533      fix_range (ia64_fixed_range_string);
2534  
2535 +  if (ia64_tls_size_string)
2536 +    {
2537 +      char *end;
2538 +      unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
2539 +      if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
2540 +       error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
2541 +      else
2542 +       ia64_tls_size = tmp;
2543 +    }
2544 +
2545    ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2546    flag_schedule_insns_after_reload = 0;
2547  
2548 @@ -4607,6 +4845,13 @@ rtx_needs_barrier (x, flags, pred)
2549           need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
2550           break;
2551  
2552 +       case UNSPEC_LTOFF_DTPMOD:
2553 +       case UNSPEC_LTOFF_DTPREL:
2554 +       case UNSPEC_DTPREL:
2555 +       case UNSPEC_LTOFF_TPREL:
2556 +       case UNSPEC_TPREL:
2557 +          break;
2558 +
2559         default:
2560           abort ();
2561         }
2562 @@ -6872,6 +7117,9 @@ ia64_encode_section_info (decl)
2563       tree decl;
2564  {
2565    const char *symbol_str;
2566 +  bool is_local, is_small;
2567 +  rtx symbol;
2568 +  char encoding = 0;
2569  
2570    if (TREE_CODE (decl) == FUNCTION_DECL)
2571      {
2572 @@ -6885,75 +7133,111 @@ ia64_encode_section_info (decl)
2573        || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
2574      return;
2575      
2576 -  symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
2577 +  symbol = XEXP (DECL_RTL (decl), 0);
2578 +  symbol_str = XSTR (symbol, 0);
2579 +
2580 +  /* A non-decl is an entry in the constant pool.  */
2581 +  if (!DECL_P (decl))
2582 +    is_local = true;
2583 +  /* Static variables are always local.  */
2584 +  else if (! TREE_PUBLIC (decl))
2585 +    is_local = true;
2586 +  /* A variable is local if the user tells us so.  */
2587 +  else if (MODULE_LOCAL_P (decl))
2588 +    is_local = true;
2589 +  /* Otherwise, variables defined outside this object may not be local.  */
2590 +  else if (DECL_EXTERNAL (decl))
2591 +    is_local = false;
2592 +  /* Linkonce and weak data are never local.  */
2593 +  else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
2594 +    is_local = false;
2595 +  /* If PIC, then assume that any global name can be overridden by
2596 +     symbols resolved from other modules.  */
2597 +  else if (flag_pic)
2598 +    is_local = false;
2599 +  /* Uninitialized COMMON variable may be unified with symbols
2600 +     resolved from other modules.  */
2601 +  else if (DECL_COMMON (decl)
2602 +          && (DECL_INITIAL (decl) == NULL
2603 +              || DECL_INITIAL (decl) == error_mark_node))
2604 +    is_local = false;
2605 +  /* Otherwise we're left with initialized (or non-common) global data
2606 +     which is of necessity defined locally.  */
2607 +  else
2608 +    is_local = true;
2609  
2610 -  /* We assume that -fpic is used only to create a shared library (dso).
2611 -     With -fpic, no global data can ever be sdata.
2612 -     Without -fpic, global common uninitialized data can never be sdata, since
2613 -     it can unify with a real definition in a dso.  */
2614 -  /* ??? Actually, we can put globals in sdata, as long as we don't use gprel
2615 -     to access them.  The linker may then be able to do linker relaxation to
2616 -     optimize references to them.  Currently sdata implies use of gprel.  */
2617 -  /* We need the DECL_EXTERNAL check for C++.  static class data members get
2618 -     both TREE_STATIC and DECL_EXTERNAL set, to indicate that they are
2619 -     statically allocated, but the space is allocated somewhere else.  Such
2620 -     decls can not be own data.  */
2621 -  if (! TARGET_NO_SDATA
2622 -      && ((TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
2623 -          && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
2624 -          && ! (TREE_PUBLIC (decl)
2625 -                && (flag_pic
2626 -                    || (DECL_COMMON (decl)
2627 -                        && (DECL_INITIAL (decl) == 0
2628 -                            || DECL_INITIAL (decl) == error_mark_node)))))
2629 -         || MODULE_LOCAL_P (decl))
2630 -      /* Either the variable must be declared without a section attribute,
2631 -        or the section must be sdata or sbss.  */
2632 -      && (DECL_SECTION_NAME (decl) == 0
2633 -         || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
2634 -                      ".sdata")
2635 -         || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
2636 -                      ".sbss")))
2637 +  is_small = false;
2638 +  if (TARGET_NO_SDATA)
2639 +    ;
2640 +  else if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
2641 +    {
2642 +      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
2643 +      if (strcmp (section, ".sdata") == 0
2644 +         || strcmp (section, ".sbss") == 0)
2645 +       is_small = true;
2646 +    }
2647 +  else
2648      {
2649        HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
2650  
2651 -      /* If the variable has already been defined in the output file, then it
2652 -        is too late to put it in sdata if it wasn't put there in the first
2653 -        place.  The test is here rather than above, because if it is already
2654 -        in sdata, then it can stay there.  */
2655 -
2656 -      if (TREE_ASM_WRITTEN (decl))
2657 -       ;
2658 -
2659 -      /* If this is an incomplete type with size 0, then we can't put it in
2660 -        sdata because it might be too big when completed.
2661 -        Objects bigger than threshold should have SDATA_NAME_FLAG_CHAR
2662 -        added if they are in .sdata or .sbss explicitely.  */
2663 -      else if (((size > 0
2664 -                && size <= (HOST_WIDE_INT) ia64_section_threshold)
2665 -               || DECL_SECTION_NAME (decl))
2666 -              && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
2667 -       {
2668 -         size_t len = strlen (symbol_str);
2669 -         char *newstr = alloca (len + 1);
2670 -         const char *string;
2671 +      /* If this is an incomplete type with size 0, then we can't put it
2672 +        in sdata because it might be too big when completed.  */
2673 +      if (size > 0 && size <= ia64_section_threshold)
2674 +       is_small = true;
2675 +    }
2676  
2677 -         *newstr = SDATA_NAME_FLAG_CHAR;
2678 -         memcpy (newstr + 1, symbol_str, len + 1);
2679 -         
2680 -         string = ggc_alloc_string (newstr, len + 1);
2681 -         XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
2682 +  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
2683 +    {
2684 +      enum tls_model kind;
2685 +      if (!flag_pic)
2686 +       {
2687 +         if (is_local)
2688 +           kind = TLS_MODEL_LOCAL_EXEC;
2689 +         else
2690 +           kind = TLS_MODEL_INITIAL_EXEC;
2691         }
2692 -    }
2693 -  /* This decl is marked as being in small data/bss but it shouldn't
2694 -     be; one likely explanation for this is that the decl has been
2695 -     moved into a different section from the one it was in when
2696 -     ENCODE_SECTION_INFO was first called.  Remove the '@'.  */
2697 -  else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
2698 +      else if (is_local)
2699 +       kind = TLS_MODEL_LOCAL_DYNAMIC;
2700 +      else
2701 +       kind = TLS_MODEL_GLOBAL_DYNAMIC;
2702 +      if (kind < flag_tls_default)
2703 +       kind = flag_tls_default;
2704 +
2705 +      encoding = " GLil"[kind];
2706 +    }
2707 +  /* Determine if DECL will wind up in .sdata/.sbss.  */
2708 +  else if (is_local && is_small)
2709 +    encoding = 's';
2710 +  
2711 +  /* Finally, encode this into the symbol string.  */
2712 +  if (encoding)
2713      {
2714 -      XSTR (XEXP (DECL_RTL (decl), 0), 0)
2715 -       = ggc_strdup (symbol_str + 1);
2716 +      char *newstr;
2717 +      size_t len;
2718 +  
2719 +      if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
2720 +       {
2721 +         if (encoding == symbol_str[1])
2722 +           return;
2723 +         /* ??? Sdata became thread or thread becaome not thread.  Lose.  */
2724 +         abort ();
2725 +       }
2726 +
2727 +      len = strlen (symbol_str);
2728 +      newstr = alloca (len + 3);
2729 +      newstr[0] = ENCODE_SECTION_INFO_CHAR;
2730 +      newstr[1] = encoding;
2731 +      memcpy (newstr + 2, symbol_str, len + 1);
2732 +
2733 +      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
2734      }
2735 +  
2736 +  /* This decl is marked as being in small data/bss but it shouldn't be;
2737 +     one likely explanation for this is that the decl has been moved into
2738 +     a different section from the one it was in when encode_section_info
2739 +     was first called.  Remove the encoding.  */
2740 +  else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
2741 +    XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
2742  }
2743  \f
2744  /* Output assembly directives for prologue regions.  */
2745 --- gcc/config/ia64/ia64.h.jj   Tue Apr 23 20:28:21 2002
2746 +++ gcc/config/ia64/ia64.h      Wed Jun 19 19:33:52 2002
2747 @@ -109,6 +109,11 @@ extern int target_flags;
2748  
2749  #define TARGET_DWARF2_ASM      (target_flags & MASK_DWARF2_ASM)
2750  
2751 +extern int ia64_tls_size;
2752 +#define TARGET_TLS14           (ia64_tls_size == 14)
2753 +#define TARGET_TLS22           (ia64_tls_size == 22)
2754 +#define TARGET_TLS64           (ia64_tls_size == 64)
2755 +
2756  /* This macro defines names of command options to set and clear bits in
2757     `target_flags'.  Its definition is an initializer with a subgrouping for
2758     each command option.  */
2759 @@ -177,10 +182,13 @@ extern int target_flags;
2760     subgrouping for each command option.  */
2761  
2762  extern const char *ia64_fixed_range_string;
2763 +extern const char *ia64_tls_size_string;
2764  #define TARGET_OPTIONS \
2765  {                                                                      \
2766    { "fixed-range=",    &ia64_fixed_range_string,                       \
2767        N_("Specify range of registers to make fixed")},                 \
2768 +  { "tls-size=",       &ia64_tls_size_string,                          \
2769 +      N_("Specify bit size of immediate TLS offsets")},                        \
2770  }
2771  
2772  /* Sometimes certain combinations of command options do not make sense on a
2773 @@ -1801,7 +1809,7 @@ do {                                                                      \
2774      && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL) \
2775         || DECL_SECTION_NAME (DECL) != 0))
2776  
2777 -#define SDATA_NAME_FLAG_CHAR '@'
2778 +#define ENCODE_SECTION_INFO_CHAR '@'
2779  
2780  #define IA64_DEFAULT_GVALUE 8
2781  
2782 @@ -1811,8 +1819,8 @@ do {                                                                      \
2783  #define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME)  \
2784  do {                                           \
2785    (VAR) = (SYMBOL_NAME);                       \
2786 -  if ((VAR)[0] == SDATA_NAME_FLAG_CHAR)                \
2787 -    (VAR)++;                                   \
2788 +  if ((VAR)[0] == ENCODE_SECTION_INFO_CHAR)    \
2789 +    (VAR) += 2;                                        \
2790    if ((VAR)[0] == '*')                         \
2791      (VAR)++;                                   \
2792  } while (0)
2793 --- gcc/config/ia64/ia64.md.jj  Tue Apr 23 20:28:21 2002
2794 +++ gcc/config/ia64/ia64.md     Wed Jun 19 19:33:52 2002
2795 @@ -68,7 +68,19 @@
2796  ;;     23      cycle display
2797  ;;      24      addp4
2798  ;;     25      prologue_use
2799 -;;
2800 +
2801 +;; More unspec:
2802 +
2803 +(define_constants
2804 +  [; Relocations
2805 +   (UNSPEC_LTOFF_DTPMOD                14)
2806 +   (UNSPEC_LTOFF_DTPREL                15)
2807 +   (UNSPEC_DTPREL              16)
2808 +   (UNSPEC_LTOFF_TPREL         17)
2809 +   (UNSPEC_TPREL               18)
2810 +   (UNSPEC_LD_BASE             26)
2811 +  ])
2812 +
2813  ;; unspec_volatile:
2814  ;;     0       alloc
2815  ;;     1       blockage
2816 @@ -272,12 +284,12 @@
2817    [(set (match_operand:QI 0 "general_operand" "")
2818         (match_operand:QI 1 "general_operand" ""))]
2819    ""
2820 -  "
2821  {
2822 -  if (! reload_in_progress && ! reload_completed
2823 -      && ! ia64_move_ok (operands[0], operands[1]))
2824 -    operands[1] = force_reg (QImode, operands[1]);
2825 -}")
2826 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
2827 +  if (!op1)
2828 +    DONE;
2829 +  operands[1] = op1;
2830 +})
2831  
2832  (define_insn "*movqi_internal"
2833    [(set (match_operand:QI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
2834 @@ -297,12 +309,12 @@
2835    [(set (match_operand:HI 0 "general_operand" "")
2836         (match_operand:HI 1 "general_operand" ""))]
2837    ""
2838 -  "
2839  {
2840 -  if (! reload_in_progress && ! reload_completed
2841 -      && ! ia64_move_ok (operands[0], operands[1]))
2842 -    operands[1] = force_reg (HImode, operands[1]);
2843 -}")
2844 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
2845 +  if (!op1)
2846 +    DONE;
2847 +  operands[1] = op1;
2848 +})
2849  
2850  (define_insn "*movhi_internal"
2851    [(set (match_operand:HI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
2852 @@ -322,12 +334,12 @@
2853    [(set (match_operand:SI 0 "general_operand" "")
2854         (match_operand:SI 1 "general_operand" ""))]
2855    ""
2856 -  "
2857  {
2858 -  if (! reload_in_progress && ! reload_completed
2859 -      && ! ia64_move_ok (operands[0], operands[1]))
2860 -    operands[1] = force_reg (SImode, operands[1]);
2861 -}")
2862 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
2863 +  if (!op1)
2864 +    DONE;
2865 +  operands[1] = op1;
2866 +})
2867  
2868  (define_insn "*movsi_internal"
2869    [(set (match_operand:SI 0 "destination_operand" "=r,r,r,r, m, r,*f,*f, r,*d")
2870 @@ -351,32 +363,12 @@
2871    [(set (match_operand:DI 0 "general_operand" "")
2872         (match_operand:DI 1 "general_operand" ""))]
2873    ""
2874 -  "
2875  {
2876 -  if (! reload_in_progress && ! reload_completed
2877 -      && ! ia64_move_ok (operands[0], operands[1]))
2878 -    operands[1] = force_reg (DImode, operands[1]);
2879 -  if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode))
2880 -    {
2881 -      /* Before optimization starts, delay committing to any particular
2882 -        type of PIC address load.  If this function gets deferred, we
2883 -        may acquire information that changes the value of the
2884 -        sdata_symbolic_operand predicate.  */
2885 -      /* But don't delay for function pointers.  Loading a function address
2886 -        actually loads the address of the descriptor not the function.
2887 -        If we represent these as SYMBOL_REFs, then they get cse'd with
2888 -        calls, and we end up with calls to the descriptor address instead of
2889 -        calls to the function address.  Functions are not candidates for
2890 -        sdata anyways.  */
2891 -      if (rtx_equal_function_value_matters
2892 -         && ! (GET_CODE (operands[1]) == SYMBOL_REF
2893 -               && SYMBOL_REF_FLAG (operands[1])))
2894 -       emit_insn (gen_movdi_symbolic (operands[0], operands[1], gen_reg_rtx (DImode)));
2895 -      else
2896 -        ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
2897 -      DONE;
2898 -    }
2899 -}")
2900 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
2901 +  if (!op1)
2902 +    DONE;
2903 +  operands[1] = op1;
2904 +})
2905  
2906  ;; This is used during early compilation to delay the decision on
2907  ;; how to refer to a variable as long as possible.  This is especially
2908 @@ -384,19 +376,22 @@
2909  ;; deferred functions, since we may acquire additional information
2910  ;; on the variables used in the meantime.
2911  
2912 -;; ??? This causes us to lose REG_LABEL notes, because the insn splitter
2913 -;; does not attempt to preserve any REG_NOTES on the input instruction.
2914 -
2915  (define_insn_and_split "movdi_symbolic"
2916    [(set (match_operand:DI 0 "register_operand" "=r")
2917         (match_operand:DI 1 "symbolic_operand" "s"))
2918 -   (clobber (match_operand:DI  2 "register_operand" "+r"))
2919 +   (clobber (match_scratch:DI 2 "=r"))
2920     (use (reg:DI 1))]
2921    ""
2922    "* abort ();"
2923 -  ""
2924 +  "!no_new_pseudos || reload_completed"
2925    [(const_int 0)]
2926 -  "ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE;")
2927 +{
2928 +  rtx scratch = operands[2];
2929 +  if (!reload_completed)
2930 +    gen_reg_rtx (Pmode);
2931 +  ia64_expand_load_address (operands[0], operands[1], scratch); 
2932 +  DONE;
2933 +})
2934  
2935  (define_insn "*movdi_internal"
2936    [(set (match_operand:DI 0 "destination_operand"
2937 @@ -510,6 +505,131 @@
2938    "addl %0 = @ltoff(%1), gp"
2939    [(set_attr "itanium_class" "ialu")])
2940  
2941 +(define_insn "load_ltoff_dtpmod"
2942 +  [(set (match_operand:DI 0 "register_operand" "=r")
2943 +       (plus:DI (reg:DI 1)
2944 +                (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
2945 +                           UNSPEC_LTOFF_DTPMOD)))]
2946 +  ""
2947 +  "addl %0 = @ltoff(@dtpmod(%1)), gp"
2948 +  [(set_attr "itanium_class" "ialu")])
2949 +
2950 +(define_insn "load_ltoff_dtprel"
2951 +  [(set (match_operand:DI 0 "register_operand" "=r")
2952 +       (plus:DI (reg:DI 1)
2953 +                (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
2954 +                           UNSPEC_LTOFF_DTPREL)))]
2955 +  ""
2956 +  "addl %0 = @ltoff(@dtprel(%1)), gp"
2957 +  [(set_attr "itanium_class" "ialu")])
2958 +
2959 +(define_expand "load_dtprel"
2960 +  [(set (match_operand:DI 0 "register_operand" "")
2961 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
2962 +                  UNSPEC_DTPREL))]
2963 +  ""
2964 +  "")
2965 +
2966 +(define_insn "*load_dtprel64"
2967 +  [(set (match_operand:DI 0 "register_operand" "=r")
2968 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
2969 +                  UNSPEC_DTPREL))]
2970 +  "TARGET_TLS64"
2971 +  "movl %0 = @dtprel(%1)"
2972 +  [(set_attr "itanium_class" "long_i")])
2973 +
2974 +(define_insn "*load_dtprel22"
2975 +  [(set (match_operand:DI 0 "register_operand" "=r")
2976 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
2977 +                  UNSPEC_DTPREL))]
2978 +  ""
2979 +  "addl %0 = @dtprel(%1), r0"
2980 +  [(set_attr "itanium_class" "ialu")])
2981 +
2982 +(define_expand "add_dtprel"
2983 +  [(set (match_operand:DI 0 "register_operand" "")
2984 +       (plus:DI (match_operand:DI 1 "register_operand" "")
2985 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
2986 +                           UNSPEC_DTPREL)))]
2987 +  "!TARGET_TLS64"
2988 +  "")
2989 +
2990 +(define_insn "*add_dtprel14"
2991 +  [(set (match_operand:DI 0 "register_operand" "=r")
2992 +       (plus:DI (match_operand:DI 1 "register_operand" "r")
2993 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
2994 +                           UNSPEC_DTPREL)))]
2995 +  "TARGET_TLS14"
2996 +  "adds %0 = @dtprel(%2), %1"
2997 +  [(set_attr "itanium_class" "ialu")])
2998 +
2999 +(define_insn "*add_dtprel22"
3000 +  [(set (match_operand:DI 0 "register_operand" "=r")
3001 +       (plus:DI (match_operand:DI 1 "register_operand" "a")
3002 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
3003 +                           UNSPEC_DTPREL)))]
3004 +  "TARGET_TLS22"
3005 +  "addl %0 = @dtprel(%2), %1"
3006 +  [(set_attr "itanium_class" "ialu")])
3007 +
3008 +(define_insn "load_ltoff_tprel"
3009 +  [(set (match_operand:DI 0 "register_operand" "=r")
3010 +       (plus:DI (reg:DI 1)
3011 +                (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
3012 +                           UNSPEC_LTOFF_TPREL)))]
3013 +  ""
3014 +  "addl %0 = @ltoff(@tprel(%1)), gp"
3015 +  [(set_attr "itanium_class" "ialu")])
3016 +
3017 +(define_expand "load_tprel"
3018 +  [(set (match_operand:DI 0 "register_operand" "")
3019 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
3020 +                  UNSPEC_TPREL))]
3021 +  ""
3022 +  "")
3023 +
3024 +(define_insn "*load_tprel64"
3025 +  [(set (match_operand:DI 0 "register_operand" "=r")
3026 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
3027 +                  UNSPEC_TPREL))]
3028 +  "TARGET_TLS64"
3029 +  "movl %0 = @tprel(%1)"
3030 +  [(set_attr "itanium_class" "long_i")])
3031 +
3032 +(define_insn "*load_tprel22"
3033 +  [(set (match_operand:DI 0 "register_operand" "=r")
3034 +       (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
3035 +                  UNSPEC_TPREL))]
3036 +  ""
3037 +  "addl %0 = @tprel(%1), r0"
3038 +  [(set_attr "itanium_class" "ialu")])
3039 +
3040 +(define_expand "add_tprel"
3041 +  [(set (match_operand:DI 0 "register_operand" "")
3042 +       (plus:DI (match_operand:DI 1 "register_operand" "")
3043 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
3044 +                           UNSPEC_TPREL)))]
3045 +  "!TARGET_TLS64"
3046 +  "")
3047 +
3048 +(define_insn "*add_tprel14"
3049 +  [(set (match_operand:DI 0 "register_operand" "=r")
3050 +       (plus:DI (match_operand:DI 1 "register_operand" "r")
3051 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
3052 +                           UNSPEC_TPREL)))]
3053 +  "TARGET_TLS14"
3054 +  "adds %0 = @tprel(%2), %1"
3055 +  [(set_attr "itanium_class" "ialu")])
3056 +
3057 +(define_insn "*add_tprel22"
3058 +  [(set (match_operand:DI 0 "register_operand" "=r")
3059 +       (plus:DI (match_operand:DI 1 "register_operand" "a")
3060 +                (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
3061 +                           UNSPEC_TPREL)))]
3062 +  "TARGET_TLS22"
3063 +  "addl %0 = @tprel(%2), %1"
3064 +  [(set_attr "itanium_class" "ialu")])
3065 +
3066  ;; With no offsettable memory references, we've got to have a scratch
3067  ;; around to play with the second word.
3068  (define_expand "movti"
3069 @@ -517,12 +637,12 @@
3070                    (match_operand:TI 1 "general_operand" ""))
3071               (clobber (match_scratch:DI 2 ""))])]
3072    ""
3073 -  "
3074  {
3075 -  if (! reload_in_progress && ! reload_completed
3076 -      && ! ia64_move_ok (operands[0], operands[1]))
3077 -    operands[1] = force_reg (TImode, operands[1]);
3078 -}")
3079 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
3080 +  if (!op1)
3081 +    DONE;
3082 +  operands[1] = op1;
3083 +})
3084  
3085  (define_insn_and_split "*movti_internal"
3086    [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
3087 @@ -639,12 +759,12 @@
3088    [(set (match_operand:SF 0 "general_operand" "")
3089         (match_operand:SF 1 "general_operand" ""))]
3090    ""
3091 -  "
3092  {
3093 -  if (! reload_in_progress && ! reload_completed
3094 -      && ! ia64_move_ok (operands[0], operands[1]))
3095 -    operands[1] = force_reg (SFmode, operands[1]);
3096 -}")
3097 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
3098 +  if (!op1)
3099 +    DONE;
3100 +  operands[1] = op1;
3101 +})
3102  
3103  (define_insn "*movsf_internal"
3104    [(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
3105 @@ -665,12 +785,12 @@
3106    [(set (match_operand:DF 0 "general_operand" "")
3107         (match_operand:DF 1 "general_operand" ""))]
3108    ""
3109 -  "
3110  {
3111 -  if (! reload_in_progress && ! reload_completed
3112 -      && ! ia64_move_ok (operands[0], operands[1]))
3113 -    operands[1] = force_reg (DFmode, operands[1]);
3114 -}")
3115 +  rtx op1 = ia64_expand_move (operands[0], operands[1]);
3116 +  if (!op1)
3117 +    DONE;
3118 +  operands[1] = op1;
3119 +})
3120  
3121  (define_insn "*movdf_internal"
3122    [(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
3123 --- gcc/config/ia64/sysv4.h.jj  Mon Jun  3 17:24:18 2002
3124 +++ gcc/config/ia64/sysv4.h     Wed Jun 19 19:33:52 2002
3125 @@ -42,8 +42,7 @@ extern int size_directive_output;
3126  #undef ASM_OUTPUT_ALIGNED_LOCAL
3127  #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
3128  do {                                                                   \
3129 -  if ((DECL)                                                           \
3130 -      && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \
3131 +  if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
3132      sbss_section ();                                                   \
3133    else                                                                 \
3134      bss_section ();                                                    \
3135 @@ -62,8 +61,8 @@ do {                                                                  \
3136  #define ASM_OUTPUT_LABELREF(STREAM, NAME)      \
3137  do {                                           \
3138    const char *name_ = NAME;                    \
3139 -  if (*name_ == SDATA_NAME_FLAG_CHAR)          \
3140 -    name_++;                                   \
3141 +  if (*name_ == ENCODE_SECTION_INFO_CHAR)      \
3142 +    name_ += 2;                                        \
3143    if (*name_ == '*')                           \
3144      name_++;                                   \
3145    else                                         \
3146 @@ -149,9 +148,11 @@ do {                                                                       \
3147         0       .text
3148         1       .rodata
3149         2       .data
3150 -       3       .sdata
3151 -       4       .bss
3152 +       3       .bss
3153 +       4       .sdata
3154         5       .sbss
3155 +       6       .tdata
3156 +       7       .tbss
3157  */
3158  #define DO_SELECT_SECTION(SECNUM, DECL, RELOC)                         \
3159    do                                                                   \
3160 @@ -167,9 +168,10 @@ do {                                                                       \
3161         }                                                               \
3162        else if (TREE_CODE (DECL) == VAR_DECL)                           \
3163         {                                                               \
3164 -         if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0]                    \
3165 -             == SDATA_NAME_FLAG_CHAR)                                  \
3166 -           SECNUM = 3;                                                 \
3167 +         if (DECL_THREAD_LOCAL (DECL))                                 \
3168 +           SECNUM = 6;                                                 \
3169 +         else if (sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode))\
3170 +           SECNUM = 4;                                                 \
3171           /* ??? We need the extra RELOC check, because the default     \
3172              is to only check RELOC if flag_pic is set, and we don't    \
3173              set flag_pic (yet?).  */                                   \
3174 @@ -184,13 +186,18 @@ do {                                                                      \
3175             SECNUM = 0x201;                                             \
3176           else                                                          \
3177             SECNUM = 0x301;                                             \
3178 +                                                                       \
3179 +         if (SECNUM >= 2                                               \
3180 +             && (!DECL_INITIAL (DECL)                                  \
3181 +                 || DECL_INITIAL (DECL) == error_mark_node))           \
3182 +           SECNUM++;                                                   \
3183         }                                                               \
3184        /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
3185          in which case we can't put it in a shared library rodata.  */  \
3186        else if (flag_pic && (RELOC))                                    \
3187 -       SECNUM = 3;                                                     \
3188 -      else                                                             \
3189         SECNUM = 2;                                                     \
3190 +      else                                                             \
3191 +       SECNUM = 1;                                                     \
3192      }                                                                  \
3193    while (0)
3194  
3195 @@ -206,8 +213,8 @@ do {                                                                        \
3196         text_section,                                                   \
3197         const_section,                                                  \
3198         data_section,                                                   \
3199 -       sdata_section,                                                  \
3200         bss_section,                                                    \
3201 +       sdata_section,                                                  \
3202         sbss_section                                                    \
3203        };                                                               \
3204                                                                         \
3205 @@ -217,6 +224,12 @@ do {                                                                       \
3206                                                                         \
3207        switch (sec)                                                     \
3208         {                                                               \
3209 +       case 6:                                                         \
3210 +         named_section (NULL_TREE, ".tdata", RELOC);                   \
3211 +         break;                                                        \
3212 +       case 7:                                                         \
3213 +         named_section (NULL_TREE, ".tbss", RELOC);                    \
3214 +         break;                                                        \
3215         case 0x101:                                                     \
3216           mergeable_string_section (DECL, ALIGN, 0);                    \
3217           break;                                                        \
3218 @@ -244,9 +257,11 @@ do {                                                                       \
3219         { ".text.",   ".gnu.linkonce.t." },                             \
3220         { ".rodata.", ".gnu.linkonce.r." },                             \
3221         { ".data.",   ".gnu.linkonce.d." },                             \
3222 -       { ".sdata.",  ".gnu.linkonce.s." },                             \
3223         { ".bss.",    ".gnu.linkonce.b." },                             \
3224 -       { ".sbss.",   ".gnu.linkonce.sb." }                             \
3225 +       { ".sdata.",  ".gnu.linkonce.s." },                             \
3226 +       { ".sbss.",   ".gnu.linkonce.sb." },                            \
3227 +       { ".tdata.",  ".gnu.linkonce.td." },                            \
3228 +       { ".tbss.",   ".gnu.linkonce.tb." }                             \
3229        };                                                               \
3230                                                                         \
3231        int nlen, plen, sec;                                             \
3232 --- gcc/config/elfos.h.jj       Tue Dec 18 01:30:48 2001
3233 +++ gcc/config/elfos.h  Wed Jun 19 19:33:52 2002
3234 @@ -288,24 +288,28 @@ const_section ()                                          \
3235        const char *name;                                                \
3236        char *string;                                            \
3237        const char *prefix;                                      \
3238 -      static const char *const prefixes[4][2] =                        \
3239 +      static const char *const prefixes[][2] =                 \
3240        {                                                                \
3241         { ".text.",   ".gnu.linkonce.t." },                     \
3242         { ".rodata.", ".gnu.linkonce.r." },                     \
3243         { ".data.",   ".gnu.linkonce.d." },                     \
3244 -       { ".bss.",    ".gnu.linkonce.b." }                      \
3245 +       { ".bss.",    ".gnu.linkonce.b." },                     \
3246 +       { ".tdata",   ".gnu.linkonce.td." },                    \
3247 +       { ".tbss",    ".gnu.linkonce.tb." },                    \
3248        };                                                       \
3249                                                                 \
3250        if (TREE_CODE (DECL) == FUNCTION_DECL)                   \
3251         sec = 0;                                                \
3252        else if (DECL_INITIAL (DECL) == 0                                \
3253                || DECL_INITIAL (DECL) == error_mark_node)       \
3254 -        sec =  3;                                              \
3255 +        sec = 3;                                               \
3256        else if (DECL_READONLY_SECTION (DECL, RELOC))            \
3257         sec = 1;                                                \
3258        else                                                     \
3259         sec = 2;                                                \
3260 -                                                               \
3261 +      if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) \
3262 +       sec = (sec == 3 ? 5 : 4);                               \
3263 +                                                               \
3264        name   = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL));        \
3265        /* Strip off any encoding in name.  */                   \
3266        STRIP_NAME_ENCODING (name, name);                                \
3267 @@ -367,10 +371,18 @@ const_section ()                                          \
3268      }                                                          \
3269    else if (TREE_CODE (DECL) == VAR_DECL)                       \
3270      {                                                          \
3271 -      if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL)    \
3272 -         || !DECL_INITIAL (DECL)                               \
3273 -         || (DECL_INITIAL (DECL) != error_mark_node            \
3274 -             && !TREE_CONSTANT (DECL_INITIAL (DECL))))         \
3275 +      if (DECL_THREAD_LOCAL (DECL))                            \
3276 +       {                                                       \
3277 +         if (!DECL_INITIAL (DECL)                              \
3278 +             || DECL_INITIAL (DECL) == error_mark_node)        \
3279 +           named_section (NULL_TREE, ".tbss", RELOC);          \
3280 +         else                                                  \
3281 +           named_section (NULL_TREE, ".tdata", RELOC);         \
3282 +       }                                                       \
3283 +      else if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
3284 +              || !DECL_INITIAL (DECL)                          \
3285 +              || (DECL_INITIAL (DECL) != error_mark_node       \
3286 +                  && !TREE_CONSTANT (DECL_INITIAL (DECL))))    \
3287         {                                                       \
3288           if (flag_pic && ((RELOC) & 2))                        \
3289             named_section (NULL_TREE, ".data.rel", RELOC);      \
3290 --- gcc/fixinc/fixincl.x.jj     Thu May  2 12:15:15 2002
3291 +++ gcc/fixinc/fixincl.x        Wed Jun 19 19:33:52 2002
3292 @@ -5,7 +5,7 @@
3293   * files which are fixed to work correctly with ANSI C and placed in a
3294   * directory that GNU C will search.
3295   *
3296 - * This file contains 151 fixup descriptions.
3297 + * This file contains 152 fixup descriptions.
3298   *
3299   * See README for more information.
3300   *
3301 @@ -4568,6 +4568,41 @@ static const char* apzSysz_Stdlib_For_Su
3302  
3303  /* * * * * * * * * * * * * * * * * * * * * * * * * *
3304   *
3305 + *  Description of Thread_Keyword fix
3306 + */
3307 +tSCC zThread_KeywordName[] =
3308 +     "thread_keyword";
3309 +
3310 +/*
3311 + *  File name selection pattern
3312 + */
3313 +tSCC zThread_KeywordList[] =
3314 +  "|pthread.h|bits/sigthread.h|";
3315 +/*
3316 + *  Machine/OS name selection pattern
3317 + */
3318 +#define apzThread_KeywordMachs (const char**)NULL
3319 +
3320 +/*
3321 + *  content selection pattern - do fix if pattern found
3322 + */
3323 +tSCC zThread_KeywordSelect0[] =
3324 +       " __thread([,)])";
3325 +
3326 +#define    THREAD_KEYWORD_TEST_CT  1
3327 +static tTestDesc aThread_KeywordTests[] = {
3328 +  { TT_EGREP,    zThread_KeywordSelect0, (regex_t*)NULL }, };
3329 +
3330 +/*
3331 + *  Fix Command Arguments for Thread_Keyword
3332 + */
3333 +static const char* apzThread_KeywordPatch[] = {
3334 +    "format",
3335 +    " __thr%1",
3336 +    (char*)NULL };
3337 +
3338 +/* * * * * * * * * * * * * * * * * * * * * * * * * *
3339 + *
3340   *  Description of Tinfo_Cplusplus fix
3341   */
3342  tSCC zTinfo_CplusplusName[] =
3343 @@ -5581,9 +5616,9 @@ static const char* apzX11_SprintfPatch[]
3344   *
3345   *  List of all fixes
3346   */
3347 -#define REGEX_COUNT          163
3348 +#define REGEX_COUNT          164
3349  #define MACH_LIST_SIZE_LIMIT 279
3350 -#define FIX_COUNT            151
3351 +#define FIX_COUNT            152
3352  
3353  /*
3354   *  Enumerate the fixes
3355 @@ -5705,6 +5740,7 @@ typedef enum {
3356      SVR4_PROFIL_FIXIDX,
3357      SYSV68_STRING_FIXIDX,
3358      SYSZ_STDLIB_FOR_SUN_FIXIDX,
3359 +    THREAD_KEYWORD_FIXIDX,
3360      TINFO_CPLUSPLUS_FIXIDX,
3361      ULTRIX_ATEXIT_PARAM_FIXIDX,
3362      ULTRIX_ATOF_PARAM_FIXIDX,
3363 @@ -6314,6 +6350,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
3364       SYSZ_STDLIB_FOR_SUN_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
3365       aSysz_Stdlib_For_SunTests,   apzSysz_Stdlib_For_SunPatch, 0 },
3366  
3367 +  {  zThread_KeywordName,    zThread_KeywordList,
3368 +     apzThread_KeywordMachs,
3369 +     THREAD_KEYWORD_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
3370 +     aThread_KeywordTests,   apzThread_KeywordPatch, 0 },
3371 +
3372    {  zTinfo_CplusplusName,    zTinfo_CplusplusList,
3373       apzTinfo_CplusplusMachs,
3374       TINFO_CPLUSPLUS_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
3375 --- gcc/fixinc/inclhack.def.jj  Thu May  2 12:15:17 2002
3376 +++ gcc/fixinc/inclhack.def     Wed Jun 19 19:33:52 2002
3377 @@ -1,4 +1,3 @@
3378 -
3379  /* -*- Mode: C -*-  */
3380  
3381  autogen definitions fixincl;
3382 @@ -2886,6 +2885,24 @@ fix = {
3383  };
3384  
3385  
3386 +/*
3387 + * __thread is now a keyword.
3388 + */
3389 +fix = {
3390 +    hackname  = thread_keyword;
3391 +    files     = "pthread.h";
3392 +    files     = "bits/sigthread.h";
3393 +    select    = " __thread([,)])";
3394 +    c_fix     = format;
3395 +    c_fix_arg = " __thr%1";
3396 +
3397 +    test_text =
3398 +        "extern int pthread_create (pthread_t *__restrict __thread,\n"
3399 +        "extern int pthread_kill (pthread_t __thread, int __signo);\n"
3400 +        "extern int pthread_cancel (pthread_t __thread);";
3401 +};
3402 +
3403 +
3404  /*
3405   *  if the #if says _cplusplus, not the double underscore __cplusplus
3406   *  that it should be
3407 --- gcc/testsuite/g++.dg/dg.exp.jj      Thu Feb 14 13:26:12 2002
3408 +++ gcc/testsuite/g++.dg/dg.exp Wed Jun 19 19:33:52 2002
3409 @@ -28,10 +28,12 @@ if ![info exists DEFAULT_CXXFLAGS] then 
3410  # Initialize `dg'.
3411  dg-init
3412  
3413 -# Gather a list of all tests, excluding those in special/; those are handled
3414 -# well, specially.
3415 -set all [lsort [find $srcdir/$subdir *.C]]
3416 -set tests [prune [prune $all $srcdir/$subdir/special/*] $srcdir/$subdir/debug/*]
3417 +# Gather a list of all tests, with the exception of those in directories
3418 +# that are handled specially.
3419 +set tests [lsort [find $srcdir/$subdir *.C]]
3420 +set tests [prune $tests $srcdir/$subdir/debug/*]
3421 +set tests [prune $tests $srcdir/$subdir/special/*]
3422 +set tests [prune $tests $srcdir/$subdir/tls/*]
3423  
3424  # Main loop.
3425  dg-runtest $tests "" $DEFAULT_CXXFLAGS
3426 --- gcc/testsuite/g++.dg/tls/diag-1.C.jj        Wed Jun 19 19:33:52 2002
3427 +++ gcc/testsuite/g++.dg/tls/diag-1.C   Wed Jun 19 19:33:52 2002
3428 @@ -0,0 +1,30 @@
3429 +/* Valid __thread specifiers.  */
3430 +
3431 +__thread int g1;
3432 +extern __thread int g2;
3433 +static __thread int g3;
3434 +
3435 +void foo()
3436 +{
3437 +  extern __thread int l1;
3438 +  static __thread int l2;
3439 +}
3440 +
3441 +struct A {
3442 +  static __thread int i;
3443 +};
3444 +
3445 +__thread int A::i = 42;
3446 +
3447 +template <typename T> struct B {
3448 +  static __thread T t;
3449 +};
3450 +
3451 +template <typename T>
3452 +__thread T B<T>::t = 42;
3453 +
3454 +void bar ()
3455 +{
3456 +  int j = B<int>::t;
3457 +  int k = B<const int>::t;
3458 +}
3459 --- gcc/testsuite/g++.dg/tls/diag-2.C.jj        Wed Jun 19 19:33:52 2002
3460 +++ gcc/testsuite/g++.dg/tls/diag-2.C   Wed Jun 19 19:33:52 2002
3461 @@ -0,0 +1,25 @@
3462 +/* Invalid __thread specifiers.  */
3463 +
3464 +__thread extern int g1;                /* { dg-error "`__thread' before `extern'" } */
3465 +__thread static int g2;                /* { dg-error "`__thread' before `static'" } */
3466 +__thread __thread int g3;      /* { dg-error "duplicate `__thread'" } */
3467 +typedef __thread int g4;       /* { dg-error "multiple storage classes" } */
3468 +
3469 +void foo()
3470 +{
3471 +  __thread int l1;             /* { dg-error "implicitly auto and declared `__thread'" } */
3472 +  auto __thread int l2;                /* { dg-error "multiple storage classes" } */
3473 +  __thread extern int l3;      /* { dg-error "`__thread' before `extern'" } */
3474 +  register __thread int l4;    /* { dg-error "multiple storage classes" } */
3475 +}
3476 +
3477 +__thread void f1 ();           /* { dg-error "invalid for function" } */
3478 +extern __thread void f2 ();    /* { dg-error "invalid for function" } */
3479 +static __thread void f3 ();    /* { dg-error "invalid for function" } */
3480 +__thread void f4 () { }                /* { dg-error "invalid for function" } */
3481 +
3482 +void bar(__thread int p1);     /* { dg-error "(invalid in parameter)|(specified for parameter)" } */
3483 +
3484 +struct A {
3485 +  __thread int i;              /* { dg-error "specified for field" } */
3486 +};
3487 --- gcc/testsuite/g++.dg/tls/init-1.C.jj        Wed Jun 19 19:33:52 2002
3488 +++ gcc/testsuite/g++.dg/tls/init-1.C   Wed Jun 19 19:33:52 2002
3489 @@ -0,0 +1,13 @@
3490 +/* Valid initializations.  */
3491 +
3492 +__thread int i = 42;
3493 +
3494 +static int j;
3495 +__thread int *p = &j;
3496 +
3497 +/* Note that this is valid in C++ (unlike C) as a run-time initialization.  */
3498 +int *q = &i;
3499 +
3500 +/* Valid because "const int k" is an integral constant expression in C++.  */
3501 +__thread const int k = 42;
3502 +__thread const int l = k;
3503 --- gcc/testsuite/g++.dg/tls/init-2.C.jj        Wed Jun 19 19:33:52 2002
3504 +++ gcc/testsuite/g++.dg/tls/init-2.C   Wed Jun 19 19:33:52 2002
3505 @@ -0,0 +1,13 @@
3506 +/* Invalid initializations.  */
3507 +
3508 +extern __thread int i;
3509 +__thread int *p = &i;  /* { dg-error "run-time initialization" } */
3510 +
3511 +extern int f();
3512 +__thread int j = f();  /* { dg-error "run-time initialization" } */
3513 +
3514 +struct S
3515 +{
3516 +  S();
3517 +};
3518 +__thread S s;          /* { dg-error "run-time initialization" } */
3519 --- gcc/testsuite/g++.dg/tls/tls.exp.jj Wed Jun 19 19:33:52 2002
3520 +++ gcc/testsuite/g++.dg/tls/tls.exp    Wed Jun 19 19:33:52 2002
3521 @@ -0,0 +1,44 @@
3522 +#   Copyright (C) 2002 Free Software Foundation, Inc.
3523 +
3524 +# This program is free software; you can redistribute it and/or modify
3525 +# it under the terms of the GNU General Public License as published by
3526 +# the Free Software Foundation; either version 2 of the License, or
3527 +# (at your option) any later version.
3528 +# 
3529 +# This program is distributed in the hope that it will be useful,
3530 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
3531 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3532 +# GNU General Public License for more details.
3533 +# 
3534 +# You should have received a copy of the GNU General Public License
3535 +# along with this program; if not, write to the Free Software
3536 +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
3537 +
3538 +# GCC testsuite that uses the `dg.exp' driver.
3539 +
3540 +# Load support procs.
3541 +load_lib g++-dg.exp
3542 +
3543 +# Test for thread-local data supported by the platform.  If it
3544 +# isn't, everything will fail with the "not supported" message.
3545 +
3546 +set comp_output [g++_target_compile \
3547 +               "$srcdir/$subdir/trivial.C" "trivial.S" assembly ""]
3548 +if { [string match "*not supported*" $comp_output] } {
3549 +  return 0
3550 +}
3551 +
3552 +# If a testcase doesn't have special options, use these.
3553 +global DEFAULT_CXXFLAGS
3554 +if ![info exists DEFAULT_CXXFLAGS] then {
3555 +    set DEFAULT_CXXFLAGS " -ansi -pedantic-errors -Wno-long-long"
3556 +}
3557 +
3558 +# Initialize `dg'.
3559 +dg-init
3560 +
3561 +# Main loop.
3562 +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" $DEFAULT_CXXFLAGS
3563 +
3564 +# All done.
3565 +dg-finish
3566 --- gcc/testsuite/g++.dg/tls/trivial.C.jj       Wed Jun 19 19:33:52 2002
3567 +++ gcc/testsuite/g++.dg/tls/trivial.C  Wed Jun 19 19:33:52 2002
3568 @@ -0,0 +1 @@
3569 +__thread int i;
3570 --- gcc/testsuite/gcc.dg/tls/diag-1.c.jj        Wed Jun 19 19:33:52 2002
3571 +++ gcc/testsuite/gcc.dg/tls/diag-1.c   Wed Jun 19 19:33:52 2002
3572 @@ -0,0 +1,11 @@
3573 +/* Valid __thread specifiers.  */
3574 +
3575 +__thread int g1;
3576 +extern __thread int g2;
3577 +static __thread int g3;
3578 +
3579 +void foo()
3580 +{
3581 +  extern __thread int l1;
3582 +  static __thread int l2;
3583 +}
3584 --- gcc/testsuite/gcc.dg/tls/diag-2.c.jj        Wed Jun 19 19:33:52 2002
3585 +++ gcc/testsuite/gcc.dg/tls/diag-2.c   Wed Jun 19 19:33:52 2002
3586 @@ -0,0 +1,21 @@
3587 +/* Invalid __thread specifiers.  */
3588 +
3589 +__thread extern int g1;                /* { dg-error "`__thread' before `extern'" } */
3590 +__thread static int g2;                /* { dg-error "`__thread' before `static'" } */
3591 +__thread __thread int g3;      /* { dg-error "duplicate `__thread'" } */
3592 +typedef __thread int g4;       /* { dg-error "multiple storage classes" } */
3593 +
3594 +void foo()
3595 +{
3596 +  __thread int l1;             /* { dg-error "implicitly auto and declared `__thread'" } */
3597 +  auto __thread int l2;                /* { dg-error "multiple storage classes" } */
3598 +  __thread extern int l3;      /* { dg-error "`__thread' before `extern'" } */
3599 +  register __thread int l4;    /* { dg-error "multiple storage classes" } */
3600 +}
3601 +
3602 +__thread void f1 ();           /* { dg-error "invalid storage class for function" } */
3603 +extern __thread void f2 ();    /* { dg-error "invalid storage class for function" } */
3604 +static __thread void f3 ();    /* { dg-error "invalid storage class for function" } */
3605 +__thread void f4 () { }                /* { dg-error "function definition declared `__thread'" } */
3606 +
3607 +void bar(__thread int p1);     /* { dg-error "storage class specified for parameter" } */
3608 --- gcc/testsuite/gcc.dg/tls/init-1.c.jj        Wed Jun 19 19:33:52 2002
3609 +++ gcc/testsuite/gcc.dg/tls/init-1.c   Wed Jun 19 19:33:52 2002
3610 @@ -0,0 +1,4 @@
3611 +/* Invalid initializations.  */
3612 +
3613 +extern __thread int i;
3614 +int *p = &i;   /* { dg-error "initializer element is not constant" } */
3615 --- gcc/testsuite/gcc.dg/tls/tls.exp.jj Wed Jun 19 19:33:52 2002
3616 +++ gcc/testsuite/gcc.dg/tls/tls.exp    Wed Jun 19 19:33:52 2002
3617 @@ -0,0 +1,45 @@
3618 +#   Copyright (C) 2002 Free Software Foundation, Inc.
3619 +
3620 +# This program is free software; you can redistribute it and/or modify
3621 +# it under the terms of the GNU General Public License as published by
3622 +# the Free Software Foundation; either version 2 of the License, or
3623 +# (at your option) any later version.
3624 +# 
3625 +# This program is distributed in the hope that it will be useful,
3626 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
3627 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3628 +# GNU General Public License for more details.
3629 +# 
3630 +# You should have received a copy of the GNU General Public License
3631 +# along with this program; if not, write to the Free Software
3632 +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
3633 +
3634 +# GCC testsuite that uses the `dg.exp' driver.
3635 +
3636 +# Load support procs.
3637 +load_lib gcc-dg.exp
3638 +
3639 +# Test for thread-local data supported by the platform.  If it
3640 +# isn't, everything will fail with the "not supported" message.
3641 +
3642 +set comp_output [gcc_target_compile \
3643 +               "$srcdir/$subdir/trivial.c" "trivial.S" assembly ""]
3644 +if { [string match "*not supported*" $comp_output] } {
3645 +  return 0
3646 +}
3647 +
3648 +# If a testcase doesn't have special options, use these.
3649 +global DEFAULT_CFLAGS
3650 +if ![info exists DEFAULT_CFLAGS] then {
3651 +    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
3652 +}
3653 +
3654 +# Initialize `dg'.
3655 +dg-init
3656 +
3657 +# Main loop.
3658 +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
3659 +        "" $DEFAULT_CFLAGS
3660 +
3661 +# All done.
3662 +dg-finish
3663 --- gcc/testsuite/gcc.dg/tls/trivial.c.jj       Wed Jun 19 19:33:52 2002
3664 +++ gcc/testsuite/gcc.dg/tls/trivial.c  Wed Jun 19 19:33:52 2002
3665 @@ -0,0 +1 @@
3666 +__thread int i;
3667 --- gcc/c-common.h.jj   Wed Apr 17 15:34:36 2002
3668 +++ gcc/c-common.h      Wed Jun 19 19:33:52 2002
3669 @@ -58,7 +58,7 @@ enum rid
3670    RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
3671  
3672    /* C extensions */
3673 -  RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX,
3674 +  RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX, RID_THREAD,
3675  
3676    /* C++ */
3677    RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
3678 --- gcc/c-decl.c.jj     Wed Jun 19 19:33:50 2002
3679 +++ gcc/c-decl.c        Wed Jun 19 19:33:52 2002
3680 @@ -3571,9 +3571,19 @@ start_decl (declarator, declspecs, initi
3681    /* ANSI specifies that a tentative definition which is not merged with
3682       a non-tentative definition behaves exactly like a definition with an
3683       initializer equal to zero.  (Section 3.7.2)
3684 -     -fno-common gives strict ANSI behavior.  Usually you don't want it.
3685 -     This matters only for variables with external linkage.  */
3686 -  if (! flag_no_common || ! TREE_PUBLIC (decl))
3687 +
3688 +     -fno-common gives strict ANSI behavior, though this tends to break
3689 +     a large body of code that grew up without this rule.
3690 +
3691 +     Thread-local variables are never common, since there's no entrenched
3692 +     body of code to break, and it allows more efficient variable references
3693 +     in the presense of dynamic linking.  */
3694 +
3695 +  if (TREE_CODE (decl) == VAR_DECL
3696 +      && !initialized
3697 +      && TREE_PUBLIC (decl)
3698 +      && !DECL_THREAD_LOCAL (decl)
3699 +      && !flag_no_common)
3700      DECL_COMMON (decl) = 1;
3701  
3702    /* Set attributes here so if duplicate decl, will have proper attributes.  */
3703 @@ -4172,7 +4182,7 @@ grokdeclarator (declarator, declspecs, d
3704           enum rid i = C_RID_CODE (id);
3705           if ((int) i <= (int) RID_LAST_MODIFIER)
3706             {
3707 -             if (i == RID_LONG && (specbits & (1 << (int) i)))
3708 +             if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
3709                 {
3710                   if (longlong)
3711                     error ("`long long long' is too long for GCC");
3712 @@ -4186,6 +4196,19 @@ grokdeclarator (declarator, declspecs, d
3713                 }
3714               else if (specbits & (1 << (int) i))
3715                 pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
3716 +
3717 +             /* Diagnose "__thread extern".  Recall that this list
3718 +                is in the reverse order seen in the text.  */
3719 +             if (i == RID_THREAD
3720 +                 && (specbits & (1 << (int) RID_EXTERN
3721 +                                 | 1 << (int) RID_STATIC)))
3722 +               {
3723 +                 if (specbits & 1 << (int) RID_EXTERN)
3724 +                   error ("`__thread' before `extern'");
3725 +                 else
3726 +                   error ("`__thread' before `static'");
3727 +               }
3728 +
3729               specbits |= 1 << (int) i;
3730               goto found;
3731             }
3732 @@ -4438,6 +4461,12 @@ grokdeclarator (declarator, declspecs, d
3733      if (specbits & 1 << (int) RID_REGISTER) nclasses++;
3734      if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
3735  
3736 +    /* "static __thread" and "extern __thread" are allowed.  */
3737 +    if ((specbits & (1 << (int) RID_THREAD
3738 +                    | 1 << (int) RID_STATIC
3739 +                    | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
3740 +      nclasses++;
3741 +
3742      /* Warn about storage classes that are invalid for certain
3743         kinds of declarations (parameters, typenames, etc.).  */
3744  
3745 @@ -4447,7 +4476,8 @@ grokdeclarator (declarator, declspecs, d
3746              && (specbits
3747                  & ((1 << (int) RID_REGISTER)
3748                     | (1 << (int) RID_AUTO)
3749 -                   | (1 << (int) RID_TYPEDEF))))
3750 +                   | (1 << (int) RID_TYPEDEF)
3751 +                   | (1 << (int) RID_THREAD))))
3752        {
3753         if (specbits & 1 << (int) RID_AUTO
3754             && (pedantic || current_binding_level == global_binding_level))
3755 @@ -4456,8 +4486,10 @@ grokdeclarator (declarator, declspecs, d
3756           error ("function definition declared `register'");
3757         if (specbits & 1 << (int) RID_TYPEDEF)
3758           error ("function definition declared `typedef'");
3759 +       if (specbits & 1 << (int) RID_THREAD)
3760 +         error ("function definition declared `__thread'");
3761         specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
3762 -                     | (1 << (int) RID_AUTO));
3763 +                     | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
3764        }
3765      else if (decl_context != NORMAL && nclasses > 0)
3766        {
3767 @@ -4480,7 +4512,7 @@ grokdeclarator (declarator, declspecs, d
3768               }
3769             specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
3770                           | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
3771 -                         | (1 << (int) RID_EXTERN));
3772 +                         | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
3773           }
3774        }
3775      else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
3776 @@ -4491,12 +4523,25 @@ grokdeclarator (declarator, declspecs, d
3777         else
3778           error ("`%s' has both `extern' and initializer", name);
3779        }
3780 -    else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
3781 -            && current_binding_level != global_binding_level)
3782 -      error ("nested function `%s' declared `extern'", name);
3783 -    else if (current_binding_level == global_binding_level
3784 -            && specbits & (1 << (int) RID_AUTO))
3785 -      error ("top-level declaration of `%s' specifies `auto'", name);
3786 +    else if (current_binding_level == global_binding_level)
3787 +      {
3788 +       if (specbits & 1 << (int) RID_AUTO)
3789 +         error ("top-level declaration of `%s' specifies `auto'", name);
3790 +      }
3791 +    else
3792 +      {
3793 +       if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
3794 +         error ("nested function `%s' declared `extern'", name);
3795 +       else if ((specbits & (1 << (int) RID_THREAD
3796 +                              | 1 << (int) RID_EXTERN
3797 +                              | 1 << (int) RID_STATIC))
3798 +                == (1 << (int) RID_THREAD))
3799 +         {
3800 +           error ("function-scope `%s' implicitly auto and declared `__thread'",
3801 +                  name);
3802 +           specbits &= ~(1 << (int) RID_THREAD);
3803 +         }
3804 +      }
3805    }
3806  
3807    /* Now figure out the structure of the declarator proper.
3808 @@ -5095,6 +5140,8 @@ grokdeclarator (declarator, declspecs, d
3809           pedwarn ("invalid storage class for function `%s'", name);
3810         if (specbits & (1 << (int) RID_REGISTER))
3811           error ("invalid storage class for function `%s'", name);
3812 +       if (specbits & (1 << (int) RID_THREAD))
3813 +         error ("invalid storage class for function `%s'", name);
3814         /* Function declaration not at top level.
3815            Storage classes other than `extern' are not allowed
3816            and `extern' makes no difference.  */
3817 @@ -5187,22 +5234,32 @@ grokdeclarator (declarator, declspecs, d
3818           pedwarn_with_decl (decl, "variable `%s' declared `inline'");
3819  
3820         DECL_EXTERNAL (decl) = extern_ref;
3821 +
3822         /* At top level, the presence of a `static' or `register' storage
3823            class specifier, or the absence of all storage class specifiers
3824            makes this declaration a definition (perhaps tentative).  Also,
3825            the absence of both `static' and `register' makes it public.  */
3826         if (current_binding_level == global_binding_level)
3827           {
3828 -           TREE_PUBLIC (decl)
3829 -             = !(specbits
3830 -                 & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
3831 -           TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
3832 +           TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
3833 +                                              | (1 << (int) RID_REGISTER)));
3834 +           TREE_STATIC (decl) = !extern_ref;
3835           }
3836         /* Not at top level, only `static' makes a static definition.  */
3837         else
3838           {
3839             TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
3840 -           TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
3841 +           TREE_PUBLIC (decl) = extern_ref;
3842 +         }
3843 +
3844 +       if (specbits & 1 << (int) RID_THREAD)
3845 +         {
3846 +           if (targetm.have_tls)
3847 +             DECL_THREAD_LOCAL (decl) = 1;
3848 +           else
3849 +             /* A mere warning is sure to result in improper semantics
3850 +                at runtime.  Don't bother to allow this to compile.  */
3851 +             error ("thread-local storage not supported for this target");
3852           }
3853        }
3854  
3855 --- gcc/c-parse.in.jj   Wed Apr 17 15:34:46 2002
3856 +++ gcc/c-parse.in      Wed Jun 19 19:33:52 2002
3857 @@ -3329,6 +3329,7 @@ static const struct resword reswords[] =
3858    { "__restrict__",    RID_RESTRICT,   0 },
3859    { "__signed",                RID_SIGNED,     0 },
3860    { "__signed__",      RID_SIGNED,     0 },
3861 +  { "__thread",                RID_THREAD,     0 },
3862    { "__typeof",                RID_TYPEOF,     0 },
3863    { "__typeof__",      RID_TYPEOF,     0 },
3864    { "__unbounded",     RID_UNBOUNDED,  0 },
3865 @@ -3424,6 +3425,7 @@ static const short rid_to_yy[RID_MAX] =
3866    /* RID_BOUNDED */    TYPE_QUAL,
3867    /* RID_UNBOUNDED */  TYPE_QUAL,
3868    /* RID_COMPLEX */    TYPESPEC,
3869 +  /* RID_THREAD */     SCSPEC,
3870  
3871    /* C++ */
3872    /* RID_FRIEND */     0,
3873 --- gcc/config.in.jj    Sat Jun  8 00:38:25 2002
3874 +++ gcc/config.in       Wed Jun 19 19:33:52 2002
3875 @@ -523,6 +523,9 @@
3876  /* Define if your assembler supports marking sections with SHF_MERGE flag. */
3877  #undef HAVE_GAS_SHF_MERGE
3878  
3879 +/* Define if your assembler supports thread-local storage. */
3880 +#undef HAVE_AS_TLS
3881 +
3882  /* Define if your assembler supports explicit relocations. */
3883  #undef HAVE_AS_EXPLICIT_RELOCS
3884  
3885 --- gcc/flags.h.jj      Sat Mar 23 12:02:51 2002
3886 +++ gcc/flags.h Wed Jun 19 19:33:52 2002
3887 @@ -450,11 +450,22 @@ extern int flag_pretend_float;
3888  
3889  extern int flag_pedantic_errors;
3890  
3891 -/* Nonzero means generate position-independent code.
3892 -   This is not fully implemented yet.  */
3893 +/* Nonzero means generate position-independent code.  1 vs 2 for a 
3894 +   target-dependent "small" or "large" mode.  */
3895  
3896  extern int flag_pic;
3897  
3898 +/* Set to the default thread-local storage (tls) model to use.  */
3899 +
3900 +enum tls_model {
3901 +  TLS_MODEL_GLOBAL_DYNAMIC = 1,
3902 +  TLS_MODEL_LOCAL_DYNAMIC,
3903 +  TLS_MODEL_INITIAL_EXEC,
3904 +  TLS_MODEL_LOCAL_EXEC
3905 +};
3906 +
3907 +extern enum tls_model flag_tls_default;
3908 +
3909  /* Nonzero means generate extra code for exception handling and enable
3910     exception handling.  */
3911  
3912 --- gcc/configure.in.jj Sat Jun  8 00:38:27 2002
3913 +++ gcc/configure.in    Wed Jun 19 19:33:52 2002
3914 @@ -1715,6 +1715,72 @@ if test x"$gcc_cv_as_shf_merge" = xyes; 
3915  fi
3916  AC_MSG_RESULT($gcc_cv_as_shf_merge)
3917  
3918 +AC_MSG_CHECKING(assembler thread-local storage support)
3919 +gcc_cv_as_tls=no
3920 +conftest_s=
3921 +tls_first_major=
3922 +tls_first_minor=
3923 +case "$target" in
3924 +changequote(,)dnl
3925 +  i[34567]86-*-*)
3926 +changequote([,])dnl
3927 +    conftest_s='
3928 +       .section ".tdata","awT",@progbits
3929 +foo:   .long   25
3930 +       .text
3931 +       movl    %gs:0, %eax
3932 +       leal    foo@TLSGD(,%ebx,1), %eax
3933 +       leal    foo@TLSLDM(%ebx), %eax
3934 +       leal    foo@DTPOFF(%eax), %edx
3935 +       movl    foo@GOTTPOFF(%ebx), %eax
3936 +       subl    foo@GOTTPOFF(%ebx), %eax
3937 +       movl    $foo@TPOFF, %eax
3938 +       subl    $foo@TPOFF, %eax
3939 +       leal    foo@NTPOFF(%ecx), %eax'
3940 +       tls_first_major=2
3941 +       tls_first_minor=13
3942 +       ;;
3943 +  ia64-*-*)
3944 +    conftest_s='
3945 +       .section ".tdata","awT",@progbits
3946 +foo:   data8   25
3947 +       .text
3948 +       addl    r16 = @ltoff(@dtpmod(foo#)), gp
3949 +       addl    r17 = @ltoff(@dtprel(foo#)), gp
3950 +       addl    r18 = @ltoff(@tprel(foo#)), gp
3951 +       addl    r19 = @dtprel(foo#), gp
3952 +       adds    r21 = @dtprel(foo#), r13
3953 +       movl    r23 = @dtprel(foo#)
3954 +       addl    r20 = @tprel(foo#), gp
3955 +       adds    r22 = @tprel(foo#), r13
3956 +       movl    r24 = @tprel(foo#)'
3957 +       tls_first_major=2
3958 +       tls_first_minor=13
3959 +       ;;
3960 +esac
3961 +if test -z "$tls_first_major"; then
3962 +  :
3963 +elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
3964 +then
3965 +  if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
3966 +         -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
3967 +         -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
3968 +    gcc_cv_as_tls=yes
3969 +  fi
3970 +elif test x$gcc_cv_as != x; then
3971 +  echo "$conftest_s" > conftest.s
3972 +  if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
3973 +  then
3974 +    gcc_cv_as_tls=yes
3975 +  fi
3976 +  rm -f conftest.s conftest.o
3977 +fi
3978 +if test "$gcc_cv_as_tls" = yes; then
3979 +  AC_DEFINE(HAVE_AS_TLS, 1,
3980 +           [Define if your assembler supports thread-local storage.])
3981 +fi
3982 +AC_MSG_RESULT($gcc_cv_as_tls)
3983 +
3984  case "$target" in
3985    # All TARGET_ABI_OSF targets.
3986    alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
3987 --- gcc/configure.jj    Sat Jun  8 00:38:27 2002
3988 +++ gcc/configure       Wed Jun 19 22:28:09 2002
3989 @@ -7391,6 +7391,73 @@ EOF
3990  fi
3991  echo "$ac_t""$gcc_cv_as_shf_merge" 1>&6
3992  
3993 +echo $ac_n "checking assembler thread-local storage support""... $ac_c" 1>&6
3994 +echo "configure:7399: checking assembler thread-local storage support" >&5
3995 +gcc_cv_as_tls=no
3996 +conftest_s=
3997 +tls_first_major=
3998 +tls_first_minor=
3999 +case "$target" in
4000 +  i[34567]86-*-*)
4001 +    conftest_s='
4002 +       .section ".tdata","awT",@progbits
4003 +foo:   .long   25
4004 +       .text
4005 +       movl    %gs:0, %eax
4006 +       leal    foo@TLSGD(,%ebx,1), %eax
4007 +       leal    foo@TLSLDM(%ebx), %eax
4008 +       leal    foo@DTPOFF(%eax), %edx
4009 +       movl    foo@GOTTPOFF(%ebx), %eax
4010 +       subl    foo@GOTTPOFF(%ebx), %eax
4011 +       movl    $foo@TPOFF, %eax
4012 +       subl    $foo@TPOFF, %eax
4013 +       leal    foo@NTPOFF(%ecx), %eax'
4014 +       tls_first_major=2
4015 +       tls_first_minor=13
4016 +       ;;
4017 +  ia64-*-*)
4018 +    conftest_s='
4019 +       .section ".tdata","awT",@progbits
4020 +foo:   data8   25
4021 +       .text
4022 +       addl    r16 = @ltoff(@dtpmod(foo#)), gp
4023 +       addl    r17 = @ltoff(@dtprel(foo#)), gp
4024 +       addl    r18 = @ltoff(@tprel(foo#)), gp
4025 +       addl    r19 = @dtprel(foo#), gp
4026 +       adds    r21 = @dtprel(foo#), r13
4027 +       movl    r23 = @dtprel(foo#)
4028 +       addl    r20 = @tprel(foo#), gp
4029 +       adds    r22 = @tprel(foo#), r13
4030 +       movl    r24 = @tprel(foo#)'
4031 +       tls_first_major=2
4032 +       tls_first_minor=13
4033 +       ;;
4034 +esac
4035 +if test -z "$tls_first_major"; then
4036 +  :
4037 +elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
4038 +then
4039 +  if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
4040 +         -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
4041 +         -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
4042 +    gcc_cv_as_tls=yes
4043 +  fi
4044 +elif test x$gcc_cv_as != x; then
4045 +  echo "$conftest_s" > conftest.s
4046 +  if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
4047 +  then
4048 +    gcc_cv_as_tls=yes
4049 +  fi
4050 +  rm -f conftest.s conftest.o
4051 +fi
4052 +if test "$gcc_cv_as_tls" = yes; then
4053 +  cat >> confdefs.h <<\EOF
4054 +#define HAVE_AS_TLS 1
4055 +EOF
4056 +
4057 +fi
4058 +echo "$ac_t""$gcc_cv_as_tls" 1>&6
4059 +
4060  case "$target" in
4061    # All TARGET_ABI_OSF targets.
4062    alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
4063 --- gcc/output.h.jj     Wed Jun 19 19:33:50 2002
4064 +++ gcc/output.h        Wed Jun 19 19:33:52 2002
4065 @@ -514,7 +514,8 @@ extern void no_asm_to_stream PARAMS ((FI
4066  #define SECTION_STRINGS  0x10000       /* contains zero terminated strings without
4067                                            embedded zeros */
4068  #define SECTION_OVERRIDE 0x20000       /* allow override of default flags */
4069 -#define SECTION_MACH_DEP 0x40000       /* subsequent bits reserved for target */
4070 +#define SECTION_TLS     0x40000        /* contains thread-local storage */
4071 +#define SECTION_MACH_DEP 0x80000       /* subsequent bits reserved for target */
4072  
4073  extern unsigned int get_named_section_flags PARAMS ((const char *));
4074  extern bool set_named_section_flags    PARAMS ((const char *, unsigned int));
4075 --- gcc/print-tree.c.jj Mon Mar 18 23:19:57 2002
4076 +++ gcc/print-tree.c    Wed Jun 19 19:33:52 2002
4077 @@ -363,6 +363,8 @@ print_node (file, prefix, node, indent)
4078  
4079        if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
4080         fputs (" in-text-section", file);
4081 +      if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))
4082 +       fputs (" thread-local", file);
4083  
4084        if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
4085         fputs (" transparent-union", file);
4086 --- gcc/target-def.h.jj Tue Feb 12 16:19:14 2002
4087 +++ gcc/target-def.h    Wed Jun 19 19:33:52 2002
4088 @@ -98,6 +98,10 @@ Foundation, 59 Temple Place - Suite 330,
4089  #define TARGET_HAVE_NAMED_SECTIONS false
4090  #endif
4091  
4092 +#ifndef TARGET_HAVE_TLS
4093 +#define TARGET_HAVE_TLS false
4094 +#endif
4095 +
4096  #ifndef TARGET_ASM_EXCEPTION_SECTION
4097  #define TARGET_ASM_EXCEPTION_SECTION default_exception_section
4098  #endif
4099 @@ -194,9 +198,10 @@ Foundation, 59 Temple Place - Suite 330,
4100    TARGET_INIT_BUILTINS,                                \
4101    TARGET_EXPAND_BUILTIN,                       \
4102    TARGET_SECTION_TYPE_FLAGS,                   \
4103 +  TARGET_CANNOT_MODIFY_JUMPS_P,                        \
4104    TARGET_HAVE_NAMED_SECTIONS,                  \
4105    TARGET_HAVE_CTORS_DTORS,                     \
4106 -  TARGET_CANNOT_MODIFY_JUMPS_P                 \
4107 +  TARGET_HAVE_TLS                              \
4108  }
4109  
4110  #include "hooks.h"
4111 --- gcc/target.h.jj     Tue Feb 12 16:19:14 2002
4112 +++ gcc/target.h        Wed Jun 19 19:33:52 2002
4113 @@ -178,6 +178,10 @@ struct gcc_target
4114    /* ??? Should be merged with SELECT_SECTION and UNIQUE_SECTION.  */
4115    unsigned int (* section_type_flags) PARAMS ((tree, const char *, int));
4116  
4117 +  /* True if new jumps cannot be created, to replace existing ones or
4118 +     not, at the current point in the compilation.  */
4119 +  bool (* cannot_modify_jumps_p) PARAMS ((void));
4120 +
4121    /* True if arbitrary sections are supported.  */
4122    bool have_named_sections;
4123  
4124 @@ -185,9 +189,8 @@ struct gcc_target
4125       false if we're using collect2 for the job.  */
4126    bool have_ctors_dtors;
4127  
4128 -  /* True if new jumps cannot be created, to replace existing ones or
4129 -     not, at the current point in the compilation.  */
4130 -  bool (* cannot_modify_jumps_p) PARAMS ((void));
4131 +  /* True if thread-local storage is supported.  */
4132 +  bool have_tls;
4133  };
4134  
4135  extern struct gcc_target targetm;
4136 --- gcc/toplev.c.jj     Thu May 30 11:08:44 2002
4137 +++ gcc/toplev.c        Wed Jun 19 19:33:52 2002
4138 @@ -682,12 +682,15 @@ int flag_shared_data;
4139  int flag_delayed_branch;
4140  
4141  /* Nonzero if we are compiling pure (sharable) code.
4142 -   Value is 1 if we are doing reasonable (i.e. simple
4143 -   offset into offset table) pic.  Value is 2 if we can
4144 -   only perform register offsets.  */
4145 +   Value is 1 if we are doing "small" pic; value is 2 if we're doing
4146 +   "large" pic.  */
4147  
4148  int flag_pic;
4149  
4150 +/* Set to the default thread-local storage (tls) model to use.  */
4151 +
4152 +enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
4153 +
4154  /* Nonzero means generate extra code for exception handling and enable
4155     exception handling.  */
4156  
4157 @@ -3609,6 +3612,7 @@ display_help ()
4158    printf (_("  -finline-limit=<number> Limits the size of inlined functions to <number>\n"));
4159    printf (_("  -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line.  0 suppresses line-wrapping\n"));
4160    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"));
4161 +  printf (_("  -ftls-model=[global-dynamic | local-dynamic | initial-exec | local-exec] Indicates the default thread-local storage code generation model\n"));
4162  
4163    for (i = ARRAY_SIZE (f_options); i--;)
4164      {
4165 @@ -3887,6 +3891,19 @@ decode_f_option (arg)
4166                                  MAX_INLINE_INSNS);
4167        set_param_value ("max-inline-insns", val);
4168      }
4169 +  else if ((option_value = skip_leading_substring (arg, "tls-model=")))
4170 +    {
4171 +      if (strcmp (option_value, "global-dynamic") == 0)
4172 +       flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
4173 +      else if (strcmp (option_value, "local-dynamic") == 0)
4174 +       flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
4175 +      else if (strcmp (option_value, "initial-exec") == 0)
4176 +       flag_tls_default = TLS_MODEL_INITIAL_EXEC;
4177 +      else if (strcmp (option_value, "local-exec") == 0)
4178 +       flag_tls_default = TLS_MODEL_LOCAL_EXEC;
4179 +      else
4180 +       warning ("`%s': unknown tls-model option", arg - 2);
4181 +    }
4182  #ifdef INSN_SCHEDULING
4183    else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
4184      fix_sched_param ("verbose", option_value);
4185 --- gcc/tree.c.jj       Sun Apr 28 23:20:20 2002
4186 +++ gcc/tree.c  Wed Jun 19 19:33:52 2002
4187 @@ -1510,12 +1510,13 @@ staticp (arg)
4188      case FUNCTION_DECL:
4189        /* Nested functions aren't static, since taking their address
4190          involves a trampoline.  */
4191 -      return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
4192 -       && ! DECL_NON_ADDR_CONST_P (arg);
4193 +      return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
4194 +             && ! DECL_NON_ADDR_CONST_P (arg));
4195  
4196      case VAR_DECL:
4197 -      return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
4198 -       && ! DECL_NON_ADDR_CONST_P (arg);
4199 +      return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
4200 +             && ! DECL_THREAD_LOCAL (arg)
4201 +             && ! DECL_NON_ADDR_CONST_P (arg));
4202  
4203      case CONSTRUCTOR:
4204        return TREE_STATIC (arg);
4205 --- gcc/tree.h.jj       Wed Jun 19 19:33:50 2002
4206 +++ gcc/tree.h  Wed Jun 19 19:33:52 2002
4207 @@ -1614,6 +1614,10 @@ struct tree_type
4208  /* In a FUNCTION_DECL, nonzero if the function cannot be inlined.  */
4209  #define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
4210  
4211 +/* In a VAR_DECL, nonzero if the data should be allocated from 
4212 +   thread-local storage.  */
4213 +#define DECL_THREAD_LOCAL(NODE) (VAR_DECL_CHECK (NODE)->decl.thread_local_flag)
4214 +
4215  /* In a FUNCTION_DECL, the saved representation of the body of the
4216     entire function.  Usually a COMPOUND_STMT, but in C++ this may also
4217     be a RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK.  */
4218 @@ -1792,7 +1796,8 @@ struct tree_decl
4219    unsigned non_addressable : 1;
4220    unsigned user_align : 1;
4221    unsigned uninlinable : 1;
4222 -  /* Three unused bits.  */
4223 +  unsigned thread_local_flag : 1;
4224 +  /* Two unused bits.  */
4225  
4226    unsigned lang_flag_0 : 1;
4227    unsigned lang_flag_1 : 1;
4228 --- gcc/varasm.c.jj     Wed Jun 19 19:33:51 2002
4229 +++ gcc/varasm.c        Wed Jun 19 19:33:52 2002
4230 @@ -1599,14 +1599,24 @@ assemble_variable (decl, top_level, at_e
4231  
4232    /* Handle uninitialized definitions.  */
4233  
4234 -  if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
4235 -      /* If the target can't output uninitialized but not common global data
4236 -        in .bss, then we have to use .data.  */
4237 -#if ! defined ASM_EMIT_BSS
4238 -      && DECL_COMMON (decl)
4239 +  /* If the decl has been given an explicit section name, then it
4240 +     isn't common, and shouldn't be handled as such.  */
4241 +  if (DECL_SECTION_NAME (decl) || dont_output_data)
4242 +    ;
4243 +  /* We don't implement common thread-local data at present.  */
4244 +  else if (DECL_THREAD_LOCAL (decl))
4245 +    {
4246 +      if (DECL_COMMON (decl))
4247 +       sorry ("thread-local COMMON data not implemented");
4248 +    }
4249 +#ifndef ASM_EMIT_BSS
4250 +  /* If the target can't output uninitialized but not common global data
4251 +     in .bss, then we have to use .data.  */
4252 +  else if (!DECL_COMMON (decl))
4253 +    ;
4254  #endif
4255 -      && DECL_SECTION_NAME (decl) == NULL_TREE
4256 -      && ! dont_output_data)
4257 +  else if (DECL_INITIAL (decl) == 0
4258 +          || DECL_INITIAL (decl) == error_mark_node)
4259      {
4260        unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
4261        unsigned HOST_WIDE_INT rounded = size;
4262 @@ -5324,14 +5334,22 @@ default_section_type_flags (decl, name, 
4263    if (decl && DECL_ONE_ONLY (decl))
4264      flags |= SECTION_LINKONCE;
4265  
4266 +  if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4267 +    flags |= SECTION_TLS | SECTION_WRITE;
4268 +
4269    if (strcmp (name, ".bss") == 0
4270        || strncmp (name, ".bss.", 5) == 0
4271        || strncmp (name, ".gnu.linkonce.b.", 16) == 0
4272        || strcmp (name, ".sbss") == 0
4273        || strncmp (name, ".sbss.", 6) == 0
4274 -      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
4275 +      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
4276 +      || strcmp (name, ".tbss") == 0)
4277      flags |= SECTION_BSS;
4278  
4279 +  if (strcmp (name, ".tdata") == 0
4280 +      || strcmp (name, ".tbss") == 0)
4281 +    flags |= SECTION_TLS;
4282 +
4283    return flags;
4284  }
4285  
4286 @@ -5374,6 +5392,8 @@ default_elf_asm_named_section (name, fla
4287      *f++ = 'M';
4288    if (flags & SECTION_STRINGS)
4289      *f++ = 'S';
4290 +  if (flags & SECTION_TLS)
4291 +    *f++ = 'T';
4292    *f = '\0';
4293  
4294    if (flags & SECTION_BSS)
This page took 0.376731 seconds and 3 git commands to generate.