RTA update - statistics only until inlining
[cacao.git] / headers.c
1 /* headers.c *******************************************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         This module replaces 'main' for header file generation. It also fakes some
8         references to external modules which would otherwise depend on the header
9         files generated by this very program.
10
11         This module is quite a quick hack and not documented very well as a
12         consequence.
13
14         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
15         Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
16                  Philipp Tomsich     EMAIL: cacao@complang.tuwien.ac.at
17
18         Last Change: $Id: headers.c 364 2003-06-13 13:55:35Z twisti $
19
20 *******************************************************************************/
21
22 #define CACAOH
23
24 #include "config.h" /* phil */
25 #include "global.h"
26 #include "tables.h"
27 #include "loader.h"
28
29
30 /******* replace some external functions  *********/
31  
32 functionptr native_findfunction (utf *cname, utf *mname, utf *desc, bool isstatic)
33 { return NULL; }
34
35 java_objectheader *javastring_new (utf *text)         /* schani */
36 { return NULL; }
37
38 void throw_classnotfoundexception() 
39
40         panic("class not found"); 
41 }
42
43 java_objectheader *literalstring_new (utf *u)
44 { return NULL; }  
45
46 void literalstring_free (java_objectheader *o) { }
47 void stringtable_update () { }
48 void synchronize_caches() { }
49 void asm_call_jit_compiler () { }
50 void asm_calljavamethod () { }
51 void asm_dumpregistersandcall () { }
52 s4 asm_builtin_checkcast(java_objectheader *obj, classinfo *class) { return 0; }
53
54 s4 asm_builtin_idiv (s4 a, s4 b) {return 0;}
55 s4 asm_builtin_irem (s4 a, s4 b) {return 0;}
56 s8 asm_builtin_ldiv (s8 a, s8 b) {return 0;}
57 s8 asm_builtin_lrem (s8 a, s8 b) {return 0;}
58 float asm_builtin_frem (float a, float b) {}
59
60
61 void asm_builtin_monitorenter (java_objectheader *o) {}
62 void asm_builtin_monitorexit (java_objectheader *o) {}
63
64 s4 asm_builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *d) {return 0;}
65
66 #ifdef __I386__
67 s4 asm_builtin_arrayinstanceof(java_objectheader *obj, classinfo *class) { return 0; }
68 void asm_builtin_anewarray (s4 size, classinfo *elementtype) {}
69 void asm_builtin_newarray_array (s4 size, constant_arraydescriptor *elementdesc) {}
70 #endif
71 void asm_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o) {}
72
73 u1 *createcompilerstub (methodinfo *m) {return NULL;}
74 u1 *createnativestub (functionptr f, methodinfo *m) {return NULL;}
75 u1 *oldcreatenativestub (functionptr f, methodinfo *m) {return NULL;}
76
77 void removecompilerstub (u1 *stub) {}
78 void removenativestub (u1 *stub) {}
79
80 void asm_perform_threadswitch (u1 **from, u1 **to) {}
81 u1* asm_initialize_thread_stack (void *func, u1 *stack) { return NULL; }
82 void asm_switchstackandcall () { }
83
84 java_objectheader *native_new_and_init (void *p) { return NULL; }
85
86 /************************ global variables **********************/
87
88 java_objectheader *exceptionptr;                       /* schani */
89 int  newcompiler = true;
90 bool verbose =  false;
91
92 static chain *nativemethod_chain;                              /* chain with native methods     */
93 static chain *nativeclass_chain;                               /* chain with processed classes  */      
94 static chain *ident_chain;        /* chain with method and field names in current class */
95 static FILE *file = NULL;
96 static u4 outputsize;
97 static bool dopadding;
98
99 static void printIDpart (int c) 
100 {
101                 if (     (c>='a' && c<='z')
102                       || (c>='A' && c<='Z')
103                       || (c>='0' && c<='9')
104                       || (c=='_') )          
105                            putc (c,file);
106         else       putc ('_',file);
107
108 }
109
110 static void printID (utf *u)
111 {
112         char *utf_ptr = u->text;
113         int i;
114
115         for (i=0; i<utf_strlen(u); i++) 
116                 printIDpart (utf_nextu2(&utf_ptr));
117 }
118
119 static void addoutputsize (int len)
120 {
121         u4 newsize,i;
122         if (!dopadding) return;
123
124         newsize = ALIGN (outputsize, len);
125         
126         for (i=outputsize; i<newsize; i++) fprintf (file, "   u1 pad%d\n",(int) i);
127         outputsize = newsize;
128 }
129
130
131 static char *printtype (char *utf_ptr)
132 {
133         u2 c;
134
135         switch (utf_nextu2(&utf_ptr)) {
136                 case 'V': fprintf (file, "void");
137                           break;
138                 case 'I':
139                 case 'S':
140                 case 'B':
141                 case 'C':
142                 case 'Z': addoutputsize (4);
143                   fprintf (file, "s4");
144                   break;
145                 case 'J': addoutputsize (8);
146                   fprintf (file, "s8");
147                   break;
148                 case 'F': addoutputsize (4);
149                   fprintf (file, "float");
150                   break;
151                 case 'D': addoutputsize (8);
152                   fprintf (file, "double");
153                   break;
154                 case '[':
155                         addoutputsize ( sizeof(java_arrayheader*) ); 
156                         switch (utf_nextu2(&utf_ptr)) {
157                                 case 'I':  fprintf (file, "java_intarray*"); break;
158                                 case 'J':  fprintf (file, "java_longarray*"); break;
159                                 case 'Z':  fprintf (file, "java_booleanarray*"); break;
160                                 case 'B':  fprintf (file, "java_bytearray*"); break;
161                                 case 'S':  fprintf (file, "java_shortarray*"); break;
162                                 case 'C':  fprintf (file, "java_chararray*"); break;
163                                 case 'F':  fprintf (file, "java_floatarray*"); break;
164                                 case 'D':  fprintf (file, "java_doublearray*"); break;
165                                 
166                                 case '[':  fprintf (file, "java_arrayarray*");                                         
167                                            while ((c = utf_nextu2(&utf_ptr)) == '[') ;
168                                            if (c=='L') 
169                                                            while (utf_nextu2(&utf_ptr) != ';');
170                            break;
171                            
172                                 case 'L':  fprintf (file, "java_objectarray*");
173                                            while ( utf_nextu2(&utf_ptr) != ';');
174                                            break;
175                                 default: panic ("invalid type descriptor");
176                                 }
177                         break;
178                 
179                 case 'L': 
180                         addoutputsize ( sizeof(java_objectheader*));
181             fprintf (file, "struct ");
182             while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);         
183             fprintf (file, "*");
184                         break;
185                                         
186                 default:  panic ("Unknown type in field descriptor");
187         }
188         
189         return utf_ptr;
190 }
191
192 /******* determine the number of entries of a utf string in the ident chain *****/
193
194 static int searchidentchain_utf(utf *ident) 
195 {
196         utf *u = chain_first(ident_chain);     /* first element of list */
197         int count = 0;
198
199         while (u) {
200                 if (u==ident) count++;         /* string found */
201                 u = chain_next(ident_chain);   /* next element in list */ 
202         }
203
204         return count;
205 }
206
207 /**************** print structure for direct access to objects ******************/      
208
209 static void printfields (classinfo *c)
210 {
211         u4 i;
212         fieldinfo *f;
213         int ident_count;
214         
215         if (!c) {
216                 addoutputsize ( sizeof(java_objectheader) );
217                 fprintf (file, "   java_objectheader header;\n");
218                 return;
219                 }
220                 
221         printfields (c->super);
222         
223         for (i=0; i<c->fieldscount; i++) {
224                 f = &(c->fields[i]);
225                 
226                 if (! (f->flags & ACC_STATIC) ) {
227                         fprintf (file,"   ");
228                         printtype (f->descriptor->text);
229                         fprintf (file, " ");
230                         utf_fprint (file, f->name);
231
232                         /* rename multiple fieldnames */
233                         if (ident_count = searchidentchain_utf(f->name))
234                                 fprintf(file,"%d",ident_count - 1);             
235                         chain_addlast(ident_chain,f->name);     
236
237                         fprintf (file, ";\n");
238                         }
239                 }
240 }
241
242 /***************** store prototype for native method in file ******************/
243
244 static void printmethod (methodinfo *m)
245 {
246         char *utf_ptr;
247         u2 paramnum=1;
248         u2 ident_count;
249
250         /* search for return-type in descriptor */      
251         utf_ptr = m->descriptor->text;
252         while (utf_nextu2(&utf_ptr) != ')');
253
254         /* create remarks */
255         fprintf (file,"/*\n * Class:     ");
256         utf_fprint (file, m->class->name);
257         fprintf (file,"\n * Method:    ");
258         utf_fprint (file, m->name);
259         fprintf (file,"\n * Signature: ");
260         utf_fprint (file, m->descriptor);
261         fprintf (file,"\n */\n");       
262
263         /* create prototype */                  
264         fprintf (file,"JNIEXPORT ");                            
265         printtype (utf_ptr);
266         fprintf (file," JNICALL Java_");
267         printID (m->class->name);           
268
269         /* rename overloaded method */
270         if (ident_count = searchidentchain_utf(m->name))
271                 fprintf(file,"%d",ident_count - 1);             
272         chain_addlast(ident_chain,m->name);     
273
274         fprintf (file,"_");
275         printID (m->name);
276         fprintf (file," (JNIEnv *env ");
277         
278         utf_ptr = m->descriptor->text+1;
279                         
280         if (! (m->flags & ACC_STATIC) ) {
281         
282                 fprintf (file, ",  struct ");
283                 printID (m->class->name);
284                 fprintf (file, "* this ");
285
286             };
287
288         if ((*utf_ptr)!=')') fprintf (file, ", "); 
289                         
290         while ((*utf_ptr)!=')') {
291                 utf_ptr = printtype (utf_ptr);
292                 fprintf (file, " par%d", paramnum++);
293                 if ((*utf_ptr)!=')') fprintf (file, ", ");
294                 }
295                         
296         fprintf (file, ");\n");
297 }
298
299
300 /****************** remove package-name in fully-qualified classname *********************/
301
302 static void simple_classname(char *buffer, utf *u)
303 {
304   int i, simplename_start;
305
306   for (i=utf_strlen(u)-1; i>=0; i--) { 
307
308         if (u->text[i] == '$') u->text[i] = '_'; else /* convert '$' to '_' */
309     if (u->text[i] == '/') {
310         /* beginning of simple name */
311         simplename_start = i+1;
312                 break;
313         }
314   }
315
316   for (i=simplename_start; i < utf_strlen(u); i++) 
317                   buffer[i-simplename_start] = u->text[i];
318
319   buffer[i-simplename_start] = '\0';                
320 }
321
322 /*********** create headerfile for classes and store native methods in chain ************/
323
324 static void headerfile_generate (classinfo *c)
325 {
326         char header_filename[1024] = "";
327         char classname[1024]; 
328         u2 i;
329         methodinfo *m;                  
330                       
331         /* store class in chain */                    
332         chain_addlast (nativeclass_chain, c);                                                           
333                                 
334         /* open headerfile for class */
335         simple_classname(classname,c->name);                                                                                                                                            
336
337         /* create chain for renaming fields */
338         ident_chain = chain_new ();
339         
340         sprintf(header_filename, "nat/%s.h", classname);
341         file = fopen (header_filename, "w");
342         if (!file) panic ("Can not open file to store header information");                                                                                     
343         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
344
345         /* create structure for direct access to objects */     
346         fprintf (file, "/* Structure information for class: ");
347         utf_fprint (file, c->name);
348         fprintf (file, " */\n\n");
349         fprintf (file, "typedef struct ");
350         printID (c->name);                                                      
351         fprintf (file, " {\n");
352         outputsize=0;
353         dopadding=true;
354         printfields (c);                                                        
355         fprintf (file, "} ");
356         printID (c->name);
357         fprintf (file, ";\n\n");                            
358
359         /* create chain for renaming overloaded methods */
360         chain_free(ident_chain);                                        
361         ident_chain = chain_new ();
362
363         /* create method-prototypes */
364                                 
365         for (i=0; i<c->methodscount; i++) {
366
367                 m = &(c->methods[i]);
368
369                 if (m->flags & ACC_NATIVE) {
370                         chain_addlast (nativemethod_chain, m);     
371                         printmethod(m);                                             
372                         }                                                       
373                 }
374                                 
375
376         chain_free(ident_chain);                                 
377         fclose(file);
378 }
379
380 /******** print classname, '$' used to seperate inner-class name ***********/
381
382 void print_classname (classinfo *clazz)
383 {
384         utf *u = clazz->name;
385     char *endpos  = u->text + u->blength;
386     char *utf_ptr = u->text; 
387         u2 c;
388
389     while (utf_ptr<endpos) {
390                 if ((c=utf_nextu2(&utf_ptr)) == '_')
391                         putc ('$',file);
392                 else
393                         putc (c,file);
394         }
395
396
397
398 /*************** create table for locating native functions ****************/
399
400 static void printnativetableentry (methodinfo *m)
401 {
402         fprintf (file, "   { \"");
403         print_classname(m->class);
404         fprintf (file, "\",\n     \"");
405         utf_fprint (file, m->name);
406         fprintf (file, "\",\n     \"");
407         utf_fprint (file, m->descriptor);
408         fprintf (file, "\",\n     ");
409         if ( (m->flags & ACC_STATIC) !=0)  fprintf (file, "true");
410                                       else fprintf (file, "false");
411         fprintf (file, ",\n     ");
412         fprintf (file, "(functionptr) Java_");
413         printID (m->class->name);
414         fprintf (file,"_");
415         printID (m->name);
416         fprintf (file,"\n   },\n");
417 }
418
419
420 /***************************************************************************
421
422         create the nativetypes-headerfile which includes 
423         the headerfiles of the classes stored in the classes-chain 
424
425 ****************************************************************************/
426
427 static void headers_finish ()
428 {
429         methodinfo *m;
430         classinfo *c;
431         char classname[1024];
432         
433         file = fopen ("nativetypes.hh", "w");
434         if (!file) panic ("Can not open file 'native.h' to store header information");
435         
436         fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
437         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");     
438         fprintf (file, "\n/* include native-Headerfiles */\n\n");
439                         
440         c = chain_first (nativeclass_chain);
441         while (c) {
442         
443                 dopadding=false;
444                 simple_classname(classname,c->name);                                                                                                                                                                                    
445                 fprintf(file,"#include \"nat/%s.h\"\n",classname);              
446                 c = chain_next (nativeclass_chain);             
447         }
448
449     fclose(file);
450         chain_free (nativeclass_chain);
451         
452         /* create table of native-methods */
453
454         file = fopen ("nativetable.hh", "w");
455         if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
456
457         fprintf (file, "/* Table of native methods: nativetables.hh */\n");
458         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
459
460         while ( (m = chain_first (nativemethod_chain)) != NULL) {
461                 chain_remove (nativemethod_chain);              
462                 printnativetableentry (m);
463         }
464                 
465         chain_free (nativemethod_chain);
466         fclose (file);
467
468 }
469
470
471 /******************** internal function: print_usage ************************
472
473 Prints usage information for the JAVA header generator to stdout.
474
475 ***************************************************************************/
476
477 static void print_usage()
478 {
479         printf ("USAGE: jch class [class..]\n");
480 }   
481
482
483
484 /************************** Function: main *******************************
485
486    Main program.
487    
488 **************************************************************************/
489
490 int main(int argc, char **argv)
491 {
492         s4 i,a;
493         char *cp;
494         classinfo *topclass;
495         void *dummy;
496                 
497
498    /********** internal (only used by main) *****************************/
499    
500         char classpath[500] = "";
501         char offsets_filename[1024] = ""; /* phil */
502         u4 heapsize = 100000;
503
504    /*********** options so only headers are generated *******************/
505    
506    makeinitializations=false;
507    
508
509    /************ Collect some info from the environment *****************/
510
511         cp = getenv ("CLASSPATH");
512         if (cp) {
513                 strcpy (classpath + strlen(classpath), ":");
514                 strcpy (classpath + strlen(classpath), cp);
515                 }
516
517         if (argc < 2) {
518                 print_usage ();
519                 exit(10);
520                 }
521
522
523    /**************************** Program start **************************/
524
525         log_init (NULL);
526         log_text ("Java - header-generator started"); 
527         
528         sprintf(offsets_filename, "%s/offsets.h", SYSDEP_DIR); /* phil */
529         file = fopen(offsets_filename, "w");
530         if (file == NULL) {
531                 fprintf (stderr, "Can not open file '%s' for write", offsets_filename);
532                 exit(-1);
533         }
534         
535         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
536
537         fprintf (file, "#define offobjvftbl    %3d\n", (int) OFFSET(java_objectheader, vftbl));
538         fprintf (file, "#define offarraysize   %3d\n", (int) OFFSET(java_arrayheader, size));
539         fprintf (file, "#define offobjarrdata  %3d\n\n", (int) OFFSET(java_objectarray, data[0]));
540         fprintf (file, "#define offbaseval     %3d\n", (int) OFFSET(vftbl, baseval));
541         fprintf (file, "#define offdiffval     %3d\n", (int) OFFSET(vftbl, diffval));
542
543         fclose (file);
544
545         suck_init (classpath);
546    
547         tables_init ();
548         heap_init (heapsize, heapsize, &dummy);
549         loader_init ();
550
551
552    /*********************** Load JAVA classes  **************************/
553         
554         nativemethod_chain = chain_new ();
555         nativeclass_chain = chain_new ();
556         
557         for (a=1; a<argc; a++) {   
558  
559                 cp = argv[a];
560
561                 /* convert classname */
562                 for (i=strlen(cp)-1; i>=0; i--)    
563                         switch (cp[i]) {
564                           case '.': cp[i]='/';
565                                         break;
566                           case '_': cp[i]='$';    
567                         }
568         
569                 topclass = loader_load ( utf_new_char (cp) );
570                 
571         headerfile_generate (topclass);
572         }
573
574         headers_finish ();
575
576    /************************ Release all resources **********************/
577
578         loader_close ();
579         heap_close ();
580         tables_close ( literalstring_free );
581         
582
583    /* Print "finished" message */
584
585         log_text ("Java - header-generator stopped");
586         log_cputime ();
587         mem_usagelog(1);
588         
589         return 0;
590 }
591
592
593 /*
594  * These are local overrides for various environment variables in Emacs.
595  * Please do not remove this and leave it at the end of the file, where
596  * Emacs will automagically detect them.
597  * ---------------------------------------------------------------------
598  * Local variables:
599  * mode: c
600  * indent-tabs-mode: t
601  * c-basic-offset: 4
602  * tab-width: 4
603  * End:
604  */