summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-11 10:47:43 +0000
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-11 10:47:43 +0000
commit39101666a2b9ca7c4c35cada9be85a4ebe12e0b4 (patch)
tree22431b761201f7586d181a8501e813148ae881b4
parent669b0b523ebfe2537057b3111917d6c776df9a43 (diff)
downloadgcc-39101666a2b9ca7c4c35cada9be85a4ebe12e0b4.tar.gz
2012-04-11 Andrew Haley <aph@redhat.com>
* jcf.h (bootstrap_method): New. (BootstrapMethods): New. (JCF): Add BootstrapMethods. (enum cpool_tag): Add MethodHandle, MethodType, and InvokeDynamic. * jcf-reader.c (jcf_parse_bootstrap_methods): New. (jcf_parse_constant_pool): Handlers for MethodHandle, MethodType, and InvokeDynamic. (jcf_parse_bootstrap_methods): New. * javaop.def (invokedynamic): New opcode. * jcf-parse.c (get_constant): An unknown constant type should not be an internal error, but a fatal one. Make it so. * jcf-dump.c (HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE): New. (HANDLE_END_BOOTSTRAP_METHODS): New. (print_constant): Handlers for MethodHandle, MethodType, and InvokeDynamic. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186307 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/java/ChangeLog18
-rw-r--r--gcc/java/javaop.def1
-rw-r--r--gcc/java/jcf-dump.c64
-rw-r--r--gcc/java/jcf-io.c20
-rw-r--r--gcc/java/jcf-parse.c4
-rw-r--r--gcc/java/jcf-reader.c57
-rw-r--r--gcc/java/jcf.h16
7 files changed, 178 insertions, 2 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 3e6cb4d9dc9..49db1cb7bfb 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,21 @@
+2012-04-11 Andrew Haley <aph@redhat.com>
+
+ * jcf.h (bootstrap_method): New.
+ (BootstrapMethods): New.
+ (JCF): Add BootstrapMethods.
+ (enum cpool_tag): Add MethodHandle, MethodType, and InvokeDynamic.
+ * jcf-reader.c (jcf_parse_bootstrap_methods): New.
+ (jcf_parse_constant_pool): Handlers for MethodHandle, MethodType,
+ and InvokeDynamic.
+ (jcf_parse_bootstrap_methods): New.
+ * javaop.def (invokedynamic): New opcode.
+ * jcf-parse.c (get_constant): An unknown constant type should not
+ be an internal error, but a fatal one. Make it so.
+ * jcf-dump.c (HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE): New.
+ (HANDLE_END_BOOTSTRAP_METHODS): New.
+ (print_constant): Handlers for MethodHandle, MethodType, and
+ InvokeDynamic.
+
2012-04-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* class.c (emit_register_classes_in_jcr_section): Set DECL_USER_ALIGN.
diff --git a/gcc/java/javaop.def b/gcc/java/javaop.def
index 653c77f72b8..6fe986d5d2d 100644
--- a/gcc/java/javaop.def
+++ b/gcc/java/javaop.def
@@ -292,6 +292,7 @@ JAVAOP (invokevirtual, 182, INVOKE, VIRTUAL,0)
JAVAOP (invokespecial, 183, INVOKE, SPECIAL, 0)
JAVAOP (invokestatic, 184, INVOKE, STATIC, 0)
JAVAOP (invokeinterface,185, INVOKE, INTERFACE, 1)
+JAVAOP (invokedynamic, 186, INVOKE, DYNAMIC, 1)
JAVAOP (new, 187, OBJECT, PTR, NEW)
JAVAOP (newarray, 188, ARRAY, NUM, NEW)
JAVAOP (anewarray, 189, ARRAY, PTR, NEW)
diff --git a/gcc/java/jcf-dump.c b/gcc/java/jcf-dump.c
index 0c5878cc579..9173ea473cc 100644
--- a/gcc/java/jcf-dump.c
+++ b/gcc/java/jcf-dump.c
@@ -430,6 +430,23 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
print_element_value (out, jcf, 1); \
}
+#define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \
+}
+
+#define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \
+ { \
+ int i; \
+ for (i = 0; i < NUM_METHODS; i++) \
+ { \
+ bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \
+ fprintf (out, " %d: ", i); \
+ print_constant (out, jcf, m->method_ref, 1); \
+ fprintf (out, "\n"); \
+ } \
+ }
#define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
{ COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
@@ -898,6 +915,53 @@ print_constant (FILE *out, JCF *jcf, int index, int verbosity)
fputc ('\"', out);
}
break;
+ case CONSTANT_MethodHandle:
+ {
+ int kind = JPOOL_USHORT1 (jcf, index);
+ if (verbosity > 0)
+ fprintf (out, "MethodHandle kind: %d=", kind);
+ switch(kind) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (verbosity > 0)
+ fprintf (out, "Fieldref: %ld=", JPOOL_USHORT2 (jcf, index));
+ print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ if (verbosity > 0)
+ fprintf (out, "Methodref: %ld=", JPOOL_USHORT2 (jcf, index));
+ print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
+ break;
+ case 9:
+ if (verbosity > 0)
+ fprintf (out, "InterfaceMethodref: %ld=", JPOOL_USHORT2 (jcf, index));
+ print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
+ break;
+ }
+ break;
+ }
+ case CONSTANT_MethodType:
+ if (verbosity > 0)
+ fprintf (out, "MethodType %ld: ", JPOOL_USHORT1 (jcf, index));
+ print_signature (out, jcf, JPOOL_USHORT1 (jcf, index), 0);
+ break;
+ case CONSTANT_InvokeDynamic:
+ {
+ uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
+ if (verbosity > 0)
+ fprintf (out, "InvokeDynamic: ");
+ fprintf (out, "bootstrap_method: %ld ", JPOOL_USHORT1 (jcf, index));
+ if (verbosity == 2)
+ fprintf (out, " name_and_type: %d=<", name_and_type);
+ print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
+ if (verbosity == 2)
+ fputc ('>', out);
+ break;
+ }
default:
fprintf (out, "(Unknown constant type %d)", kind);
}
diff --git a/gcc/java/jcf-io.c b/gcc/java/jcf-io.c
index 0dc761534c6..c50ec49ccc5 100644
--- a/gcc/java/jcf-io.c
+++ b/gcc/java/jcf-io.c
@@ -518,6 +518,26 @@ verify_constant_pool (JCF *jcf)
case CONSTANT_Utf8:
case CONSTANT_Unicode:
break;
+ case CONSTANT_MethodHandle:
+ n = JPOOL_USHORT1 (jcf, i);
+ if (n < 1 || n > 9)
+ return i;
+ n = JPOOL_USHORT2 (jcf, i);
+ if (n <= 0 || n >= JPOOL_SIZE(jcf))
+ return i;
+ break;
+ case CONSTANT_MethodType:
+ n = JPOOL_USHORT1 (jcf, i);
+ if (n <= 0 || n >= JPOOL_SIZE(jcf)
+ || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
+ return i;
+ break;
+ case CONSTANT_InvokeDynamic:
+ n = JPOOL_USHORT2 (jcf, i);
+ if (n <= 0 || n >= JPOOL_SIZE(jcf)
+ || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
+ return i;
+ break;
default:
return i;
}
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 04c04f575cf..c799676074e 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -1113,8 +1113,8 @@ get_constant (JCF *jcf, int index)
jcf->cpool.data[index].t = value;
return value;
bad:
- internal_error ("bad value constant type %d, index %d",
- JPOOL_TAG (jcf, index), index);
+ fatal_error ("bad value constant type %d, index %d",
+ JPOOL_TAG (jcf, index), index);
}
tree
diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
index 315bd411a52..c47436a5b0f 100644
--- a/gcc/java/jcf-reader.c
+++ b/gcc/java/jcf-reader.c
@@ -36,6 +36,7 @@ static int jcf_parse_fields (JCF *);
static int jcf_parse_one_method (JCF *, int);
static int jcf_parse_methods (JCF *);
static int jcf_parse_final_attributes (JCF *);
+static int jcf_parse_bootstrap_methods (JCF *, int );
#ifdef NEED_PEEK_ATTRIBUTE
static int peek_attribute (JCF *, int, const char *, int);
#endif
@@ -293,6 +294,15 @@ get_attribute (JCF *jcf, int index,
}
else
#endif
+ if (MATCH_ATTRIBUTE ("BootstrapMethods"))
+ {
+#ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE
+ HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE();
+#else
+ JCF_SKIP (jcf, attribute_length);
+#endif
+ }
+ else
{
#ifdef PROCESS_OTHER_ATTRIBUTE
PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length);
@@ -382,6 +392,17 @@ jcf_parse_constant_pool (JCF* jcf)
JCF_SKIP (jcf, n);
#endif
break;
+ case CONSTANT_MethodHandle:
+ jcf->cpool.data[i].w = JCF_readu (jcf);
+ jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
+ break;
+ case CONSTANT_MethodType:
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
+ break;
+ case CONSTANT_InvokeDynamic:
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
+ jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
+ break;
default:
return i;
}
@@ -521,3 +542,39 @@ jcf_parse_final_attributes (JCF *jcf)
return 0;
}
+/* Read and handle the "BootstrapMethods" attribute.
+
+ Return 0 if OK.
+*/
+static int
+jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED)
+{
+ int i;
+ uint16 num_methods = JCF_readu2 (jcf);
+ jcf->bootstrap_methods.count = num_methods;
+ jcf->bootstrap_methods.methods
+ = (bootstrap_method *) ggc_alloc_atomic (num_methods
+ * sizeof (bootstrap_method));
+#ifdef HANDLE_START_BOOTSTRAP_METHODS
+ HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods);
+#endif
+
+ for (i = 0; i < num_methods; i++)
+ {
+ unsigned j;
+ bootstrap_method *m = &jcf->bootstrap_methods.methods[i];
+ m->method_ref = JCF_readu2 (jcf);
+ m->num_arguments = JCF_readu2 (jcf);
+ m->bootstrap_arguments
+ = (unsigned *) ggc_alloc_atomic (m->num_arguments
+ * sizeof (unsigned));
+ for (j = 0; j < m->num_arguments; j++)
+ m->bootstrap_arguments[j] = JCF_readu2 (jcf);
+ }
+
+#ifdef HANDLE_END_BOOTSTRAP_METHODS
+ HANDLE_END_BOOTSTRAP_METHODS (num_methods);
+#endif
+
+ return 0;
+}
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index b066b2967c3..40b4ae2d278 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -88,6 +88,17 @@ typedef struct GTY(()) CPool {
desc ("cpool_entry_is_tree (%1.tags%a)"))) data;
} CPool;
+typedef struct GTY(()) bootstrap_method {
+ unsigned method_ref;
+ unsigned num_arguments;
+ unsigned* GTY((length ("%h.num_arguments"))) bootstrap_arguments;
+} bootstrap_method;
+
+typedef struct GTY(()) BootstrapMethods {
+ unsigned count;
+ bootstrap_method* GTY((length ("%h.count"))) methods;
+} BootstrapMethods;
+
struct ZipDirectory;
/* JCF encapsulates the state of reading a Java Class File. */
@@ -109,6 +120,7 @@ typedef struct GTY(()) JCF {
JCF_u2 this_class;
JCF_u2 super_class;
CPool cpool;
+ BootstrapMethods bootstrap_methods;
} JCF;
/*typedef JCF* JCF_FILE;*/
@@ -245,6 +257,10 @@ enum cpool_tag
CONSTANT_NameAndType = 12,
CONSTANT_Utf8 = 1,
CONSTANT_Unicode = 2,
+ CONSTANT_MethodHandle = 15,
+ CONSTANT_MethodType = 16,
+ CONSTANT_InvokeDynamic = 18,
+
CONSTANT_None = 0
};