constants.c 17.6 KB
Newer Older
Anthony Green committed
1
/* 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  Free Software Foundation, Inc.
Anthony Green committed
4

5
This file is part of GCC.
Anthony Green committed
6

7
GCC is free software; you can redistribute it and/or modify
Anthony Green committed
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)
Anthony Green committed
10 11
any later version.

12
GCC is distributed in the hope that it will be useful,
Anthony Green committed
13 14 15 16
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
17 18
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>. 
Anthony Green committed
19 20 21 22 23 24

Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc.  */

#include "config.h"
25
#include "system.h"
26 27
#include "coretypes.h"
#include "tm.h"
28
#include "jcf.h"
Anthony Green committed
29 30
#include "tree.h"
#include "java-tree.h"
31
#include "diagnostic-core.h"
32
#include "toplev.h"
33
#include "ggc.h"
Anthony Green committed
34

35
static void set_constant_entry (CPool *, int, int, jword);
36
static int find_tree_constant (CPool *, int, tree);
37 38
static int find_name_and_type_constant (CPool *, tree, tree);
static tree get_tag_node (int);
39

Anthony Green committed
40 41
/* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */

42
static void
43
set_constant_entry (CPool *cpool, int index, int tag, jword value)
Anthony Green committed
44 45 46 47
{
  if (cpool->data == NULL)
    {
      cpool->capacity = 100;
48 49 50 51 52
      cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
						* cpool->capacity);
      cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
						       (union cpool_entry),
						       cpool->capacity);
Anthony Green committed
53 54 55 56
      cpool->count = 1;
    }
  if (index >= cpool->capacity)
    {
57
      int old_cap = cpool->capacity;
Anthony Green committed
58 59 60
      cpool->capacity *= 2;
      if (index >= cpool->capacity)
	cpool->capacity = index + 10;
61 62 63
      cpool->tags = GGC_RESIZEVEC (uint8, cpool->tags, cpool->capacity);
      cpool->data = GGC_RESIZEVEC (union cpool_entry, cpool->data,
				   cpool->capacity);
64 65 66 67 68

      /* Make sure GC never sees uninitialized tag values.  */
      memset (cpool->tags + old_cap, 0, cpool->capacity - old_cap);
      memset (cpool->data + old_cap, 0,
	      (cpool->capacity - old_cap) * sizeof (union cpool_entry));
Anthony Green committed
69 70 71 72
    }
  if (index >= cpool->count)
    cpool->count = index + 1;
  cpool->tags[index] = tag;
73
  cpool->data[index].w = value;
Anthony Green committed
74 75 76 77 78
}

/* Find (or create) a constant pool entry matching TAG and VALUE. */

int
79
find_constant1 (CPool *cpool, int tag, jword value)
Anthony Green committed
80 81 82 83
{
  int i;
  for (i = cpool->count;  --i > 0; )
    {
84
      if (cpool->tags[i] == tag && cpool->data[i].w == value)
Anthony Green committed
85 86 87 88 89 90 91 92 93 94
	return i;
    }
  i = cpool->count == 0 ? 1 : cpool->count;
  set_constant_entry (cpool, i, tag, value);
  return i;
}

/* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */

int
95
find_constant2 (CPool *cpool, int tag, jword word1, jword word2)
Anthony Green committed
96 97 98 99 100
{
  int i;
  for (i = cpool->count - 1;  --i > 0; )
    {
      if (cpool->tags[i] == tag
101 102
	  && cpool->data[i].w == word1
	  && cpool->data[i+1].w == word2)
Anthony Green committed
103 104 105 106 107 108 109 110
	return i;
    }
  i = cpool->count == 0 ? 1 : cpool->count;
  set_constant_entry (cpool, i, tag, word1);
  set_constant_entry (cpool, i+1, 0, word2);
  return i;
}

111
static int
112
find_tree_constant (CPool *cpool, int tag, tree value)
113 114 115 116 117 118 119 120 121 122 123 124 125 126
{
  int i;
  for (i = cpool->count;  --i > 0; )
    {
      if (cpool->tags[i] == tag && cpool->data[i].t == value)
	return i;
    }
  i = cpool->count == 0 ? 1 : cpool->count;
  set_constant_entry (cpool, i, tag, 0);
  cpool->data[i].t = value;
  return i;
}


Anthony Green committed
127
int
128
find_utf8_constant (CPool *cpool, tree name)
Anthony Green committed
129 130 131
{
  if (name == NULL_TREE)
    return 0;
132
  return find_tree_constant (cpool, CONSTANT_Utf8, name);
Anthony Green committed
133 134
}

135
int
136
find_class_or_string_constant (CPool *cpool, int tag, tree name)
Anthony Green committed
137
{
138
  jword j = find_utf8_constant (cpool, name);
Anthony Green committed
139 140 141
  int i;
  for (i = cpool->count;  --i > 0; )
    {
142
      if (cpool->tags[i] == tag && cpool->data[i].w == j)
Anthony Green committed
143 144 145
	return i;
    }
  i = cpool->count;
146
  set_constant_entry (cpool, i, tag, j);
Anthony Green committed
147 148 149 150
  return i;
}

int
151
find_class_constant (CPool *cpool, tree type)
Anthony Green committed
152 153 154 155 156
{
  return find_class_or_string_constant (cpool, CONSTANT_Class,
					build_internal_class_name (type));
}

157 158 159
/* Allocate a CONSTANT_string entry given a STRING_CST. */

int
160
find_string_constant (CPool *cpool, tree string)
161 162 163 164 165 166
{
  string = get_identifier (TREE_STRING_POINTER (string));
  return find_class_or_string_constant (cpool, CONSTANT_String, string);

}

Anthony Green committed
167 168 169
/* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE.
   Return its index in the constant pool CPOOL. */

170
static int
171
find_name_and_type_constant (CPool *cpool, tree name, tree type)
Anthony Green committed
172 173 174 175 176 177 178 179 180 181 182
{
  int name_index = find_utf8_constant (cpool, name);
  int type_index = find_utf8_constant (cpool, build_java_signature (type));
  return find_constant1 (cpool, CONSTANT_NameAndType,
			 (name_index << 16) | type_index);
}

/* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL).
   Return its index in the constant pool CPOOL. */

int
183
find_fieldref_index (CPool *cpool, tree decl)
Anthony Green committed
184 185 186 187 188 189 190 191 192 193 194 195
{
  int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
  int name_type_index
    = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
  return find_constant1 (cpool, CONSTANT_Fieldref,
			 (class_index << 16) | name_type_index);
}

/* Find (or create) a CONSTANT_Methodref for DECL (a FUNCTION_DECL).
   Return its index in the constant pool CPOOL. */

int
196
find_methodref_index (CPool *cpool, tree decl)
Anthony Green committed
197
{
198 199 200 201
  return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
}

int
202
find_methodref_with_class_index (CPool *cpool, tree decl, tree mclass)
203
{
204
  int class_index = find_class_constant (cpool, mclass);
Anthony Green committed
205 206
  tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
    : DECL_NAME (decl);
207 208 209
  int name_type_index;
  name_type_index = 
      find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
210 211 212 213
  return find_constant1 (cpool,
			 CLASS_INTERFACE (TYPE_NAME (mclass))
			 ? CONSTANT_InterfaceMethodref
			 : CONSTANT_Methodref,
Anthony Green committed
214 215 216 217 218 219
			 (class_index << 16) | name_type_index);
}

#define PUT1(X)  (*ptr++ = (X))
#define PUT2(X)  (PUT1((X) >> 8), PUT1(X))
#define PUT4(X)  (PUT2((X) >> 16), PUT2(X))
220
#define PUTN(P, N)  (memcpy(ptr, (P), (N)), ptr += (N))
Anthony Green committed
221 222 223 224 225

/* Give the number of bytes needed in a .class file for the CPOOL
   constant pool.  Includes the 2-byte constant_pool_count. */

int
226
count_constant_pool_bytes (CPool *cpool)
Anthony Green committed
227 228 229
{
  int size = 2;
  int i = 1;
230
  for ( ;  i < cpool->count;  i++)
Anthony Green committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    {
      size++;
      switch (cpool->tags[i])
	{
	case CONSTANT_NameAndType:
	case CONSTANT_Fieldref:
	case CONSTANT_Methodref:
	case CONSTANT_InterfaceMethodref:
	case CONSTANT_Float:
	case CONSTANT_Integer:
	  size += 4;
	  break;
	case CONSTANT_Class:
	case CONSTANT_String:
	  size += 2;
	  break;
	case CONSTANT_Long:
	case CONSTANT_Double:
249 250
	  size += 8;
	  i++;
Anthony Green committed
251 252 253
	  break;
	case CONSTANT_Utf8:
	  {
254
	    tree t = cpool->data[i].t;
Anthony Green committed
255 256 257 258
	    int len = IDENTIFIER_LENGTH (t);
	    size += len + 2;
	  }
	  break;
259 260 261
	default:
	  /* Second word of CONSTANT_Long and  CONSTANT_Double. */
	  size--;
Anthony Green committed
262 263 264 265 266 267 268 269 270
	}
    }
  return size;
}

/* Write the constant pool CPOOL into BUFFER.
   The length of BUFFER is LENGTH, which must match the needed length. */

void
271
write_constant_pool (CPool *cpool, unsigned char *buffer, int length)
Anthony Green committed
272
{
273
  unsigned char *ptr = buffer;
Anthony Green committed
274
  int i = 1;
275
  union cpool_entry *datap = &cpool->data[1];
Anthony Green committed
276 277 278 279 280 281 282 283 284 285 286 287 288
  PUT2 (cpool->count);
  for ( ;  i < cpool->count;  i++, datap++)
    {
      int tag = cpool->tags[i];
      PUT1 (tag);
      switch (tag)
	{
	case CONSTANT_NameAndType:
	case CONSTANT_Fieldref:
	case CONSTANT_Methodref:
	case CONSTANT_InterfaceMethodref:
	case CONSTANT_Float:
	case CONSTANT_Integer:
289
	  PUT4 (datap->w);
Anthony Green committed
290 291 292
	  break;
	case CONSTANT_Class:
	case CONSTANT_String:
293
	  PUT2 (datap->w);
Anthony Green committed
294 295 296 297
	  break;
	  break;
	case CONSTANT_Long:
	case CONSTANT_Double:
298
	  PUT4(datap->w);
Anthony Green committed
299 300
	  i++;
	  datap++;
301
	  PUT4 (datap->w);
Anthony Green committed
302 303 304
	  break;
	case CONSTANT_Utf8:
	  {
305
	    tree t = datap->t;
Anthony Green committed
306 307 308 309 310 311 312
	    int len = IDENTIFIER_LENGTH (t);
	    PUT2 (len);
	    PUTN (IDENTIFIER_POINTER (t), len);
	  }
	  break;
	}
    }
313

314
  gcc_assert (ptr == buffer + length);
Anthony Green committed
315 316
}

317
static GTY(()) tree tag_nodes[13];
318
static tree
319
get_tag_node (int tag)
Anthony Green committed
320
{
321
  /* A Cache for build_int_cst (CONSTANT_XXX, 0). */
322

323 324 325
  if (tag >= 13)
    return build_int_cst (NULL_TREE, tag);

Anthony Green committed
326
  if (tag_nodes[tag] == NULL_TREE)
327
    tag_nodes[tag] = build_int_cst (NULL_TREE, tag);
Anthony Green committed
328 329 330
  return tag_nodes[tag];
}

331 332
/* Given a class, return its constant pool, creating one if necessary.  */

333
CPool *
334
cpool_for_class (tree klass)
335
{
336
  CPool *cpool = TYPE_CPOOL (klass);
337 338 339

  if (cpool == NULL)
    {
340
      cpool = ggc_alloc_cleared_CPool ();
341
      TYPE_CPOOL (klass) = cpool;
342 343 344 345
    }
  return cpool;
}

Anthony Green committed
346 347 348 349 350 351 352
/* Look for a constant pool entry that matches TAG and NAME.
   Creates a new entry if not found.
   TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class.
   NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class.
   Returns the index of the entry. */

int
353
alloc_name_constant (int tag, tree name)
Anthony Green committed
354
{
355
  CPool *outgoing_cpool = cpool_for_class (output_class);
356
  return find_tree_constant (outgoing_cpool, tag, name);
Anthony Green committed
357 358
}

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
/* Create a constant pool entry for a name_and_type.  This one has '.'
   rather than '/' because it isn't going into a class file, it's
   going into a compiled object.  We don't use the '/' separator in
   compiled objects.  */

static int
find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
{
  int name_index = find_utf8_constant (cpool, name);
  int type_index 
    = find_utf8_constant (cpool, 
			  identifier_subst (build_java_signature (type), 
					    "", '/', '.', ""));
  return find_constant1 (cpool, CONSTANT_NameAndType,
			 (name_index << 16) | type_index);
}

/* Look for a field ref that matches DECL in the constant pool of
377
   KLASS.  
378 379 380
   Return the index of the entry.  */

int
381
alloc_constant_fieldref (tree klass, tree decl)
382
{
383
  CPool *outgoing_cpool = cpool_for_class (klass);
384 385 386 387 388 389 390 391 392 393
  int class_index 
    = find_tree_constant (outgoing_cpool, CONSTANT_Class, 
			  DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
  int name_type_index
    = find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl), 
					TREE_TYPE (decl));
  return find_constant1 (outgoing_cpool, CONSTANT_Fieldref,
			 (class_index << 16) | name_type_index);
}

Anthony Green committed
394 395 396
/* Build an identifier for the internal name of reference type TYPE. */

tree
397
build_internal_class_name (tree type)
Anthony Green committed
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
{
  tree name;
  if (TYPE_ARRAY_P (type))
    name = build_java_signature (type);
  else
    {
      name = TYPE_NAME (type);
      if (TREE_CODE (name) != IDENTIFIER_NODE)
	name = DECL_NAME (name);
      name = identifier_subst (name, "", '.', '/', "");
    }
  return name;
}

/* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */

int
415
alloc_class_constant (tree clas)
Anthony Green committed
416
{
417 418
  tree class_name = build_internal_class_name (clas);
  
Anthony Green committed
419
  return alloc_name_constant (CONSTANT_Class,
420 421 422
			      (unmangle_classname 
			       (IDENTIFIER_POINTER(class_name),
				IDENTIFIER_LENGTH(class_name))));
Anthony Green committed
423 424
}

425
/* Return the decl of the data array of the current constant pool. */
Anthony Green committed
426

427 428
tree
build_constant_data_ref (bool indirect)
Anthony Green committed
429
{
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
  if (indirect)
    {
      tree d;
      tree cpool_type = build_array_type (ptr_type_node, NULL_TREE);
      tree decl = build_class_ref (output_class);
      tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
			   decl);
      tree constants = build3 (COMPONENT_REF, 
			       TREE_TYPE (constants_field_decl_node), klass,
			       constants_field_decl_node,
			       NULL_TREE);
      tree data = build3 (COMPONENT_REF, 
			  TREE_TYPE (constants_data_field_decl_node), 
			  constants,
			  constants_data_field_decl_node,
			  NULL_TREE);
446

447 448 449 450 451 452 453
      TREE_THIS_NOTRAP (klass) = 1;
      data = fold_convert (build_pointer_type (cpool_type), data);
      d = build1 (INDIRECT_REF, cpool_type, data);

      return d;
    }
  else
Anthony Green committed
454
    {
455
      tree decl_name = mangled_classname ("_CD_", output_class);
456
      tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
457

458 459 460 461 462 463 464 465 466 467 468 469
      if (! decl)
	{
	  /* Build a type with unspecified bounds.  The will make sure
	     that targets do the right thing with whatever size we end
	     up with at the end.  Using bounds that are too small risks
	     assuming the data is in the small data section.  */
	  tree type = build_array_type (ptr_type_node, NULL_TREE);

	  /* We need to lay out the type ourselves, since build_array_type
	     thinks the type is incomplete.  */
	  layout_type (type);

470
	  decl = build_decl (input_location, VAR_DECL, decl_name, type);
471 472 473
	  TREE_STATIC (decl) = 1;
	  IDENTIFIER_GLOBAL_VALUE (decl_name) = decl;
	}
474

475 476
      return decl;
    }
Anthony Green committed
477 478 479 480 481
}

/* Get the pointer value at the INDEX'th element of the constant pool. */

tree
482
build_ref_from_constant_pool (int index)
Anthony Green committed
483
{
484 485 486 487 488 489 490
  tree i;
  tree d = TYPE_CPOOL_DATA_REF (output_class);

  if (d == NULL_TREE)
    d = build_constant_data_ref (flag_indirect_classes);

  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;
Anthony Green committed
494 495
}

496
/* Build an initializer for the constants field of the current constant pool.
Anthony Green committed
497 498 499
   Should only be called at top-level, since it may emit declarations. */

tree
500
build_constants_constructor (void)
Anthony Green committed
501
{
502
  CPool *outgoing_cpool = cpool_for_class (current_class);
Anthony Green committed
503 504
  tree tags_value, data_value;
  tree cons;
505
  VEC(constructor_elt,gc) *v = NULL;
Anthony Green committed
506
  int i;
507 508 509 510
  VEC(constructor_elt,gc) *tags = NULL;
  VEC(constructor_elt,gc) *data = NULL;
  constructor_elt *t = NULL;
  constructor_elt *d = NULL;
511

512 513 514 515 516 517 518 519 520 521
  if (outgoing_cpool->count > 0)
    {
      int c = outgoing_cpool->count;
      VEC_safe_grow_cleared (constructor_elt, gc, tags, c);
      VEC_safe_grow_cleared (constructor_elt, gc, data, c);
      t = VEC_index (constructor_elt, tags, c-1);
      d = VEC_index (constructor_elt, data, c-1);
    }

#define CONSTRUCTOR_PREPEND_VALUE(E, V) E->value = V, E--
Anthony Green committed
522
  for (i = outgoing_cpool->count;  --i > 0; )
523
    switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
524
      {
525 526
      case CONSTANT_None:  /* The second half of a Double or Long on a
			      32-bit target.  */
527 528
      case CONSTANT_Fieldref:
      case CONSTANT_NameAndType:
529 530 531 532 533 534
      case CONSTANT_Float:
      case CONSTANT_Integer:
      case CONSTANT_Double:
      case CONSTANT_Long:
      case CONSTANT_Methodref:
      case CONSTANT_InterfaceMethodref:
535
	{
536 537
	  unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;

538 539
	  /* Make sure that on a big-endian machine with 64-bit
	     pointers this 32-bit jint appears in the first word.
540 541 542
	     FIXME: This is a kludge.  The field we're initializing is
	     not a scalar but a union, and that's how we should
	     represent it in the compiler.  We should fix this.  */
543 544
	  if (BYTES_BIG_ENDIAN)
	    temp <<= ((POINTER_SIZE > 32) ? POINTER_SIZE - 32 : 0);
545

546 547 548 549 550
          CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
          CONSTRUCTOR_PREPEND_VALUE (d,
                                     fold_convert (ptr_type_node, 
                                                   (build_int_cst (NULL_TREE,
                                                                   temp))));
551 552
	}
	break;
553 554 555 556 557

      case CONSTANT_Class:
      case CONSTANT_String:
      case CONSTANT_Unicode:
      case CONSTANT_Utf8:
558 559
        CONSTRUCTOR_PREPEND_VALUE (t, get_tag_node (outgoing_cpool->tags[i]));
        CONSTRUCTOR_PREPEND_VALUE (d, build_utf8_ref (outgoing_cpool->data[i].t));
560
	break;
561 562 563

      default:
	gcc_assert (false);
564
      }
565 566
#undef CONSTRUCTOR_PREPEND_VALUE

Anthony Green committed
567 568 569
  if (outgoing_cpool->count > 0)
    {
      tree data_decl, tags_decl, tags_type;
570
      tree max_index = build_int_cst (sizetype, outgoing_cpool->count - 1);
571
      tree index_type = build_index_type (max_index);
572
      tree tem;
Anthony Green committed
573 574

      /* Add dummy 0'th element of constant pool. */
575 576 577 578
      gcc_assert (t == VEC_address (constructor_elt, tags));
      gcc_assert (d == VEC_address (constructor_elt, data));
      t->value = get_tag_node (0);
      d->value = null_pointer_node;
Anthony Green committed
579
  
580 581 582
      /* Change the type of the decl to have the proper array size.
         ???  Make sure to transition the old type-pointer-to list to this
	 new type to not invalidate all build address expressions.  */
583
      data_decl = build_constant_data_ref (false);
584 585 586 587
      tem = TYPE_POINTER_TO (TREE_TYPE (data_decl));
      if (!tem)
	tem = build_pointer_type (TREE_TYPE (data_decl));
      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = NULL_TREE;
588
      TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
589
      TYPE_POINTER_TO (TREE_TYPE (data_decl)) = tem;
590
      DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), data);
Anthony Green committed
591
      DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
592
      DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
593
      rest_of_decl_compilation (data_decl, 1, 0);
Anthony Green committed
594 595 596
      data_value = build_address_of (data_decl);

      tags_type = build_array_type (unsigned_byte_type_node, index_type);
597 598
      tags_decl = build_decl (input_location, 
      			      VAR_DECL, mangled_classname ("_CT_", 
Anthony Green committed
599 600 601
							   current_class),
			      tags_type);
      TREE_STATIC (tags_decl) = 1;
602
      DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags);
603
      rest_of_decl_compilation (tags_decl, 1, 0);
Anthony Green committed
604 605 606 607 608 609 610
      tags_value = build_address_of (tags_decl);
    }
  else
    {
      data_value = null_pointer_node;
      tags_value = null_pointer_node;
    }
611 612
  START_RECORD_CONSTRUCTOR (v, constants_type_node);
  PUSH_FIELD_VALUE (v, "size",
613
		    build_int_cst (NULL_TREE, outgoing_cpool->count));
614 615 616
  PUSH_FIELD_VALUE (v, "tags", tags_value);
  PUSH_FIELD_VALUE (v, "data", data_value);
  FINISH_RECORD_CONSTRUCTOR (cons, v, constants_type_node);
Anthony Green committed
617 618
  return cons;
}
619 620

#include "gt-java-constants.h"