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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [config/] [sh/] [symbian.c] - Blame information for rev 12

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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