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 592 2003-11-09 19:46:15Z twisti $
57 #include "toolbox/memory.h"
58 #include "toolbox/loging.h"
61 #define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
62 #define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
64 static u1* mcodebase = NULL; /* base pointer of code area */
65 static s4* mcodeend = NULL; /* pointer to end of code area */
66 static int mcodesize; /* complete size of code area (bytes) */
68 static u1* dsegtop = NULL; /* pointer to top (end) of data area */
69 static int dsegsize; /* complete size of data area (bytes) */
70 int dseglen; /* used size of data area (bytes) */
71 /* data area grows from top to bottom */
73 static jumpref *jumpreferences; /* list of jumptable target addresses */
74 static dataref *datareferences; /* list of data segment references */
75 static branchref *xboundrefs; /* list of bound check branches */
76 static branchref *xcheckarefs; /* list of array size check branches */
77 static branchref *xnullrefs; /* list of null check branches */
78 static branchref *xcastrefs; /* list of cast check branches */
79 static branchref *xdivrefs; /* list of divide by zero branches */
81 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
83 void codegen_init(); /* allocates code and data area */
84 void codegen_close(); /* releases temporary storage */
85 static void codegen_finish(); /* makes code and data area permanent and */
86 /* updates branch references to code/data */
88 static s4 dseg_adds4(s4 value); /* adds an int to data area */
89 static s4 dseg_adds8(s8 value); /* adds an long to data area */
90 static s4 dseg_addfloat (float value); /* adds an float to data area */
91 static s4 dseg_adddouble(double value); /* adds an double to data area */
94 #define dseg_addaddress(value) dseg_adds8((s8)(value))
96 #define dseg_addaddress(value) dseg_adds4((s4)(value))
99 static void dseg_addtarget(basicblock *target);
100 static void dseg_adddata(u1 *ptr);
101 static void codegen_addreference(basicblock *target, void *branchptr);
102 static void codegen_addxboundrefs(void *branchptr);
103 static void codegen_addxnullrefs(void *branchptr);
104 static void codegen_addxcastrefs(void *branchptr);
105 static void codegen_addxdivrefs(void *branchptr);
107 void dseg_display(s4 *s4ptr);
111 /* codegen_init allocates and initialises code area, data area and references */
116 mcodebase = MNEW(u1, MCODEINITSIZE);
117 mcodesize = MCODEINITSIZE;
121 dsegtop = MNEW(u1, DSEGINITSIZE);
122 dsegsize = DSEGINITSIZE;
128 jumpreferences = NULL;
129 datareferences = NULL;
138 /* codegen_close releases temporary code and data area */
143 MFREE(mcodebase, u1, mcodesize);
148 MFREE(dsegtop - dsegsize, u1, dsegsize);
155 /* codegen_increase doubles code area */
157 static s4 *codegen_increase(u1 *codeptr)
161 len = codeptr - mcodebase;
162 mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
164 mcodeend = (s4*) (mcodebase + mcodesize);
165 return (s4*) (mcodebase + len);
170 /* desg_increase doubles data area */
172 static void dseg_increase()
174 u1 *newstorage = MNEW(u1, dsegsize * 2);
175 memcpy(newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
176 MFREE(dsegtop - dsegsize, u1, dsegsize);
177 dsegtop = newstorage;
184 static s4 dseg_adds4_increase(s4 value)
187 *((s4 *) (dsegtop - dseglen)) = value;
193 static s4 dseg_adds4(s4 value)
198 dataptr = (s4 *) (dsegtop - dseglen);
199 if (dseglen > dsegsize)
200 return dseg_adds4_increase(value);
207 static s4 dseg_adds8_increase(s8 value)
210 *((s8 *) (dsegtop - dseglen)) = value;
216 static s4 dseg_adds8(s8 value)
220 dseglen = ALIGN (dseglen + 8, 8);
221 dataptr = (s8 *) (dsegtop - dseglen);
222 if (dseglen > dsegsize)
223 return dseg_adds8_increase(value);
230 static s4 dseg_addfloat_increase(float value)
233 *((float *) (dsegtop - dseglen)) = value;
239 static s4 dseg_addfloat(float value)
244 dataptr = (float *) (dsegtop - dseglen);
245 if (dseglen > dsegsize)
246 return dseg_addfloat_increase(value);
253 static s4 dseg_adddouble_increase(double value)
256 *((double *) (dsegtop - dseglen)) = value;
262 static s4 dseg_adddouble(double value)
266 dseglen = ALIGN (dseglen + 8, 8);
267 dataptr = (double *) (dsegtop - dseglen);
268 if (dseglen > dsegsize)
269 return dseg_adddouble_increase(value);
276 static void dseg_addtarget(basicblock *target)
278 jumpref *jr = DNEW(jumpref);
280 jr->tablepos = dseg_addaddress(NULL);
282 jr->next = jumpreferences;
288 static void dseg_adddata(u1 *ptr)
290 dataref *dr = DNEW(dataref);
292 dr->pos = (u1 *) (ptr - mcodebase);
293 dr->next = datareferences;
299 static void codegen_addreference(basicblock *target, void *branchptr)
301 s4 branchpos = (u1*) branchptr - mcodebase;
303 if (target->mpc >= 0) {
304 gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
307 branchref *br = DNEW(branchref);
309 br->branchpos = branchpos;
310 br->next = target->branchrefs;
311 target->branchrefs= br;
317 static void codegen_addxboundrefs(void *branchptr)
319 s4 branchpos = (u1*) branchptr - mcodebase;
321 branchref *br = DNEW(branchref);
323 br->branchpos = branchpos;
324 br->next = xboundrefs;
330 static void codegen_addxcheckarefs(void *branchptr)
332 s4 branchpos = (u1*) branchptr - mcodebase;
334 branchref *br = DNEW(branchref);
336 br->branchpos = branchpos;
337 br->next = xcheckarefs;
343 static void codegen_addxnullrefs(void *branchptr)
345 s4 branchpos = (u1*) branchptr - mcodebase;
347 branchref *br = DNEW(branchref);
349 br->branchpos = branchpos;
350 br->next = xnullrefs;
356 static void codegen_addxcastrefs(void *branchptr)
358 s4 branchpos = (u1*) branchptr - mcodebase;
360 branchref *br = DNEW(branchref);
362 br->branchpos = branchpos;
363 br->next = xcastrefs;
369 static void codegen_addxdivrefs(void *branchptr)
371 s4 branchpos = (u1*) branchptr - mcodebase;
373 branchref *br = DNEW(branchref);
375 br->branchpos = branchpos;
382 static void codegen_finish(int mcodelen)
387 count_code_len += mcodelen;
388 count_data_len += dseglen;
390 dseglen = ALIGN(dseglen, MAX_ALIGN);
392 method -> mcodelength = mcodelen + dseglen;
393 method -> mcode = CNEW(u1, mcodelen + dseglen);
395 memcpy ( method->mcode, dsegtop - dseglen, dseglen);
396 memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
398 method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
400 /* jump table resolving */
403 *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
407 #if defined(__I386__) || defined(__X86_64__)
410 /* add method into datastructure to find the entrypoint */
411 addmethod(method->entrypoint, method->entrypoint + mcodelen);
413 /* data segment references resolving */
416 *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
425 void dseg_display(s4 *s4ptr)
429 printf(" --- dump of datasegment\n");
430 for (i = dseglen; i > 0 ; i -= 4) {
431 printf("-%6x: %8x\n", i, (int)(*s4ptr++));
433 printf(" --- begin of data segment: %p\n", s4ptr);
438 * These are local overrides for various environment variables in Emacs.
439 * Please do not remove this and leave it at the end of the file, where
440 * Emacs will automagically detect them.
441 * ---------------------------------------------------------------------
444 * indent-tabs-mode: t