00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "jcf.h"
00027 #include "tree.h"
00028 #include "java-tree.h"
00029 #include "toplev.h"
00030 #include "ggc.h"
00031
00032 extern struct obstack permanent_obstack;
00033
00034 static void set_constant_entry PARAMS ((CPool *, int, int, jword));
00035 static int find_class_or_string_constant PARAMS ((CPool *, int, tree));
00036 static int find_name_and_type_constant PARAMS ((CPool *, tree, tree));
00037 static tree get_tag_node PARAMS ((int));
00038 static tree build_constant_data_ref PARAMS ((void));
00039
00040
00041
00042 static void
00043 set_constant_entry (cpool, index, tag, value)
00044 CPool *cpool;
00045 int index;
00046 int tag;
00047 jword value;
00048 {
00049 if (cpool->data == NULL)
00050 {
00051 cpool->capacity = 100;
00052 cpool->tags = (uint8*) xmalloc (sizeof(uint8) * cpool->capacity);
00053 cpool->data = (jword*) xmalloc (sizeof(jword) * cpool->capacity);
00054 cpool->count = 1;
00055 }
00056 if (index >= cpool->capacity)
00057 {
00058 cpool->capacity *= 2;
00059 if (index >= cpool->capacity)
00060 cpool->capacity = index + 10;
00061 cpool->tags = (uint8*) xrealloc (cpool->tags,
00062 sizeof(uint8) * cpool->capacity);
00063 cpool->data = (jword*) xrealloc (cpool->data,
00064 sizeof(jword) * cpool->capacity);
00065 }
00066 if (index >= cpool->count)
00067 cpool->count = index + 1;
00068 cpool->tags[index] = tag;
00069 cpool->data[index] = value;
00070 }
00071
00072
00073
00074 int
00075 find_constant1 (cpool, tag, value)
00076 CPool *cpool;
00077 int tag;
00078 jword value;
00079 {
00080 int i;
00081 for (i = cpool->count; --i > 0; )
00082 {
00083 if (cpool->tags[i] == tag && cpool->data[i] == value)
00084 return i;
00085 }
00086 i = cpool->count == 0 ? 1 : cpool->count;
00087 set_constant_entry (cpool, i, tag, value);
00088 return i;
00089 }
00090
00091
00092
00093 int
00094 find_constant2 (cpool, tag, word1, word2)
00095 CPool *cpool;
00096 int tag;
00097 jword word1, word2;
00098 {
00099 int i;
00100 for (i = cpool->count - 1; --i > 0; )
00101 {
00102 if (cpool->tags[i] == tag
00103 && cpool->data[i] == word1
00104 && cpool->data[i+1] == word2)
00105 return i;
00106 }
00107 i = cpool->count == 0 ? 1 : cpool->count;
00108 set_constant_entry (cpool, i, tag, word1);
00109 set_constant_entry (cpool, i+1, 0, word2);
00110 return i;
00111 }
00112
00113 int
00114 find_utf8_constant (cpool, name)
00115 CPool *cpool;
00116 tree name;
00117 {
00118 if (name == NULL_TREE)
00119 return 0;
00120 return find_constant1 (cpool, CONSTANT_Utf8, (jword) name);
00121 }
00122
00123 static int
00124 find_class_or_string_constant (cpool, tag, name)
00125 CPool *cpool;
00126 int tag;
00127 tree name;
00128 {
00129 int j = find_utf8_constant (cpool, name);
00130 int i;
00131 for (i = cpool->count; --i > 0; )
00132 {
00133 if (cpool->tags[i] == tag && cpool->data[i] == (jword) j)
00134 return i;
00135 }
00136 i = cpool->count;
00137 set_constant_entry (cpool, i, tag, (jword) j);
00138 return i;
00139 }
00140
00141 int
00142 find_class_constant (cpool, type)
00143 CPool *cpool;
00144 tree type;
00145 {
00146 return find_class_or_string_constant (cpool, CONSTANT_Class,
00147 build_internal_class_name (type));
00148 }
00149
00150
00151
00152 int
00153 find_string_constant (cpool, string)
00154 CPool *cpool;
00155 tree string;
00156 {
00157 string = get_identifier (TREE_STRING_POINTER (string));
00158 return find_class_or_string_constant (cpool, CONSTANT_String, string);
00159
00160 }
00161
00162
00163
00164
00165 static int
00166 find_name_and_type_constant (cpool, name, type)
00167 CPool *cpool;
00168 tree name;
00169 tree type;
00170 {
00171 int name_index = find_utf8_constant (cpool, name);
00172 int type_index = find_utf8_constant (cpool, build_java_signature (type));
00173 return find_constant1 (cpool, CONSTANT_NameAndType,
00174 (name_index << 16) | type_index);
00175 }
00176
00177
00178
00179
00180 int
00181 find_fieldref_index (cpool, decl)
00182 CPool *cpool;
00183 tree decl;
00184 {
00185 int class_index = find_class_constant (cpool, DECL_CONTEXT (decl));
00186 int name_type_index
00187 = find_name_and_type_constant (cpool, DECL_NAME (decl), TREE_TYPE (decl));
00188 return find_constant1 (cpool, CONSTANT_Fieldref,
00189 (class_index << 16) | name_type_index);
00190 }
00191
00192
00193
00194
00195 int
00196 find_methodref_index (cpool, decl)
00197 CPool *cpool;
00198 tree decl;
00199 {
00200 return find_methodref_with_class_index (cpool, decl, DECL_CONTEXT (decl));
00201 }
00202
00203 int
00204 find_methodref_with_class_index (cpool, decl, mclass)
00205 CPool *cpool;
00206 tree decl;
00207 tree mclass;
00208 {
00209 int class_index = find_class_constant (cpool, mclass);
00210 tree name = DECL_CONSTRUCTOR_P (decl) ? init_identifier_node
00211 : DECL_NAME (decl);
00212 int name_type_index;
00213 name_type_index =
00214 find_name_and_type_constant (cpool, name, TREE_TYPE (decl));
00215 return find_constant1 (cpool,
00216 CLASS_INTERFACE (TYPE_NAME (mclass))
00217 ? CONSTANT_InterfaceMethodref
00218 : CONSTANT_Methodref,
00219 (class_index << 16) | name_type_index);
00220 }
00221
00222 #define PUT1(X) (*ptr++ = (X))
00223 #define PUT2(X) (PUT1((X) >> 8), PUT1(X))
00224 #define PUT4(X) (PUT2((X) >> 16), PUT2(X))
00225 #define PUTN(P, N) (memcpy(ptr, (P), (N)), ptr += (N))
00226
00227
00228
00229
00230 int
00231 count_constant_pool_bytes (cpool)
00232 CPool *cpool;
00233 {
00234 int size = 2;
00235 int i = 1;
00236 for ( ; i < cpool->count; i++)
00237 {
00238 size++;
00239 switch (cpool->tags[i])
00240 {
00241 case CONSTANT_NameAndType:
00242 case CONSTANT_Fieldref:
00243 case CONSTANT_Methodref:
00244 case CONSTANT_InterfaceMethodref:
00245 case CONSTANT_Float:
00246 case CONSTANT_Integer:
00247 size += 4;
00248 break;
00249 case CONSTANT_Class:
00250 case CONSTANT_String:
00251 size += 2;
00252 break;
00253 case CONSTANT_Long:
00254 case CONSTANT_Double:
00255 size += 8;
00256 i++;
00257 break;
00258 case CONSTANT_Utf8:
00259 {
00260 tree t = (tree) cpool->data[i];
00261 int len = IDENTIFIER_LENGTH (t);
00262 size += len + 2;
00263 }
00264 break;
00265 default:
00266
00267 size--;
00268 }
00269 }
00270 return size;
00271 }
00272
00273
00274
00275
00276 void
00277 write_constant_pool (cpool, buffer, length)
00278 CPool *cpool;
00279 unsigned char *buffer;
00280 int length;
00281 {
00282 unsigned char *ptr = buffer;
00283 int i = 1;
00284 jword *datap = &cpool->data[1];
00285 PUT2 (cpool->count);
00286 for ( ; i < cpool->count; i++, datap++)
00287 {
00288 int tag = cpool->tags[i];
00289 PUT1 (tag);
00290 switch (tag)
00291 {
00292 case CONSTANT_NameAndType:
00293 case CONSTANT_Fieldref:
00294 case CONSTANT_Methodref:
00295 case CONSTANT_InterfaceMethodref:
00296 case CONSTANT_Float:
00297 case CONSTANT_Integer:
00298 PUT4 (*datap);
00299 break;
00300 case CONSTANT_Class:
00301 case CONSTANT_String:
00302 PUT2 (*datap);
00303 break;
00304 break;
00305 case CONSTANT_Long:
00306 case CONSTANT_Double:
00307 PUT4(*datap);
00308 i++;
00309 datap++;
00310 PUT4 (*datap);
00311 break;
00312 case CONSTANT_Utf8:
00313 {
00314 tree t = (tree) *datap;
00315 int len = IDENTIFIER_LENGTH (t);
00316 PUT2 (len);
00317 PUTN (IDENTIFIER_POINTER (t), len);
00318 }
00319 break;
00320 }
00321 }
00322
00323 if (ptr != buffer + length)
00324 abort ();
00325 }
00326
00327 CPool *outgoing_cpool;
00328
00329 static tree
00330 get_tag_node (tag)
00331 int tag;
00332 {
00333
00334 static tree tag_nodes[13];
00335 static int initialized_p;
00336
00337
00338 if (!initialized_p)
00339 {
00340 ggc_add_tree_root (tag_nodes, 13);
00341 initialized_p = 1;
00342 }
00343
00344 if (tag_nodes[tag] == NULL_TREE)
00345 tag_nodes[tag] = build_int_2 (tag, 0);
00346 return tag_nodes[tag];
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 int
00356 alloc_name_constant (tag, name)
00357 int tag;
00358 tree name;
00359 {
00360 return find_constant1 (outgoing_cpool, tag, (jword) name);
00361 }
00362
00363
00364
00365 tree
00366 build_internal_class_name (type)
00367 tree type;
00368 {
00369 tree name;
00370 if (TYPE_ARRAY_P (type))
00371 name = build_java_signature (type);
00372 else
00373 {
00374 name = TYPE_NAME (type);
00375 if (TREE_CODE (name) != IDENTIFIER_NODE)
00376 name = DECL_NAME (name);
00377 name = identifier_subst (name, "", '.', '/', "");
00378 }
00379 return name;
00380 }
00381
00382
00383
00384 int
00385 alloc_class_constant (clas)
00386 tree clas;
00387 {
00388 tree class_name = build_internal_class_name (clas);
00389
00390 return alloc_name_constant (CONSTANT_Class,
00391 (unmangle_classname
00392 (IDENTIFIER_POINTER(class_name),
00393 IDENTIFIER_LENGTH(class_name))));
00394 }
00395
00396
00397
00398 static tree
00399 build_constant_data_ref ()
00400 {
00401 if (TYPE_CPOOL_DATA_REF (current_class))
00402 current_constant_pool_data_ref = TYPE_CPOOL_DATA_REF (current_class);
00403
00404 else if (current_constant_pool_data_ref == NULL_TREE)
00405 {
00406 tree decl;
00407 tree decl_name = mangled_classname ("_CD_", current_class);
00408 decl = build_decl (VAR_DECL, decl_name,
00409 build_array_type (ptr_type_node,
00410 one_elt_array_domain_type));
00411 TREE_STATIC (decl) = 1;
00412 make_decl_rtl (decl, NULL);
00413 TYPE_CPOOL_DATA_REF (current_class) = current_constant_pool_data_ref
00414 = build1 (ADDR_EXPR, ptr_type_node, decl);
00415 }
00416 return current_constant_pool_data_ref;
00417 }
00418
00419
00420
00421 tree
00422 build_ref_from_constant_pool (index)
00423 int index;
00424 {
00425 tree t = build_constant_data_ref ();
00426 index *= int_size_in_bytes (ptr_type_node);
00427 t = fold (build (PLUS_EXPR, ptr_type_node,
00428 t, build_int_2 (index, 0)));
00429 return build1 (INDIRECT_REF, ptr_type_node, t);
00430 }
00431
00432
00433
00434
00435 tree
00436 build_constants_constructor ()
00437 {
00438 tree tags_value, data_value;
00439 tree cons;
00440 tree tags_list = NULL_TREE;
00441 tree data_list = NULL_TREE;
00442 int i;
00443 for (i = outgoing_cpool->count; --i > 0; )
00444 {
00445 tags_list
00446 = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
00447 tags_list);
00448 data_list
00449 = tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]),
00450 data_list);
00451 }
00452 if (outgoing_cpool->count > 0)
00453 {
00454 tree index_type;
00455 tree data_decl, tags_decl, tags_type;
00456 tree max_index = build_int_2 (outgoing_cpool->count - 1, 0);
00457 TREE_TYPE (max_index) = sizetype;
00458 index_type = build_index_type (max_index);
00459
00460
00461 tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list);
00462 data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
00463
00464 data_decl = TREE_OPERAND (build_constant_data_ref (), 0);
00465 TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type),
00466 DECL_INITIAL (data_decl) = build (CONSTRUCTOR, TREE_TYPE (data_decl),
00467 NULL_TREE, data_list);
00468 DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
00469 DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
00470 rest_of_decl_compilation (data_decl, (char *) 0, 1, 0);
00471 data_value = build_address_of (data_decl);
00472
00473 tags_type = build_array_type (unsigned_byte_type_node, index_type);
00474 tags_decl = build_decl (VAR_DECL, mangled_classname ("_CT_",
00475 current_class),
00476 tags_type);
00477 TREE_STATIC (tags_decl) = 1;
00478 DECL_INITIAL (tags_decl) = build (CONSTRUCTOR, tags_type,
00479 NULL_TREE, tags_list);
00480 rest_of_decl_compilation (tags_decl, (char*) 0, 1, 0);
00481 tags_value = build_address_of (tags_decl);
00482 }
00483 else
00484 {
00485 data_value = null_pointer_node;
00486 tags_value = null_pointer_node;
00487 }
00488 START_RECORD_CONSTRUCTOR (cons, constants_type_node);
00489 PUSH_FIELD_VALUE (cons, "size", build_int_2 (outgoing_cpool->count, 0));
00490 PUSH_FIELD_VALUE (cons, "tags", tags_value);
00491 PUSH_FIELD_VALUE (cons, "data", data_value);
00492 FINISH_RECORD_CONSTRUCTOR (cons);
00493 return cons;
00494 }