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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [attribs.c] - Blame information for rev 433

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

Line No. Rev Author Line
1 280 jeremybenn
/* Functions dealing with attribute handling, used by most front ends.
2
   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3
   2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
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 "tree.h"
27
#include "flags.h"
28
#include "toplev.h"
29
#include "output.h"
30
#include "rtl.h"
31
#include "ggc.h"
32
#include "tm_p.h"
33
#include "cpplib.h"
34
#include "target.h"
35
#include "langhooks.h"
36
#include "hashtab.h"
37
#include "plugin.h"
38
 
39
static void init_attributes (void);
40
 
41
/* Table of the tables of attributes (common, language, format, machine)
42
   searched.  */
43
static const struct attribute_spec *attribute_tables[4];
44
 
45
/* Hashtable mapping names (represented as substrings) to attribute specs. */
46
static htab_t attribute_hash;
47
 
48
/* Substring representation.  */
49
 
50
struct substring
51
{
52
  const char *str;
53
  int length;
54
};
55
 
56
static bool attributes_initialized = false;
57
 
58
/* Default empty table of attributes.  */
59
 
60
static const struct attribute_spec empty_attribute_table[] =
61
{
62
  { NULL, 0, 0, false, false, false, NULL }
63
};
64
 
65
/* Return base name of the attribute.  Ie '__attr__' is turned into 'attr'.
66
   To avoid need for copying, we simply return length of the string.  */
67
 
68
static void
69
extract_attribute_substring (struct substring *str)
70
{
71
  if (str->length > 4 && str->str[0] == '_' && str->str[1] == '_'
72
      && str->str[str->length - 1] == '_' && str->str[str->length - 2] == '_')
73
    {
74
      str->length -= 4;
75
      str->str += 2;
76
    }
77
}
78
 
79
/* Simple hash function to avoid need to scan whole string.  */
80
 
81
static inline hashval_t
82
substring_hash (const char *str, int l)
83
{
84
  return str[0] + str[l - 1] * 256 + l * 65536;
85
}
86
 
87
/* Used for attribute_hash.  */
88
 
89
static hashval_t
90
hash_attr (const void *p)
91
{
92
  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
93
  const int l = strlen (spec->name);
94
 
95
  return substring_hash (spec->name, l);
96
}
97
 
98
/* Used for attribute_hash.  */
99
 
100
static int
101
eq_attr (const void *p, const void *q)
102
{
103
  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
104
  const struct substring *const str = (const struct substring *) q;
105
 
106
  return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
107
}
108
 
109
/* Initialize attribute tables, and make some sanity checks
110
   if --enable-checking.  */
111
 
112
static void
113
init_attributes (void)
114
{
115
  size_t i;
116
  int k;
117
 
118
  attribute_tables[0] = lang_hooks.common_attribute_table;
119
  attribute_tables[1] = lang_hooks.attribute_table;
120
  attribute_tables[2] = lang_hooks.format_attribute_table;
121
  attribute_tables[3] = targetm.attribute_table;
122
 
123
  /* Translate NULL pointers to pointers to the empty table.  */
124
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
125
    if (attribute_tables[i] == NULL)
126
      attribute_tables[i] = empty_attribute_table;
127
 
128
#ifdef ENABLE_CHECKING
129
  /* Make some sanity checks on the attribute tables.  */
130
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
131
    {
132
      int j;
133
 
134
      for (j = 0; attribute_tables[i][j].name != NULL; j++)
135
        {
136
          /* The name must not begin and end with __.  */
137
          const char *name = attribute_tables[i][j].name;
138
          int len = strlen (name);
139
 
140
          gcc_assert (!(name[0] == '_' && name[1] == '_'
141
                        && name[len - 1] == '_' && name[len - 2] == '_'));
142
 
143
          /* The minimum and maximum lengths must be consistent.  */
144
          gcc_assert (attribute_tables[i][j].min_length >= 0);
145
 
146
          gcc_assert (attribute_tables[i][j].max_length == -1
147
                      || (attribute_tables[i][j].max_length
148
                          >= attribute_tables[i][j].min_length));
149
 
150
          /* An attribute cannot require both a DECL and a TYPE.  */
151
          gcc_assert (!attribute_tables[i][j].decl_required
152
                      || !attribute_tables[i][j].type_required);
153
 
154
          /* If an attribute requires a function type, in particular
155
             it requires a type.  */
156
          gcc_assert (!attribute_tables[i][j].function_type_required
157
                      || attribute_tables[i][j].type_required);
158
        }
159
    }
160
 
161
  /* Check that each name occurs just once in each table.  */
162
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
163
    {
164
      int j, k;
165
      for (j = 0; attribute_tables[i][j].name != NULL; j++)
166
        for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
167
          gcc_assert (strcmp (attribute_tables[i][j].name,
168
                              attribute_tables[i][k].name));
169
    }
170
  /* Check that no name occurs in more than one table.  */
171
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
172
    {
173
      size_t j, k, l;
174
 
175
      for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
176
        for (k = 0; attribute_tables[i][k].name != NULL; k++)
177
          for (l = 0; attribute_tables[j][l].name != NULL; l++)
178
            gcc_assert (strcmp (attribute_tables[i][k].name,
179
                                attribute_tables[j][l].name));
180
    }
181
#endif
182
 
183
  attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
184
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
185
    for (k = 0; attribute_tables[i][k].name != NULL; k++)
186
      {
187
        register_attribute (&attribute_tables[i][k]);
188
      }
189
  invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
190
  attributes_initialized = true;
191
}
192
 
193
/* Insert a single ATTR into the attribute table.  */
194
 
195
void
196
register_attribute (const struct attribute_spec *attr)
197
{
198
  struct substring str;
199
  void **slot;
200
 
201
  str.str = attr->name;
202
  str.length = strlen (str.str);
203
  slot = htab_find_slot_with_hash (attribute_hash, &str,
204
                                   substring_hash (str.str, str.length),
205
                                   INSERT);
206
  gcc_assert (!*slot);
207
  *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
208
}
209
 
210
/* Return the spec for the attribute named NAME.  */
211
 
212
const struct attribute_spec *
213
lookup_attribute_spec (tree name)
214
{
215
  struct substring attr;
216
 
217
  attr.str = IDENTIFIER_POINTER (name);
218
  attr.length = IDENTIFIER_LENGTH (name);
219
  extract_attribute_substring (&attr);
220
  return (const struct attribute_spec *)
221
    htab_find_with_hash (attribute_hash, &attr,
222
                         substring_hash (attr.str, attr.length));
223
}
224
 
225
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
226
   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
227
   it should be modified in place; if a TYPE, a copy should be created
228
   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
229
   information, in the form of a bitwise OR of flags in enum attribute_flags
230
   from tree.h.  Depending on these flags, some attributes may be
231
   returned to be applied at a later stage (for example, to apply
232
   a decl attribute to the declaration rather than to its type).  */
233
 
234
tree
235
decl_attributes (tree *node, tree attributes, int flags)
236
{
237
  tree a;
238
  tree returned_attrs = NULL_TREE;
239
 
240
  if (TREE_TYPE (*node) == error_mark_node)
241
    return NULL_TREE;
242
 
243
  if (!attributes_initialized)
244
    init_attributes ();
245
 
246
  /* If this is a function and the user used #pragma GCC optimize, add the
247
     options to the attribute((optimize(...))) list.  */
248
  if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
249
    {
250
      tree cur_attr = lookup_attribute ("optimize", attributes);
251
      tree opts = copy_list (current_optimize_pragma);
252
 
253
      if (! cur_attr)
254
        attributes
255
          = tree_cons (get_identifier ("optimize"), opts, attributes);
256
      else
257
        TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
258
    }
259
 
260
  if (TREE_CODE (*node) == FUNCTION_DECL
261
      && optimization_current_node != optimization_default_node
262
      && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
263
    DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
264
 
265
  /* If this is a function and the user used #pragma GCC target, add the
266
     options to the attribute((target(...))) list.  */
267
  if (TREE_CODE (*node) == FUNCTION_DECL
268
      && current_target_pragma
269
      && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
270
                                                  current_target_pragma, 0))
271
    {
272
      tree cur_attr = lookup_attribute ("target", attributes);
273
      tree opts = copy_list (current_target_pragma);
274
 
275
      if (! cur_attr)
276
        attributes = tree_cons (get_identifier ("target"), opts, attributes);
277
      else
278
        TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
279
    }
280
 
281
  targetm.insert_attributes (*node, &attributes);
282
 
283
  for (a = attributes; a; a = TREE_CHAIN (a))
284
    {
285
      tree name = TREE_PURPOSE (a);
286
      tree args = TREE_VALUE (a);
287
      tree *anode = node;
288
      const struct attribute_spec *spec = lookup_attribute_spec (name);
289
      bool no_add_attrs = 0;
290
      int fn_ptr_quals = 0;
291
      tree fn_ptr_tmp = NULL_TREE;
292
 
293
      if (spec == NULL)
294
        {
295
          warning (OPT_Wattributes, "%qE attribute directive ignored",
296
                   name);
297
          continue;
298
        }
299
      else if (list_length (args) < spec->min_length
300
               || (spec->max_length >= 0
301
                   && list_length (args) > spec->max_length))
302
        {
303
          error ("wrong number of arguments specified for %qE attribute",
304
                 name);
305
          continue;
306
        }
307
      gcc_assert (is_attribute_p (spec->name, name));
308
 
309
      if (spec->decl_required && !DECL_P (*anode))
310
        {
311
          if (flags & ((int) ATTR_FLAG_DECL_NEXT
312
                       | (int) ATTR_FLAG_FUNCTION_NEXT
313
                       | (int) ATTR_FLAG_ARRAY_NEXT))
314
            {
315
              /* Pass on this attribute to be tried again.  */
316
              returned_attrs = tree_cons (name, args, returned_attrs);
317
              continue;
318
            }
319
          else
320
            {
321
              warning (OPT_Wattributes, "%qE attribute does not apply to types",
322
                       name);
323
              continue;
324
            }
325
        }
326
 
327
      /* If we require a type, but were passed a decl, set up to make a
328
         new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
329
         would have applied if we'd been passed a type, but we cannot modify
330
         the decl's type in place here.  */
331
      if (spec->type_required && DECL_P (*anode))
332
        {
333
          anode = &TREE_TYPE (*anode);
334
          /* Allow ATTR_FLAG_TYPE_IN_PLACE for the type's naming decl.  */
335
          if (!(TREE_CODE (*anode) == TYPE_DECL
336
                && *anode == TYPE_NAME (TYPE_MAIN_VARIANT
337
                                        (TREE_TYPE (*anode)))))
338
            flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
339
        }
340
 
341
      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
342
          && TREE_CODE (*anode) != METHOD_TYPE)
343
        {
344
          if (TREE_CODE (*anode) == POINTER_TYPE
345
              && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
346
                  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
347
            {
348
              /* OK, this is a bit convoluted.  We can't just make a copy
349
                 of the pointer type and modify its TREE_TYPE, because if
350
                 we change the attributes of the target type the pointer
351
                 type needs to have a different TYPE_MAIN_VARIANT.  So we
352
                 pull out the target type now, frob it as appropriate, and
353
                 rebuild the pointer type later.
354
 
355
                 This would all be simpler if attributes were part of the
356
                 declarator, grumble grumble.  */
357
              fn_ptr_tmp = TREE_TYPE (*anode);
358
              fn_ptr_quals = TYPE_QUALS (*anode);
359
              anode = &fn_ptr_tmp;
360
              flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
361
            }
362
          else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
363
            {
364
              /* Pass on this attribute to be tried again.  */
365
              returned_attrs = tree_cons (name, args, returned_attrs);
366
              continue;
367
            }
368
 
369
          if (TREE_CODE (*anode) != FUNCTION_TYPE
370
              && TREE_CODE (*anode) != METHOD_TYPE)
371
            {
372
              warning (OPT_Wattributes,
373
                       "%qE attribute only applies to function types",
374
                       name);
375
              continue;
376
            }
377
        }
378
 
379
      if (TYPE_P (*anode)
380
          && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
381
          && TYPE_SIZE (*anode) != NULL_TREE)
382
        {
383
          warning (OPT_Wattributes, "type attributes ignored after type is already defined");
384
          continue;
385
        }
386
 
387
      if (spec->handler != NULL)
388
        returned_attrs = chainon ((*spec->handler) (anode, name, args,
389
                                                    flags, &no_add_attrs),
390
                                  returned_attrs);
391
 
392
      /* Layout the decl in case anything changed.  */
393
      if (spec->type_required && DECL_P (*node)
394
          && (TREE_CODE (*node) == VAR_DECL
395
              || TREE_CODE (*node) == PARM_DECL
396
              || TREE_CODE (*node) == RESULT_DECL))
397
        relayout_decl (*node);
398
 
399
      if (!no_add_attrs)
400
        {
401
          tree old_attrs;
402
          tree a;
403
 
404
          if (DECL_P (*anode))
405
            old_attrs = DECL_ATTRIBUTES (*anode);
406
          else
407
            old_attrs = TYPE_ATTRIBUTES (*anode);
408
 
409
          for (a = lookup_attribute (spec->name, old_attrs);
410
               a != NULL_TREE;
411
               a = lookup_attribute (spec->name, TREE_CHAIN (a)))
412
            {
413
              if (simple_cst_equal (TREE_VALUE (a), args) == 1)
414
                break;
415
            }
416
 
417
          if (a == NULL_TREE)
418
            {
419
              /* This attribute isn't already in the list.  */
420
              if (DECL_P (*anode))
421
                DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
422
              else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
423
                {
424
                  TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
425
                  /* If this is the main variant, also push the attributes
426
                     out to the other variants.  */
427
                  if (*anode == TYPE_MAIN_VARIANT (*anode))
428
                    {
429
                      tree variant;
430
                      for (variant = *anode; variant;
431
                           variant = TYPE_NEXT_VARIANT (variant))
432
                        {
433
                          if (TYPE_ATTRIBUTES (variant) == old_attrs)
434
                            TYPE_ATTRIBUTES (variant)
435
                              = TYPE_ATTRIBUTES (*anode);
436
                          else if (!lookup_attribute
437
                                   (spec->name, TYPE_ATTRIBUTES (variant)))
438
                            TYPE_ATTRIBUTES (variant) = tree_cons
439
                              (name, args, TYPE_ATTRIBUTES (variant));
440
                        }
441
                    }
442
                }
443
              else
444
                *anode = build_type_attribute_variant (*anode,
445
                                                       tree_cons (name, args,
446
                                                                  old_attrs));
447
            }
448
        }
449
 
450
      if (fn_ptr_tmp)
451
        {
452
          /* Rebuild the function pointer type and put it in the
453
             appropriate place.  */
454
          fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
455
          if (fn_ptr_quals)
456
            fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
457
          if (DECL_P (*node))
458
            TREE_TYPE (*node) = fn_ptr_tmp;
459
          else
460
            {
461
              gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
462
              *node = fn_ptr_tmp;
463
            }
464
        }
465
    }
466
 
467
  return returned_attrs;
468
}

powered by: WebSVN 2.1.0

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