Initial revision
[cacao.git] / ncomp / 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
54 static void mcode_init();           /* allocates code and data area           */
55 static void mcode_close();          /* releases temporary storage             */
56 static void mcode_finish();         /* makes code and data area permanent and */
57                                     /* updates branch references to code/data */
58
59 static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
60 static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
61 static s4 dseg_addfloat (float value);  /* adds an float to data area         */
62 static s4 dseg_adddouble(double value); /* adds an double to data area        */
63
64 #if POINTERSIZE==8
65 #define dseg_addaddress(value)      dseg_adds8((s8)(value))
66 #else
67 #define dseg_addaddress(value)      dseg_adds4((s4)(value))
68 #endif
69
70 static void dseg_addtarget(basicblock *target);
71 static void mcode_addreference(basicblock *target, void *branchptr);
72 static void mcode_addxboundrefs(void *branchptr);
73 static void mcode_addxnullrefs(void *branchptr);
74
75 static void dseg_display(s4 *s4ptr);
76
77 /* mcode_init allocates and initialises code area, data area and references   */
78
79 static void mcode_init()
80 {
81         if (!mcodebase) {
82                 mcodebase = MNEW (u1, MCODEINITSIZE);
83                 mcodesize = MCODEINITSIZE;
84                 }
85
86         if (!dsegtop) {
87                 dsegtop = MNEW (u1, DSEGINITSIZE);
88                 dsegsize = DSEGINITSIZE;
89                 dsegtop += dsegsize;
90                 }
91
92         dseglen = 0;
93
94         jumpreferences = NULL;
95         xboundrefs = NULL;
96         xnullrefs = NULL;
97 }
98
99
100 /* mcode_close releases temporary code and data area                          */
101
102 static void mcode_close()
103 {
104         if (mcodebase) {
105                 MFREE (mcodebase, u1, mcodesize);
106                 mcodebase = NULL;
107                 }
108         if (dsegtop) {
109                 MFREE (dsegtop - dsegsize, u1, dsegsize);
110                 dsegtop = NULL;
111                 }
112 }
113
114
115 /* mcode_increase doubles code area                                           */
116
117 static s4 *mcode_increase(u1 *codeptr)
118 {
119         long len;
120
121         len = codeptr - mcodebase;
122         mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
123         mcodesize *= 2;
124         mcodeend = (s4*) (mcodebase + mcodesize);
125         return (s4*) (mcodebase + len);
126 }
127
128
129 /* desg_increase doubles data area                                            */
130
131 static void dseg_increase() {
132         u1 *newstorage = MNEW (u1, dsegsize * 2);
133         memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
134         MFREE (dsegtop - dsegsize, u1, dsegsize);
135         dsegtop = newstorage;
136         dsegsize *= 2;
137         dsegtop += dsegsize;
138 }
139
140
141 static s4 dseg_adds4_increase(s4 value)
142 {
143         dseg_increase();
144         *((s4 *) (dsegtop - dseglen)) = value;
145         return -dseglen;
146 }
147
148
149 static s4 dseg_adds4(s4 value)
150 {
151         s4 *dataptr;
152
153         dseglen += 4;
154         dataptr = (s4 *) (dsegtop - dseglen);
155         if (dseglen > dsegsize)
156                 return dseg_adds4_increase(value);
157         *dataptr = value;
158         return -dseglen;
159 }
160
161
162 static s4 dseg_adds8_increase(s8 value)
163 {
164         dseg_increase();
165         *((s8 *) (dsegtop - dseglen)) = value;
166         return -dseglen;
167 }
168
169
170 static s4 dseg_adds8(s8 value)
171 {
172         s8 *dataptr;
173
174         dseglen = ALIGN (dseglen + 8, 8);
175         dataptr = (s8 *) (dsegtop - dseglen);
176         if (dseglen > dsegsize)
177                 return dseg_adds8_increase(value);
178         *dataptr = value;
179         return -dseglen;
180 }
181
182
183 static s4 dseg_addfloat_increase(float value)
184 {
185         dseg_increase();
186         *((float *) (dsegtop - dseglen)) = value;
187         return -dseglen;
188 }
189
190
191 static s4 dseg_addfloat(float value)
192 {
193         float *dataptr;
194
195         dseglen += 4;
196         dataptr = (float *) (dsegtop - dseglen);
197         if (dseglen > dsegsize)
198                 return dseg_addfloat_increase(value);
199         *dataptr = value;
200         return -dseglen;
201 }
202
203
204 static s4 dseg_adddouble_increase(double value)
205 {
206         dseg_increase();
207         *((double *) (dsegtop - dseglen)) = value;
208         return -dseglen;
209 }
210
211
212 static s4 dseg_adddouble(double value)
213 {
214         double *dataptr;
215
216         dseglen = ALIGN (dseglen + 8, 8);
217         dataptr = (double *) (dsegtop - dseglen);
218         if (dseglen > dsegsize)
219                 return dseg_adddouble_increase(value);
220         *dataptr = value;
221         return -dseglen;
222 }
223
224
225 static void dseg_addtarget(basicblock *target)
226 {
227         jumpref *jr = DNEW(jumpref);
228
229         jr->tablepos = dseg_addaddress(NULL);
230         jr->target = target;
231         jr->next = jumpreferences;
232         jumpreferences = jr;
233 }
234
235
236 static void mcode_addreference(basicblock *target, void *branchptr)
237 {
238         s4 branchpos = (u1*) branchptr - mcodebase;
239
240         if (target->mpc >= 0) {
241                 gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
242                 }
243         else {
244                 branchref *br = DNEW(branchref);
245
246                 br->branchpos = branchpos;
247                 br->next = target->branchrefs;
248                 target->branchrefs= br;
249                 }
250 }
251
252
253 static void mcode_addxboundrefs(void *branchptr)
254 {
255         s4 branchpos = (u1*) branchptr - mcodebase;
256
257         branchref *br = DNEW(branchref);
258
259         br->branchpos = branchpos;
260         br->next = xboundrefs;
261         xboundrefs = br;
262 }
263
264
265 static void mcode_addxcheckarefs(void *branchptr)
266 {
267         s4 branchpos = (u1*) branchptr - mcodebase;
268
269         branchref *br = DNEW(branchref);
270
271         br->branchpos = branchpos;
272         br->next = xcheckarefs;
273         xcheckarefs = br;
274 }
275
276
277 static void mcode_addxnullrefs(void *branchptr)
278 {
279         s4 branchpos = (u1*) branchptr - mcodebase;
280
281         branchref *br = DNEW(branchref);
282
283         br->branchpos = branchpos;
284         br->next = xnullrefs;
285         xnullrefs = br;
286 }
287
288
289 static void mcode_finish(int mcodelen)
290 {
291         jumpref *jr;
292         u1 *epoint;
293
294         count_code_len += mcodelen;
295         count_data_len += dseglen;
296
297         dseglen = ALIGN(dseglen, MAX_ALIGN);
298
299         method -> mcodelength = mcodelen + dseglen;
300         method -> mcode = CNEW(u1, mcodelen + dseglen);
301
302         memcpy ( method->mcode, dsegtop - dseglen, dseglen);
303         memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
304
305         method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
306
307         /* jump table resolving */
308
309         jr = jumpreferences;
310         while (jr != NULL) {
311                 *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
312                 jr = jr->next;
313                 }
314
315 #ifdef CACHE_FLUSH_BLOCK
316         synchronize_caches(method->mcode, (mcodelen>>2));
317 #endif
318         
319 }
320
321
322 static void dseg_display(s4 *s4ptr)
323 {
324         int i;
325         
326         printf("  --- dump of datasegment\n");
327         for (i = dseglen; i > 0 ; i -= 4) {
328                 printf("-%6x: %8x\n", i, (int)(*s4ptr++));
329                 }
330         printf("  --- begin of data segment: %p\n", s4ptr);
331 }