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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [java/] [constants.c] - Blame information for rev 715

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 715 jeremybenn
/* Handle the constant pool of the Java(TM) Virtual Machine.
2
   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
3
   2007, 2008, 2010, 2011  Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 3, or (at your option)
10
any later version.
11
 
12
GCC is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING3.  If not see
18
<http://www.gnu.org/licenses/>.
19
 
20
Java and all Java-based marks are trademarks or registered trademarks
21
of Sun Microsystems, Inc. in the United States and other countries.
22
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
23
 
24
#include "config.h"
25
#include "system.h"
26
#include "coretypes.h"
27
#include "tm.h"
28
#include "jcf.h"
29
#include "tree.h"
30
#include "java-tree.h"
31
#include "diagnostic-core.h"
32
#include "toplev.h"
33
#include "ggc.h"
34
 
35
static void set_constant_entry (CPool *, int, int, jword);
36
static int find_tree_constant (CPool *, int, tree);
37
static int find_name_and_type_constant (CPool *, tree, tree);
38
static tree get_tag_node (int);
39
 
40
/* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
41
 
42
static void
43
set_constant_entry (CPool *cpool, int index, int tag, jword value)
44
{
45
  if (cpool->data == NULL)
46
    {
47
      cpool->capacity = 100;
48
      cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
49
                                                * cpool->capacity);
50
      cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
51
                                                       (union cpool_entry),
52
                                                       cpool->capacity);
53
      cpool->count = 1;
54
    }
55
  if (index >= cpool->capacity)
56
    {
57
      int old_cap = cpool->capacity;
58
      cpool->capacity *= 2;
59
      if (index >= cpool->capacity)
60
        cpool->capacity = index + 10;
61
      cpool->tags = GGC_RESIZEVEC (uint8, cpool->tags, cpool->capacity);
62
      cpool->data = GGC_RESIZEVEC (union cpool_entry, cpool->data,
63
                                   cpool->capacity);
64
 
65
      /* Make sure GC never sees uninitialized tag values.  */
66
      memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
67
      memset (cpool->data + old_cap, 0,
68
              (cpool->capacity - old_cap) * sizeof (union cpool_entry));
69
    }
70
  if (index >= cpool->count)
71
    cpool->count = index + 1;
72
  cpool->tags[index] = tag;
73
  cpool->data[index].w = value;
74
}
75
 
76
/* Find (or create) a constant pool entry matching TAG and VALUE. */
77
 
78
int
79
find_constant1 (CPool *cpool, int tag, jword value)
80
{
81
  int i;
82
  for (i = cpool->count;  --i > 0; )
83
    {
84
      if (cpool->tags[i] == tag && cpool->data[i].w == value)
85
        return i;
86
    }
87
  i = cpool->count == 0 ? 1 : cpool->count;
88
  set_constant_entry (cpool, i, tag, value);
89
  return i;
90
}
91
 
92
/* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
93
 
94
int
95
find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
96
{
97
  int i;
98
  for (i = cpool->count - 1;  --i > 0; )
99
    {
100
      if (cpool->tags[i] == tag
101
          && cpool->data[i].w == word1
102
          && cpool->data[i+1].w == word2)
103
        return i;
104
    }
105
  i = cpool->count == 0 ? 1 : cpool->count;
106
  set_constant_entry (cpool, i, tag, word1);
107
  set_constant_entry (cpool, i+1, 0, word2);
108
  return i;
109
}
110
 
111
static int
112
find_tree_constant (CPool *cpool, int tag, tree value)
113
{
114
  int i;
115
  for (i = cpool->count;  --i > 0; )
116
    {
117
      if (cpool->tags[i] == tag && cpool->data[i].t == value)
118
        return i;
119
    }
120
  i = cpool->count == 0 ? 1 : cpool->count;
121
  set_constant_entry (cpool, i, tag, 0);
122
  cpool->data[i].t = value;
123
  return i;
124
}
125
 
126
 
127
int
128
find_utf8_constant (CPool *cpool, tree name)
129
{
130
  if (name == NULL_TREE)
131
    return 0;
132
  return find_tree_constant (cpool, CONSTANT_Utf8, name);
133
}
134
 
135
int
136
find_class_or_string_constant (CPool *cpool, int tag, tree name)
137
{
138
  jword j = find_utf8_constant (cpool, name);
139
  int i;
140
  for (i = cpool->count;  --i > 0; )
141
    {
142
      if (cpool->tags[i] == tag && cpool->data[i].w == j)
143
        return i;
144
    }
145
  i = cpool->count;
146
  set_constant_entry (cpool, i, tag, j);
147
  return i;
148
}
149
 
150
int
151
find_class_constant (CPool *cpool, tree type)
152
{
153
  return find_class_or_string_constant (cpool, CONSTANT_Class,
154
                                        build_internal_class_name (type));
155
}
156
 
157
/* Allocate a CONSTANT_string entry given a STRING_CST. */
158
 
159
int
160
find_string_constant (CPool *cpool, tree string)
161
{
162
  string = get_identifier (TREE_STRING_POINTER (string));
163
  return find_class_or_string_constant (cpool, CONSTANT_String, string);
164
 
165
}
166
 
167
/* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
168
   Return its index in the constant pool CPOOL. */
169
 
170
static int
171
find_name_and_type_constant (CPool *cpool, tree name, tree type)
172
{
173
  int name_index = find_utf8_constant (cpool, name);
174
  int type_index = find_utf8_constant (cpool, build_java_signature (type));
175
  return find_constant1 (cpool, CONSTANT_NameAndType,
176
                         (name_index << 16) | type_index);
177
}
178
 
179
/* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
180
   Return its index in the constant pool CPOOL. */
181
 
182
int
183
find_fieldref_index (CPool *cpool, tree decl)
184
{
185
  int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
186
  int name_type_index
187
    = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
188
  return find_constant1 (cpool, CONSTANT_Fieldref,
189
                         (class_index << 16) | name_type_index);
190
}
191
 
192
/* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
193
   Return its index in the constant pool CPOOL. */
194
 
195
int
196
find_methodref_index (CPool *cpool, tree decl)
197
{
198
  return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
199
}
200
 
201
int
202
find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
203
{
204
  int class_index = find_class_constant (cpool, mclass);
205
  tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
206
    : DECL_NAME (decl);
207
  int name_type_index;
208
  name_type_index =
209
      find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
210
  return find_constant1 (cpool,
211
                         CLASS_INTERFACE (TYPE_NAME (mclass))
212
                         ? CONSTANT_InterfaceMethodref
213
                         : CONSTANT_Methodref,
214
                         (class_index << 16) | name_type_index);
215
}
216
 
217
#define PUT1(X)  (*ptr++ = (X))
218
#define PUT2(X)  (PUT1((X) >> 8), PUT1(X))
219
#define PUT4(X)  (PUT2((X) >> 16), PUT2(X))
220
#define PUTN(P, N)  (memcpy(ptr, (P), (N)), ptr += (N))
221
 
222
/* Give the number of bytes needed in a .class file for the CPOOL
223
   constant pool.  Includes the 2-byte constant_pool_count. */
224
 
225
int
226
count_constant_pool_bytes (CPool *cpool)
227
{
228
  int size = 2;
229
  int i = 1;
230
  for ( ;  i < cpool->count;  i++)
231
    {
232
      size++;
233
      switch (cpool->tags[i])
234
        {
235
        case CONSTANT_NameAndType:
236
        case CONSTANT_Fieldref:
237
        case CONSTANT_Methodref:
238
        case CONSTANT_InterfaceMethodref:
239
        case CONSTANT_Float:
240
        case CONSTANT_Integer:
241
          size += 4;
242
          break;
243
        case CONSTANT_Class:
244
        case CONSTANT_String:
245
          size += 2;
246
          break;
247
        case CONSTANT_Long:
248
        case CONSTANT_Double:
249
          size += 8;
250
          i++;
251
          break;
252
        case CONSTANT_Utf8:
253
          {
254
            tree t = cpool->data[i].t;
255
            int len = IDENTIFIER_LENGTH (t);
256
            size += len + 2;
257
          }
258
          break;
259
        default:
260
          /* Second word of CONSTANT_Long and  CONSTANT_Double. */
261
          size--;
262
        }
263
    }
264
  return size;
265
}
266
 
267
/* Write the constant pool CPOOL into BUFFER.
268
   The length of BUFFER is LENGTH, which must match the needed length. */
269
 
270
void
271
write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
272
{
273
  unsigned char *ptr = buffer;
274
  int i = 1;
275
  union cpool_entry *datap = &cpool->data[1];
276
  PUT2 (cpool->count);
277
  for ( ;  i < cpool->count;  i++, datap++)
278
    {
279
      int tag = cpool->tags[i];
280
      PUT1 (tag);
281
      switch (tag)
282
        {
283
        case CONSTANT_NameAndType:
284
        case CONSTANT_Fieldref:
285
        case CONSTANT_Methodref:
286
        case CONSTANT_InterfaceMethodref:
287
        case CONSTANT_Float:
288
        case CONSTANT_Integer:
289
          PUT4 (datap->w);
290
          break;
291
        case CONSTANT_Class:
292
        case CONSTANT_String:
293
          PUT2 (datap->w);
294
          break;
295
          break;
296
        case CONSTANT_Long:
297
        case CONSTANT_Double:
298
          PUT4(datap->w);
299
          i++;
300
          datap++;
301
          PUT4 (datap->w);
302
          break;
303
        case CONSTANT_Utf8:
304
          {
305
            tree t = datap->t;
306
            int len = IDENTIFIER_LENGTH (t);
307
            PUT2 (len);
308
            PUTN (IDENTIFIER_POINTER (t), len);
309
          }
310
          break;
311
        }
312
    }
313
 
314
  gcc_assert (ptr == buffer + length);
315
}
316
 
317
static GTY(()) tree tag_nodes[13];
318
static tree
319
get_tag_node (int tag)
320
{
321
  /* A Cache for build_int_cst (CONSTANT_XXX, 0). */
322
 
323
  if (tag >= 13)
324
    return build_int_cst (NULL_TREE, tag);
325
 
326
  if (tag_nodes[tag] == NULL_TREE)
327
    tag_nodes[tag] = build_int_cst (NULL_TREE, tag);
328
  return tag_nodes[tag];
329
}
330
 
331
/* Given a class, return its constant pool, creating one if necessary.  */
332
 
333
CPool *
334
cpool_for_class (tree klass)
335
{
336
  CPool *cpool = TYPE_CPOOL (klass);
337
 
338
  if (cpool == NULL)
339
    {
340
      cpool = ggc_alloc_cleared_CPool ();
341
      TYPE_CPOOL (klass) = cpool;
342
    }
343
  return cpool;
344
}
345
 
346
/* Look for a constant pool entry that matches TAG and NAME.
347
   Creates a new entry if not found.
348
   TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
349
   NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
350
   Returns the index of the entry. */
351
 
352
int
353
alloc_name_constant (int tag, tree name)
354
{
355
  CPool *outgoing_cpool = cpool_for_class (output_class);
356
  return find_tree_constant (outgoing_cpool, tag, name);
357
}
358
 
359
/* Create a constant pool entry for a name_and_type.  This one has '.'
360
   rather than '/' because it isn't going into a class file, it's
361
   going into a compiled object.  We don't use the '/' separator in
362
   compiled objects.  */
363
 
364
static int
365
find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
366
{
367
  int name_index = find_utf8_constant (cpool, name);
368
  int type_index
369
    = find_utf8_constant (cpool,
370
                          identifier_subst (build_java_signature (type),
371
                                            "", '/', '.', ""));
372
  return find_constant1 (cpool, CONSTANT_NameAndType,
373
                         (name_index << 16) | type_index);
374
}
375
 
376
/* Look for a field ref that matches DECL in the constant pool of
377
   KLASS.
378
   Return the index of the entry.  */
379
 
380
int
381
alloc_constant_fieldref (tree klass, tree decl)
382
{
383
  CPool *outgoing_cpool = cpool_for_class (klass);
384
  int class_index
385
    = find_tree_constant (outgoing_cpool, CONSTANT_Class,
386
                          DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
387
  int name_type_index
388
    = find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl),
389
                                        TREE_TYPE (decl));
390
  return find_constant1 (outgoing_cpool, CONSTANT_Fieldref,
391
                         (class_index << 16) | name_type_index);
392
}
393
 
394
/* Build an identifier for the internal name of reference type TYPE. */
395
 
396
tree
397
build_internal_class_name (tree type)
398
{
399
  tree name;
400
  if (TYPE_ARRAY_P (type))
401
    name = build_java_signature (type);
402
  else
403
    {
404
      name = TYPE_NAME (type);
405
      if (TREE_CODE (name) != IDENTIFIER_NODE)
406
        name = DECL_NAME (name);
407
      name = identifier_subst (name, "", '.', '/', "");
408
    }
409
  return name;
410
}
411
 
412
/* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */
413
 
414
int
415
alloc_class_constant (tree clas)
416
{
417
  tree class_name = build_internal_class_name (clas);
418
 
419
  return alloc_name_constant (CONSTANT_Class,
420
                              (unmangle_classname
421
                               (IDENTIFIER_POINTER(class_name),
422
                                IDENTIFIER_LENGTH(class_name))));
423
}
424
 
425
/* Return the decl of the data array of the current constant pool. */
426
 
427
tree
428
build_constant_data_ref (bool indirect)
429
{
430
  if (indirect)
431
    {
432
      tree d;
433
      tree cpool_type = build_array_type (ptr_type_node, NULL_TREE);
434
      tree decl = build_class_ref (output_class);
435
      tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
436
                           decl);
437
      tree constants = build3 (COMPONENT_REF,
438
                               TREE_TYPE (constants_field_decl_node), klass,
439
                               constants_field_decl_node,
440
                               NULL_TREE);
441
      tree data = build3 (COMPONENT_REF,
442
                          TREE_TYPE (constants_data_field_decl_node),
443
                          constants,
444
                          constants_data_field_decl_node,
445
                          NULL_TREE);
446
 
447
      TREE_THIS_NOTRAP (klass) = 1;
448
      data = fold_convert (build_pointer_type (cpool_type), data);
449
      d = build1 (INDIRECT_REF, cpool_type, data);
450
 
451
      return d;
452
    }
453
  else
454
    {
455
      tree decl_name = mangled_classname ("_CD_", output_class);
456
      tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
457
 
458
      if (! decl)
459
        {
460
          /* Build a type with unspecified bounds.  The will make sure
461
             that targets do the right thing with whatever size we end
462
             up with at the end.  Using bounds that are too small risks
463
             assuming the data is in the small data section.  */
464
          tree type = build_array_type (ptr_type_node, NULL_TREE);
465
 
466
          /* We need to lay out the type ourselves, since build_array_type
467
             thinks the type is incomplete.  */
468
          layout_type (type);
469
 
470
          decl = build_decl (input_location, VAR_DECL, decl_name, type);
471
          TREE_STATIC (decl) = 1;
472
          IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
473
        }
474
 
475
      return decl;
476
    }
477
}
478
 
479
/* Get the pointer value at the INDEX'th element of the constant pool. */
480
 
481
tree
482
build_ref_from_constant_pool (int index)
483
{
484
  tree i;
485
  tree d = TYPE_CPOOL_DATA_REF (output_class);
486
 
487
  if (d == NULL_TREE)
488
    d = build_constant_data_ref (flag_indirect_classes);
489
 
490
  i = build_int_cst (NULL_TREE, index);
491
  d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
492
                 NULL_TREE, NULL_TREE);
493
  return d;
494
}
495
 
496
/* Build an initializer for the constants field of the current constant pool.
497
   Should only be called at top-level, since it may emit declarations. */
498
 
499
tree
500
build_constants_constructor (void)
501
{
502
  CPool *outgoing_cpool = cpool_for_class (current_class);
503
  tree tags_value, data_value;
504
  tree cons;
505
  VEC(constructor_elt,gc) *v = NULL;
506
  int i;
507
  VEC(constructor_elt,gc) *tags = NULL;
508
  VEC(constructor_elt,gc) *data = NULL;
509
  constructor_elt *t = NULL;
510
  constructor_elt *d = NULL;
511
 
512
  if (outgoing_cpool->count > 0)
513
    {
514
      int c = outgoing_cpool->count;
515
      VEC_safe_grow_cleared (constructor_elt, gc, tags, c);
516
      VEC_safe_grow_cleared (constructor_elt, gc, data, c);
517
      t = VEC_index (constructor_elt, tags, c-1);
518
      d = VEC_index (constructor_elt, data, c-1);
519
    }
520
 
521
#define CONSTRUCTOR_PREPEND_VALUE(E, V) E->value = V, E--
522
  for (i = outgoing_cpool->count;  --i > 0; )
523
    switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
524
      {
525
      case CONSTANT_None:  /* The second half of a Double or Long on a
526
                              32-bit target.  */
527
      case CONSTANT_Fieldref:
528
      case CONSTANT_NameAndType:
529
      case CONSTANT_Float:
530
      case CONSTANT_Integer:
531
      case CONSTANT_Double:
532
      case CONSTANT_Long:
533
      case CONSTANT_Methodref:
534
      case CONSTANT_InterfaceMethodref:
535
        {
536
          unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;
537
 
538
          /* Make sure that on a big-endian machine with 64-bit
539
             pointers this 32-bit jint appears in the first word.
540
             FIXME: This is a kludge.  The field we're initializing is
541
             not a scalar but a union, and that's how we should
542
             represent it in the compiler.  We should fix this.  */
543
          if (BYTES_BIG_ENDIAN)
544
            temp <<= ((POINTER_SIZE > 32) ? POINTER_SIZE - 32 : 0);
545
 
546
          CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
547
          CONSTRUCTOR_PREPEND_VALUE (d, build_int_cst (ptr_type_node, temp));
548
        }
549
        break;
550
 
551
      case CONSTANT_Class:
552
      case CONSTANT_String:
553
      case CONSTANT_Unicode:
554
      case CONSTANT_Utf8:
555
        CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
556
        CONSTRUCTOR_PREPEND_VALUE (d, build_utf8_ref (outgoing_cpool->data[i].t));
557
        break;
558
 
559
      default:
560
        gcc_assert (false);
561
      }
562
#undef CONSTRUCTOR_PREPEND_VALUE
563
 
564
  if (outgoing_cpool->count > 0)
565
    {
566
      tree data_decl, tags_decl, tags_type;
567
      tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1);
568
      tree index_type = build_index_type (max_index);
569
      tree tem;
570
 
571
      /* Add dummy 0'th element of constant pool. */
572
      gcc_assert (t == VEC_address (constructor_elt, tags));
573
      gcc_assert (d == VEC_address (constructor_elt, data));
574
      t->value = get_tag_node (0);
575
      d->value = null_pointer_node;
576
 
577
      /* Change the type of the decl to have the proper array size.
578
         ???  Make sure to transition the old type-pointer-to list to this
579
         new type to not invalidate all build address expressions.  */
580
      data_decl = build_constant_data_ref (false);
581
      tem = TYPE_POINTER_TO (TREE_TYPE (data_decl));
582
      if (!tem)
583
        tem = build_pointer_type (TREE_TYPE (data_decl));
584
      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = NULL_TREE;
585
      TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
586
      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem;
587
      DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), data);
588
      DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
589
      DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
590
      rest_of_decl_compilation (data_decl, 1, 0);
591
      data_value = build_address_of (data_decl);
592
 
593
      tags_type = build_array_type (unsigned_byte_type_node, index_type);
594
      tags_decl = build_decl (input_location,
595
                              VAR_DECL, mangled_classname ("_CT_",
596
                                                           current_class),
597
                              tags_type);
598
      TREE_STATIC (tags_decl) = 1;
599
      DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags);
600
      rest_of_decl_compilation (tags_decl, 1, 0);
601
      tags_value = build_address_of (tags_decl);
602
    }
603
  else
604
    {
605
      data_value = null_pointer_node;
606
      tags_value = null_pointer_node;
607
    }
608
  START_RECORD_CONSTRUCTOR (v, constants_type_node);
609
  PUSH_FIELD_VALUE (v, "size",
610
                    build_int_cst (NULL_TREE, outgoing_cpool->count));
611
  PUSH_FIELD_VALUE (v, "tags", tags_value);
612
  PUSH_FIELD_VALUE (v, "data", data_value);
613
  FINISH_RECORD_CONSTRUCTOR (cons, v, constants_type_node);
614
  return cons;
615
}
616
 
617
#include "gt-java-constants.h"

powered by: WebSVN 2.1.0

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