1 /* jit/codegen.inc - architecture independent code generator
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,
9 This file is part of CACAO.
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.
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.
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
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Reinhard Grafl
31 Changes: Michael Gschwind
34 All functions assume the following code area / data area layout:
38 | code area | code area grows to higher addresses
40 +-----------+ <-- start of procedure
42 | data area | data area grows to lower addresses
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).
51 $Id: codegen.inc 883 2004-01-14 12:42:52Z stefan $
57 #include "toolbox/memory.h"
58 #include "toolbox/loging.h"
59 #include "threads/thread.h"
62 /************************* critical sections *********************************/
64 struct threadcritnodetemp {
65 struct threadcritnodetemp *next;
66 int mcodebegin, mcodeend;
69 #define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
70 #define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
72 static u1* mcodebase = NULL; /* base pointer of code area */
73 static s4* mcodeend = NULL; /* pointer to end of code area */
74 static int mcodesize; /* complete size of code area (bytes) */
76 static u1* dsegtop = NULL; /* pointer to top (end) of data area */
77 static int dsegsize; /* complete size of data area (bytes) */
78 int dseglen; /* used size of data area (bytes) */
79 /* data area grows from top to bottom */
81 static jumpref *jumpreferences; /* list of jumptable target addresses */
82 static dataref *datareferences; /* list of data segment references */
83 static branchref *xboundrefs; /* list of bound check branches */
84 static branchref *xcheckarefs; /* list of array size check branches */
85 static branchref *xnullrefs; /* list of null check branches */
86 static branchref *xcastrefs; /* list of cast check branches */
87 static branchref *xdivrefs; /* list of divide by zero branches */
89 static struct threadcritnodetemp *threadcrit;
90 /* List of critical code regions */
91 static struct threadcritnodetemp threadcritcurrent;
92 static int threadcritcount; /* Number of critical regions */
94 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
96 void codegen_init(); /* allocates code and data area */
97 void codegen_close(); /* releases temporary storage */
98 static void codegen_finish(); /* makes code and data area permanent and */
99 /* updates branch references to code/data */
101 static s4 dseg_adds4(s4 value); /* adds an int to data area */
102 static s4 dseg_adds8(s8 value); /* adds an long to data area */
103 static s4 dseg_addfloat (float value); /* adds an float to data area */
104 static s4 dseg_adddouble(double value); /* adds an double to data area */
107 #define dseg_addaddress(value) dseg_adds8((s8)(value))
109 #define dseg_addaddress(value) dseg_adds4((s4)(value))
112 static void dseg_addtarget(basicblock *target);
113 static void dseg_adddata(u1 *ptr);
114 static void codegen_addreference(basicblock *target, void *branchptr);
115 static void codegen_addxboundrefs(void *branchptr);
116 static void codegen_addxnullrefs(void *branchptr);
117 static void codegen_addxcastrefs(void *branchptr);
118 static void codegen_addxdivrefs(void *branchptr);
119 static void codegen_threadcritstart(int offset);
120 static void codegen_threadcritstop(int offset);
122 void dseg_display(s4 *s4ptr);
126 /* codegen_init allocates and initialises code area, data area and references */
131 mcodebase = MNEW(u1, MCODEINITSIZE);
132 mcodesize = MCODEINITSIZE;
136 dsegtop = MNEW(u1, DSEGINITSIZE);
137 dsegsize = DSEGINITSIZE;
143 jumpreferences = NULL;
144 datareferences = NULL;
150 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
151 threadcritcurrent.next = NULL;
158 /* codegen_close releases temporary code and data area */
163 MFREE(mcodebase, u1, mcodesize);
168 MFREE(dsegtop - dsegsize, u1, dsegsize);
175 /* codegen_increase doubles code area */
177 static s4 *codegen_increase(u1 *codeptr)
181 len = codeptr - mcodebase;
182 mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
184 mcodeend = (s4*) (mcodebase + mcodesize);
185 return (s4*) (mcodebase + len);
190 /* desg_increase doubles data area */
192 static void dseg_increase()
194 u1 *newstorage = MNEW(u1, dsegsize * 2);
195 memcpy(newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
196 MFREE(dsegtop - dsegsize, u1, dsegsize);
197 dsegtop = newstorage;
204 static s4 dseg_adds4_increase(s4 value)
207 *((s4 *) (dsegtop - dseglen)) = value;
213 static s4 dseg_adds4(s4 value)
218 dataptr = (s4 *) (dsegtop - dseglen);
219 if (dseglen > dsegsize)
220 return dseg_adds4_increase(value);
227 static s4 dseg_adds8_increase(s8 value)
230 *((s8 *) (dsegtop - dseglen)) = value;
236 static s4 dseg_adds8(s8 value)
240 dseglen = ALIGN (dseglen + 8, 8);
241 dataptr = (s8 *) (dsegtop - dseglen);
242 if (dseglen > dsegsize)
243 return dseg_adds8_increase(value);
250 static s4 dseg_addfloat_increase(float value)
253 *((float *) (dsegtop - dseglen)) = value;
259 static s4 dseg_addfloat(float value)
264 dataptr = (float *) (dsegtop - dseglen);
265 if (dseglen > dsegsize)
266 return dseg_addfloat_increase(value);
273 static s4 dseg_adddouble_increase(double value)
276 *((double *) (dsegtop - dseglen)) = value;
282 static s4 dseg_adddouble(double value)
286 dseglen = ALIGN (dseglen + 8, 8);
287 dataptr = (double *) (dsegtop - dseglen);
288 if (dseglen > dsegsize)
289 return dseg_adddouble_increase(value);
296 static void dseg_addtarget(basicblock *target)
298 jumpref *jr = DNEW(jumpref);
300 jr->tablepos = dseg_addaddress(NULL);
302 jr->next = jumpreferences;
308 static void dseg_adddata(u1 *ptr)
310 dataref *dr = DNEW(dataref);
312 dr->pos = (u1 *) (ptr - mcodebase);
313 dr->next = datareferences;
319 static void codegen_addreference(basicblock *target, void *branchptr)
321 s4 branchpos = (u1*) branchptr - mcodebase;
323 if (target->mpc >= 0) {
324 gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
327 branchref *br = DNEW(branchref);
329 br->branchpos = branchpos;
330 br->next = target->branchrefs;
331 target->branchrefs= br;
337 static void codegen_addxboundrefs(void *branchptr)
339 s4 branchpos = (u1*) branchptr - mcodebase;
341 branchref *br = DNEW(branchref);
343 br->branchpos = branchpos;
344 br->next = xboundrefs;
350 static void codegen_addxcheckarefs(void *branchptr)
352 s4 branchpos = (u1*) branchptr - mcodebase;
354 branchref *br = DNEW(branchref);
356 br->branchpos = branchpos;
357 br->next = xcheckarefs;
363 static void codegen_addxnullrefs(void *branchptr)
365 s4 branchpos = (u1*) branchptr - mcodebase;
367 branchref *br = DNEW(branchref);
369 br->branchpos = branchpos;
370 br->next = xnullrefs;
376 static void codegen_addxcastrefs(void *branchptr)
378 s4 branchpos = (u1*) branchptr - mcodebase;
380 branchref *br = DNEW(branchref);
382 br->branchpos = branchpos;
383 br->next = xcastrefs;
389 static void codegen_addxdivrefs(void *branchptr)
391 s4 branchpos = (u1*) branchptr - mcodebase;
393 branchref *br = DNEW(branchref);
395 br->branchpos = branchpos;
402 static void codegen_finish(int mcodelen)
409 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
410 extralen += sizeof(threadcritnode) * threadcritcount;
413 count_code_len += mcodelen;
414 count_data_len += dseglen;
416 dseglen = ALIGN(dseglen, MAX_ALIGN);
418 method -> mcodelength = mcodelen + dseglen;
419 method -> mcode = CNEW(u1, mcodelen + dseglen + extralen);
421 memcpy ( method->mcode, dsegtop - dseglen, dseglen);
422 memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
424 method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
426 /* jump table resolving */
429 *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
433 #if defined(__I386__) || defined(__X86_64__)
436 /* add method into datastructure to find the entrypoint */
437 addmethod(method->entrypoint, method->entrypoint + mcodelen);
439 /* data segment references resolving */
442 *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
448 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
450 threadcritnode *n = (threadcritnode*) (method->mcode + mcodelen + dseglen);
452 struct threadcritnodetemp *nt = threadcrit;
454 for (i=0; i<threadcritcount; i++)
456 n->mcodebegin = method->mcode + nt->mcodebegin;
457 n->mcodeend = method->mcode + nt->mcodeend;
458 thread_registercritical(n);
468 void dseg_display(s4 *s4ptr)
472 printf(" --- dump of datasegment\n");
473 for (i = dseglen; i > 0 ; i -= 4) {
474 printf("-%6x: %8x\n", i, (int)(*s4ptr++));
476 printf(" --- begin of data segment: %p\n", s4ptr);
479 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
480 void codegen_threadcritstart(int offset)
482 threadcritcurrent.mcodebegin = offset;
485 void codegen_threadcritstop(int offset)
487 threadcritcurrent.next = threadcrit;
488 threadcritcurrent.mcodeend = offset;
489 threadcrit = DNEW(struct threadcritnodetemp);
490 *threadcrit = threadcritcurrent;
496 * These are local overrides for various environment variables in Emacs.
497 * Please do not remove this and leave it at the end of the file, where
498 * Emacs will automagically detect them.
499 * ---------------------------------------------------------------------
502 * indent-tabs-mode: t