1 /* Handle the constant pool of the Java(TM) Virtual Machine. 2 Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 3 4 This file is part of GNU CC. 5 6 GNU CC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU CC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 You should have received a copy of the GNU General Public License 16 along with GNU CC; see the file COPYING. If not, write to 17 the Free Software Foundation, 59 Temple Place - Suite 330, 18 Boston, MA 02111-1307, USA. 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 "jcf.h" 27 #include "tree.h" 28 #include "java-tree.h" 29 #include "toplev.h" 30 #include "ggc.h" 31 32 static void set_constant_entry PARAMS ((CPool *, int, int, jword)); 33 static int find_class_or_string_constant PARAMS ((CPool *, int, tree)); 34 static int find_name_and_type_constant PARAMS ((CPool *, tree, tree)); 35 static tree get_tag_node PARAMS ((int)); 36 static tree build_constant_data_ref PARAMS ((void)); 37 38 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */ 39 40 static void 41 set_constant_entry (cpool, index, tag, value) 42 CPool *cpool; 43 int index; 44 int tag; 45 jword value; 46 { 47 if (cpool->data == NULL) 48 { 49 cpool->capacity = 100; 50 cpool->tags = xmalloc (sizeof(uint8) * cpool->capacity); 51 cpool->data = xmalloc (sizeof(jword) * cpool->capacity); 52 cpool->count = 1; 53 } 54 if (index >= cpool->capacity) 55 { 56 cpool->capacity *= 2; 57 if (index >= cpool->capacity) 58 cpool->capacity = index + 10; 59 cpool->tags = xrealloc (cpool->tags, sizeof(uint8) * cpool->capacity); 60 cpool->data = xrealloc (cpool->data, sizeof(jword) * cpool->capacity); 61 } 62 if (index >= cpool->count) 63 cpool->count = index + 1; 64 cpool->tags[index] = tag; 65 cpool->data[index] = value; 66 } 67 68 /* Find (or create) a constant pool entry matching TAG and VALUE. */ 69 70 int 71 find_constant1 (cpool, tag, value) 72 CPool *cpool; 73 int tag; 74 jword value; 75 { 76 int i; 77 for (i = cpool->count; --i > 0; ) 78 { 79 if (cpool->tags[i] == tag && cpool->data[i] == value) 80 return i; 81 } 82 i = cpool->count == 0 ? 1 : cpool->count; 83 set_constant_entry (cpool, i, tag, value); 84 return i; 85 } 86 87 /* Find a double-word constant pool entry matching TAG and WORD1/WORD2. */ 88 89 int 90 find_constant2 (cpool, tag, word1, word2) 91 CPool *cpool; 92 int tag; 93 jword word1, word2; 94 { 95 int i; 96 for (i = cpool->count - 1; --i > 0; ) 97 { 98 if (cpool->tags[i] == tag 99 && cpool->data[i] == word1 100 && cpool->data[i+1] == word2) 101 return i; 102 } 103 i = cpool->count == 0 ? 1 : cpool->count; 104 set_constant_entry (cpool, i, tag, word1); 105 set_constant_entry (cpool, i+1, 0, word2); 106 return i; 107 } 108 109 int 110 find_utf8_constant (cpool, name) 111 CPool *cpool; 112 tree name; 113 { 114 if (name == NULL_TREE) 115 return 0; 116 return find_constant1 (cpool, CONSTANT_Utf8, (jword) name); 117 } 118 119 static int 120 find_class_or_string_constant (cpool, tag, name) 121 CPool *cpool; 122 int tag; 123 tree name; 124 { 125 int j = find_utf8_constant (cpool, name); 126 int i; 127 for (i = cpool->count; --i > 0; ) 128 { 129 if (cpool->tags[i] == tag && cpool->data[i] == (jword) j) 130 return i; 131 } 132 i = cpool->count; 133 set_constant_entry (cpool, i, tag, (jword) j); 134 return i; 135 } 136 137 int 138 find_class_constant (cpool, type) 139 CPool *cpool; 140 tree type; 141 { 142 return find_class_or_string_constant (cpool, CONSTANT_Class, 143 build_internal_class_name (type)); 144 } 145 146 /* Allocate a CONSTANT_string entry given a STRING_CST. */ 147 148 int 149 find_string_constant (cpool, string) 150 CPool *cpool; 151 tree string; 152 { 153 string = get_identifier (TREE_STRING_POINTER (string)); 154 return find_class_or_string_constant (cpool, CONSTANT_String, string); 155 156 } 157 158 /* Find (or create) a CONSTANT_NameAndType matching NAME and TYPE. 159 Return its index in the constant pool CPOOL. */ 160 161 static int 162 find_name_and_type_constant (cpool, name, type) 163 CPool *cpool; 164 tree name; 165 tree type; 166 { 167 int name_index = find_utf8_constant (cpool, name); 168 int type_index = find_utf8_constant (cpool, build_java_signature (type)); 169 return find_constant1 (cpool, CONSTANT_NameAndType, 170 (name_index << 16) | type_index); 171 } 172 173 /* Find (or create) a CONSTANT_Fieldref for DECL (a FIELD_DECL or VAR_DECL). 174 Return its index in the constant pool CPOOL. */ 175 176 int 177 find_fieldref_index (cpool, decl) 178 CPool *cpool; 179 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, decl) 193 CPool *cpool; 194 tree decl; 195 { 196 return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl)); 197 } 198 199 int 200 find_methodref_with_class_index (cpool, decl, mclass) 201 CPool *cpool; 202 tree decl; 203 tree mclass; 204 { 205 int class_index = find_class_constant (cpool, mclass); 206 tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node 207 : DECL_NAME (decl); 208 int name_type_index; 209 name_type_index = 210 find_name_and_type_constant (cpool, name, TREE_TYPE (decl)); 211 return find_constant1 (cpool, 212 CLASS_INTERFACE (TYPE_NAME (mclass)) 213 ? CONSTANT_InterfaceMethodref 214 : CONSTANT_Methodref, 215 (class_index << 16) | name_type_index); 216 } 217 218 #define PUT1(X) (*ptr++ = (X)) 219 #define PUT2(X) (PUT1((X) >> 8), PUT1(X)) 220 #define PUT4(X) (PUT2((X) >> 16), PUT2(X)) 221 #define PUTN(P, N) (memcpy(ptr, (P), (N)), ptr += (N)) 222 223 /* Give the number of bytes needed in a .class file for the CPOOL 224 constant pool. Includes the 2-byte constant_pool_count. */ 225 226 int 227 count_constant_pool_bytes (cpool) 228 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 = (tree) cpool->data[i]; 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, buffer, length) 274 CPool *cpool; 275 unsigned char *buffer; 276 int length; 277 { 278 unsigned char *ptr = buffer; 279 int i = 1; 280 jword *datap = &cpool->data[1]; 281 PUT2 (cpool->count); 282 for ( ; i < cpool->count; i++, datap++) 283 { 284 int tag = cpool->tags[i]; 285 PUT1 (tag); 286 switch (tag) 287 { 288 case CONSTANT_NameAndType: 289 case CONSTANT_Fieldref: 290 case CONSTANT_Methodref: 291 case CONSTANT_InterfaceMethodref: 292 case CONSTANT_Float: 293 case CONSTANT_Integer: 294 PUT4 (*datap); 295 break; 296 case CONSTANT_Class: 297 case CONSTANT_String: 298 PUT2 (*datap); 299 break; 300 break; 301 case CONSTANT_Long: 302 case CONSTANT_Double: 303 PUT4(*datap); 304 i++; 305 datap++; 306 PUT4 (*datap); 307 break; 308 case CONSTANT_Utf8: 309 { 310 tree t = (tree) *datap; 311 int len = IDENTIFIER_LENGTH (t); 312 PUT2 (len); 313 PUTN (IDENTIFIER_POINTER (t), len); 314 } 315 break; 316 } 317 } 318 319 if (ptr != buffer + length) 320 abort (); 321 } 322 323 CPool *outgoing_cpool; 324 325 static GTY(()) tree tag_nodes[13]; 326 static tree 327 get_tag_node (tag) 328 int tag; 329 { 330 /* A Cache for build_int_2 (CONSTANT_XXX, 0). */ 331 332 if (tag_nodes[tag] == NULL_TREE) 333 tag_nodes[tag] = build_int_2 (tag, 0); 334 return tag_nodes[tag]; 335 } 336 337 /* Look for a constant pool entry that matches TAG and NAME. 338 Creates a new entry if not found. 339 TAG is one of CONSTANT_Utf8, CONSTANT_String or CONSTANT_Class. 340 NAME is an IDENTIFIER_NODE naming the Utf8 constant, string, or class. 341 Returns the index of the entry. */ 342 343 int 344 alloc_name_constant (tag, name) 345 int tag; 346 tree name; 347 { 348 return find_constant1 (outgoing_cpool, tag, (jword) name); 349 } 350 351 /* Build an identifier for the internal name of reference type TYPE. */ 352 353 tree 354 build_internal_class_name (type) 355 tree type; 356 { 357 tree name; 358 if (TYPE_ARRAY_P (type)) 359 name = build_java_signature (type); 360 else 361 { 362 name = TYPE_NAME (type); 363 if (TREE_CODE (name) != IDENTIFIER_NODE) 364 name = DECL_NAME (name); 365 name = identifier_subst (name, "", '.', '/', ""); 366 } 367 return name; 368 } 369 370 /* Look for a CONSTANT_Class entry for CLAS, creating a new one if needed. */ 371 372 int 373 alloc_class_constant (clas) 374 tree clas; 375 { 376 tree class_name = build_internal_class_name (clas); 377 378 return alloc_name_constant (CONSTANT_Class, 379 (unmangle_classname 380 (IDENTIFIER_POINTER(class_name), 381 IDENTIFIER_LENGTH(class_name)))); 382 } 383 384 /* Return a reference to the data array of the current constant pool. */ 385 386 static tree 387 build_constant_data_ref () 388 { 389 if (TYPE_CPOOL_DATA_REF (current_class)) 390 current_constant_pool_data_ref = TYPE_CPOOL_DATA_REF (current_class); 391 392 else if (current_constant_pool_data_ref == NULL_TREE) 393 { 394 tree decl; 395 tree decl_name = mangled_classname ("_CD_", current_class); 396 decl = build_decl (VAR_DECL, decl_name, 397 build_array_type (ptr_type_node, 398 one_elt_array_domain_type)); 399 TREE_STATIC (decl) = 1; 400 make_decl_rtl (decl, NULL); 401 TYPE_CPOOL_DATA_REF (current_class) = current_constant_pool_data_ref 402 = build1 (ADDR_EXPR, ptr_type_node, decl); 403 } 404 return current_constant_pool_data_ref; 405 } 406 407 /* Get the pointer value at the INDEX'th element of the constant pool. */ 408 409 tree 410 build_ref_from_constant_pool (index) 411 int index; 412 { 413 tree t = build_constant_data_ref (); 414 index *= int_size_in_bytes (ptr_type_node); 415 t = fold (build (PLUS_EXPR, ptr_type_node, 416 t, build_int_2 (index, 0))); 417 return build1 (INDIRECT_REF, ptr_type_node, t); 418 } 419 420 /* Build an initializer for the constants field of the current constal pool. 421 Should only be called at top-level, since it may emit declarations. */ 422 423 tree 424 build_constants_constructor () 425 { 426 tree tags_value, data_value; 427 tree cons; 428 tree tags_list = NULL_TREE; 429 tree data_list = NULL_TREE; 430 int i; 431 for (i = outgoing_cpool->count; --i > 0; ) 432 { 433 tags_list 434 = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]), 435 tags_list); 436 data_list 437 = tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]), 438 data_list); 439 } 440 if (outgoing_cpool->count > 0) 441 { 442 tree index_type; 443 tree data_decl, tags_decl, tags_type; 444 tree max_index = build_int_2 (outgoing_cpool->count - 1, 0); 445 TREE_TYPE (max_index) = sizetype; 446 index_type = build_index_type (max_index); 447 448 /* Add dummy 0'th element of constant pool. */ 449 tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list); 450 data_list = tree_cons (NULL_TREE, null_pointer_node, data_list); 451 452 data_decl = TREE_OPERAND (build_constant_data_ref (), 0); 453 TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type), 454 DECL_INITIAL (data_decl) = build (CONSTRUCTOR, TREE_TYPE (data_decl), 455 NULL_TREE, data_list); 456 DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl)); 457 DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl)); 458 rest_of_decl_compilation (data_decl, (char *) 0, 1, 0); 459 data_value = build_address_of (data_decl); 460 461 tags_type = build_array_type (unsigned_byte_type_node, index_type); 462 tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_", 463 current_class), 464 tags_type); 465 TREE_STATIC (tags_decl) = 1; 466 DECL_INITIAL (tags_decl) = build (CONSTRUCTOR, tags_type, 467 NULL_TREE, tags_list); 468 rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0); 469 tags_value = build_address_of (tags_decl); 470 } 471 else 472 { 473 data_value = null_pointer_node; 474 tags_value = null_pointer_node; 475 } 476 START_RECORD_CONSTRUCTOR (cons, constants_type_node); 477 PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0)); 478 PUSH_FIELD_VALUE (cons, "tags", tags_value); 479 PUSH_FIELD_VALUE (cons, "data", data_value); 480 FINISH_RECORD_CONSTRUCTOR (cons); 481 return cons; 482 } 483 484 #include "gt-java-constants.h" 485