OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [darwin.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Functions for generic Darwin as target machine for GNU C compiler.
2
   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
3
   2005, 2007
4
   Free Software Foundation, Inc.
5
   Contributed by Apple Computer Inc.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3, or (at your option)
12
any later version.
13
 
14
GCC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
#include "rtl.h"
28
#include "regs.h"
29
#include "hard-reg-set.h"
30
#include "real.h"
31
#include "insn-config.h"
32
#include "conditions.h"
33
#include "insn-flags.h"
34
#include "output.h"
35
#include "insn-attr.h"
36
#include "flags.h"
37
#include "tree.h"
38
#include "expr.h"
39
#include "reload.h"
40
#include "function.h"
41
#include "ggc.h"
42
#include "langhooks.h"
43
#include "target.h"
44
#include "tm_p.h"
45
#include "toplev.h"
46
#include "hashtab.h"
47
 
48
/* Darwin supports a feature called fix-and-continue, which is used
49
   for rapid turn around debugging.  When code is compiled with the
50
   -mfix-and-continue flag, two changes are made to the generated code
51
   that allow the system to do things that it would normally not be
52
   able to do easily.  These changes allow gdb to load in
53
   recompilation of a translation unit that has been changed into a
54
   running program and replace existing functions and methods of that
55
   translation unit with versions of those functions and methods
56
   from the newly compiled translation unit.  The new functions access
57
   the existing static symbols from the old translation unit, if the
58
   symbol existed in the unit to be replaced, and from the new
59
   translation unit, otherwise.
60
 
61
   The changes are to insert 5 nops at the beginning of all functions
62
   and to use indirection to get at static symbols.  The 5 nops
63
   are required by consumers of the generated code.  Currently, gdb
64
   uses this to patch in a jump to the overriding function, this
65
   allows all uses of the old name to forward to the replacement,
66
   including existing function pointers and virtual methods.  See
67
   rs6000_emit_prologue for the code that handles the nop insertions.
68
 
69
   The added indirection allows gdb to redirect accesses to static
70
   symbols from the newly loaded translation unit to the existing
71
   symbol, if any.  @code{static} symbols are special and are handled by
72
   setting the second word in the .non_lazy_symbol_pointer data
73
   structure to symbol.  See indirect_data for the code that handles
74
   the extra indirection, and machopic_output_indirection and its use
75
   of MACHO_SYMBOL_STATIC for the code that handles @code{static}
76
   symbol indirection.  */
77
 
78
/* Section names.  */
79
section * darwin_sections[NUM_DARWIN_SECTIONS];
80
 
81
/* True if we're setting __attribute__ ((ms_struct)).  */
82
int darwin_ms_struct = false;
83
 
84
/* A get_unnamed_section callback used to switch to an ObjC section.
85
   DIRECTIVE is as for output_section_asm_op.  */
86
 
87
static void
88
output_objc_section_asm_op (const void *directive)
89
{
90
  static bool been_here = false;
91
 
92
  if (! been_here)
93
    {
94
      static const enum darwin_section_enum tomark[] =
95
        {
96
          /* written, cold -> hot */
97
          objc_cat_cls_meth_section,
98
          objc_cat_inst_meth_section,
99
          objc_string_object_section,
100
          objc_constant_string_object_section,
101
          objc_selector_refs_section,
102
          objc_selector_fixup_section,
103
          objc_cls_refs_section,
104
          objc_class_section,
105
          objc_meta_class_section,
106
          /* shared, hot -> cold */
107
          objc_cls_meth_section,
108
          objc_inst_meth_section,
109
          objc_protocol_section,
110
          objc_class_names_section,
111
          objc_meth_var_types_section,
112
          objc_meth_var_names_section,
113
          objc_category_section,
114
          objc_class_vars_section,
115
          objc_instance_vars_section,
116
          objc_module_info_section,
117
          objc_symbols_section
118
        };
119
      size_t i;
120
 
121
      been_here = true;
122
      for (i = 0; i < ARRAY_SIZE (tomark); i++)
123
        switch_to_section (darwin_sections[tomark[i]]);
124
    }
125
  output_section_asm_op (directive);
126
}
127
 
128
/* Implement TARGET_ASM_INIT_SECTIONS.  */
129
 
130
void
131
darwin_init_sections (void)
132
{
133
#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC)               \
134
  darwin_sections[NAME] =                                       \
135
    get_unnamed_section (FLAGS, (OBJC                           \
136
                                 ? output_objc_section_asm_op   \
137
                                 : output_section_asm_op),      \
138
                         "\t" DIRECTIVE);
139
#include "config/darwin-sections.def"
140
#undef DEF_SECTION
141
 
142
  readonly_data_section = darwin_sections[const_section];
143
  exception_section = darwin_sections[darwin_exception_section];
144
  eh_frame_section = darwin_sections[darwin_eh_frame_section];
145
}
146
 
147
int
148
name_needs_quotes (const char *name)
149
{
150
  int c;
151
  while ((c = *name++) != '\0')
152
    if (! ISIDNUM (c) && c != '.' && c != '$')
153
      return 1;
154
  return 0;
155
}
156
 
157
/* Return true if SYM_REF can be used without an indirection.  */
158
static int
159
machopic_symbol_defined_p (rtx sym_ref)
160
{
161
  if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
162
    return true;
163
 
164
  /* If a symbol references local and is not an extern to this
165
     file, then the symbol might be able to declared as defined.  */
166
  if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
167
    {
168
      /* If the symbol references a variable and the variable is a
169
         common symbol, then this symbol is not defined.  */
170
      if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
171
        {
172
          tree decl = SYMBOL_REF_DECL (sym_ref);
173
          if (!decl)
174
            return true;
175
          if (DECL_COMMON (decl))
176
            return false;
177
        }
178
      return true;
179
    }
180
  return false;
181
}
182
 
183
/* This module assumes that (const (symbol_ref "foo")) is a legal pic
184
   reference, which will not be changed.  */
185
 
186
enum machopic_addr_class
187
machopic_classify_symbol (rtx sym_ref)
188
{
189
  int flags;
190
  bool function_p;
191
 
192
  flags = SYMBOL_REF_FLAGS (sym_ref);
193
  function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
194
  if (machopic_symbol_defined_p (sym_ref))
195
    return (function_p
196
            ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
197
  else
198
    return (function_p
199
            ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
200
}
201
 
202
#ifndef TARGET_FIX_AND_CONTINUE
203
#define TARGET_FIX_AND_CONTINUE 0
204
#endif
205
 
206
/* Indicate when fix-and-continue style code generation is being used
207
   and when a reference to data should be indirected so that it can be
208
   rebound in a new translation unit to reference the original instance
209
   of that data.  Symbol names that are for code generation local to
210
   the translation unit are bound to the new translation unit;
211
   currently this means symbols that begin with L or _OBJC_;
212
   otherwise, we indicate that an indirect reference should be made to
213
   permit the runtime to rebind new instances of the translation unit
214
   to the original instance of the data.  */
215
 
216
static int
217
indirect_data (rtx sym_ref)
218
{
219
  int lprefix;
220
  const char *name;
221
 
222
  /* If we aren't generating fix-and-continue code, don't do anything special.  */
223
  if (TARGET_FIX_AND_CONTINUE == 0)
224
    return 0;
225
 
226
  /* Otherwise, all symbol except symbols that begin with L or _OBJC_
227
     are indirected.  Symbols that begin with L and _OBJC_ are always
228
     bound to the current translation unit as they are used for
229
     generated local data of the translation unit.  */
230
 
231
  name = XSTR (sym_ref, 0);
232
 
233
  lprefix = (((name[0] == '*' || name[0] == '&')
234
              && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
235
             || (strncmp (name, "_OBJC_", 6) == 0));
236
 
237
  return ! lprefix;
238
}
239
 
240
 
241
static int
242
machopic_data_defined_p (rtx sym_ref)
243
{
244
  if (indirect_data (sym_ref))
245
    return 0;
246
 
247
  switch (machopic_classify_symbol (sym_ref))
248
    {
249
    case MACHOPIC_DEFINED_DATA:
250
    case MACHOPIC_DEFINED_FUNCTION:
251
      return 1;
252
    default:
253
      return 0;
254
    }
255
}
256
 
257
void
258
machopic_define_symbol (rtx mem)
259
{
260
  rtx sym_ref;
261
 
262
  gcc_assert (GET_CODE (mem) == MEM);
263
  sym_ref = XEXP (mem, 0);
264
  SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
265
}
266
 
267
static GTY(()) char * function_base;
268
 
269
const char *
270
machopic_function_base_name (void)
271
{
272
  /* if dynamic-no-pic is on, we should not get here */
273
  gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
274
 
275
  if (function_base == NULL)
276
    function_base =
277
      (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
278
 
279
  current_function_uses_pic_offset_table = 1;
280
 
281
  return function_base;
282
}
283
 
284
/* Return a SYMBOL_REF for the PIC function base.  */
285
 
286
rtx
287
machopic_function_base_sym (void)
288
{
289
  rtx sym_ref;
290
 
291
  sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
292
  SYMBOL_REF_FLAGS (sym_ref)
293
    |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
294
  return sym_ref;
295
}
296
 
297
/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending
298
   on whether pic_base is NULL or not.  */
299
static inline rtx
300
gen_pic_offset (rtx orig, rtx pic_base)
301
{
302
  if (!pic_base)
303
    return orig;
304
  else
305
    return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base));
306
}
307
 
308
static GTY(()) const char * function_base_func_name;
309
static GTY(()) int current_pic_label_num;
310
 
311
void
312
machopic_output_function_base_name (FILE *file)
313
{
314
  const char *current_name;
315
 
316
  /* If dynamic-no-pic is on, we should not get here.  */
317
  gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
318
  current_name =
319
    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
320
  if (function_base_func_name != current_name)
321
    {
322
      ++current_pic_label_num;
323
      function_base_func_name = current_name;
324
    }
325
  fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
326
}
327
 
328
/* The suffix attached to non-lazy pointer symbols.  */
329
#define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
330
/* The suffix attached to stub symbols.  */
331
#define STUB_SUFFIX "$stub"
332
 
333
typedef struct machopic_indirection GTY (())
334
{
335
  /* The SYMBOL_REF for the entity referenced.  */
336
  rtx symbol;
337
  /* The name of the stub or non-lazy pointer.  */
338
  const char * ptr_name;
339
  /* True iff this entry is for a stub (as opposed to a non-lazy
340
     pointer).  */
341
  bool stub_p;
342
  /* True iff this stub or pointer pointer has been referenced.  */
343
  bool used;
344
} machopic_indirection;
345
 
346
/* A table mapping stub names and non-lazy pointer names to
347
   SYMBOL_REFs for the stubbed-to and pointed-to entities.  */
348
 
349
static GTY ((param_is (struct machopic_indirection))) htab_t
350
  machopic_indirections;
351
 
352
/* Return a hash value for a SLOT in the indirections hash table.  */
353
 
354
static hashval_t
355
machopic_indirection_hash (const void *slot)
356
{
357
  const machopic_indirection *p = (const machopic_indirection *) slot;
358
  return htab_hash_string (p->ptr_name);
359
}
360
 
361
/* Returns true if the KEY is the same as that associated with
362
   SLOT.  */
363
 
364
static int
365
machopic_indirection_eq (const void *slot, const void *key)
366
{
367
  return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
368
}
369
 
370
/* Return the name of the non-lazy pointer (if STUB_P is false) or
371
   stub (if STUB_B is true) corresponding to the given name.  */
372
 
373
const char *
374
machopic_indirection_name (rtx sym_ref, bool stub_p)
375
{
376
  char *buffer;
377
  const char *name = XSTR (sym_ref, 0);
378
  size_t namelen = strlen (name);
379
  machopic_indirection *p;
380
  void ** slot;
381
  bool saw_star = false;
382
  bool needs_quotes;
383
  const char *suffix;
384
  const char *prefix = user_label_prefix;
385
  const char *quote = "";
386
  tree id;
387
 
388
  id = maybe_get_identifier (name);
389
  if (id)
390
    {
391
      tree id_orig = id;
392
 
393
      while (IDENTIFIER_TRANSPARENT_ALIAS (id))
394
        id = TREE_CHAIN (id);
395
      if (id != id_orig)
396
        {
397
          name = IDENTIFIER_POINTER (id);
398
          namelen = strlen (name);
399
        }
400
    }
401
 
402
  if (name[0] == '*')
403
    {
404
      saw_star = true;
405
      prefix = "";
406
      ++name;
407
      --namelen;
408
    }
409
 
410
  needs_quotes = name_needs_quotes (name);
411
  if (needs_quotes)
412
    {
413
      quote = "\"";
414
    }
415
 
416
  if (stub_p)
417
    suffix = STUB_SUFFIX;
418
  else
419
    suffix = NON_LAZY_POINTER_SUFFIX;
420
 
421
  buffer = alloca (strlen ("&L")
422
                   + strlen (prefix)
423
                   + namelen
424
                   + strlen (suffix)
425
                   + 2 * strlen (quote)
426
                   + 1 /* '\0' */);
427
 
428
  /* Construct the name of the non-lazy pointer or stub.  */
429
  sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote);
430
 
431
  if (!machopic_indirections)
432
    machopic_indirections = htab_create_ggc (37,
433
                                             machopic_indirection_hash,
434
                                             machopic_indirection_eq,
435
                                             /*htab_del=*/NULL);
436
 
437
  slot = htab_find_slot_with_hash (machopic_indirections, buffer,
438
                                   htab_hash_string (buffer), INSERT);
439
  if (*slot)
440
    {
441
      p = (machopic_indirection *) *slot;
442
    }
443
  else
444
    {
445
      p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
446
      p->symbol = sym_ref;
447
      p->ptr_name = xstrdup (buffer);
448
      p->stub_p = stub_p;
449
      p->used = false;
450
      *slot = p;
451
    }
452
 
453
  return p->ptr_name;
454
}
455
 
456
/* Return the name of the stub for the mcount function.  */
457
 
458
const char*
459
machopic_mcount_stub_name (void)
460
{
461
  rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
462
  return machopic_indirection_name (symbol, /*stub_p=*/true);
463
}
464
 
465
/* If NAME is the name of a stub or a non-lazy pointer , mark the stub
466
   or non-lazy pointer as used -- and mark the object to which the
467
   pointer/stub refers as used as well, since the pointer/stub will
468
   emit a reference to it.  */
469
 
470
void
471
machopic_validate_stub_or_non_lazy_ptr (const char *name)
472
{
473
  machopic_indirection *p;
474
 
475
  p = ((machopic_indirection *)
476
       (htab_find_with_hash (machopic_indirections, name,
477
                             htab_hash_string (name))));
478
  if (p && ! p->used)
479
    {
480
      const char *real_name;
481
      tree id;
482
 
483
      p->used = true;
484
 
485
      /* Do what output_addr_const will do when we actually call it.  */
486
      if (SYMBOL_REF_DECL (p->symbol))
487
        mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
488
 
489
      real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
490
 
491
      id = maybe_get_identifier (real_name);
492
      if (id)
493
        mark_referenced (id);
494
    }
495
}
496
 
497
/* Transform ORIG, which may be any data source, to the corresponding
498
   source using indirections.  */
499
 
500
rtx
501
machopic_indirect_data_reference (rtx orig, rtx reg)
502
{
503
  rtx ptr_ref = orig;
504
 
505
  if (! MACHOPIC_INDIRECT)
506
    return orig;
507
 
508
  if (GET_CODE (orig) == SYMBOL_REF)
509
    {
510
      int defined = machopic_data_defined_p (orig);
511
 
512
      if (defined && MACHO_DYNAMIC_NO_PIC_P)
513
        {
514
#if defined (TARGET_TOC)
515
          /* Create a new register for CSE opportunities.  */
516
          rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
517
          emit_insn (gen_macho_high (hi_reg, orig));
518
          emit_insn (gen_macho_low (reg, hi_reg, orig));
519
#else
520
           /* some other cpu -- writeme!  */
521
           gcc_unreachable ();
522
#endif
523
           return reg;
524
        }
525
      else if (defined)
526
        {
527
#if defined (TARGET_TOC) || defined (HAVE_lo_sum)
528
          rtx pic_base = machopic_function_base_sym ();
529
          rtx offset = gen_pic_offset (orig, pic_base);
530
#endif
531
 
532
#if defined (TARGET_TOC) /* i.e., PowerPC */
533
          rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
534
 
535
          gcc_assert (reg);
536
 
537
          emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
538
                              gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
539
                                       gen_rtx_HIGH (Pmode, offset))));
540
          emit_insn (gen_rtx_SET (Pmode, reg,
541
                                  gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
542
 
543
          orig = reg;
544
#else
545
#if defined (HAVE_lo_sum)
546
          gcc_assert (reg);
547
 
548
          emit_insn (gen_rtx_SET (VOIDmode, reg,
549
                                  gen_rtx_HIGH (Pmode, offset)));
550
          emit_insn (gen_rtx_SET (VOIDmode, reg,
551
                                  gen_rtx_LO_SUM (Pmode, reg, offset)));
552
          emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
553
 
554
          orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
555
#endif
556
#endif
557
          return orig;
558
        }
559
 
560
      ptr_ref = (gen_rtx_SYMBOL_REF
561
                 (Pmode,
562
                  machopic_indirection_name (orig, /*stub_p=*/false)));
563
 
564
      SYMBOL_REF_DATA (ptr_ref) = SYMBOL_REF_DATA (orig);
565
 
566
      ptr_ref = gen_const_mem (Pmode, ptr_ref);
567
      machopic_define_symbol (ptr_ref);
568
 
569
      return ptr_ref;
570
    }
571
  else if (GET_CODE (orig) == CONST)
572
    {
573
      rtx base, result;
574
 
575
      /* legitimize both operands of the PLUS */
576
      if (GET_CODE (XEXP (orig, 0)) == PLUS)
577
        {
578
          base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
579
                                                   reg);
580
          orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
581
                                                   (base == reg ? 0 : reg));
582
        }
583
      else
584
        return orig;
585
 
586
      if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
587
        result = plus_constant (base, INTVAL (orig));
588
      else
589
        result = gen_rtx_PLUS (Pmode, base, orig);
590
 
591
      if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
592
        {
593
          if (reg)
594
            {
595
              emit_move_insn (reg, result);
596
              result = reg;
597
            }
598
          else
599
            {
600
              result = force_reg (GET_MODE (result), result);
601
            }
602
        }
603
 
604
      return result;
605
 
606
    }
607
  else if (GET_CODE (orig) == MEM)
608
    XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
609
  /* When the target is i386, this code prevents crashes due to the
610
     compiler's ignorance on how to move the PIC base register to
611
     other registers.  (The reload phase sometimes introduces such
612
     insns.)  */
613
  else if (GET_CODE (orig) == PLUS
614
           && GET_CODE (XEXP (orig, 0)) == REG
615
           && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
616
#ifdef I386
617
           /* Prevent the same register from being erroneously used
618
              as both the base and index registers.  */
619
           && GET_CODE (XEXP (orig, 1)) == CONST
620
#endif
621
           && reg)
622
    {
623
      emit_move_insn (reg, XEXP (orig, 0));
624
      XEXP (ptr_ref, 0) = reg;
625
    }
626
  return ptr_ref;
627
}
628
 
629
/* Transform TARGET (a MEM), which is a function call target, to the
630
   corresponding symbol_stub if necessary.  Return a new MEM.  */
631
 
632
rtx
633
machopic_indirect_call_target (rtx target)
634
{
635
  if (GET_CODE (target) != MEM)
636
    return target;
637
 
638
  if (MACHOPIC_INDIRECT
639
      && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
640
      && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
641
           & MACHO_SYMBOL_FLAG_DEFINED))
642
    {
643
      rtx sym_ref = XEXP (target, 0);
644
      const char *stub_name = machopic_indirection_name (sym_ref,
645
                                                         /*stub_p=*/true);
646
      enum machine_mode mode = GET_MODE (sym_ref);
647
 
648
      XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
649
      SYMBOL_REF_DATA (XEXP (target, 0)) = SYMBOL_REF_DATA (sym_ref);
650
      MEM_READONLY_P (target) = 1;
651
      MEM_NOTRAP_P (target) = 1;
652
    }
653
 
654
  return target;
655
}
656
 
657
rtx
658
machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
659
{
660
  rtx pic_ref = orig;
661
 
662
  if (! MACHOPIC_INDIRECT)
663
    return orig;
664
 
665
  /* First handle a simple SYMBOL_REF or LABEL_REF */
666
  if (GET_CODE (orig) == LABEL_REF
667
      || (GET_CODE (orig) == SYMBOL_REF
668
          ))
669
    {
670
      /* addr(foo) = &func+(foo-func) */
671
      rtx pic_base;
672
 
673
      orig = machopic_indirect_data_reference (orig, reg);
674
 
675
      if (GET_CODE (orig) == PLUS
676
          && GET_CODE (XEXP (orig, 0)) == REG)
677
        {
678
          if (reg == 0)
679
            return force_reg (mode, orig);
680
 
681
          emit_move_insn (reg, orig);
682
          return reg;
683
        }
684
 
685
      /* if dynamic-no-pic we don't have a pic base  */
686
      if (MACHO_DYNAMIC_NO_PIC_P)
687
        pic_base = NULL;
688
      else
689
        pic_base = machopic_function_base_sym ();
690
 
691
      if (GET_CODE (orig) == MEM)
692
        {
693
          if (reg == 0)
694
            {
695
              gcc_assert (!reload_in_progress);
696
              reg = gen_reg_rtx (Pmode);
697
            }
698
 
699
#ifdef HAVE_lo_sum
700
          if (MACHO_DYNAMIC_NO_PIC_P
701
              && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
702
                  || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
703
            {
704
#if defined (TARGET_TOC)        /* ppc  */
705
              rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
706
              rtx asym = XEXP (orig, 0);
707
              rtx mem;
708
 
709
              emit_insn (gen_macho_high (temp_reg, asym));
710
              mem = gen_const_mem (GET_MODE (orig),
711
                                   gen_rtx_LO_SUM (Pmode, temp_reg, asym));
712
              emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
713
#else
714
              /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
715
              gcc_unreachable ();
716
#endif
717
              pic_ref = reg;
718
            }
719
          else
720
          if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
721
              || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
722
            {
723
              rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base);
724
#if defined (TARGET_TOC) /* i.e., PowerPC */
725
              /* Generating a new reg may expose opportunities for
726
                 common subexpression elimination.  */
727
              rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
728
              rtx mem;
729
              rtx insn;
730
              rtx sum;
731
 
732
              sum = gen_rtx_HIGH (Pmode, offset);
733
              if (! MACHO_DYNAMIC_NO_PIC_P)
734
                sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
735
 
736
              emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
737
 
738
              mem = gen_const_mem (GET_MODE (orig),
739
                                  gen_rtx_LO_SUM (Pmode,
740
                                                  hi_sum_reg, offset));
741
              insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
742
              REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
743
                                                    REG_NOTES (insn));
744
 
745
              pic_ref = reg;
746
#else
747
              emit_insn (gen_rtx_USE (VOIDmode,
748
                                      gen_rtx_REG (Pmode,
749
                                                   PIC_OFFSET_TABLE_REGNUM)));
750
 
751
              emit_insn (gen_rtx_SET (VOIDmode, reg,
752
                                      gen_rtx_HIGH (Pmode,
753
                                                    gen_rtx_CONST (Pmode,
754
                                                                   offset))));
755
              emit_insn (gen_rtx_SET (VOIDmode, reg,
756
                                  gen_rtx_LO_SUM (Pmode, reg,
757
                                           gen_rtx_CONST (Pmode, offset))));
758
              pic_ref = gen_rtx_PLUS (Pmode,
759
                                      pic_offset_table_rtx, reg);
760
#endif
761
            }
762
          else
763
#endif  /* HAVE_lo_sum */
764
            {
765
              rtx pic = pic_offset_table_rtx;
766
              if (GET_CODE (pic) != REG)
767
                {
768
                  emit_move_insn (reg, pic);
769
                  pic = reg;
770
                }
771
#if 0
772
              emit_insn (gen_rtx_USE (VOIDmode,
773
                                      gen_rtx_REG (Pmode,
774
                                                   PIC_OFFSET_TABLE_REGNUM)));
775
#endif
776
 
777
              if (reload_in_progress)
778
                regs_ever_live[REGNO (pic)] = 1;
779
              pic_ref = gen_rtx_PLUS (Pmode, pic,
780
                                      gen_pic_offset (XEXP (orig, 0),
781
                                                      pic_base));
782
            }
783
 
784
#if !defined (TARGET_TOC)
785
          emit_move_insn (reg, pic_ref);
786
          pic_ref = gen_const_mem (GET_MODE (orig), reg);
787
#endif
788
        }
789
      else
790
        {
791
 
792
#ifdef HAVE_lo_sum
793
          if (GET_CODE (orig) == SYMBOL_REF
794
              || GET_CODE (orig) == LABEL_REF)
795
            {
796
              rtx offset = gen_pic_offset (orig, pic_base);
797
#if defined (TARGET_TOC) /* i.e., PowerPC */
798
              rtx hi_sum_reg;
799
 
800
              if (reg == 0)
801
                {
802
                  gcc_assert (!reload_in_progress);
803
                  reg = gen_reg_rtx (Pmode);
804
                }
805
 
806
              hi_sum_reg = reg;
807
 
808
              emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
809
                                      (MACHO_DYNAMIC_NO_PIC_P)
810
                                      ? gen_rtx_HIGH (Pmode, offset)
811
                                      : gen_rtx_PLUS (Pmode,
812
                                                      pic_offset_table_rtx,
813
                                                      gen_rtx_HIGH (Pmode,
814
                                                                    offset))));
815
              emit_insn (gen_rtx_SET (VOIDmode, reg,
816
                                      gen_rtx_LO_SUM (Pmode,
817
                                                      hi_sum_reg, offset)));
818
              pic_ref = reg;
819
#else
820
              emit_insn (gen_rtx_SET (VOIDmode, reg,
821
                                      gen_rtx_HIGH (Pmode, offset)));
822
              emit_insn (gen_rtx_SET (VOIDmode, reg,
823
                                      gen_rtx_LO_SUM (Pmode, reg, offset)));
824
              pic_ref = gen_rtx_PLUS (Pmode,
825
                                      pic_offset_table_rtx, reg);
826
#endif
827
            }
828
          else
829
#endif  /*  HAVE_lo_sum  */
830
            {
831
              if (REG_P (orig)
832
                  || GET_CODE (orig) == SUBREG)
833
                {
834
                  return orig;
835
                }
836
              else
837
                {
838
                  rtx pic = pic_offset_table_rtx;
839
                  if (GET_CODE (pic) != REG)
840
                    {
841
                      emit_move_insn (reg, pic);
842
                      pic = reg;
843
                    }
844
#if 0
845
                  emit_insn (gen_rtx_USE (VOIDmode,
846
                                          pic_offset_table_rtx));
847
#endif
848
                  if (reload_in_progress)
849
                    regs_ever_live[REGNO (pic)] = 1;
850
                  pic_ref = gen_rtx_PLUS (Pmode,
851
                                          pic,
852
                                          gen_pic_offset (orig, pic_base));
853
                }
854
            }
855
        }
856
 
857
      if (GET_CODE (pic_ref) != REG)
858
        {
859
          if (reg != 0)
860
            {
861
              emit_move_insn (reg, pic_ref);
862
              return reg;
863
            }
864
          else
865
            {
866
              return force_reg (mode, pic_ref);
867
            }
868
        }
869
      else
870
        {
871
          return pic_ref;
872
        }
873
    }
874
 
875
  else if (GET_CODE (orig) == SYMBOL_REF)
876
    return orig;
877
 
878
  else if (GET_CODE (orig) == PLUS
879
           && (GET_CODE (XEXP (orig, 0)) == MEM
880
               || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
881
               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
882
           && XEXP (orig, 0) != pic_offset_table_rtx
883
           && GET_CODE (XEXP (orig, 1)) != REG)
884
 
885
    {
886
      rtx base;
887
      int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
888
 
889
      base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
890
      orig = machopic_legitimize_pic_address (XEXP (orig, 1),
891
                                              Pmode, (base == reg ? 0 : reg));
892
      if (GET_CODE (orig) == CONST_INT)
893
        {
894
          pic_ref = plus_constant (base, INTVAL (orig));
895
          is_complex = 1;
896
        }
897
      else
898
        pic_ref = gen_rtx_PLUS (Pmode, base, orig);
899
 
900
      if (reg && is_complex)
901
        {
902
          emit_move_insn (reg, pic_ref);
903
          pic_ref = reg;
904
        }
905
      /* Likewise, should we set special REG_NOTEs here?  */
906
    }
907
 
908
  else if (GET_CODE (orig) == CONST)
909
    {
910
      return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
911
    }
912
 
913
  else if (GET_CODE (orig) == MEM
914
           && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
915
    {
916
      rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
917
      addr = replace_equiv_address (orig, addr);
918
      emit_move_insn (reg, addr);
919
      pic_ref = reg;
920
    }
921
 
922
  return pic_ref;
923
}
924
 
925
/* Output the stub or non-lazy pointer in *SLOT, if it has been used.
926
   DATA is the FILE* for assembly output.  Called from
927
   htab_traverse.  */
928
 
929
static int
930
machopic_output_indirection (void **slot, void *data)
931
{
932
  machopic_indirection *p = *((machopic_indirection **) slot);
933
  FILE *asm_out_file = (FILE *) data;
934
  rtx symbol;
935
  const char *sym_name;
936
  const char *ptr_name;
937
 
938
  if (!p->used)
939
    return 1;
940
 
941
  symbol = p->symbol;
942
  sym_name = XSTR (symbol, 0);
943
  ptr_name = p->ptr_name;
944
 
945
  if (p->stub_p)
946
    {
947
      char *sym;
948
      char *stub;
949
      tree id;
950
 
951
      id = maybe_get_identifier (sym_name);
952
      if (id)
953
        {
954
          tree id_orig = id;
955
 
956
          while (IDENTIFIER_TRANSPARENT_ALIAS (id))
957
            id = TREE_CHAIN (id);
958
          if (id != id_orig)
959
            sym_name = IDENTIFIER_POINTER (id);
960
        }
961
 
962
      sym = alloca (strlen (sym_name) + 2);
963
      if (sym_name[0] == '*' || sym_name[0] == '&')
964
        strcpy (sym, sym_name + 1);
965
      else if (sym_name[0] == '-' || sym_name[0] == '+')
966
        strcpy (sym, sym_name);
967
      else
968
        sprintf (sym, "%s%s", user_label_prefix, sym_name);
969
 
970
      stub = alloca (strlen (ptr_name) + 2);
971
      if (ptr_name[0] == '*' || ptr_name[0] == '&')
972
        strcpy (stub, ptr_name + 1);
973
      else
974
        sprintf (stub, "%s%s", user_label_prefix, ptr_name);
975
 
976
      machopic_output_stub (asm_out_file, sym, stub);
977
    }
978
  else if (! indirect_data (symbol)
979
           && (machopic_symbol_defined_p (symbol)
980
               || SYMBOL_REF_LOCAL_P (symbol)))
981
    {
982
      switch_to_section (data_section);
983
      assemble_align (GET_MODE_ALIGNMENT (Pmode));
984
      assemble_label (ptr_name);
985
      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
986
                        GET_MODE_SIZE (Pmode),
987
                        GET_MODE_ALIGNMENT (Pmode), 1);
988
    }
989
  else
990
    {
991
      rtx init = const0_rtx;
992
 
993
      switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
994
      assemble_name (asm_out_file, ptr_name);
995
      fprintf (asm_out_file, ":\n");
996
 
997
      fprintf (asm_out_file, "\t.indirect_symbol ");
998
      assemble_name (asm_out_file, sym_name);
999
      fprintf (asm_out_file, "\n");
1000
 
1001
      /* Variables that are marked with MACHO_SYMBOL_STATIC need to
1002
         have their symbol name instead of 0 in the second entry of
1003
         the non-lazy symbol pointer data structure when they are
1004
         defined.  This allows the runtime to rebind newer instances
1005
         of the translation unit with the original instance of the
1006
         symbol.  */
1007
 
1008
      if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
1009
          && machopic_symbol_defined_p (symbol))
1010
        init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
1011
 
1012
      assemble_integer (init, GET_MODE_SIZE (Pmode),
1013
                        GET_MODE_ALIGNMENT (Pmode), 1);
1014
    }
1015
 
1016
  return 1;
1017
}
1018
 
1019
void
1020
machopic_finish (FILE *asm_out_file)
1021
{
1022
  if (machopic_indirections)
1023
    htab_traverse_noresize (machopic_indirections,
1024
                            machopic_output_indirection,
1025
                            asm_out_file);
1026
}
1027
 
1028
int
1029
machopic_operand_p (rtx op)
1030
{
1031
  if (MACHOPIC_JUST_INDIRECT)
1032
    {
1033
      while (GET_CODE (op) == CONST)
1034
        op = XEXP (op, 0);
1035
 
1036
      if (GET_CODE (op) == SYMBOL_REF)
1037
        return machopic_symbol_defined_p (op);
1038
      else
1039
        return 0;
1040
    }
1041
 
1042
  while (GET_CODE (op) == CONST)
1043
    op = XEXP (op, 0);
1044
 
1045
  if (GET_CODE (op) == MINUS
1046
      && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1047
      && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1048
      && machopic_symbol_defined_p (XEXP (op, 0))
1049
      && machopic_symbol_defined_p (XEXP (op, 1)))
1050
      return 1;
1051
 
1052
  return 0;
1053
}
1054
 
1055
/* This function records whether a given name corresponds to a defined
1056
   or undefined function or variable, for machopic_classify_ident to
1057
   use later.  */
1058
 
1059
void
1060
darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
1061
{
1062
  rtx sym_ref;
1063
 
1064
  /* Do the standard encoding things first.  */
1065
  default_encode_section_info (decl, rtl, first);
1066
 
1067
  if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
1068
    return;
1069
 
1070
  sym_ref = XEXP (rtl, 0);
1071
  if (TREE_CODE (decl) == VAR_DECL)
1072
    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
1073
 
1074
  if (!DECL_EXTERNAL (decl)
1075
      && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
1076
      && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
1077
      && ((TREE_STATIC (decl)
1078
           && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1079
          || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
1080
              && DECL_INITIAL (decl) != error_mark_node)))
1081
    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
1082
 
1083
  if (! TREE_PUBLIC (decl))
1084
    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
1085
}
1086
 
1087
void
1088
darwin_mark_decl_preserved (const char *name)
1089
{
1090
  fprintf (asm_out_file, ".no_dead_strip ");
1091
  assemble_name (asm_out_file, name);
1092
  fputc ('\n', asm_out_file);
1093
}
1094
 
1095
int
1096
machopic_reloc_rw_mask (void)
1097
{
1098
  return MACHOPIC_INDIRECT ? 3 : 0;
1099
}
1100
 
1101
section *
1102
machopic_select_section (tree exp, int reloc,
1103
                         unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1104
{
1105
  section *base_section;
1106
  bool weak_p = (DECL_P (exp) && DECL_WEAK (exp)
1107
                 && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp))
1108
                     || ! lookup_attribute ("weak_import",
1109
                                            DECL_ATTRIBUTES (exp))));
1110
 
1111
  if (TREE_CODE (exp) == FUNCTION_DECL)
1112
    {
1113
      if (reloc == 1)
1114
        base_section = (weak_p
1115
                        ? darwin_sections[text_unlikely_coal_section]
1116
                        : unlikely_text_section ());
1117
      else
1118
        base_section = weak_p ? darwin_sections[text_coal_section] : text_section;
1119
    }
1120
  else if (decl_readonly_section (exp, reloc))
1121
    base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section];
1122
  else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1123
    base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section];
1124
  else
1125
    base_section = weak_p ? darwin_sections[data_coal_section] : data_section;
1126
 
1127
  if (TREE_CODE (exp) == STRING_CST
1128
      && ((size_t) TREE_STRING_LENGTH (exp)
1129
          == strlen (TREE_STRING_POINTER (exp)) + 1))
1130
    return darwin_sections[cstring_section];
1131
  else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1132
           && flag_merge_constants)
1133
    {
1134
      tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
1135
 
1136
      if (TREE_CODE (size) == INTEGER_CST &&
1137
          TREE_INT_CST_LOW (size) == 4 &&
1138
          TREE_INT_CST_HIGH (size) == 0)
1139
        return darwin_sections[literal4_section];
1140
      else if (TREE_CODE (size) == INTEGER_CST &&
1141
               TREE_INT_CST_LOW (size) == 8 &&
1142
               TREE_INT_CST_HIGH (size) == 0)
1143
        return darwin_sections[literal8_section];
1144
      else if (TARGET_64BIT
1145
               && TREE_CODE (size) == INTEGER_CST
1146
               && TREE_INT_CST_LOW (size) == 16
1147
               && TREE_INT_CST_HIGH (size) == 0)
1148
        return darwin_sections[literal16_section];
1149
      else
1150
        return base_section;
1151
    }
1152
  else if (TREE_CODE (exp) == CONSTRUCTOR
1153
           && TREE_TYPE (exp)
1154
           && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1155
           && TYPE_NAME (TREE_TYPE (exp)))
1156
    {
1157
      tree name = TYPE_NAME (TREE_TYPE (exp));
1158
      if (TREE_CODE (name) == TYPE_DECL)
1159
        name = DECL_NAME (name);
1160
 
1161
      if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
1162
        {
1163
          if (flag_next_runtime)
1164
            return darwin_sections[objc_constant_string_object_section];
1165
          else
1166
            return darwin_sections[objc_string_object_section];
1167
        }
1168
      else
1169
        return base_section;
1170
    }
1171
  else if (TREE_CODE (exp) == VAR_DECL &&
1172
           DECL_NAME (exp) &&
1173
           TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1174
           IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1175
           !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1176
    {
1177
      const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1178
 
1179
      if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1180
        return darwin_sections[objc_cls_meth_section];
1181
      else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1182
        return darwin_sections[objc_inst_meth_section];
1183
      else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1184
        return darwin_sections[objc_cat_cls_meth_section];
1185
      else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1186
        return darwin_sections[objc_cat_inst_meth_section];
1187
      else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1188
        return darwin_sections[objc_class_vars_section];
1189
      else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1190
        return darwin_sections[objc_instance_vars_section];
1191
      else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1192
        return darwin_sections[objc_cat_cls_meth_section];
1193
      else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1194
        return darwin_sections[objc_class_names_section];
1195
      else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1196
        return darwin_sections[objc_meth_var_names_section];
1197
      else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1198
        return darwin_sections[objc_meth_var_types_section];
1199
      else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1200
        return darwin_sections[objc_cls_refs_section];
1201
      else if (!strncmp (name, "_OBJC_CLASS_", 12))
1202
        return darwin_sections[objc_class_section];
1203
      else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1204
        return darwin_sections[objc_meta_class_section];
1205
      else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1206
        return darwin_sections[objc_category_section];
1207
      else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1208
        return darwin_sections[objc_selector_refs_section];
1209
      else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1210
        return darwin_sections[objc_selector_fixup_section];
1211
      else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1212
        return darwin_sections[objc_symbols_section];
1213
      else if (!strncmp (name, "_OBJC_MODULES", 13))
1214
        return darwin_sections[objc_module_info_section];
1215
      else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1216
        return darwin_sections[objc_image_info_section];
1217
      else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1218
        return darwin_sections[objc_cat_inst_meth_section];
1219
      else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1220
        return darwin_sections[objc_cat_cls_meth_section];
1221
      else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1222
        return darwin_sections[objc_cat_cls_meth_section];
1223
      else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1224
        return darwin_sections[objc_protocol_section];
1225
      else
1226
        return base_section;
1227
    }
1228
  else
1229
    return base_section;
1230
}
1231
 
1232
/* This can be called with address expressions as "rtx".
1233
   They must go in "const".  */
1234
 
1235
section *
1236
machopic_select_rtx_section (enum machine_mode mode, rtx x,
1237
                             unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1238
{
1239
  if (GET_MODE_SIZE (mode) == 8
1240
      && (GET_CODE (x) == CONST_INT
1241
          || GET_CODE (x) == CONST_DOUBLE))
1242
    return darwin_sections[literal8_section];
1243
  else if (GET_MODE_SIZE (mode) == 4
1244
           && (GET_CODE (x) == CONST_INT
1245
               || GET_CODE (x) == CONST_DOUBLE))
1246
    return darwin_sections[literal4_section];
1247
  else if (TARGET_64BIT
1248
           && GET_MODE_SIZE (mode) == 16
1249
           && (GET_CODE (x) == CONST_INT
1250
               || GET_CODE (x) == CONST_DOUBLE
1251
               || GET_CODE (x) == CONST_VECTOR))
1252
    return darwin_sections[literal16_section];
1253
  else if (MACHOPIC_INDIRECT
1254
           && (GET_CODE (x) == SYMBOL_REF
1255
               || GET_CODE (x) == CONST
1256
               || GET_CODE (x) == LABEL_REF))
1257
    return darwin_sections[const_data_section];
1258
  else
1259
    return darwin_sections[const_section];
1260
}
1261
 
1262
void
1263
machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1264
{
1265
  if (MACHOPIC_INDIRECT)
1266
    switch_to_section (darwin_sections[mod_init_section]);
1267
  else
1268
    switch_to_section (darwin_sections[constructor_section]);
1269
  assemble_align (POINTER_SIZE);
1270
  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1271
 
1272
  if (! MACHOPIC_INDIRECT)
1273
    fprintf (asm_out_file, ".reference .constructors_used\n");
1274
}
1275
 
1276
void
1277
machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1278
{
1279
  if (MACHOPIC_INDIRECT)
1280
    switch_to_section (darwin_sections[mod_term_section]);
1281
  else
1282
    switch_to_section (darwin_sections[destructor_section]);
1283
  assemble_align (POINTER_SIZE);
1284
  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1285
 
1286
  if (! MACHOPIC_INDIRECT)
1287
    fprintf (asm_out_file, ".reference .destructors_used\n");
1288
}
1289
 
1290
void
1291
darwin_globalize_label (FILE *stream, const char *name)
1292
{
1293
  if (!!strncmp (name, "_OBJC_", 6))
1294
    default_globalize_label (stream, name);
1295
}
1296
 
1297
void
1298
darwin_asm_named_section (const char *name,
1299
                          unsigned int flags ATTRIBUTE_UNUSED,
1300
                          tree decl ATTRIBUTE_UNUSED)
1301
{
1302
  fprintf (asm_out_file, "\t.section %s\n", name);
1303
}
1304
 
1305
void
1306
darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
1307
{
1308
  /* Darwin does not use unique sections.  */
1309
}
1310
 
1311
/* Handle __attribute__ ((apple_kext_compatibility)).
1312
   This only applies to darwin kexts for 2.95 compatibility -- it shrinks the
1313
   vtable for classes with this attribute (and their descendants) by not
1314
   outputting the new 3.0 nondeleting destructor.  This means that such
1315
   objects CANNOT be allocated on the stack or as globals UNLESS they have
1316
   a completely empty `operator delete'.
1317
   Luckily, this fits in with the Darwin kext model.
1318
 
1319
   This attribute also disables gcc3's potential overlaying of derived
1320
   class data members on the padding at the end of the base class.  */
1321
 
1322
tree
1323
darwin_handle_kext_attribute (tree *node, tree name,
1324
                              tree args ATTRIBUTE_UNUSED,
1325
                              int flags ATTRIBUTE_UNUSED,
1326
                              bool *no_add_attrs)
1327
{
1328
  /* APPLE KEXT stuff -- only applies with pure static C++ code.  */
1329
  if (! TARGET_KEXTABI)
1330
    {
1331
      warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1332
               "only when compiling a kext", IDENTIFIER_POINTER (name));
1333
 
1334
      *no_add_attrs = true;
1335
    }
1336
  else if (TREE_CODE (*node) != RECORD_TYPE)
1337
    {
1338
      warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1339
               "only to C++ classes", IDENTIFIER_POINTER (name));
1340
 
1341
      *no_add_attrs = true;
1342
    }
1343
 
1344
  return NULL_TREE;
1345
}
1346
 
1347
/* Handle a "weak_import" attribute; arguments as in
1348
   struct attribute_spec.handler.  */
1349
 
1350
tree
1351
darwin_handle_weak_import_attribute (tree *node, tree name,
1352
                                     tree ARG_UNUSED (args),
1353
                                     int ARG_UNUSED (flags),
1354
                                     bool * no_add_attrs)
1355
{
1356
  if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
1357
    {
1358
      warning (OPT_Wattributes, "%qs attribute ignored",
1359
               IDENTIFIER_POINTER (name));
1360
      *no_add_attrs = true;
1361
    }
1362
  else
1363
    declare_weak (*node);
1364
 
1365
  return NULL_TREE;
1366
}
1367
 
1368
static void
1369
no_dead_strip (FILE *file, const char *lab)
1370
{
1371
  fprintf (file, ".no_dead_strip %s\n", lab);
1372
}
1373
 
1374
/* Emit a label for an FDE, making it global and/or weak if appropriate.
1375
   The third parameter is nonzero if this is for exception handling.
1376
   The fourth parameter is nonzero if this is just a placeholder for an
1377
   FDE that we are omitting. */
1378
 
1379
void
1380
darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1381
{
1382
  const char *base;
1383
  char *lab;
1384
  bool need_quotes;
1385
 
1386
  if (DECL_ASSEMBLER_NAME_SET_P (decl))
1387
    base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1388
  else
1389
    base = IDENTIFIER_POINTER (DECL_NAME (decl));
1390
 
1391
  base = targetm.strip_name_encoding (base);
1392
  need_quotes = name_needs_quotes (base);
1393
 
1394
  if (! for_eh)
1395
    return;
1396
 
1397
  lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
1398
                need_quotes ? "\"" : "", NULL);
1399
 
1400
  if (TREE_PUBLIC (decl))
1401
    fprintf (file, "\t%s %s\n",
1402
             (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1403
              ? ".globl"
1404
              : ".private_extern"),
1405
             lab);
1406
 
1407
  if (DECL_WEAK (decl))
1408
    fprintf (file, "\t.weak_definition %s\n", lab);
1409
 
1410
  if (empty)
1411
    {
1412
      fprintf (file, "%s = 0\n", lab);
1413
 
1414
      /* Mark the absolute .eh and .eh1 style labels as needed to
1415
         ensure that we don't dead code strip them and keep such
1416
         labels from another instantiation point until we can fix this
1417
         properly with group comdat support.  */
1418
      no_dead_strip (file, lab);
1419
    }
1420
  else
1421
    fprintf (file, "%s:\n", lab);
1422
 
1423
  free (lab);
1424
}
1425
 
1426
static GTY(()) unsigned long except_table_label_num;
1427
 
1428
void
1429
darwin_emit_except_table_label (FILE *file)
1430
{
1431
  char section_start_label[30];
1432
 
1433
  ASM_GENERATE_INTERNAL_LABEL (section_start_label, "GCC_except_table",
1434
                               except_table_label_num++);
1435
  ASM_OUTPUT_LABEL (file, section_start_label);
1436
}
1437
/* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */
1438
 
1439
void
1440
darwin_non_lazy_pcrel (FILE *file, rtx addr)
1441
{
1442
  const char *nlp_name;
1443
 
1444
  gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1445
 
1446
  nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1447
  fputs ("\t.long\t", file);
1448
  ASM_OUTPUT_LABELREF (file, nlp_name);
1449
  fputs ("-.", file);
1450
}
1451
 
1452
/* Emit an assembler directive to set visibility for a symbol.  The
1453
   only supported visibilities are VISIBILITY_DEFAULT and
1454
   VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1455
   extern".  There is no MACH-O equivalent of ELF's
1456
   VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1457
 
1458
void
1459
darwin_assemble_visibility (tree decl, int vis)
1460
{
1461
  if (vis == VISIBILITY_DEFAULT)
1462
    ;
1463
  else if (vis == VISIBILITY_HIDDEN)
1464
    {
1465
      fputs ("\t.private_extern ", asm_out_file);
1466
      assemble_name (asm_out_file,
1467
                     (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1468
      fputs ("\n", asm_out_file);
1469
    }
1470
  else
1471
    warning (OPT_Wattributes, "internal and protected visibility attributes "
1472
             "not supported in this configuration; ignored");
1473
}
1474
 
1475
/* Output a difference of two labels that will be an assembly time
1476
   constant if the two labels are local.  (.long lab1-lab2 will be
1477
   very different if lab1 is at the boundary between two sections; it
1478
   will be relocated according to the second section, not the first,
1479
   so one ends up with a difference between labels in different
1480
   sections, which is bad in the dwarf2 eh context for instance.)  */
1481
 
1482
static int darwin_dwarf_label_counter;
1483
 
1484
void
1485
darwin_asm_output_dwarf_delta (FILE *file, int size,
1486
                               const char *lab1, const char *lab2)
1487
{
1488
  int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1489
                     && lab2[0] == '*' && lab2[1] == 'L');
1490
  const char *directive = (size == 8 ? ".quad" : ".long");
1491
 
1492
  if (islocaldiff)
1493
    fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1494
  else
1495
    fprintf (file, "\t%s\t", directive);
1496
  assemble_name_raw (file, lab1);
1497
  fprintf (file, "-");
1498
  assemble_name_raw (file, lab2);
1499
  if (islocaldiff)
1500
    fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
1501
}
1502
 
1503
/* Output labels for the start of the DWARF sections if necessary.  */
1504
void
1505
darwin_file_start (void)
1506
{
1507
  if (write_symbols == DWARF2_DEBUG)
1508
    {
1509
      static const char * const debugnames[] =
1510
        {
1511
          DEBUG_FRAME_SECTION,
1512
          DEBUG_INFO_SECTION,
1513
          DEBUG_ABBREV_SECTION,
1514
          DEBUG_ARANGES_SECTION,
1515
          DEBUG_MACINFO_SECTION,
1516
          DEBUG_LINE_SECTION,
1517
          DEBUG_LOC_SECTION,
1518
          DEBUG_PUBNAMES_SECTION,
1519
          DEBUG_STR_SECTION,
1520
          DEBUG_RANGES_SECTION
1521
        };
1522
      size_t i;
1523
 
1524
      for (i = 0; i < ARRAY_SIZE (debugnames); i++)
1525
        {
1526
          int namelen;
1527
 
1528
          switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL));
1529
 
1530
          gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0);
1531
          gcc_assert (strchr (debugnames[i] + 8, ','));
1532
 
1533
          namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8);
1534
          fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
1535
        }
1536
    }
1537
}
1538
 
1539
/* Output an offset in a DWARF section on Darwin.  On Darwin, DWARF section
1540
   offsets are not represented using relocs in .o files; either the
1541
   section never leaves the .o file, or the linker or other tool is
1542
   responsible for parsing the DWARF and updating the offsets.  */
1543
 
1544
void
1545
darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
1546
                                section *base)
1547
{
1548
  char sname[64];
1549
  int namelen;
1550
 
1551
  gcc_assert (base->common.flags & SECTION_NAMED);
1552
  gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
1553
  gcc_assert (strchr (base->named.name + 8, ','));
1554
 
1555
  namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
1556
  sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
1557
  darwin_asm_output_dwarf_delta (file, size, lab, sname);
1558
}
1559
 
1560
void
1561
darwin_file_end (void)
1562
{
1563
  machopic_finish (asm_out_file);
1564
  if (strcmp (lang_hooks.name, "GNU C++") == 0)
1565
    {
1566
      switch_to_section (darwin_sections[constructor_section]);
1567
      switch_to_section (darwin_sections[destructor_section]);
1568
      ASM_OUTPUT_ALIGN (asm_out_file, 1);
1569
    }
1570
  fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1571
}
1572
 
1573
/* TODO: Add a language hook for identifying if a decl is a vtable.  */
1574
#define DARWIN_VTABLE_P(DECL) 0
1575
 
1576
/* Cross-module name binding.  Darwin does not support overriding
1577
   functions at dynamic-link time, except for vtables in kexts.  */
1578
 
1579
bool
1580
darwin_binds_local_p (tree decl)
1581
{
1582
  return default_binds_local_p_1 (decl,
1583
                                  TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
1584
}
1585
 
1586
#if 0
1587
/* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet.  */
1588
/* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR.  Define the
1589
   anchor relative to ".", the current section position.  We cannot use
1590
   the default one because ASM_OUTPUT_DEF is wrong for Darwin.  */
1591
 
1592
void
1593
darwin_asm_output_anchor (rtx symbol)
1594
{
1595
  fprintf (asm_out_file, "\t.set\t");
1596
  assemble_name (asm_out_file, XSTR (symbol, 0));
1597
  fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n",
1598
           SYMBOL_REF_BLOCK_OFFSET (symbol));
1599
}
1600
#endif
1601
 
1602
/* Set the darwin specific attributes on TYPE.  */
1603
void
1604
darwin_set_default_type_attributes (tree type)
1605
{
1606
  if (darwin_ms_struct
1607
      && TREE_CODE (type) == RECORD_TYPE)
1608
    TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
1609
                                        NULL_TREE,
1610
                                        TYPE_ATTRIBUTES (type));
1611
}
1612
 
1613
/* True, iff we're generating code for loadable kernel extentions.  */
1614
 
1615
bool
1616
darwin_kextabi_p (void) {
1617
  return flag_apple_kext;
1618
}
1619
 
1620
void
1621
darwin_override_options (void)
1622
{
1623
  if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0)
1624
    {
1625
      warning (0, "command line option %<-fapple-kext%> is only valid for C++");
1626
      flag_apple_kext = 0;
1627
    }
1628
  if (flag_mkernel || flag_apple_kext)
1629
    {
1630
      /* -mkernel implies -fapple-kext for C++ */
1631
      if (strcmp (lang_hooks.name, "GNU C++") == 0)
1632
        flag_apple_kext = 1;
1633
 
1634
      flag_no_common = 1;
1635
 
1636
      /* No EH in kexts.  */
1637
      flag_exceptions = 0;
1638
      /* No -fnon-call-exceptions data in kexts.  */
1639
      flag_non_call_exceptions = 0;
1640
    }
1641
}
1642
 
1643
#include "gt-darwin.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.