int is_array_type_p (tree type) { return TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE && TYPE_ARRAY_P (TREE_TYPE (type)); }
static void mangle_type (tree type) { switch (TREE_CODE (type)) { char code; case BOOLEAN_TYPE: code = 'b'; goto primitive; case VOID_TYPE: code = 'v'; goto primitive; case INTEGER_TYPE: if (type == char_type_node || type == promoted_char_type_node) { code = 'w'; goto primitive; } /* Get the original type instead of the arguments promoted type. Avoid symbol name clashes. Should call a function to do that. FIXME. */ if (type == promoted_short_type_node) type = short_type_node; if (type == promoted_byte_type_node) type = byte_type_node; switch (TYPE_PRECISION (type)) { case 8: code = 'c'; goto primitive; case 16: code = 's'; goto primitive; case 32: code = 'i'; goto primitive; case 64: code = 'x'; goto primitive; default: goto bad_type; } primitive: obstack_1grow (mangle_obstack, code); break; case REAL_TYPE: switch (TYPE_PRECISION (type)) { case 32: code = 'f'; goto primitive; case 64: code = 'd'; goto primitive; default: goto bad_type; } case POINTER_TYPE: if (TYPE_ARRAY_P (TREE_TYPE (type))) mangle_array_type (type); else mangle_pointer_type (type); break; bad_type: default: gcc_unreachable (); } }
tree build_java_signature (tree type) { tree sig, t; while (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); sig = TYPE_SIGNATURE (type); if (sig == NULL_TREE) { char sg[2]; switch (TREE_CODE (type)) { case BOOLEAN_TYPE: sg[0] = 'Z'; goto native; case VOID_TYPE: sg[0] = 'V'; goto native; case INTEGER_TYPE: if (type == char_type_node || type == promoted_char_type_node) { sg[0] = 'C'; goto native; } switch (TYPE_PRECISION (type)) { case 8: sg[0] = 'B'; goto native; case 16: sg[0] = 'S'; goto native; case 32: sg[0] = 'I'; goto native; case 64: sg[0] = 'J'; goto native; default: goto bad_type; } case REAL_TYPE: switch (TYPE_PRECISION (type)) { case 32: sg[0] = 'F'; goto native; case 64: sg[0] = 'D'; goto native; default: goto bad_type; } native: sg[1] = 0; sig = get_identifier (sg); break; case RECORD_TYPE: if (TYPE_ARRAY_P (type)) { t = build_java_signature (TYPE_ARRAY_ELEMENT (type)); sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), "[", 0, 0, ""); } else { t = DECL_NAME (TYPE_NAME (type)); sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), "L", '.', '/', ";"); } break; case METHOD_TYPE: case FUNCTION_TYPE: { extern struct obstack temporary_obstack; sig = build_java_argument_signature (type); obstack_1grow (&temporary_obstack, '('); obstack_grow (&temporary_obstack, IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig)); obstack_1grow (&temporary_obstack, ')'); t = build_java_signature (TREE_TYPE (type)); obstack_grow0 (&temporary_obstack, IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); sig = get_identifier ((char *) obstack_base (&temporary_obstack)); obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); } break; bad_type: default: gcc_unreachable (); } TYPE_SIGNATURE (type) = sig; } return sig; }
tree build_java_array_type (tree element_type, HOST_WIDE_INT length) { tree sig, t, fld, atype, arfld; char buf[23]; tree elsig = build_java_signature (element_type); tree el_name = element_type; buf[0] = '['; if (length >= 0) sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length); else buf[1] = '\0'; sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig), buf, 0, 0, ""); t = IDENTIFIER_SIGNATURE_TYPE (sig); if (t != NULL_TREE) return TREE_TYPE (t); t = make_class (); IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t); TYPE_ARRAY_P (t) = 1; if (TREE_CODE (el_name) == POINTER_TYPE) el_name = TREE_TYPE (el_name); el_name = TYPE_NAME (el_name); if (TREE_CODE (el_name) == TYPE_DECL) el_name = DECL_NAME (el_name); { char suffix[23]; if (length >= 0) sprintf (suffix, "[%d]", (int)length); else strcpy (suffix, "[]"); TYPE_NAME (t) = TYPE_STUB_DECL (t) = build_decl (input_location, TYPE_DECL, identifier_subst (el_name, "", '.', '.', suffix), t); TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (t)) = true; } set_java_signature (t, sig); set_super_info (0, t, object_type_node, 0); if (TREE_CODE (element_type) == RECORD_TYPE) element_type = promote_type (element_type); TYPE_ARRAY_ELEMENT (t) = element_type; /* Add length pseudo-field. */ fld = build_decl (input_location, FIELD_DECL, get_identifier ("length"), int_type_node); TYPE_FIELDS (t) = fld; DECL_CONTEXT (fld) = t; FIELD_PUBLIC (fld) = 1; FIELD_FINAL (fld) = 1; TREE_READONLY (fld) = 1; atype = build_prim_array_type (element_type, length); arfld = build_decl (input_location, FIELD_DECL, get_identifier ("data"), atype); DECL_CONTEXT (arfld) = t; DECL_CHAIN (fld) = arfld; DECL_ALIGN (arfld) = TYPE_ALIGN (element_type); /* We could layout_class, but that loads java.lang.Object prematurely. * This is called by the parser, and it is a bad idea to do load_class * in the middle of parsing, because of possible circularity problems. */ push_super_field (t, object_type_node); layout_type (t); return t; }
bool vfy_is_array (vfy_jclass klass) { return TYPE_ARRAY_P (klass); }
static tree merge_types (tree type1, tree type2) { if (type1 == type2) return type1; if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN || type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR) return TYPE_UNKNOWN; if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE) { int depth1, depth2; tree tt1, tt2; /* ptr_type_node is only used for a null reference, which is compatible with any reference type. */ if (type1 == ptr_type_node || type2 == object_ptr_type_node) return type2; if (type2 == ptr_type_node || type1 == object_ptr_type_node) return type1; tt1 = TREE_TYPE (type1); tt2 = TREE_TYPE (type2); /* If tt{1,2} haven't been properly loaded, now is a good time to do it. */ if (!TYPE_SIZE (tt1)) { load_class (tt1, 1); safe_layout_class (tt1); } if (!TYPE_SIZE (tt2)) { load_class (tt2, 1); safe_layout_class (tt2); } if (TYPE_ARRAY_P (tt1) || TYPE_ARRAY_P (tt2)) { if (TYPE_ARRAY_P (tt1) == TYPE_ARRAY_P (tt2)) { tree el_type1 = TYPE_ARRAY_ELEMENT (tt1); tree el_type2 = TYPE_ARRAY_ELEMENT (tt2); tree el_type = NULL_TREE; if (el_type1 == el_type2) el_type = el_type1; else if (TREE_CODE (el_type1) == POINTER_TYPE && TREE_CODE (el_type2) == POINTER_TYPE) el_type = merge_types (el_type1, el_type2); if (el_type != NULL_TREE) { HOST_WIDE_INT len1 = java_array_type_length (tt1); HOST_WIDE_INT len2 = java_array_type_length (tt2); if (len1 != len2) len1 = -1; else if (el_type1 == el_type2) return type1; return promote_type (build_java_array_type (el_type, len1)); } } return object_ptr_type_node; } if (CLASS_INTERFACE (TYPE_NAME (tt1))) { /* FIXME: should see if two interfaces have a common superinterface. */ if (CLASS_INTERFACE (TYPE_NAME (tt2))) { /* This is a kludge, but matches what Sun's verifier does. It can be tricked, but is safe as long as type errors (i.e. interface method calls) are caught at run-time. */ return object_ptr_type_node; } else { if (can_widen_reference_to (tt2, tt1)) return type1; else return object_ptr_type_node; } } else if (CLASS_INTERFACE (TYPE_NAME (tt2))) { if (can_widen_reference_to (tt1, tt2)) return type2; else return object_ptr_type_node; } type1 = tt1; type2 = tt2; depth1 = class_depth (type1); depth2 = class_depth (type2); for ( ; depth1 > depth2; depth1--) type1 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type1), 0)); for ( ; depth2 > depth1; depth2--) type2 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type2), 0)); while (type1 != type2) { type1 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type1), 0)); type2 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type2), 0)); } return promote_type (type1); } if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2) && TYPE_PRECISION (type1) <= 32 && TYPE_PRECISION (type2) <= 32) return int_type_node; return TYPE_UNKNOWN; }