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 557 2003-11-02 22:51:59Z twisti $
56 #include "toolbox/memory.h"
57 #include "toolbox/loging.h"
60 #define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
61 #define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
63 static u1* mcodebase = NULL; /* base pointer of code area */
64 static s4* mcodeend = NULL; /* pointer to end of code area */
65 static int mcodesize; /* complete size of code area (bytes) */
67 static u1* dsegtop = NULL; /* pointer to top (end) of data area */
68 static int dsegsize; /* complete size of data area (bytes) */
69 int dseglen; /* used size of data area (bytes) */
70 /* data area grows from top to bottom */
72 static jumpref *jumpreferences; /* list of jumptable target addresses */
73 static dataref *datareferences; /* list of data segment references */
74 static branchref *xboundrefs; /* list of bound check branches */
75 static branchref *xcheckarefs; /* list of array size check branches */
76 static branchref *xnullrefs; /* list of null check branches */
77 static branchref *xcastrefs; /* list of cast check branches */
78 static branchref *xdivrefs; /* list of divide by zero branches */
80 void codegen_init(); /* allocates code and data area */
81 void codegen_close(); /* releases temporary storage */
82 static void codegen_finish(); /* makes code and data area permanent and */
83 /* updates branch references to code/data */
85 static s4 dseg_adds4(s4 value); /* adds an int to data area */
86 static s4 dseg_adds8(s8 value); /* adds an long to data area */
87 static s4 dseg_addfloat (float value); /* adds an float to data area */
88 static s4 dseg_adddouble(double value); /* adds an double to data area */
91 #define dseg_addaddress(value) dseg_adds8((s8)(value))
93 #define dseg_addaddress(value) dseg_adds4((s4)(value))
96 static void dseg_addtarget(basicblock *target);
97 static void dseg_adddata(u1 *ptr);
98 static void codegen_addreference(basicblock *target, void *branchptr);
99 static void codegen_addxboundrefs(void *branchptr);
100 static void codegen_addxnullrefs(void *branchptr);
101 static void codegen_addxcastrefs(void *branchptr);
102 static void codegen_addxdivrefs(void *branchptr);
104 void dseg_display(s4 *s4ptr);
108 /* codegen_init allocates and initialises code area, data area and references */
113 mcodebase = MNEW(u1, MCODEINITSIZE);
114 mcodesize = MCODEINITSIZE;
118 dsegtop = MNEW(u1, DSEGINITSIZE);
119 dsegsize = DSEGINITSIZE;
125 jumpreferences = NULL;
126 datareferences = NULL;
135 /* codegen_close releases temporary code and data area */
140 MFREE(mcodebase, u1, mcodesize);
145 MFREE(dsegtop - dsegsize, u1, dsegsize);
152 /* codegen_increase doubles code area */
154 static s4 *codegen_increase(u1 *codeptr)
158 len = codeptr - mcodebase;
159 mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
161 mcodeend = (s4*) (mcodebase + mcodesize);
162 return (s4*) (mcodebase + len);
167 /* desg_increase doubles data area */
169 static void dseg_increase()
171 u1 *newstorage = MNEW(u1, dsegsize * 2);
172 memcpy(newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
173 MFREE(dsegtop - dsegsize, u1, dsegsize);
174 dsegtop = newstorage;
181 static s4 dseg_adds4_increase(s4 value)
184 *((s4 *) (dsegtop - dseglen)) = value;
190 static s4 dseg_adds4(s4 value)
195 dataptr = (s4 *) (dsegtop - dseglen);
196 if (dseglen > dsegsize)
197 return dseg_adds4_increase(value);
204 static s4 dseg_adds8_increase(s8 value)
207 *((s8 *) (dsegtop - dseglen)) = value;
213 static s4 dseg_adds8(s8 value)
217 dseglen = ALIGN (dseglen + 8, 8);
218 dataptr = (s8 *) (dsegtop - dseglen);
219 if (dseglen > dsegsize)
220 return dseg_adds8_increase(value);
227 static s4 dseg_addfloat_increase(float value)
230 *((float *) (dsegtop - dseglen)) = value;
236 static s4 dseg_addfloat(float value)
241 dataptr = (float *) (dsegtop - dseglen);
242 if (dseglen > dsegsize)
243 return dseg_addfloat_increase(value);
250 static s4 dseg_adddouble_increase(double value)
253 *((double *) (dsegtop - dseglen)) = value;
259 static s4 dseg_adddouble(double value)
263 dseglen = ALIGN (dseglen + 8, 8);
264 dataptr = (double *) (dsegtop - dseglen);
265 if (dseglen > dsegsize)
266 return dseg_adddouble_increase(value);
273 static void dseg_addtarget(basicblock *target)
275 jumpref *jr = DNEW(jumpref);
277 jr->tablepos = dseg_addaddress(NULL);
279 jr->next = jumpreferences;
285 static void dseg_adddata(u1 *ptr)
287 dataref *dr = DNEW(dataref);
289 dr->pos = (u1 *) (ptr - mcodebase);
290 dr->next = datareferences;
296 static void codegen_addreference(basicblock *target, void *branchptr)
298 s4 branchpos = (u1*) branchptr - mcodebase;
300 if (target->mpc >= 0) {
301 gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
304 branchref *br = DNEW(branchref);
306 br->branchpos = branchpos;
307 br->next = target->branchrefs;
308 target->branchrefs= br;
314 static void codegen_addxboundrefs(void *branchptr)
316 s4 branchpos = (u1*) branchptr - mcodebase;
318 branchref *br = DNEW(branchref);
320 br->branchpos = branchpos;
321 br->next = xboundrefs;
327 static void codegen_addxcheckarefs(void *branchptr)
329 s4 branchpos = (u1*) branchptr - mcodebase;
331 branchref *br = DNEW(branchref);
333 br->branchpos = branchpos;
334 br->next = xcheckarefs;
340 static void codegen_addxnullrefs(void *branchptr)
342 s4 branchpos = (u1*) branchptr - mcodebase;
344 branchref *br = DNEW(branchref);
346 br->branchpos = branchpos;
347 br->next = xnullrefs;
353 static void codegen_addxcastrefs(void *branchptr)
355 s4 branchpos = (u1*) branchptr - mcodebase;
357 branchref *br = DNEW(branchref);
359 br->branchpos = branchpos;
360 br->next = xcastrefs;
366 static void codegen_addxdivrefs(void *branchptr)
368 s4 branchpos = (u1*) branchptr - mcodebase;
370 branchref *br = DNEW(branchref);
372 br->branchpos = branchpos;
379 static void codegen_finish(int mcodelen)
384 count_code_len += mcodelen;
385 count_data_len += dseglen;
387 dseglen = ALIGN(dseglen, MAX_ALIGN);
389 method -> mcodelength = mcodelen + dseglen;
390 method -> mcode = CNEW(u1, mcodelen + dseglen);
392 memcpy ( method->mcode, dsegtop - dseglen, dseglen);
393 memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
395 method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
397 /* jump table resolving */
400 *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
404 #if defined(__I386__) || defined(__X86_64__)
407 /* add method into datastructure to find the entrypoint */
408 addmethod(method->entrypoint, method->entrypoint + mcodelen);
410 /* data segment references resolving */
413 *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
422 void dseg_display(s4 *s4ptr)
426 printf(" --- dump of datasegment\n");
427 for (i = dseglen; i > 0 ; i -= 4) {
428 printf("-%6x: %8x\n", i, (int)(*s4ptr++));
430 printf(" --- begin of data segment: %p\n", s4ptr);
435 * These are local overrides for various environment variables in Emacs.
436 * Please do not remove this and leave it at the end of the file, where
437 * Emacs will automagically detect them.
438 * ---------------------------------------------------------------------
441 * indent-tabs-mode: t