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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [java/] [constants.c] - Blame information for rev 826

Details | Compare with Previous | View Log

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