narray first check in
[cacao.git] / jit / mcode.c
1 /***************************** comp/mcode.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 file is an include file for "compiler.c" . It contains (mostly)
8         architecture independent functions for writing instructions into the
9         code area and constants into the data area.
10
11         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
12                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
13         Changes: Micheal Gschwind    EMAIL: cacao@complang.tuwien.ac.at
14
15         Last Change: 1998/08/10
16
17
18         All functions assume the following code area / data area layout:
19
20         +-----------+
21         |           |
22         | code area | code area grows to higher addresses
23         |           |
24         +-----------+ <-- start of procedure
25         |           |
26         | data area | data area grows to lower addresses
27         |           |
28         +-----------+
29
30         The functions first write into a temporary code/data area allocated by
31         "mcode_init". "mcode_finish" copies the code and data area into permanent
32         memory. All functions writing values into the data area return the offset
33         relative the begin of the code area (start of procedure).       
34
35 *******************************************************************************/
36
37 #define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
38 #define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
39
40 static u1* mcodebase = NULL;        /* base pointer of code area              */
41 static s4* mcodeend  = NULL;        /* pointer to end of code area            */
42 static int mcodesize;               /* complete size of code area (bytes)     */
43
44 static u1* dsegtop = NULL;          /* pointer to top (end) of data area      */
45 static int dsegsize;                /* complete size of data area (bytes)     */
46 static int dseglen;                 /* used size of data area (bytes)         */
47                                     /* data area grows from top to bottom     */
48
49 static jumpref *jumpreferences;     /* list of jumptable target addresses     */
50 static branchref *xboundrefs;       /* list of bound check branches           */
51 static branchref *xcheckarefs;      /* list of array size check branches      */
52 static branchref *xnullrefs;        /* list of null check branches            */
53 static branchref *xcastrefs;        /* list of cast check branches            */
54
55 static void mcode_init();           /* allocates code and data area           */
56 static void mcode_close();          /* releases temporary storage             */
57 static void mcode_finish();         /* makes code and data area permanent and */
58                                     /* updates branch references to code/data */
59
60 static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
61 static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
62 static s4 dseg_addfloat (float value);  /* adds an float to data area         */
63 static s4 dseg_adddouble(double value); /* adds an double to data area        */
64
65 #if POINTERSIZE==8
66 #define dseg_addaddress(value)      dseg_adds8((s8)(value))
67 #else
68 #define dseg_addaddress(value)      dseg_adds4((s4)(value))
69 #endif
70
71 static void dseg_addtarget(basicblock *target);
72 static void mcode_addreference(basicblock *target, void *branchptr);
73 static void mcode_addxboundrefs(void *branchptr);
74 static void mcode_addxnullrefs(void *branchptr);
75 static void mcode_addxcastrefs(void *branchptr);
76
77 static void dseg_display(s4 *s4ptr);
78
79 /* mcode_init allocates and initialises code area, data area and references   */
80
81 static void mcode_init()
82 {
83         if (!mcodebase) {
84                 mcodebase = MNEW (u1, MCODEINITSIZE);
85                 mcodesize = MCODEINITSIZE;
86                 }
87
88         if (!dsegtop) {
89                 dsegtop = MNEW (u1, DSEGINITSIZE);
90                 dsegsize = DSEGINITSIZE;
91                 dsegtop += dsegsize;
92                 }
93
94         dseglen = 0;
95
96         jumpreferences = NULL;
97         xboundrefs = NULL;
98         xnullrefs = NULL;
99         xcastrefs = NULL;
100 }
101
102
103 /* mcode_close releases temporary code and data area                          */
104
105 static void mcode_close()
106 {
107         if (mcodebase) {
108                 MFREE (mcodebase, u1, mcodesize);
109                 mcodebase = NULL;
110                 }
111         if (dsegtop) {
112                 MFREE (dsegtop - dsegsize, u1, dsegsize);
113                 dsegtop = NULL;
114                 }
115 }
116
117
118 /* mcode_increase doubles code area                                           */
119
120 static s4 *mcode_increase(u1 *codeptr)
121 {
122         long len;
123
124         len = codeptr - mcodebase;
125         mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
126         mcodesize *= 2;
127         mcodeend = (s4*) (mcodebase + mcodesize);
128         return (s4*) (mcodebase + len);
129 }
130
131
132 /* desg_increase doubles data area                                            */
133
134 static void dseg_increase() {
135         u1 *newstorage = MNEW (u1, dsegsize * 2);
136         memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
137         MFREE (dsegtop - dsegsize, u1, dsegsize);
138         dsegtop = newstorage;
139         dsegsize *= 2;
140         dsegtop += dsegsize;
141 }
142
143
144 static s4 dseg_adds4_increase(s4 value)
145 {
146         dseg_increase();
147         *((s4 *) (dsegtop - dseglen)) = value;
148         return -dseglen;
149 }
150
151
152 static s4 dseg_adds4(s4 value)
153 {
154         s4 *dataptr;
155
156         dseglen += 4;
157         dataptr = (s4 *) (dsegtop - dseglen);
158         if (dseglen > dsegsize)
159                 return dseg_adds4_increase(value);
160         *dataptr = value;
161         return -dseglen;
162 }
163
164
165 static s4 dseg_adds8_increase(s8 value)
166 {
167         dseg_increase();
168         *((s8 *) (dsegtop - dseglen)) = value;
169         return -dseglen;
170 }
171
172
173 static s4 dseg_adds8(s8 value)
174 {
175         s8 *dataptr;
176
177         dseglen = ALIGN (dseglen + 8, 8);
178         dataptr = (s8 *) (dsegtop - dseglen);
179         if (dseglen > dsegsize)
180                 return dseg_adds8_increase(value);
181         *dataptr = value;
182         return -dseglen;
183 }
184
185
186 static s4 dseg_addfloat_increase(float value)
187 {
188         dseg_increase();
189         *((float *) (dsegtop - dseglen)) = value;
190         return -dseglen;
191 }
192
193
194 static s4 dseg_addfloat(float value)
195 {
196         float *dataptr;
197
198         dseglen += 4;
199         dataptr = (float *) (dsegtop - dseglen);
200         if (dseglen > dsegsize)
201                 return dseg_addfloat_increase(value);
202         *dataptr = value;
203         return -dseglen;
204 }
205
206
207 static s4 dseg_adddouble_increase(double value)
208 {
209         dseg_increase();
210         *((double *) (dsegtop - dseglen)) = value;
211         return -dseglen;
212 }
213
214
215 static s4 dseg_adddouble(double value)
216 {
217         double *dataptr;
218
219         dseglen = ALIGN (dseglen + 8, 8);
220         dataptr = (double *) (dsegtop - dseglen);
221         if (dseglen > dsegsize)
222                 return dseg_adddouble_increase(value);
223         *dataptr = value;
224         return -dseglen;
225 }
226
227
228 static void dseg_addtarget(basicblock *target)
229 {
230         jumpref *jr = DNEW(jumpref);
231
232         jr->tablepos = dseg_addaddress(NULL);
233         jr->target = target;
234         jr->next = jumpreferences;
235         jumpreferences = jr;
236 }
237
238
239 static void mcode_addreference(basicblock *target, void *branchptr)
240 {
241         s4 branchpos = (u1*) branchptr - mcodebase;
242
243         if (target->mpc >= 0) {
244                 gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
245                 }
246         else {
247                 branchref *br = DNEW(branchref);
248
249                 br->branchpos = branchpos;
250                 br->next = target->branchrefs;
251                 target->branchrefs= br;
252                 }
253 }
254
255
256 static void mcode_addxboundrefs(void *branchptr)
257 {
258         s4 branchpos = (u1*) branchptr - mcodebase;
259
260         branchref *br = DNEW(branchref);
261
262         br->branchpos = branchpos;
263         br->next = xboundrefs;
264         xboundrefs = br;
265 }
266
267
268 static void mcode_addxcheckarefs(void *branchptr)
269 {
270         s4 branchpos = (u1*) branchptr - mcodebase;
271
272         branchref *br = DNEW(branchref);
273
274         br->branchpos = branchpos;
275         br->next = xcheckarefs;
276         xcheckarefs = br;
277 }
278
279
280 static void mcode_addxnullrefs(void *branchptr)
281 {
282         s4 branchpos = (u1*) branchptr - mcodebase;
283
284         branchref *br = DNEW(branchref);
285
286         br->branchpos = branchpos;
287         br->next = xnullrefs;
288         xnullrefs = br;
289 }
290
291
292 static void mcode_addxcastrefs(void *branchptr)
293 {
294         s4 branchpos = (u1*) branchptr - mcodebase;
295
296         branchref *br = DNEW(branchref);
297
298         br->branchpos = branchpos;
299         br->next = xcastrefs;
300         xcastrefs = br;
301 }
302
303
304 static void mcode_finish(int mcodelen)
305 {
306         jumpref *jr;
307         u1 *epoint;
308
309         count_code_len += mcodelen;
310         count_data_len += dseglen;
311
312         dseglen = ALIGN(dseglen, MAX_ALIGN);
313
314         method -> mcodelength = mcodelen + dseglen;
315         method -> mcode = CNEW(u1, mcodelen + dseglen);
316
317         memcpy ( method->mcode, dsegtop - dseglen, dseglen);
318         memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
319
320         method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
321
322         /* jump table resolving */
323
324         jr = jumpreferences;
325         while (jr != NULL) {
326             *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
327             jr = jr->next;
328             }
329 }
330
331
332 static void dseg_display(s4 *s4ptr)
333 {
334         int i;
335         
336         printf("  --- dump of datasegment\n");
337         for (i = dseglen; i > 0 ; i -= 4) {
338                 printf("-%6x: %8x\n", i, (int)(*s4ptr++));
339                 }
340         printf("  --- begin of data segment: %p\n", s4ptr);
341 }