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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [sh/] [symbian.c] - Blame information for rev 816

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Routines for GCC for a Symbian OS targeted SH backend.
2
   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by RedHat.
4
   Most of this code is stolen from i386/winnt.c.
5
 
6
   This file is part of GCC.
7
 
8
   GCC is free software; you can redistribute it and/or modify it
9
   under the terms of the GNU General Public License as published
10
   by the Free Software Foundation; either version 3, or (at your
11
   option) any later version.
12
 
13
   GCC is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GCC; see the file COPYING3.  If not see
20
   <http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "output.h"
28
#include "flags.h"
29
#include "tree.h"
30
#include "expr.h"
31
#include "tm_p.h"
32
#include "cp/cp-tree.h" /* We need access to the OVL_... macros.  */
33
#include "toplev.h"
34
 
35
/* Select the level of debugging information to display.
36
 
37
   1 for informative messages about decisions to add attributes
38
   2 for verbose information about what is being done.  */
39
#define SYMBIAN_DEBUG 0
40
/* #define SYMBIAN_DEBUG 1 */
41
/* #define SYMBIAN_DEBUG 2 */
42
 
43
/* A unique character to encode declspec encoded objects.  */
44
#define SH_SYMBIAN_FLAG_CHAR "$"
45
 
46
/* Unique strings to prefix exported and imported objects.  */
47
#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
48
#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
49
 
50
 
51
/* Return the type that we should use to determine if DECL is
52
   imported or exported.  */
53
 
54
static tree
55
sh_symbian_associated_type (tree decl)
56
{
57
  tree t = NULL_TREE;
58
 
59
  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
60
  /* Methods now inherit their dllimport/dllexport attributes correctly
61
     so there is no need to check their class.  In fact it is wrong to
62
     check their class since a method can remain unexported from an
63
     exported class.  */
64
    return t;
65
 
66
  /* Otherwise we can just take the DECL_CONTEXT as normal.  */
67
  if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
68
    t = DECL_CONTEXT (decl);
69
 
70
  return t;
71
}
72
 
73
/* Return nonzero if DECL is a dllexport'd object.  */
74
 
75
bool
76
sh_symbian_dllexport_p (tree decl)
77
{
78
  tree exp;
79
 
80
  if (   TREE_CODE (decl) != VAR_DECL
81
      && TREE_CODE (decl) != FUNCTION_DECL)
82
    return false;
83
 
84
  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
85
 
86
  /* Class members get the dllexport status of their class.  */
87
  if (exp == NULL)
88
    {
89
      tree class = sh_symbian_associated_type (decl);
90
 
91
      if (class)
92
        exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
93
    }
94
#if SYMBIAN_DEBUG
95
  if (exp)
96
    {
97
      print_node_brief (stderr, "dllexport:", decl, 0);
98
      fprintf (stderr, "\n");
99
    }
100
  else
101
#if SYMBIAN_DEBUG < 2
102
    if (TREE_CODE (decl) != FUNCTION_DECL)
103
#endif
104
    {
105
      print_node_brief (stderr, "no dllexport:", decl, 0);
106
      fprintf (stderr, "\n");
107
    }
108
#endif
109
  return exp ? true : false;
110
}
111
 
112
/* Return nonzero if DECL is a dllimport'd object.  */
113
 
114
static bool
115
sh_symbian_dllimport_p (tree decl)
116
{
117
  tree imp;
118
 
119
  if (   TREE_CODE (decl) != VAR_DECL
120
      && TREE_CODE (decl) != FUNCTION_DECL)
121
    return false;
122
 
123
  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
124
  if (imp)
125
    return true;
126
 
127
  /* Class members get the dllimport status of their class.  */
128
  imp = sh_symbian_associated_type (decl);
129
  if (! imp)
130
    return false;
131
 
132
  imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
133
  if (!imp)
134
    return false;
135
 
136
  /* Don't mark defined functions as dllimport.  If the definition itself
137
     was marked with dllimport, then sh_symbian_handle_dll_attribute reports
138
     an error. This handles the case when the definition overrides an
139
     earlier declaration.  */
140
  if (TREE_CODE (decl) ==  FUNCTION_DECL
141
      && DECL_INITIAL (decl)
142
      && !DECL_INLINE (decl))
143
    {
144
      /* Don't warn about artificial methods.  */
145
      if (!DECL_ARTIFICIAL (decl))
146
        warning (OPT_Wattributes, "function %q+D is defined after prior "
147
                 "declaration as dllimport: attribute ignored",
148
                 decl);
149
      return false;
150
    }
151
 
152
  /* We ignore the dllimport attribute for inline member functions.
153
     This differs from MSVC behavior which treats it like GNUC
154
     'extern inline' extension.   */
155
  else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
156
    {
157
      if (extra_warnings)
158
        warning (OPT_Wattributes, "inline function %q+D is declared as "
159
                 "dllimport: attribute ignored",
160
                 decl);
161
      return false;
162
    }
163
 
164
  /*  Don't allow definitions of static data members in dllimport
165
      class.  Just ignore the attribute for vtable data.  */
166
  else if (TREE_CODE (decl) == VAR_DECL
167
           && TREE_STATIC (decl)
168
           && TREE_PUBLIC (decl)
169
           && !DECL_EXTERNAL (decl))
170
    {
171
      if (!DECL_VIRTUAL_P (decl))
172
        error ("definition of static data member %q+D of dllimport'd class",
173
               decl);
174
      return false;
175
    }
176
 
177
  /* Since we can't treat a pointer to a dllimport'd symbol as a
178
     constant address, we turn off the attribute on C++ virtual
179
     methods to allow creation of vtables using thunks.  Don't mark
180
     artificial methods either (in sh_symbian_associated_type, only
181
     COMDAT artificial method get import status from class context).  */
182
  else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
183
           && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
184
    return false;
185
 
186
  return true;
187
}
188
 
189
/* Return nonzero if SYMBOL is marked as being dllexport'd.  */
190
 
191
bool
192
sh_symbian_dllexport_name_p (const char *symbol)
193
{
194
  return strncmp (DLL_EXPORT_PREFIX, symbol,
195
                  strlen (DLL_EXPORT_PREFIX)) == 0;
196
}
197
 
198
/* Return nonzero if SYMBOL is marked as being dllimport'd.  */
199
 
200
 
201
bool
202
sh_symbian_dllimport_name_p (const char *symbol)
203
{
204
  return strncmp (DLL_IMPORT_PREFIX, symbol,
205
                  strlen (DLL_IMPORT_PREFIX)) == 0;
206
}
207
 
208
/* Mark a DECL as being dllexport'd.
209
   Note that we override the previous setting (e.g.: dllimport).  */
210
 
211
static void
212
sh_symbian_mark_dllexport (tree decl)
213
{
214
  const char *oldname;
215
  char *newname;
216
  rtx rtlname;
217
  tree idp;
218
 
219
  rtlname = XEXP (DECL_RTL (decl), 0);
220
  if (GET_CODE (rtlname) == MEM)
221
    rtlname = XEXP (rtlname, 0);
222
  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
223
  oldname = XSTR (rtlname, 0);
224
 
225
  if (sh_symbian_dllimport_name_p (oldname))
226
    {
227
     /* Remove DLL_IMPORT_PREFIX.
228
        Note - we do not issue a warning here.  In Symbian's environment it
229
        is legitimate for a prototype to be marked as dllimport and the
230
        corresponding definition to be marked as dllexport.  The prototypes
231
        are in headers used everywhere and the definition is in a translation
232
        unit which has included the header in order to ensure argument
233
        correctness.  */
234
      oldname += strlen (DLL_IMPORT_PREFIX);
235
      DECL_DLLIMPORT_P (decl) = 0;
236
    }
237
  else if (sh_symbian_dllexport_name_p (oldname))
238
    return; /* Already done.  */
239
 
240
  newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
241
  sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
242
 
243
  /* We pass newname through get_identifier to ensure it has a unique
244
     address.  RTL processing can sometimes peek inside the symbol ref
245
     and compare the string's addresses to see if two symbols are
246
     identical.  */
247
  idp = get_identifier (newname);
248
 
249
  XEXP (DECL_RTL (decl), 0) =
250
    gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
251
}
252
 
253
/* Mark a DECL as being dllimport'd.  */
254
 
255
static void
256
sh_symbian_mark_dllimport (tree decl)
257
{
258
  const char *oldname;
259
  char *newname;
260
  tree idp;
261
  rtx rtlname;
262
  rtx newrtl;
263
 
264
  rtlname = XEXP (DECL_RTL (decl), 0);
265
  if (GET_CODE (rtlname) == MEM)
266
    rtlname = XEXP (rtlname, 0);
267
  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
268
  oldname = XSTR (rtlname, 0);
269
 
270
  if (sh_symbian_dllexport_name_p (oldname))
271
    {
272
      error ("%qs declared as both exported to and imported from a DLL",
273
             IDENTIFIER_POINTER (DECL_NAME (decl)));
274
    }
275
  else if (sh_symbian_dllimport_name_p (oldname))
276
    {
277
      /* Already done, but do a sanity check to prevent assembler errors.  */
278
      if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
279
        error ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage",
280
               decl);
281
    }
282
  else
283
    {
284
      newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
285
      sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
286
 
287
      /* We pass newname through get_identifier to ensure it has a unique
288
         address.  RTL processing can sometimes peek inside the symbol ref
289
         and compare the string's addresses to see if two symbols are
290
         identical.  */
291
      idp = get_identifier (newname);
292
      newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
293
      XEXP (DECL_RTL (decl), 0) = newrtl;
294
    }
295
}
296
 
297
void
298
sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
299
{
300
  default_encode_section_info (decl, rtl, first);
301
 
302
  /* Mark the decl so we can tell from the rtl whether
303
     the object is dllexport'd or dllimport'd.  */
304
  if (sh_symbian_dllexport_p (decl))
305
    sh_symbian_mark_dllexport (decl);
306
  else if (sh_symbian_dllimport_p (decl))
307
    sh_symbian_mark_dllimport (decl);
308
  /* It might be that DECL has already been marked as dllimport, but a
309
     subsequent definition nullified that.  The attribute is gone but
310
     DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
311
     that. Ditto for the DECL_DLLIMPORT_P flag.  */
312
  else if (  (TREE_CODE (decl) == FUNCTION_DECL
313
           || TREE_CODE (decl) == VAR_DECL)
314
           && DECL_RTL (decl) != NULL_RTX
315
           && GET_CODE (DECL_RTL (decl)) == MEM
316
           && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
317
           && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
318
           && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
319
    {
320
      const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
321
      /* Remove DLL_IMPORT_PREFIX.  */
322
      tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
323
      rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
324
 
325
      warning (0, "%s %q+D %s after being referenced with dllimport linkage",
326
               TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
327
               decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
328
               ? "defined locally" : "redeclared without dllimport attribute");
329
 
330
      XEXP (DECL_RTL (decl), 0) = newrtl;
331
 
332
      DECL_DLLIMPORT_P (decl) = 0;
333
    }
334
}
335
 
336
 
337
/* Return the length of a function name prefix
338
    that starts with the character 'c'.  */
339
 
340
static int
341
sh_symbian_get_strip_length (int c)
342
{
343
  /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX).  */
344
  return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
345
}
346
 
347
/* Return a pointer to a function's name with any
348
   and all prefix encodings stripped from it.  */
349
 
350
const char *
351
sh_symbian_strip_name_encoding (const char *name)
352
{
353
  int skip;
354
 
355
  while ((skip = sh_symbian_get_strip_length (*name)))
356
    name += skip;
357
 
358
  return name;
359
}
360
 
361
/* Add the named attribute to the given node.  Copes with both DECLs and
362
   TYPEs.  Will only add the attribute if it is not already present.  */
363
 
364
static void
365
symbian_add_attribute (tree node, const char *attr_name)
366
{
367
  tree attrs;
368
  tree attr;
369
 
370
  attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
371
 
372
  if (lookup_attribute (attr_name, attrs) != NULL_TREE)
373
    return;
374
 
375
  attr = get_identifier (attr_name);
376
 
377
  if (DECL_P (node))
378
    DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
379
  else
380
    TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
381
 
382
#if SYMBIAN_DEBUG
383
  fprintf (stderr, "propogate %s attribute", attr_name);
384
  print_node_brief (stderr, " to", node, 0);
385
  fprintf (stderr, "\n");
386
#endif
387
}
388
 
389
/* Handle a "dllimport" or "dllexport" attribute;
390
   arguments as in struct attribute_spec.handler.  */
391
 
392
tree
393
sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
394
                                 int flags, bool *no_add_attrs)
395
{
396
  tree thunk;
397
  tree node = *pnode;
398
  const char *attr = IDENTIFIER_POINTER (name);
399
 
400
  /* These attributes may apply to structure and union types being
401
     created, but otherwise should pass to the declaration involved.  */
402
  if (!DECL_P (node))
403
    {
404
      if (flags & ((int) ATTR_FLAG_DECL_NEXT
405
                   | (int) ATTR_FLAG_FUNCTION_NEXT
406
                   | (int) ATTR_FLAG_ARRAY_NEXT))
407
        {
408
          warning (OPT_Wattributes, "%qs attribute ignored", attr);
409
          *no_add_attrs = true;
410
          return tree_cons (name, args, NULL_TREE);
411
        }
412
 
413
      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
414
        {
415
          warning (OPT_Wattributes, "%qs attribute ignored", attr);
416
          *no_add_attrs = true;
417
        }
418
 
419
      return NULL_TREE;
420
    }
421
 
422
  /* Report error on dllimport ambiguities
423
     seen now before they cause any damage.  */
424
  else if (is_attribute_p ("dllimport", name))
425
    {
426
      if (TREE_CODE (node) == VAR_DECL)
427
        {
428
          if (DECL_INITIAL (node))
429
            {
430
              error ("variable %q+D definition is marked dllimport",
431
                     node);
432
              *no_add_attrs = true;
433
            }
434
 
435
          /* `extern' needn't be specified with dllimport.
436
             Specify `extern' now and hope for the best.  Sigh.  */
437
          DECL_EXTERNAL (node) = 1;
438
          /* Also, implicitly give dllimport'd variables declared within
439
             a function global scope, unless declared static.  */
440
          if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
441
            TREE_PUBLIC (node) = 1;
442
        }
443
    }
444
 
445
  /* If the node is an overloaded constructor or destructor, then we must
446
     make sure that the attribute is propagated along the overload chain,
447
     as it is these overloaded functions which will be emitted, rather than
448
     the user declared constructor itself.  */
449
  if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
450
      && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
451
    {
452
      tree overload;
453
 
454
      for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
455
        {
456
          tree node_args;
457
          tree func_args;
458
          tree function = OVL_CURRENT (overload);
459
 
460
          if (! function
461
              || ! DECL_P (function)
462
              || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
463
              || (DECL_DESTRUCTOR_P (node)  && ! DECL_DESTRUCTOR_P (function)))
464
            continue;
465
 
466
          /* The arguments must match as well.  */
467
          for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
468
               node_args && func_args;
469
               node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
470
            if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
471
              break;
472
 
473
          if (node_args || func_args)
474
            {
475
              /* We can ignore an extraneous __in_chrg arguments in the node.
476
                 GCC generated destructors, for example, will have this.  */
477
              if ((node_args == NULL_TREE
478
                   || func_args != NULL_TREE)
479
                  && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
480
                continue;
481
            }
482
 
483
          symbian_add_attribute (function, attr);
484
 
485
          /* Propagate the attribute to any function thunks as well.  */
486
          for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
487
            if (TREE_CODE (thunk) == FUNCTION_DECL)
488
              symbian_add_attribute (thunk, attr);
489
        }
490
    }
491
 
492
  if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
493
    {
494
      /* Propagate the attribute to any thunks of this function.  */
495
      for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
496
        if (TREE_CODE (thunk) == FUNCTION_DECL)
497
          symbian_add_attribute (thunk, attr);
498
    }
499
 
500
  /*  Report error if symbol is not accessible at global scope.  */
501
  if (!TREE_PUBLIC (node)
502
      && (   TREE_CODE (node) == VAR_DECL
503
          || TREE_CODE (node) == FUNCTION_DECL))
504
    {
505
      error ("external linkage required for symbol %q+D because of %qs attribute",
506
             node, IDENTIFIER_POINTER (name));
507
      *no_add_attrs = true;
508
    }
509
 
510
#if SYMBIAN_DEBUG
511
  print_node_brief (stderr, "mark node", node, 0);
512
  fprintf (stderr, " as %s\n", attr);
513
#endif
514
 
515
  return NULL_TREE;
516
}
517
 
518
/* This code implements a specification for exporting the vtable and rtti of
519
   classes that have members with the dllexport or dllexport attributes.
520
   This specification is defined here:
521
 
522
     http://www.armdevzone.com/EABI/exported_class.txt
523
 
524
   Basically it says that a class's vtable and rtti should be exported if
525
   the following rules apply:
526
 
527
   - If it has any non-inline non-pure virtual functions,
528
     at least one of these need to be declared dllimport
529
     OR any of the constructors is declared dllimport.
530
 
531
   AND
532
 
533
   - The class has an inline constructor/destructor and
534
     a key-function (placement of vtable uniquely defined) that
535
     is defined in this translation unit.
536
 
537
   The specification also says that for classes which will have their
538
   vtables and rtti exported that their base class(es) might also need a
539
   similar exporting if:
540
 
541
   - Every base class needs to have its vtable & rtti exported
542
     as well, if the following the conditions hold true:
543
     + The base class has a non-inline declared non-pure virtual function
544
     + The base class is polymorphic (has or inherits any virtual functions)
545
       or the base class has any virtual base classes.  */
546
 
547
/* Decide if a base class of a class should
548
   also have its vtable and rtti exported.  */
549
 
550
static void
551
symbian_possibly_export_base_class (tree base_class)
552
{
553
  VEC(tree,gc) *method_vec;
554
  int len;
555
 
556
  if (! (TYPE_CONTAINS_VPTR_P (base_class)))
557
    return;
558
 
559
  method_vec = CLASSTYPE_METHOD_VEC (base_class);
560
  len = method_vec ? VEC_length (tree, method_vec) : 0;
561
 
562
  for (;len --;)
563
    {
564
      tree member = VEC_index (tree, method_vec, len);
565
 
566
      if (! member)
567
        continue;
568
 
569
      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
570
        {
571
          if (TREE_CODE (member) != FUNCTION_DECL)
572
            continue;
573
 
574
          if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
575
            continue;
576
 
577
          if (! DECL_VIRTUAL_P (member))
578
            continue;
579
 
580
          if (DECL_PURE_VIRTUAL_P (member))
581
            continue;
582
 
583
          if (DECL_INLINE (member))
584
            continue;
585
 
586
          break;
587
        }
588
 
589
      if (member)
590
        break;
591
    }
592
 
593
  if (len < 0)
594
    return;
595
 
596
  /* FIXME: According to the spec this base class should be exported, but
597
     a) how do we do this ? and
598
     b) it does not appear to be necessary for compliance with the Symbian
599
        OS which so far is the only consumer of this code.  */
600
#if SYMBIAN_DEBUG
601
  print_node_brief (stderr, "", base_class, 0);
602
  fprintf (stderr, " EXPORTed [base class of exported class]\n");
603
#endif
604
}
605
 
606
/* Decide if a class needs its vtable and rtti exporting.  */
607
 
608
static bool
609
symbian_export_vtable_and_rtti_p (tree ctype)
610
{
611
  bool inline_ctor_dtor;
612
  bool dllimport_ctor_dtor;
613
  bool dllimport_member;
614
  tree binfo, base_binfo;
615
  VEC(tree,gc) *method_vec;
616
  tree key;
617
  int i;
618
  int len;
619
 
620
  /* Make sure that we are examining a class...  */
621
  if (TREE_CODE (ctype) != RECORD_TYPE)
622
    {
623
#if SYMBIAN_DEBUG
624
      print_node_brief (stderr, "", ctype, 0);
625
      fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
626
#endif
627
      return false;
628
    }
629
 
630
  /* If the class does not have a key function it
631
     does not need to have its vtable exported.  */
632
  if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
633
    {
634
#if SYMBIAN_DEBUG
635
      print_node_brief (stderr, "", ctype, 0);
636
      fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
637
#endif
638
      return false;
639
    }
640
 
641
  /* If the key fn has not been defined
642
     then the class should not be exported.  */
643
  if (! TREE_ASM_WRITTEN (key))
644
    {
645
#if SYMBIAN_DEBUG
646
      print_node_brief (stderr, "", ctype, 0);
647
      fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
648
#endif
649
      return false;
650
    }
651
 
652
  /* Check the class's member functions.  */
653
  inline_ctor_dtor = false;
654
  dllimport_ctor_dtor = false;
655
  dllimport_member = false;
656
 
657
  method_vec = CLASSTYPE_METHOD_VEC (ctype);
658
  len = method_vec ? VEC_length (tree, method_vec) : 0;
659
 
660
  for (;len --;)
661
    {
662
      tree member = VEC_index (tree, method_vec, len);
663
 
664
      if (! member)
665
        continue;
666
 
667
      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
668
        {
669
          if (TREE_CODE (member) != FUNCTION_DECL)
670
            continue;
671
 
672
          if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
673
            {
674
              if (DECL_INLINE (member)
675
                  /* Ignore C++ backend created inline ctors/dtors.  */
676
                  && (   DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
677
                      || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
678
                inline_ctor_dtor = true;
679
 
680
              if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
681
                dllimport_ctor_dtor = true;
682
            }
683
          else
684
            {
685
              if (DECL_PURE_VIRTUAL_P (member))
686
                continue;
687
 
688
              if (! DECL_VIRTUAL_P (member))
689
                continue;
690
 
691
              if (DECL_INLINE (member))
692
                continue;
693
 
694
              if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
695
                dllimport_member = true;
696
            }
697
        }
698
    }
699
 
700
  if (! dllimport_member && ! dllimport_ctor_dtor)
701
    {
702
#if SYMBIAN_DEBUG
703
      print_node_brief (stderr, "", ctype, 0);
704
      fprintf (stderr,
705
               " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
706
#endif
707
      return false;
708
    }
709
 
710
  if (! inline_ctor_dtor)
711
    {
712
#if SYMBIAN_DEBUG
713
      print_node_brief (stderr, "", ctype, 0);
714
      fprintf (stderr,
715
               " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
716
#endif
717
      return false;
718
    }
719
 
720
#if SYMBIAN_DEBUG
721
  print_node_brief (stderr, "", ctype, 0);
722
  fprintf (stderr, " DOES need to be EXPORTed\n");
723
#endif
724
 
725
  /* Now we must check and possibly export the base classes.  */
726
  for (i = 0, binfo = TYPE_BINFO (ctype);
727
       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
728
    symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
729
 
730
  return true;
731
}
732
 
733
/* Add the named attribute to a class and its vtable and rtti.  */
734
 
735
static void
736
symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
737
{
738
  symbian_add_attribute (ctype, attr_name);
739
 
740
  /* If the vtable exists then they need annotating as well.  */
741
  if (CLASSTYPE_VTABLES (ctype))
742
    /* XXX - Do we need to annotate any vtables other than the primary ?  */
743
    symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
744
 
745
  /* If the rtti exists then it needs annotating as well.  */
746
  if (TYPE_MAIN_VARIANT (ctype)
747
      && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
748
    symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
749
                           attr_name);
750
}
751
 
752
/* Decide if a class needs to have an attribute because
753
   one of its member functions has the attribute.  */
754
 
755
static bool
756
symbian_class_needs_attribute_p (tree ctype, const char *attribute_name)
757
{
758
  VEC(tree,gc) *method_vec;
759
 
760
  method_vec = CLASSTYPE_METHOD_VEC (ctype);
761
 
762
  /* If the key function has the attribute then the class needs it too.  */
763
  if (TYPE_POLYMORPHIC_P (ctype)
764
      && method_vec
765
      && lookup_attribute (attribute_name,
766
                           DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
767
    return true;
768
 
769
  /* Check the class's member functions.  */
770
  if (TREE_CODE (ctype) == RECORD_TYPE)
771
    {
772
      unsigned int len;
773
 
774
      len = method_vec ? VEC_length (tree, method_vec) : 0;
775
 
776
      for (;len --;)
777
        {
778
          tree member = VEC_index (tree, method_vec, len);
779
 
780
          if (! member)
781
            continue;
782
 
783
          for (member = OVL_CURRENT (member);
784
               member;
785
               member = OVL_NEXT (member))
786
            {
787
              if (TREE_CODE (member) != FUNCTION_DECL)
788
                continue;
789
 
790
              if (DECL_PURE_VIRTUAL_P (member))
791
                continue;
792
 
793
              if (! DECL_VIRTUAL_P (member))
794
                continue;
795
 
796
              if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
797
                {
798
#if SYMBIAN_DEBUG
799
                  print_node_brief (stderr, "", ctype, 0);
800
                  fprintf (stderr, " inherits %s because", attribute_name);
801
                  print_node_brief (stderr, "", member, 0);
802
                  fprintf (stderr, " has it.\n");
803
#endif
804
                  return true;
805
                }
806
            }
807
        }
808
    }
809
 
810
#if SYMBIAN_DEBUG
811
  print_node_brief (stderr, "", ctype, 0);
812
  fprintf (stderr, " does not inherit %s\n", attribute_name);
813
#endif
814
  return false;
815
}
816
 
817
int
818
symbian_import_export_class (tree ctype, int import_export)
819
{
820
  const char *attr_name = NULL;
821
 
822
  /* If we are exporting the class but it does not have the dllexport
823
     attribute then we may need to add it.  Similarly imported classes
824
     may need the dllimport attribute.  */
825
  switch (import_export)
826
    {
827
    case  1: attr_name = "dllexport"; break;
828
    case -1: attr_name = "dllimport"; break;
829
    default: break;
830
    }
831
 
832
  if (attr_name
833
      && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
834
    {
835
      if (symbian_class_needs_attribute_p (ctype, attr_name))
836
        symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
837
 
838
      /* Classes can be forced to export their
839
         vtable and rtti under certain conditions.  */
840
      if (symbian_export_vtable_and_rtti_p (ctype))
841
        {
842
          symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
843
 
844
          /* Make sure that the class and its vtable are exported.  */
845
          import_export = 1;
846
 
847
          if (CLASSTYPE_VTABLES (ctype))
848
            DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
849
 
850
          /* Check to make sure that if the class has a key method that
851
             it is now on the list of keyed classes.  That way its vtable
852
             will be emitted.  */
853
          if (CLASSTYPE_KEY_METHOD (ctype))
854
            {
855
              tree class;
856
 
857
              for (class = keyed_classes; class; class = TREE_CHAIN (class))
858
                if (class == ctype)
859
                  break;
860
 
861
              if (class == NULL_TREE)
862
                {
863
#if SYMBIAN_DEBUG
864
                  print_node_brief (stderr, "Add node", ctype, 0);
865
                  fprintf (stderr, " to the keyed classes list\n");
866
#endif
867
                  keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
868
                }
869
            }
870
 
871
          /* Make sure that the typeinfo will be emitted as well.  */
872
          if (CLASS_TYPE_P (ctype))
873
            TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
874
        }
875
    }
876
 
877
  return import_export;
878
}
879
 
880
/* Dummy definition of this array for cc1 building purposes.  */
881
tree cp_global_trees[CPTI_MAX] __attribute__((weak));
882
 
883
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
884
 
885
/* Dummy version of this G++ function for building cc1.  */
886
void lang_check_failed (const char *, int, const char *) __attribute__((weak));
887
 
888
void
889
lang_check_failed (const char *file, int line, const char *function)
890
{
891
  internal_error ("lang_* check: failed in %s, at %s:%d",
892
                  function, trim_filename (file), line);
893
}
894
#endif /* ENABLE_TREE_CHECKING */

powered by: WebSVN 2.1.0

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