add escape character for underscore to codegen_resolve_native
[cacao.git] / src / vm / jit / codegen.inc
1 /* jit/codegen.inc - architecture independent code generator
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Reinhard Grafl
29             Andreas  Krall
30
31    Changes: Michael Gschwind
32             Christian Thalinger
33
34    All functions assume the following code area / data area layout:
35
36    +-----------+
37    |           |
38    | code area | code area grows to higher addresses
39    |           |
40    +-----------+ <-- start of procedure
41    |           |
42    | data area | data area grows to lower addresses
43    |           |
44    +-----------+
45
46    The functions first write into a temporary code/data area allocated by
47    "codegen_init". "codegen_finish" copies the code and data area into permanent
48    memory. All functions writing values into the data area return the offset
49    relative the begin of the code area (start of procedure).    
50
51    $Id: codegen.inc 1463 2004-11-06 21:20:53Z motse $
52
53 */
54
55
56 #include <string.h>
57 #include "exceptions.h"
58 #include "native.h"
59 #include "options.h"
60 #include "statistics.h"
61 #include "jit/codegen.inc.h"
62 #include "toolbox/memory.h"
63 #include "toolbox/logging.h"
64 #include "toolbox/avl.h"
65 #include "threads/thread.h"
66 #ifndef STATIC_CLASSPATH
67 #include <dlfcn.h>
68 #endif
69
70 /* in this tree we store all method addresses */
71
72 #if defined(__I386__) || defined(__X86_64__)
73 static struct avl_table *methodtree = NULL;
74 static int methodtree_comparator(const void *pc, const void *element,
75                                                                  void *param);
76 #endif
77
78
79 /* codegen_init ****************************************************************
80
81    TODO
82
83 *******************************************************************************/
84
85 void codegen_init()
86 {
87 #if defined(__I386__) || defined(__X86_64__)
88         /* this tree is global, not method specific */
89         if (!methodtree) {
90                 methodtree_element *mte;
91
92                 methodtree = avl_create(methodtree_comparator, NULL, NULL);
93
94                 mte = NEW(methodtree_element);
95
96                 mte->startpc = asm_calljavafunction;
97                 mte->endpc = asm_calljavafunction2 - 1;
98
99                 avl_insert(methodtree, mte);
100
101                 mte = NEW(methodtree_element);
102
103                 mte->startpc = asm_calljavafunction2;
104                 mte->endpc = asm_call_jit_compiler - 1;
105
106                 avl_insert(methodtree, mte);
107         }
108 #endif
109 }
110
111
112 /* codegen_setup **************************************************************
113
114    allocates and initialises code area, data area and references
115
116 *******************************************************************************/
117
118 void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
119 {
120         cd->mcodebase = MNEW(u1, MCODEINITSIZE);
121         cd->mcodesize = MCODEINITSIZE;
122         
123         cd->dsegtop = MNEW(u1, DSEGINITSIZE);
124         cd->dsegsize = DSEGINITSIZE;
125         cd->dsegtop += cd->dsegsize;
126         cd->dseglen = 0;
127
128         cd->jumpreferences = NULL;
129         cd->datareferences = NULL;
130         cd->xboundrefs = NULL;
131         cd->xcheckarefs = NULL;
132         cd->xnullrefs = NULL;
133         cd->xcastrefs = NULL;
134         cd->xdivrefs = NULL;
135         cd->xexceptionrefs = NULL;
136
137         cd->linenumberreferences = NULL;
138         cd->linenumbertablesizepos = 0;
139         cd->linenumbertablestartpos = 0;
140         cd->linenumbertab = 0;
141         
142         cd->method = m;
143         cd->exceptiontable = 0;
144         cd->exceptiontablelength = 0;
145
146         if (useinlining && id) {
147                 if (id->cumextablelength > 0) {
148                         cd->exceptiontablelength = id->cumextablelength;
149                         cd->exceptiontable  = MNEW(exceptiontable, id->cumextablelength + 1);
150                 }
151
152         } else if (id && (id->method->exceptiontablelength >0)) {
153                 cd->exceptiontablelength = m->exceptiontablelength;
154                 cd->exceptiontable  = MNEW(exceptiontable, m->exceptiontablelength + 1);
155         }
156
157         if (id) {
158                 cd->maxstack = id->cummaxstack;
159                 cd->maxlocals = id->cumlocals;
160         } else {
161                 cd->maxstack = m->maxstack;
162                 cd->maxlocals = m->maxlocals;
163         }
164
165 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
166         cd->threadcritcurrent.next = NULL;
167         cd->threadcritcount = 0;
168 #endif
169 }
170
171
172 /* codegen_free ****************************************************************
173
174    releases temporary code and data area
175
176 *******************************************************************************/
177
178 void codegen_free(methodinfo *m, codegendata *cd)
179 {
180         if (cd) {
181                 if (cd->exceptiontablelength) {
182                         cd->exceptiontablelength = m->exceptiontablelength;
183                         MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
184                         cd->exceptiontable = 0;
185                         cd->exceptiontablelength = 0;
186                 }
187
188                 if (cd->mcodebase) {
189                         MFREE(cd->mcodebase, u1, cd->mcodesize);
190                         cd->mcodebase = NULL;
191                 }
192
193                 if (cd->dsegtop) {
194                         MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
195                         cd->dsegtop = NULL;
196                 }
197         }
198 }
199
200
201 /* codegen_close ***************************************************************
202
203    TODO
204
205 *******************************************************************************/
206
207 void codegen_close()
208 {
209         /* TODO: release avl tree on i386 and x86_64 */
210 }
211
212
213 /* codegen_increase doubles code area                                         */
214
215 static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
216 {
217         long len;
218
219         len = codeptr - cd->mcodebase;
220         cd->mcodebase = MREALLOC(cd->mcodebase,
221                                                          u1,
222                                                          cd->mcodesize,
223                                                          cd->mcodesize * 2);
224         cd->mcodesize *= 2;
225         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
226
227         return (s4 *) (cd->mcodebase + len);
228 }
229
230
231 /* desg_increase doubles data area                                            */
232
233 static void dseg_increase(codegendata *cd)
234 {
235         u1 *newstorage;
236
237         newstorage = MNEW(u1, cd->dsegsize * 2);
238
239         memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
240         MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
241
242         cd->dsegtop = newstorage;
243         cd->dsegsize *= 2;
244         cd->dsegtop += cd->dsegsize;
245 }
246
247
248 static s4 dseg_adds4_increase(codegendata *cd, s4 value)
249 {
250         dseg_increase(cd);
251
252         *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
253
254         return -(cd->dseglen);
255 }
256
257
258 static s4 dseg_adds4(codegendata *cd, s4 value)
259 {
260         s4 *dataptr;
261
262         cd->dseglen += 4;
263         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
264
265         if (cd->dseglen > cd->dsegsize)
266                 return dseg_adds4_increase(cd, value);
267
268         *dataptr = value;
269
270         return -(cd->dseglen);
271 }
272
273
274 #if !defined(__I386__)
275 static s4 dseg_adds8_increase(codegendata *cd, s8 value)
276 {
277         dseg_increase(cd);
278
279         *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
280
281         return -(cd->dseglen);
282 }
283
284
285 static s4 dseg_adds8(codegendata *cd, s8 value)
286 {
287         s8 *dataptr;
288
289         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
290         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
291
292         if (cd->dseglen > cd->dsegsize)
293                 return dseg_adds8_increase(cd, value);
294
295         *dataptr = value;
296
297         return -(cd->dseglen);
298 }
299 #endif
300
301
302 static s4 dseg_addfloat_increase(codegendata *cd, float value)
303 {
304         dseg_increase(cd);
305
306         *((float *) (cd->dsegtop - cd->dseglen)) = value;
307
308         return -(cd->dseglen);
309 }
310
311
312 static s4 dseg_addfloat(codegendata *cd, float value)
313 {
314         float *dataptr;
315
316         cd->dseglen += 4;
317         dataptr = (float *) (cd->dsegtop - cd->dseglen);
318
319         if (cd->dseglen > cd->dsegsize)
320                 return dseg_addfloat_increase(cd, value);
321
322         *dataptr = value;
323
324         return -(cd->dseglen);
325 }
326
327
328 static s4 dseg_adddouble_increase(codegendata *cd, double value)
329 {
330         dseg_increase(cd);
331
332         *((double *) (cd->dsegtop - cd->dseglen)) = value;
333
334         return -(cd->dseglen);
335 }
336
337
338 static s4 dseg_adddouble(codegendata *cd, double value)
339 {
340         double *dataptr;
341
342         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
343         dataptr = (double *) (cd->dsegtop - cd->dseglen);
344
345         if (cd->dseglen > cd->dsegsize)
346                 return dseg_adddouble_increase(cd, value);
347
348         *dataptr = value;
349
350         return -(cd->dseglen);
351 }
352
353
354 static void dseg_addtarget(codegendata *cd, basicblock *target)
355 {
356         jumpref *jr;
357
358         jr = DNEW(jumpref);
359         jr->tablepos = dseg_addaddress(cd, NULL);
360         jr->target = target;
361         jr->next = cd->jumpreferences;
362         cd->jumpreferences = jr;
363 }
364
365
366 static void dseg_adddata(codegendata *cd, u1 *ptr)
367 {
368         dataref *dr;
369
370         dr = DNEW(dataref);
371         dr->pos = (u1 *) (ptr - cd->mcodebase);
372         dr->next = cd->datareferences;
373         cd->datareferences = dr;
374 }
375
376
377 static void dseg_addlinenumbertablesize(codegendata *cd)
378 {
379 #ifdef __ALPHA__
380         dseg_adds4(cd, 0); /*PADDING*/
381 #endif
382         cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
383
384         cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
385 #ifdef __ALPHA__
386         dseg_adds4(cd, 0); /*PADDING*/
387 #endif
388 }
389
390
391 static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
392 {
393         linenumberref *lr;
394
395         lr = DNEW(linenumberref);
396         lr->linenumber = linenumber;
397         lr->tablepos = 0;
398         lr->targetmpc = (ptr - cd->mcodebase);
399         lr->next = cd->linenumberreferences;
400         cd->linenumberreferences = lr;
401 }
402
403
404 /* we need this function externally on i386 and x86_64, but keep the call fast
405    on alpha... */
406
407 #if defined(__I386__) || defined(__X86_64__)
408 void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
409 #else
410 static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
411 #endif
412 {
413         s4 branchpos;
414
415         branchpos = (u1 *) branchptr - cd->mcodebase;
416
417         if (target->mpc >= 0) {
418                 gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
419                                                   branchpos,
420                                                   target->mpc);
421
422         } else {
423                 branchref *br = DNEW(branchref);
424
425                 br->branchpos = branchpos;
426                 br->next = target->branchrefs;
427                 target->branchrefs = br;
428         }
429 }
430
431
432 static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
433 {
434         s4 branchpos;
435         branchref *br;
436
437         branchpos = (u1 *) branchptr - cd->mcodebase;
438
439         br = DNEW(branchref);
440         br->branchpos = branchpos;
441         br->reg = reg;
442         br->next = cd->xboundrefs;
443         cd->xboundrefs = br;
444 }
445
446
447 static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
448 {
449         s4 branchpos;
450         branchref *br;
451
452         branchpos = (u1 *) branchptr - cd->mcodebase;
453
454         br = DNEW(branchref);
455         br->branchpos = branchpos;
456         br->next = cd->xcheckarefs;
457         cd->xcheckarefs = br;
458 }
459
460
461 static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
462 {
463         s4 branchpos;
464         branchref *br;
465
466         branchpos = (u1 *) branchptr - cd->mcodebase;
467
468         br = DNEW(branchref);
469         br->branchpos = branchpos;
470         br->next = cd->xnullrefs;
471         cd->xnullrefs = br;
472 }
473
474
475 static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
476 {
477         s4 branchpos;
478         branchref *br;
479
480         branchpos = (u1 *) branchptr - cd->mcodebase;
481
482         br = DNEW(branchref);
483         br->branchpos = branchpos;
484         br->next = cd->xcastrefs;
485         cd->xcastrefs = br;
486 }
487
488
489 static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
490 {
491         s4 branchpos;
492         branchref *br;
493
494         branchpos = (u1 *) branchptr - cd->mcodebase;
495
496         br = DNEW(branchref);
497         br->branchpos = branchpos;
498         br->next = cd->xexceptionrefs;
499         cd->xexceptionrefs = br;
500 }
501
502
503 #if defined(__I386__) || defined(__X86_64__)
504 static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
505 {
506         s4 branchpos;
507         branchref *br;
508
509         branchpos = (u1 *) branchptr - cd->mcodebase;
510
511         br = DNEW(branchref);
512         br->branchpos = branchpos;
513         br->next = cd->xdivrefs;
514         cd->xdivrefs = br;
515 }
516 #endif
517
518
519 static void codegen_createlinenumbertable(codegendata *cd)
520 {
521 #ifdef __I386__
522         linenumberref *lr;
523
524         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
525                 lr->tablepos = dseg_addaddress(cd, NULL);
526
527                 if (cd->linenumbertab == 0)
528                         cd->linenumbertab = lr->tablepos;
529
530                 dseg_addaddress(cd, lr->linenumber);
531         }
532 #endif
533 }
534
535
536 #if defined(__I386__) || defined(__X86_64__)
537 static int methodtree_comparator(const void *pc, const void *element, void *param)
538 {
539         methodtree_element *mte;
540         methodtree_element *mtepc;
541
542         mte = (methodtree_element *) element;
543         mtepc = (methodtree_element *) pc;
544
545         /* compare both startpc and endpc of pc, even if they have the same value,
546            otherwise the avl_probe sometimes thinks the element is already in the
547            tree */
548         if (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc &&
549                 mte->startpc <= mtepc->endpc   && mtepc->endpc   <= mte->endpc) {
550                 return 0;
551
552         } else if (mtepc->startpc < mte->startpc) {
553                 return -1;
554
555         } else {
556                 return 1;
557         }
558 }
559
560
561 #if 0
562 void *codegen_findmethod1(void *pc)
563 {
564         void * retVal=findmethod(pc);
565         methodinfo **ma=(methodinfo**)retVal;
566         methodinfo *m=ma[-1];
567         if (m)
568                 if (m->name)
569                         utf_display(m->name);
570                 else 
571                         log_text("No Name");
572         else log_text("No methodinfo");
573         return retVal;
574 }
575 #endif
576
577
578 void codegen_insertmethod(void *startpc, void *endpc)
579 {
580         methodtree_element *mte;
581
582 #if defined(USE_THREADS)
583 #if defined(NATIVE_THREADS)
584         tables_lock();
585 #endif
586 #endif
587
588         mte = NEW(methodtree_element);
589         mte->startpc = startpc;
590         mte->endpc = endpc;
591
592         if (avl_insert(methodtree, mte)) {
593 #if defined(USE_THREADS)
594 #if defined(NATIVE_THREADS)
595                 tables_unlock();
596 #endif
597 #endif
598                 throw_cacao_exception_exit(string_java_lang_InternalError,
599                                                                    "duplicate entry");
600         }
601
602 #if defined(USE_THREADS)
603 #if defined(NATIVE_THREADS)
604         tables_unlock();
605 #endif
606 #endif
607 }
608
609
610 void *codegen_findmethod(void *pc)
611 {
612         methodtree_element *mtepc;
613         methodtree_element *mte;
614
615 #if defined(USE_THREADS)
616 #if defined(NATIVE_THREADS)
617         tables_lock();
618 #endif
619 #endif
620
621         mtepc = NEW(methodtree_element);
622         mtepc->startpc = pc;
623         mtepc->endpc = pc;
624
625         mte = avl_find(methodtree, mtepc);
626
627         FREE(mtepc, methodtree_element);
628
629         if (!mte) {
630 #if defined(USE_THREADS)
631 #if defined(NATIVE_THREADS)
632                 tables_unlock();
633 #endif
634 #endif
635                 throw_cacao_exception_exit(string_java_lang_InternalError,
636                                                                    "cannot find function");
637         }
638
639 #if defined(USE_THREADS)
640 #if defined(NATIVE_THREADS)
641         tables_unlock();
642 #endif
643 #endif
644
645         return mte->startpc;
646 }
647 #endif
648
649
650 static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
651 {
652         jumpref *jr;
653         u1 *epoint;
654         s4 extralen;
655         s4 alignedlen;
656
657 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
658         extralen = sizeof(threadcritnode) * cd->threadcritcount;
659 #else
660         extralen = 0;
661 #endif
662
663 #if defined(STATISTICS)
664         if (opt_stat) {
665                 count_code_len += mcodelen;
666                 count_data_len += cd->dseglen;
667         }
668 #endif
669
670         cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
671         alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
672
673         m->mcodelength = mcodelen + cd->dseglen;
674         m->mcode = CNEW(u1, alignedlen + extralen);
675
676         memcpy(m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
677         memcpy(m->mcode + cd->dseglen, cd->mcodebase, mcodelen);
678
679         m->entrypoint = epoint = (u1 *) (m->mcode + cd->dseglen);
680
681         /* jump table resolving */
682         jr = cd->jumpreferences;
683         while (jr != NULL) {
684                 *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
685                 jr = jr->next;
686         }
687
688 #ifdef __I386__
689         /* line number table resolving */
690         {
691                 linenumberref *lr;
692 #if POINTERSIZE == 8
693                 s8 lrtlen = 0;
694 #else
695                 s4 lrtlen = 0;
696 #endif
697
698                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
699                         lrtlen++;
700                         *((void**) (epoint + lr->tablepos)) = epoint + lr->targetmpc;
701                 }
702                 
703                 *((void**) (epoint + cd->linenumbertablestartpos)) =
704                         epoint + cd->linenumbertab;
705 #if POINTERSIZE == 8
706                 *((s8*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
707 #else
708                 *((s4*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
709 #endif
710         }
711 #endif
712
713 #if defined(__I386__) || defined(__X86_64__)
714         {
715                 dataref *dr;
716
717                 /* add method into methodtree to find the entrypoint */
718                 codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
719
720                 /* data segment references resolving */
721                 dr = cd->datareferences;
722                 while (dr != NULL) {
723                         *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
724                         dr = dr->next;
725                 }
726         }
727 #endif
728
729 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
730         {
731                 threadcritnode *n = (threadcritnode *) (m->mcode + alignedlen);
732                 s4 i;
733                 threadcritnodetemp *nt = cd->threadcrit;
734
735                 for (i = 0; i < cd->threadcritcount; i++) {
736                         n->mcodebegin = m->mcode + nt->mcodebegin;
737                         n->mcodeend = m->mcode + nt->mcodeend;
738                         n->mcoderestart = m->mcode + nt->mcoderestart;
739                         thread_registercritical(n);
740                         n++;
741                         nt = nt->next;
742                 }
743         }
744 #endif
745 }
746
747
748 void dseg_display(methodinfo *m, codegendata *cd)
749 {
750         s4 *s4ptr;
751         s4 i;
752         
753         s4ptr = (s4 *) m->mcode;
754
755         printf("  --- dump of datasegment\n");
756         for (i = cd->dseglen; i > 0 ; i -= 4) {
757                 printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
758         }
759         printf("  --- begin of data segment: %p\n", s4ptr);
760 }
761
762
763 #if !defined(__POWERPC__)
764 /* reg_of_var:
765     This function determines a register, to which the result of an operation
766     should go, when it is ultimatively intended to store the result in
767     pseudoregister v.
768     If v is assigned to an actual register, this register will be returned.
769     Otherwise (when v is spilled) this function returns tempregnum.
770     If not already done, regoff and flags are set in the stack location.
771 */        
772
773 static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
774 {
775         varinfo *var;
776
777         switch (v->varkind) {
778         case TEMPVAR:
779                 if (!(v->flags & INMEMORY))
780                         return(v->regoff);
781                 break;
782         case STACKVAR:
783                 var = &(rd->interfaces[v->varnum][v->type]);
784                 v->regoff = var->regoff;
785                 if (!(var->flags & INMEMORY))
786                         return(var->regoff);
787                 break;
788         case LOCALVAR:
789                 var = &(rd->locals[v->varnum][v->type]);
790                 v->regoff = var->regoff;
791                 if (!(var->flags & INMEMORY))
792                         return(var->regoff);
793                 break;
794         case ARGVAR:
795                 v->regoff = v->varnum;
796                 if (IS_FLT_DBL_TYPE(v->type)) {
797                         if (v->varnum < rd->fltreg_argnum) {
798                                 v->regoff = rd->argfltregs[v->varnum];
799                                 return(rd->argfltregs[v->varnum]);
800                         }
801                 }
802                 else
803                         if (v->varnum < rd->intreg_argnum) {
804                                 v->regoff = rd->argintregs[v->varnum];
805                                 return (rd->argintregs[v->varnum]);
806                         }
807                 v->regoff -= rd->intreg_argnum;
808                 break;
809         }
810         v->flags |= INMEMORY;
811         return tempregnum;
812 }
813 #endif
814
815
816 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
817 static void codegen_threadcritrestart(codegendata *cd, int offset)
818 {
819         cd->threadcritcurrent.mcoderestart = offset;
820 }
821
822
823 static void codegen_threadcritstart(codegendata *cd, int offset)
824 {
825         cd->threadcritcurrent.mcodebegin = offset;
826 }
827
828
829 static void codegen_threadcritstop(codegendata *cd, int offset)
830 {
831         cd->threadcritcurrent.next = cd->threadcrit;
832         cd->threadcritcurrent.mcodeend = offset;
833         cd->threadcrit = DNEW(threadcritnodetemp);
834         *(cd->threadcrit) = cd->threadcritcurrent;
835         cd->threadcritcount++;
836 }
837 #endif
838
839
840 #ifndef STATIC_CLASSPATH
841 static size_t codegen_overloadPartLen(utf *desc) {
842         char *utf_ptr=desc->text;
843         u2 c;
844         size_t len=2;
845         while ((c=utf_nextu2(&utf_ptr))!=')') {
846                 switch (c) {
847                         case 'I':
848                         case 'S':
849                         case 'B':
850                         case 'C':
851                         case 'Z':
852                         case 'J':
853                         case 'F':
854                         case 'D':
855                                 len ++;
856                                 break;
857                         case '[':
858                                 len = len+2;
859                                 break;
860                         case 'L':
861                                 len++;
862                                 while ( (c=utf_nextu2(&utf_ptr)) != ';')
863                                         len++;
864                                 len=len+2;
865                                 break;
866                         case '(':
867                                 break;
868                         default: panic ("invalid method descriptor");
869                 }
870         }
871         return len;
872
873 }
874
875 static void codegen_fillInOverloadPart(char *target,utf *desc) {
876         char *utf_ptr=desc->text;
877         u2 c;
878         char* insertpos=&target[strlen(target)];
879         *(insertpos++)='_';
880         *(insertpos++)='_';
881         while ((c=utf_nextu2(&utf_ptr))!=')') {
882                 switch (c) {
883                         case 'I':
884                         case 'S':
885                         case 'B':
886                         case 'C':
887                         case 'Z':
888                         case 'J':
889                         case 'F':
890                         case 'D':
891                                 *(insertpos++)=c;
892                                 break;
893                         case '[':
894                                 *(insertpos++)='_';
895                                 *(insertpos++)='3';
896                                 break;
897                         case 'L':
898                                 *(insertpos++)='L';
899                                 while ( (c=utf_nextu2(&utf_ptr)) != ';')
900                                         if ( ((c>='a') && (c<='z'))  ||
901                                                 ((c>='A') && (c<='Z')) ||
902                                                 ((c>='0') && (c<='9')) )
903                                                         *(insertpos++)=c;
904                                         else *(insertpos++)='_';
905                                 *(insertpos++)='_';
906                                 *(insertpos++)='2';
907                                 break;
908                         case '(':
909                                 break;
910                         default: panic ("invalid method descriptor");
911                 }
912         }
913         *insertpos='\0';
914
915 }
916
917 static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
918   char *nativeName, *nativeNameEscape;
919   size_t nativeLen;
920   size_t i;
921
922   builtin_monitorenter((java_objectheader*) m);
923   if ((*jmpPatchTarget)==jmpTarget) {
924     builtin_monitorexit((java_objectheader*) m);
925     return;
926   }
927   log_text("trying to resolve a native method");
928   utf_display(m->class->name);
929   utf_display(m->name);
930   
931   void *lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL);
932   if (lib) {
933     int ok=0;
934     /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
935     nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
936     nativeName=MNEW(char,nativeLen);
937     sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
938         i=5;
939     while (i<nativeLen) {
940                 if (nativeName[i]=='_') { // escape underscore
941                         nativeNameEscape = MNEW(char,nativeLen+1);
942                         memcpy(nativeNameEscape,nativeName,i+1);
943                         nativeNameEscape[i+1] = '1'; // escape sequence for _ is _1
944                         memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
945                         MFREE(nativeName,char,nativeLen);
946                         i++;
947                         nativeLen++;
948                         nativeNameEscape[nativeLen]=0;
949                         nativeName=nativeNameEscape;
950                 }
951                 if (nativeName[i]=='/') nativeName[i]='_';
952                 i++;
953     } 
954
955 /*      printf("nativename: %s\n",nativeName); */
956
957     void *sym=dlsym(lib,nativeName);
958     if (sym) {
959       ok=1;
960       log_text("resolved");
961       MFREE(nativeName,char,nativeLen);
962     } else {
963       size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
964       char *overloadedNative=MNEW(char,overloadedNativeLen);
965       sprintf(overloadedNative,"%s",nativeName);
966       MFREE(nativeName,char,nativeLen);
967       codegen_fillInOverloadPart(overloadedNative,m->descriptor);
968       log_text("symbol not found,trying harder (overloaded member ?)");
969       sym=dlsym(lib,overloadedNative);
970       if (sym) {
971         MFREE(overloadedNative,char,overloadedNativeLen);
972         ok=1;
973         log_text("resolved");
974       } else { 
975          MFREE(overloadedNative,char,overloadedNativeLen);
976          log_text("It was not possible to find the native function implementation. Not even in overloading case");
977       }
978    }
979     if (ok) {
980       (*insertionPoint)=sym;
981       (*jmpPatchTarget)=jmpTarget;
982       builtin_monitorexit((java_objectheader *) m );
983       return;
984     }
985
986   } else log_text("library not found");
987   
988
989   {
990     char *info;
991     size_t slen;
992     slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
993     info=(char*)MNEW(char,slen);
994     sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
995     
996     builtin_monitorexit((java_objectheader *) m );
997     throw_cacao_exception_exit(string_java_lang_LinkageError,
998                                                        info);
999   }
1000   
1001 }
1002 #endif
1003
1004
1005 /*
1006  * These are local overrides for various environment variables in Emacs.
1007  * Please do not remove this and leave it at the end of the file, where
1008  * Emacs will automagically detect them.
1009  * ---------------------------------------------------------------------
1010  * Local variables:
1011  * mode: c
1012  * indent-tabs-mode: t
1013  * c-basic-offset: 4
1014  * tab-width: 4
1015  * End:
1016  */