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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [java/] [constants.c] - Blame information for rev 16

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

Line No. Rev Author Line
1 12 jlechner
/* Handle the constant pool of the Java(TM) Virtual Machine.
2
   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
3
   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 2, 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 COPYING.  If not, write to
18
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.
20
 
21
Java and all Java-based marks are trademarks or registered trademarks
22
of Sun Microsystems, Inc. in the United States and other countries.
23
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
 
25
#include "config.h"
26
#include "system.h"
27
#include "coretypes.h"
28
#include "tm.h"
29
#include "jcf.h"
30
#include "tree.h"
31
#include "java-tree.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_class_or_string_constant (CPool *, int, tree);
38
static int find_name_and_type_constant (CPool *, tree, tree);
39
static tree get_tag_node (int);
40
static tree build_constant_data_ref (void);
41
static CPool *cpool_for_class (tree);
42
 
43
/* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
44
 
45
static void
46
set_constant_entry (CPool *cpool, int index, int tag, jword value)
47
{
48
  if (cpool->data == NULL)
49
    {
50
      cpool->capacity = 100;
51
      cpool->tags = ggc_alloc_cleared (sizeof(uint8) * cpool->capacity);
52
      cpool->data = ggc_alloc_cleared (sizeof(union cpool_entry)
53
                                       * cpool->capacity);
54
      cpool->count = 1;
55
    }
56
  if (index >= cpool->capacity)
57
    {
58
      int old_cap = cpool->capacity;
59
      cpool->capacity *= 2;
60
      if (index >= cpool->capacity)
61
        cpool->capacity = index + 10;
62
      cpool->tags = ggc_realloc (cpool->tags,
63
                                 sizeof(uint8) * cpool->capacity);
64
      cpool->data = ggc_realloc (cpool->data,
65
                                 sizeof(union cpool_entry) * cpool->capacity);
66
 
67
      /* Make sure GC never sees uninitialized tag values.  */
68
      memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
69
      memset (cpool->data + old_cap, 0,
70
              (cpool->capacity - old_cap) * sizeof (union cpool_entry));
71
    }
72
  if (index >= cpool->count)
73
    cpool->count = index + 1;
74
  cpool->tags[index] = tag;
75
  cpool->data[index].w = value;
76
}
77
 
78
/* Find (or create) a constant pool entry matching TAG and VALUE. */
79
 
80
int
81
find_constant1 (CPool *cpool, int tag, jword value)
82
{
83
  int i;
84
  for (i = cpool->count;  --i > 0; )
85
    {
86
      if (cpool->tags[i] == tag && cpool->data[i].w == value)
87
        return i;
88
    }
89
  i = cpool->count == 0 ? 1 : cpool->count;
90
  set_constant_entry (cpool, i, tag, value);
91
  return i;
92
}
93
 
94
/* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */
95
 
96
int
97
find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
98
{
99
  int i;
100
  for (i = cpool->count - 1;  --i > 0; )
101
    {
102
      if (cpool->tags[i] == tag
103
          && cpool->data[i].w == word1
104
          && cpool->data[i+1].w == word2)
105
        return i;
106
    }
107
  i = cpool->count == 0 ? 1 : cpool->count;
108
  set_constant_entry (cpool, i, tag, word1);
109
  set_constant_entry (cpool, i+1, 0, word2);
110
  return i;
111
}
112
 
113
static int
114
find_tree_constant (CPool *cpool, int tag, tree value)
115
{
116
  int i;
117
  for (i = cpool->count;  --i > 0; )
118
    {
119
      if (cpool->tags[i] == tag && cpool->data[i].t == value)
120
        return i;
121
    }
122
  i = cpool->count == 0 ? 1 : cpool->count;
123
  set_constant_entry (cpool, i, tag, 0);
124
  cpool->data[i].t = value;
125
  return i;
126
}
127
 
128
 
129
int
130
find_utf8_constant (CPool *cpool, tree name)
131
{
132
  if (name == NULL_TREE)
133
    return 0;
134
  return find_tree_constant (cpool, CONSTANT_Utf8, name);
135
}
136
 
137
static int
138
find_class_or_string_constant (CPool *cpool, int tag, tree name)
139
{
140
  jword j = find_utf8_constant (cpool, name);
141
  int i;
142
  for (i = cpool->count;  --i > 0; )
143
    {
144
      if (cpool->tags[i] == tag && cpool->data[i].w == j)
145
        return i;
146
    }
147
  i = cpool->count;
148
  set_constant_entry (cpool, i, tag, j);
149
  return i;
150
}
151
 
152
int
153
find_class_constant (CPool *cpool, tree type)
154
{
155
  return find_class_or_string_constant (cpool, CONSTANT_Class,
156
                                        build_internal_class_name (type));
157
}
158
 
159
/* Allocate a CONSTANT_string entry given a STRING_CST. */
160
 
161
int
162
find_string_constant (CPool *cpool, tree string)
163
{
164
  string = get_identifier (TREE_STRING_POINTER (string));
165
  return find_class_or_string_constant (cpool, CONSTANT_String, string);
166
 
167
}
168
 
169
/* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
170
   Return its index in the constant pool CPOOL. */
171
 
172
static int
173
find_name_and_type_constant (CPool *cpool, tree name, tree type)
174
{
175
  int name_index = find_utf8_constant (cpool, name);
176
  int type_index = find_utf8_constant (cpool, build_java_signature (type));
177
  return find_constant1 (cpool, CONSTANT_NameAndType,
178
                         (name_index << 16) | type_index);
179
}
180
 
181
/* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
182
   Return its index in the constant pool CPOOL. */
183
 
184
int
185
find_fieldref_index (CPool *cpool, tree decl)
186
{
187
  int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
188
  int name_type_index
189
    = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
190
  return find_constant1 (cpool, CONSTANT_Fieldref,
191
                         (class_index << 16) | name_type_index);
192
}
193
 
194
/* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
195
   Return its index in the constant pool CPOOL. */
196
 
197
int
198
find_methodref_index (CPool *cpool, tree decl)
199
{
200
  return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
201
}
202
 
203
int
204
find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
205
{
206
  int class_index = find_class_constant (cpool, mclass);
207
  tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
208
    : DECL_NAME (decl);
209
  int name_type_index;
210
  name_type_index =
211
      find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
212
  return find_constant1 (cpool,
213
                         CLASS_INTERFACE (TYPE_NAME (mclass))
214
                         ? CONSTANT_InterfaceMethodref
215
                         : CONSTANT_Methodref,
216
                         (class_index << 16) | name_type_index);
217
}
218
 
219
#define PUT1(X)  (*ptr++ = (X))
220
#define PUT2(X)  (PUT1((X) >> 8), PUT1(X))
221
#define PUT4(X)  (PUT2((X) >> 16), PUT2(X))
222
#define PUTN(P, N)  (memcpy(ptr, (P), (N)), ptr += (N))
223
 
224
/* Give the number of bytes needed in a .class file for the CPOOL
225
   constant pool.  Includes the 2-byte constant_pool_count. */
226
 
227
int
228
count_constant_pool_bytes (CPool *cpool)
229
{
230
  int size = 2;
231
  int i = 1;
232
  for ( ;  i < cpool->count;  i++)
233
    {
234
      size++;
235
      switch (cpool->tags[i])
236
        {
237
        case CONSTANT_NameAndType:
238
        case CONSTANT_Fieldref:
239
        case CONSTANT_Methodref:
240
        case CONSTANT_InterfaceMethodref:
241
        case CONSTANT_Float:
242
        case CONSTANT_Integer:
243
          size += 4;
244
          break;
245
        case CONSTANT_Class:
246
        case CONSTANT_String:
247
          size += 2;
248
          break;
249
        case CONSTANT_Long:
250
        case CONSTANT_Double:
251
          size += 8;
252
          i++;
253
          break;
254
        case CONSTANT_Utf8:
255
          {
256
            tree t = cpool->data[i].t;
257
            int len = IDENTIFIER_LENGTH (t);
258
            size += len + 2;
259
          }
260
          break;
261
        default:
262
          /* Second word of CONSTANT_Long and  CONSTANT_Double. */
263
          size--;
264
        }
265
    }
266
  return size;
267
}
268
 
269
/* Write the constant pool CPOOL into BUFFER.
270
   The length of BUFFER is LENGTH, which must match the needed length. */
271
 
272
void
273
write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
274
{
275
  unsigned char *ptr = buffer;
276
  int i = 1;
277
  union cpool_entry *datap = &cpool->data[1];
278
  PUT2 (cpool->count);
279
  for ( ;  i < cpool->count;  i++, datap++)
280
    {
281
      int tag = cpool->tags[i];
282
      PUT1 (tag);
283
      switch (tag)
284
        {
285
        case CONSTANT_NameAndType:
286
        case CONSTANT_Fieldref:
287
        case CONSTANT_Methodref:
288
        case CONSTANT_InterfaceMethodref:
289
        case CONSTANT_Float:
290
        case CONSTANT_Integer:
291
          PUT4 (datap->w);
292
          break;
293
        case CONSTANT_Class:
294
        case CONSTANT_String:
295
          PUT2 (datap->w);
296
          break;
297
          break;
298
        case CONSTANT_Long:
299
        case CONSTANT_Double:
300
          PUT4(datap->w);
301
          i++;
302
          datap++;
303
          PUT4 (datap->w);
304
          break;
305
        case CONSTANT_Utf8:
306
          {
307
            tree t = datap->t;
308
            int len = IDENTIFIER_LENGTH (t);
309
            PUT2 (len);
310
            PUTN (IDENTIFIER_POINTER (t), len);
311
          }
312
          break;
313
        }
314
    }
315
 
316
  if (ptr != buffer + length)
317
    abort ();
318
}
319
 
320
static GTY(()) tree tag_nodes[13];
321
static tree
322
get_tag_node (int tag)
323
{
324
  /* A Cache for build_int_cst (CONSTANT_XXX, 0). */
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
static CPool *
334
cpool_for_class (tree class)
335
{
336
  CPool *cpool = TYPE_CPOOL (class);
337
 
338
  if (cpool == NULL)
339
    {
340
      cpool = ggc_alloc_cleared (sizeof (struct CPool));
341
      TYPE_CPOOL (class) = 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
   CLASS.
378
   Return the index of the entry.  */
379
 
380
int
381
alloc_constant_fieldref (tree class, tree decl)
382
{
383
  CPool *outgoing_cpool = cpool_for_class (class);
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
static tree
428
build_constant_data_ref (void)
429
{
430
  tree decl = TYPE_CPOOL_DATA_REF (output_class);
431
 
432
  if (decl == NULL_TREE)
433
    {
434
      tree type;
435
      tree decl_name = mangled_classname ("_CD_", output_class);
436
 
437
      /* Build a type with unspecified bounds.  The will make sure
438
         that targets do the right thing with whatever size we end
439
         up with at the end.  Using bounds that are too small risks
440
         assuming the data is in the small data section.  */
441
      type = build_array_type (ptr_type_node, NULL_TREE);
442
 
443
      /* We need to lay out the type ourselves, since build_array_type
444
         thinks the type is incomplete.  */
445
      layout_type (type);
446
 
447
      decl = build_decl (VAR_DECL, decl_name, type);
448
      TREE_STATIC (decl) = 1;
449
      TYPE_CPOOL_DATA_REF (output_class) = decl;
450
    }
451
 
452
  return decl;
453
}
454
 
455
/* Get the pointer value at the INDEX'th element of the constant pool. */
456
 
457
tree
458
build_ref_from_constant_pool (int index)
459
{
460
  tree d = build_constant_data_ref ();
461
  tree i = build_int_cst (NULL_TREE, index);
462
  return build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
463
                 NULL_TREE, NULL_TREE);
464
}
465
 
466
/* Build an initializer for the constants field of the current constant pool.
467
   Should only be called at top-level, since it may emit declarations. */
468
 
469
tree
470
build_constants_constructor (void)
471
{
472
  CPool *outgoing_cpool = cpool_for_class (current_class);
473
  tree tags_value, data_value;
474
  tree cons;
475
  tree tags_list = NULL_TREE;
476
  tree data_list = NULL_TREE;
477
  int i;
478
  for (i = outgoing_cpool->count;  --i > 0; )
479
    switch (outgoing_cpool->tags[i])
480
      {
481
      case CONSTANT_Fieldref:
482
      case CONSTANT_NameAndType:
483
        {
484
          unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;
485
 
486
          /* Make sure that on a 64-bit big-endian machine this 32-bit
487
             jint appears in the first word.  */
488
          if (BYTES_BIG_ENDIAN && BITS_PER_WORD > 32)
489
            temp <<= BITS_PER_WORD - 32;
490
 
491
          tags_list
492
            = tree_cons (NULL_TREE,
493
                         build_int_cst (NULL_TREE, outgoing_cpool->tags[i]),
494
                         tags_list);
495
          data_list
496
            = tree_cons (NULL_TREE,
497
                         fold_convert (ptr_type_node,
498
                                       (build_int_cst (NULL_TREE, temp))),
499
                         data_list);
500
        }
501
        break;
502
      default:
503
        tags_list
504
          = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
505
                       tags_list);
506
        data_list
507
          = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
508
                       data_list);
509
        break;
510
      }
511
  if (outgoing_cpool->count > 0)
512
    {
513
      tree data_decl, tags_decl, tags_type;
514
      tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1);
515
      tree index_type = build_index_type (max_index);
516
 
517
      /* Add dummy 0'th element of constant pool. */
518
      tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
519
      data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
520
 
521
      data_decl = build_constant_data_ref ();
522
      TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
523
      DECL_INITIAL (data_decl) = build_constructor_from_list
524
                                  (TREE_TYPE (data_decl), data_list);
525
      DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
526
      DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
527
      rest_of_decl_compilation (data_decl, 1, 0);
528
      data_value = build_address_of (data_decl);
529
 
530
      tags_type = build_array_type (unsigned_byte_type_node, index_type);
531
      tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_",
532
                                                           current_class),
533
                              tags_type);
534
      TREE_STATIC (tags_decl) = 1;
535
      DECL_INITIAL (tags_decl) = build_constructor_from_list
536
                                 (tags_type, tags_list);
537
      rest_of_decl_compilation (tags_decl, 1, 0);
538
      tags_value = build_address_of (tags_decl);
539
    }
540
  else
541
    {
542
      data_value = null_pointer_node;
543
      tags_value = null_pointer_node;
544
    }
545
  START_RECORD_CONSTRUCTOR (cons, constants_type_node);
546
  PUSH_FIELD_VALUE (cons, "size",
547
                    build_int_cst (NULL_TREE, outgoing_cpool->count));
548
  PUSH_FIELD_VALUE (cons, "tags", tags_value);
549
  PUSH_FIELD_VALUE (cons, "data", data_value);
550
  FINISH_RECORD_CONSTRUCTOR (cons);
551
  return cons;
552
}
553
 
554
#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.