1 /* headers.c - main for header generation (cacaoh)
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
32 $Id: headers.c 685 2003-12-04 01:25:54Z jowenn $
44 #include "toolbox/chain.h"
45 #include "toolbox/memory.h"
46 #include "toolbox/loging.h"
49 /******* replace some external functions *********/
51 functionptr native_findfunction (utf *cname, utf *mname, utf *desc, bool isstatic)
54 java_objectheader *javastring_new (utf *text) /* schani */
57 void throw_classnotfoundexception()
59 panic("class not found----------");
63 void throw_classnotfoundexception2(utf* classname)
65 sprintf (logtext, "Loading class: ");
66 utf_sprint (logtext+strlen(logtext), classname);
67 panic("******class not found");
70 /* this is here to avoid link errors. We are not interested in linkagerrors in cacaoh right now*/
71 void throw_linkageerror2(utf* classname)
75 java_objectheader *literalstring_new (utf *u)
78 void literalstring_free(java_objectheader *o) { }
79 void stringtable_update() { }
80 void synchronize_caches() { }
81 void asm_call_jit_compiler() { }
82 void asm_calljavamethod() { }
83 void asm_dumpregistersandcall() { }
84 s4 asm_builtin_checkcast(java_objectheader *obj, classinfo *class) { return 0; }
86 s4 asm_builtin_idiv(s4 a, s4 b) {return 0;}
87 s4 asm_builtin_irem(s4 a, s4 b) {return 0;}
88 s8 asm_builtin_ldiv(s8 a, s8 b) {return 0;}
89 s8 asm_builtin_lrem(s8 a, s8 b) {return 0;}
91 s4 asm_builtin_f2i(float a) { return 0; }
92 s8 asm_builtin_f2l(float a) { return 0; }
93 s4 asm_builtin_d2i(double a) { return 0; }
94 s8 asm_builtin_d2l(double a) { return 0; }
96 void asm_builtin_monitorenter(java_objectheader *o) {}
97 void asm_builtin_monitorexit(java_objectheader *o) {}
99 s4 asm_builtin_checkarraycast(java_objectheader *o,arraydescriptor *d) {return 0;}
101 #if defined(__I386__)
102 s4 asm_builtin_arrayinstanceof(java_objectheader *obj, classinfo *class) { return 0; }
103 void asm_builtin_newarray(s4 size, vftbl *arrayvftbl) {}
106 void asm_builtin_aastore(java_objectarray *a, s4 index, java_objectheader *o) {}
108 u1 *createcompilerstub(methodinfo *m) {return NULL;}
109 u1 *createnativestub(functionptr f, methodinfo *m) {return NULL;}
110 u1 *oldcreatenativestub(functionptr f, methodinfo *m) {return NULL;}
112 void removecompilerstub(u1 *stub) {}
113 void removenativestub(u1 *stub) {}
115 void asm_perform_threadswitch(u1 **from, u1 **to) {}
116 u1* asm_initialize_thread_stack(void *func, u1 *stack) { return NULL; }
117 void asm_switchstackandcall() {}
118 void asm_handle_builtin_exception(classinfo *c) {}
120 java_objectheader *native_new_and_init(void *p) { return NULL; }
123 /************************ global variables **********************/
125 java_objectheader *exceptionptr;
127 bool verbose = false;
128 bool runverbose = false;
129 bool collectverbose = false;
131 static chain *nativemethod_chain; /* chain with native methods */
132 static chain *nativeclass_chain; /* chain with processed classes */
133 static chain *ident_chain; /* chain with method and field names in current class */
134 static FILE *file = NULL;
135 static u4 outputsize;
136 static bool dopadding;
139 static void printIDpart(int c)
141 if ((c >= 'a' && c <= 'z')
142 || (c >= 'A' && c <= 'Z')
143 || (c >= '0' && c <= '9')
151 static void printID(utf *u)
153 char *utf_ptr = u->text;
156 for (i = 0; i < utf_strlen(u); i++)
157 printIDpart(utf_nextu2(&utf_ptr));
161 static void addoutputsize (int len)
164 if (!dopadding) return;
166 newsize = ALIGN(outputsize, len);
168 for (i = outputsize; i < newsize; i++) fprintf(file, " u1 pad%d\n", (int) i);
169 outputsize = newsize;
173 static char *printtype(char *utf_ptr)
177 switch (utf_nextu2(&utf_ptr)) {
178 case 'V': fprintf (file, "void");
184 case 'Z': addoutputsize (4);
185 fprintf (file, "s4");
187 case 'J': addoutputsize (8);
188 fprintf (file, "s8");
190 case 'F': addoutputsize (4);
191 fprintf (file, "float");
193 case 'D': addoutputsize (8);
194 fprintf (file, "double");
197 addoutputsize ( sizeof(java_arrayheader*) );
198 switch (utf_nextu2(&utf_ptr)) {
199 case 'I': fprintf (file, "java_intarray*"); break;
200 case 'J': fprintf (file, "java_longarray*"); break;
201 case 'Z': fprintf (file, "java_booleanarray*"); break;
202 case 'B': fprintf (file, "java_bytearray*"); break;
203 case 'S': fprintf (file, "java_shortarray*"); break;
204 case 'C': fprintf (file, "java_chararray*"); break;
205 case 'F': fprintf (file, "java_floatarray*"); break;
206 case 'D': fprintf (file, "java_doublearray*"); break;
208 case '[': fprintf (file, "java_objectarray*");
209 while ((c = utf_nextu2(&utf_ptr)) == '[') ;
211 while (utf_nextu2(&utf_ptr) != ';');
214 case 'L': fprintf (file, "java_objectarray*");
215 while ( utf_nextu2(&utf_ptr) != ';');
217 default: panic ("invalid type descriptor");
222 addoutputsize ( sizeof(java_objectheader*));
223 fprintf (file, "struct ");
224 while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);
228 default: panic ("Unknown type in field descriptor");
235 /******* determine the number of entries of a utf string in the ident chain *****/
237 static int searchidentchain_utf(utf *ident)
239 utf *u = chain_first(ident_chain); /* first element of list */
243 if (u==ident) count++; /* string found */
244 u = chain_next(ident_chain); /* next element in list */
251 /**************** print structure for direct access to objects ******************/
253 static void printfields(classinfo *c)
260 addoutputsize(sizeof(java_objectheader));
261 fprintf(file, " java_objectheader header;\n");
265 printfields(c->super);
267 for (i = 0; i < c->fieldscount; i++) {
270 if (!(f->flags & ACC_STATIC)) {
272 printtype(f->descriptor->text);
274 utf_fprint(file, f->name);
276 /* rename multiple fieldnames */
277 if ((ident_count = searchidentchain_utf(f->name)))
278 fprintf(file, "%d", ident_count - 1);
279 chain_addlast(ident_chain, f->name);
281 fprintf(file, ";\n");
287 /***************** store prototype for native method in file ******************/
289 static void printmethod(methodinfo *m)
295 /* search for return-type in descriptor */
296 utf_ptr = m->descriptor->text;
297 while (utf_nextu2(&utf_ptr) != ')');
300 fprintf(file, "\n/*\n * Class: ");
301 utf_fprint(file, m->class->name);
302 fprintf(file, "\n * Method: ");
303 utf_fprint(file, m->name);
304 fprintf(file, "\n * Signature: ");
305 utf_fprint(file, m->descriptor);
306 fprintf(file, "\n */\n");
308 /* create prototype */
309 fprintf(file, "JNIEXPORT ");
311 fprintf(file, " JNICALL Java_");
312 printID(m->class->name);
314 /* rename overloaded method */
315 if ((ident_count = searchidentchain_utf(m->name)))
316 fprintf(file, "%d", ident_count - 1);
317 chain_addlast(ident_chain, m->name);
321 fprintf(file, "(JNIEnv *env");
323 utf_ptr = m->descriptor->text + 1;
325 if (!(m->flags & ACC_STATIC)) {
326 fprintf(file, ", struct ");
327 printID(m->class->name);
328 fprintf(file, "* this");
331 fprintf(file, ", jclass clazz");
334 if ((*utf_ptr) != ')') fprintf(file, ", ");
336 while ((*utf_ptr) != ')') {
337 utf_ptr = printtype(utf_ptr);
338 fprintf(file, " par%d", paramnum++);
339 if ((*utf_ptr)!=')') fprintf(file, ", ");
342 fprintf(file, ");\n\n");
346 /****************** remove package-name in fully-qualified classname *********************/
348 static void gen_header_filename(char *buffer, utf *u)
352 for (i = 0;i < utf_strlen(u); i++) {
353 if ((u->text[i] == '/') || (u->text[i] == '$')) buffer[i] = '_'; /* convert '$' and '/' to '_' */
354 else buffer[i] = u->text[i];
356 buffer[utf_strlen(u)] = '\0';
360 /*********** create headerfile for classes and store native methods in chain ************/
362 static void headerfile_generate(classinfo *c)
364 char header_filename[1024] = "";
365 char classname[1024];
366 char uclassname[1024];
370 /* store class in chain */
371 chain_addlast(nativeclass_chain, c);
373 /* open headerfile for class */
374 gen_header_filename(classname, c->name);
376 /* create chain for renaming fields */
377 ident_chain = chain_new();
379 sprintf(header_filename, "nat/%s.h", classname);
380 file = fopen(header_filename, "w");
381 if (!file) panic("Can not open file to store header information");
383 fprintf(file, "/* This file is machine generated, don't edit it !*/\n\n");
385 /* convert to uppercase */
386 for (i = 0; classname[i]; i++) {
387 uclassname[i] = toupper(classname[i]);
389 uclassname[i] = '\0';
391 fprintf(file, "#ifndef _%s_H\n#define _%s_H\n\n", uclassname, uclassname);
393 /* create structure for direct access to objects */
394 fprintf(file, "/* Structure information for class: ");
395 utf_fprint(file, c->name);
396 fprintf(file, " */\n\n");
397 fprintf(file, "typedef struct ");
399 fprintf(file, " {\n");
405 fprintf(file, ";\n\n");
407 /* create chain for renaming overloaded methods */
408 chain_free(ident_chain);
409 ident_chain = chain_new();
411 /* create method-prototypes */
413 for (i = 0; i < c->methodscount; i++) {
415 m = &(c->methods[i]);
417 if (m->flags & ACC_NATIVE) {
418 chain_addlast(nativemethod_chain, m);
423 chain_free(ident_chain);
425 fprintf(file, "#endif\n\n");
430 /******** print classname, '$' used to seperate inner-class name ***********/
432 void print_classname (classinfo *clazz)
434 utf *u = clazz->name;
435 char *endpos = u->text + u->blength;
436 char *utf_ptr = u->text;
439 while (utf_ptr<endpos) {
440 if ((c=utf_nextu2(&utf_ptr)) == '_')
448 /*************** create table for locating native functions ****************/
450 static void printnativetableentry(methodinfo *m)
452 fprintf(file, " { \"");
453 print_classname(m->class);
454 fprintf(file, "\",\n \"");
455 utf_fprint(file, m->name);
456 fprintf(file, "\",\n \"");
457 utf_fprint(file, m->descriptor);
458 fprintf(file, "\",\n ");
460 if ((m->flags & ACC_STATIC) != 0)
461 fprintf(file, "true");
463 fprintf(file, "false");
465 fprintf(file, ",\n ");
466 fprintf(file, "(functionptr) Java_");
467 printID(m->class->name);
470 fprintf(file,"\n },\n");
474 /***************************************************************************
476 create the nativetypes-headerfile which includes
477 the headerfiles of the classes stored in the classes-chain
479 ****************************************************************************/
481 static void headers_finish()
485 char classname[1024];
487 file = fopen("nativetypes.hh", "w");
490 panic("Can not open file 'native.h' to store header information");
492 fprintf(file, "/* Headerfile for native methods: nativetypes.hh */\n");
493 fprintf(file, "/* This file is machine generated, don't edit it !*/\n\n");
494 fprintf(file, "\n/* include native-Headerfiles */\n\n");
496 c = chain_first(nativeclass_chain);
499 gen_header_filename(classname, c->name);
500 fprintf(file, "#include \"nat/%s.h\"\n", classname);
501 c = chain_next(nativeclass_chain);
505 chain_free(nativeclass_chain);
507 /* create table of native-methods */
509 file = fopen("nativetable.hh", "w");
512 panic("Can not open file 'nativetable' to store native-link-table");
514 fprintf(file, "/* Table of native methods: nativetables.hh */\n");
515 fprintf(file, "/* This file is machine generated, don't edit it !*/\n\n");
517 while ((m = chain_first(nativemethod_chain)) != NULL) {
518 chain_remove(nativemethod_chain);
519 printnativetableentry(m);
522 chain_free(nativemethod_chain);
527 /******************** internal function: print_usage ************************
529 Prints usage information for the JAVA header generator to stdout.
531 ***************************************************************************/
533 static void print_usage()
535 printf("Usage: cacaoh class [class..]\n");
540 /************************** Function: main *******************************
544 **************************************************************************/
546 int main(int argc, char **argv)
554 /********** internal (only used by main) *****************************/
556 char classpath[500] = "";
557 char offsets_filename[1024] = ""; /* phil */
558 u4 heapsize = 100000;
560 /*********** options so only headers are generated *******************/
562 makeinitializations = false;
565 /************ Collect some info from the environment *****************/
567 cp = getenv("CLASSPATH");
569 strcpy(classpath + strlen(classpath), ":");
570 strcpy(classpath + strlen(classpath), cp);
579 /**************************** Program start **************************/
582 log_text("Java - header-generator started");
584 sprintf(offsets_filename, "jit/%s/offsets.h", ARCH_DIR); /* phil */
585 file = fopen(offsets_filename, "w");
587 fprintf(stderr, "Can not open file '%s' for write", offsets_filename);
591 fprintf(file, "/* This file is machine generated, don't edit it !*/\n\n");
593 fprintf(file, "#define offobjvftbl %3d\n", (int) OFFSET(java_objectheader, vftbl));
594 fprintf(file, "#define offarraysize %3d\n", (int) OFFSET(java_arrayheader, size));
595 fprintf(file, "#define offobjarrdata %3d\n\n", (int) OFFSET(java_objectarray, data[0]));
596 fprintf(file, "#define offbaseval %3d\n", (int) OFFSET(vftbl, baseval));
597 fprintf(file, "#define offdiffval %3d\n\n", (int) OFFSET(vftbl, diffval));
599 fprintf(file, "#define offclassvftbl %3d\n", (int) OFFSET(classinfo, vftbl));
601 fprintf(file, "#define offjniitemtype %3d\n", (int) OFFSET(jni_callblock, itemtype));
602 fprintf(file, "#define offjniitem %3d\n", (int) OFFSET(jni_callblock, item));
603 fprintf(file, "#define sizejniblock %3d\n\n", (int) sizeof(jni_callblock));
608 suck_init(classpath);
611 heap_init(heapsize, heapsize, &dummy);
615 /*********************** Load JAVA classes **************************/
617 nativemethod_chain = chain_new();
618 nativeclass_chain = chain_new();
620 for (a = 1; a < argc; a++) {
623 /* convert classname */
624 for (i = strlen(cp) - 1; i >= 0; i--) {
632 topclass = loader_load(utf_new_char(cp));
634 headerfile_generate(topclass);
639 /************************ Release all resources **********************/
643 tables_close(literalstring_free);
646 /* Print "finished" message */
648 log_text("Java - header-generator stopped");
656 void setVMClassField(classinfo *c)
661 void *Java_java_lang_VMObject_clone(void *env, void *clazz, void * this) {
667 * These are local overrides for various environment variables in Emacs.
668 * Please do not remove this and leave it at the end of the file, where
669 * Emacs will automagically detect them.
670 * ---------------------------------------------------------------------
673 * indent-tabs-mode: t