diff options
Diffstat (limited to 'gcc/java/jcf-write.c')
-rw-r--r-- | gcc/java/jcf-write.c | 170 |
1 files changed, 155 insertions, 15 deletions
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index 0745d59..4eccf25 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -35,6 +35,10 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "buffer.h" #include "toplev.h" +#ifndef DIR_SEPARATOR +#define DIR_SEPARATOR '/' +#endif + extern struct obstack temporary_obstack; /* Base directory in which `.class' files should be written. @@ -335,6 +339,9 @@ static void emit_goto PARAMS ((struct jcf_block *, struct jcf_partial *)); static void emit_jsr PARAMS ((struct jcf_block *, struct jcf_partial *)); static void call_cleanups PARAMS ((struct jcf_block *, struct jcf_partial *)); static char *make_class_file_name PARAMS ((tree)); +static unsigned char *append_synthetic_attribute PARAMS ((struct jcf_partial *)); +static void append_innerclasses_attribute PARAMS ((struct jcf_partial *, tree)); +static void append_innerclasses_attribute_entry PARAMS ((struct jcf_partial *, tree, tree)); /* Utility macros for appending (big-endian) data to a buffer. We assume a local variable 'ptr' points into where we want to @@ -665,6 +672,11 @@ get_access_flags (decl) flags |= ACC_ABSTRACT; if (CLASS_INTERFACE (decl)) flags |= ACC_INTERFACE; + if (CLASS_STATIC (decl)) + flags |= ACC_STATIC; + if (ANONYMOUS_CLASS_P (TREE_TYPE (decl)) + || LOCAL_CLASS_P (TREE_TYPE (decl))) + flags |= ACC_PRIVATE; } else fatal ("internal error - bad argument to get_access_flags"); @@ -1159,8 +1171,7 @@ generate_bytecode_conditional (exp, true_label, false_label, } break; case TRUTH_NOT_EXPR: - generate_bytecode_conditional (TREE_OPERAND (exp, 0), - false_label, true_label, + generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label, true_label, ! true_branch_first, state); break; case TRUTH_ANDIF_EXPR: @@ -1238,7 +1249,7 @@ generate_bytecode_conditional (exp, true_label, false_label, } if (integer_zerop (exp1) || integer_zerop (exp0)) { - generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp1, + generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp0, STACK_TARGET, state); op = op + (OPCODE_ifnull - OPCODE_if_acmpeq); negop = (op & 1) ? op - 1 : op + 1; @@ -1622,7 +1633,6 @@ generate_bytecode_insns (exp, target, state) define_jcf_label (else_label, state); generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state); define_jcf_label (end_label, state); - /* COND_EXPR can be used in a binop. The stack must be adjusted. */ if (TREE_TYPE (exp) != void_type_node) NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1); @@ -2131,6 +2141,9 @@ generate_bytecode_insns (exp, target, state) OP2 (index); } break; + case SAVE_EXPR: + generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state); + break; case CONVERT_EXPR: case NOP_EXPR: case FLOAT_EXPR: @@ -2535,11 +2548,6 @@ generate_bytecode_insns (exp, target, state) else OP1 (OPCODE_invokevirtual); OP2 (index); - if (interface) - { - OP1 (nargs); - OP1 (0); - } f = TREE_TYPE (TREE_TYPE (f)); if (TREE_CODE (f) != VOID_TYPE) { @@ -2549,6 +2557,11 @@ generate_bytecode_insns (exp, target, state) else NOTE_PUSH (size); } + if (interface) + { + OP1 (nargs); + OP1 (0); + } break; } } @@ -2836,16 +2849,24 @@ generate_classfile (clas, state) for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part)) { - int have_value; + int have_value, attr_count = 0; if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part)) continue; ptr = append_chunk (NULL, 8, state); i = get_access_flags (part); PUT2 (i); i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i); - i = find_utf8_constant (&state->cpool, build_java_signature (TREE_TYPE (part))); + i = find_utf8_constant (&state->cpool, + build_java_signature (TREE_TYPE (part))); PUT2(i); - have_value = DECL_INITIAL (part) != NULL_TREE && FIELD_STATIC (part); - PUT2 (have_value); /* attributes_count */ + have_value = DECL_INITIAL (part) != NULL_TREE && FIELD_STATIC (part) + && TREE_CODE (TREE_TYPE (part)) != POINTER_TYPE; + if (have_value) + attr_count++; + + if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)) + attr_count++; + + PUT2 (attr_count); /* attributes_count */ if (have_value) { tree init = DECL_INITIAL (part); @@ -2858,6 +2879,9 @@ generate_classfile (clas, state) PUT4 (2); /* attribute_length */ i = find_constant_index (init, state); PUT2 (i); } + /* Emit the "Synthetic" attribute for val$<x> and this$<n> fields. */ + if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)) + ptr = append_synthetic_attribute (state); fields_count++; } ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count); @@ -2875,6 +2899,7 @@ generate_classfile (clas, state) : DECL_NAME (part); tree type = TREE_TYPE (part); tree save_function = current_function_decl; + int synthetic_p = 0; current_function_decl = part; ptr = append_chunk (NULL, 8, state); i = get_access_flags (part); PUT2 (i); @@ -2882,7 +2907,20 @@ generate_classfile (clas, state) i = find_utf8_constant (&state->cpool, build_java_signature (type)); PUT2 (i); i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE); + + /* Make room for the Synthetic attribute (of zero length.) */ + if (DECL_FINIT_P (part) + || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))) + { + i++; + synthetic_p = 1; + } + PUT2 (i); /* attributes_count */ + + if (synthetic_p) + ptr = append_synthetic_attribute (state); + if (body != NULL_TREE) { int code_attributes_count = 0; @@ -2956,7 +2994,8 @@ generate_classfile (clas, state) if (state->linenumber_count > 0) { static tree LineNumberTable_node = NULL_TREE; - ptr = append_chunk (NULL, 8 + 4 * state->linenumber_count, state); + ptr = append_chunk (NULL, + 8 + 4 * state->linenumber_count, state); if (LineNumberTable_node == NULL_TREE) LineNumberTable_node = get_identifier ("LineNumberTable"); i = find_utf8_constant (&state->cpool, LineNumberTable_node); @@ -3031,7 +3070,10 @@ generate_classfile (clas, state) source_file = ptr+1; } ptr = append_chunk (NULL, 10, state); - PUT2 (1); /* attributes_count */ + + i = ((INNER_CLASS_TYPE_P (clas) + || DECL_INNER_CLASS_LIST (TYPE_NAME (clas))) ? 2 : 1); + PUT2 (i); /* attributes_count */ /* generate the SourceFile attribute. */ if (SourceFile_node == NULL_TREE) @@ -3041,6 +3083,7 @@ generate_classfile (clas, state) PUT4 (2); i = find_utf8_constant (&state->cpool, get_identifier (source_file)); PUT2 (i); + append_innerclasses_attribute (state, clas); /* New finally generate the contents of the constant pool chunk. */ i = count_constant_pool_bytes (&state->cpool); @@ -3051,6 +3094,103 @@ generate_classfile (clas, state) return state->first; } +static unsigned char * +append_synthetic_attribute (state) + struct jcf_partial *state; +{ + static tree Synthetic_node = NULL_TREE; + unsigned char *ptr = append_chunk (NULL, 6, state); + int i; + + if (Synthetic_node == NULL_TREE) + Synthetic_node = get_identifier ("Synthetic"); + i = find_utf8_constant (&state->cpool, Synthetic_node); + PUT2 (i); /* Attribute string index */ + PUT4 (0); /* Attribute length */ + + return ptr; +} + +static void +append_innerclasses_attribute (state, class) + struct jcf_partial *state; + tree class; +{ + static tree InnerClasses_node = NULL_TREE; + tree orig_decl = TYPE_NAME (class); + tree current, decl; + int length = 0, i; + unsigned char *ptr, *length_marker, *number_marker; + + if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl)) + return; + + ptr = append_chunk (NULL, 8, state); /* 2+4+2 */ + + if (InnerClasses_node == NULL_TREE) + InnerClasses_node = get_identifier ("InnerClasses"); + i = find_utf8_constant (&state->cpool, InnerClasses_node); + PUT2 (i); + length_marker = ptr; PUT4 (0); /* length, to be later patched */ + number_marker = ptr; PUT2 (0); /* number of classes, tblp */ + + /* Generate the entries: all inner classes visible from the one we + process: itself, up and down. */ + while (class && INNER_CLASS_TYPE_P (class)) + { + char *n; + + decl = TYPE_NAME (class); + n = IDENTIFIER_POINTER (DECL_NAME (decl)) + + IDENTIFIER_LENGTH (DECL_NAME (decl)); + + while (n[-1] != '$') + n--; + append_innerclasses_attribute_entry (state, decl, get_identifier (n)); + length++; + + class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class))); + } + + decl = orig_decl; + for (current = DECL_INNER_CLASS_LIST (decl); + current; current = TREE_CHAIN (current)) + { + append_innerclasses_attribute_entry (state, TREE_PURPOSE (current), + TREE_VALUE (current)); + length++; + } + + ptr = length_marker; PUT4 (8*length+2); + ptr = number_marker; PUT2 (length); +} + +static void +append_innerclasses_attribute_entry (state, decl, name) + struct jcf_partial *state; + tree decl, name; +{ + static tree anonymous_name = NULL_TREE; + int icii, ocii, ini, icaf; + unsigned char *ptr = append_chunk (NULL, 8, state); + + if (!anonymous_name) + anonymous_name = get_identifier (""); + + icii = find_class_constant (&state->cpool, TREE_TYPE (decl)); + ocii = find_class_constant (&state->cpool, TREE_TYPE (DECL_CONTEXT (decl))); + + /* The specs are saying that if the class is anonymous, + inner_name_index must be zero. But the implementation makes it + point to an empty string. */ + ini = find_utf8_constant (&state->cpool, + (ANONYMOUS_CLASS_P (TREE_TYPE (decl)) ? + anonymous_name : name)); + icaf = get_access_flags (decl); + + PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf); +} + static char * make_class_file_name (clas) tree clas; |