Initial revision
[cacao.git] / comp / 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: 1997/04/13
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 #include <sys/mman.h>
38 #include <errno.h>
39
40 #define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
41 #define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
42
43 static u1* mcodebase = NULL;        /* base pointer of code area              */
44 static int mcodesize;               /* complete size of code area (bytes)     */
45 static int mcodelen;                /* used size of code area (bytes)         */
46
47 static u1* dsegtop = NULL;          /* pointer to top (end) of data area      */
48 static int dsegsize;                /* complete size of data area (bytes)     */
49 static int dseglen;                 /* used size of data area (bytes)         */
50                                     /* data area grows from top to bottom     */
51
52 static list mcodereferences;        /* list of branch instruction adresses    */
53                                     /* and of jumptable target addresses      */
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 static void mcode_adds4(s4 code);   /* adds an instruction to code area       */
60
61 static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
62 static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
63 static s4 dseg_addfloat (float value);  /* adds an float to data area         */
64 static s4 dseg_adddouble(double value); /* adds an double to data area        */
65
66 /*     s4 dseg_addaddress(void* value); */
67 static s4 dseg_addtarget(basicblock *target);
68 static void mcode_addreference(basicblock *target);
69 static void dseg_display();
70
71 /* mcode_init allocates and initialises code area, data area and references   */
72
73 static void mcode_init()
74 {
75         if (!mcodebase) {
76                 mcodebase = MNEW (u1, MCODEINITSIZE);
77                 mcodesize = MCODEINITSIZE;
78                 }
79
80         if (!dsegtop) {
81                 dsegtop = MNEW (u1, DSEGINITSIZE);
82                 dsegsize = DSEGINITSIZE;
83                 dsegtop += dsegsize;
84                 }
85
86         mcodelen = 0;
87         dseglen = 0;
88
89         list_init (&mcodereferences, OFFSET(mcodereference, linkage) );
90 }
91
92
93 /* mcode_close releases temporary code and data area                          */
94
95 static void mcode_close()
96 {
97         if (mcodebase) {
98                 MFREE (mcodebase, u1, mcodesize);
99                 mcodebase = NULL;
100                 }
101         if (dsegtop) {
102                 MFREE (dsegtop - dsegsize, u1, dsegsize);
103                 dsegtop = NULL;
104                 }
105 }
106
107
108 /* mcode_adds4_increase doubles code area and adds instruction                */
109
110 static void mcode_adds4_increase(s4 code)
111 {
112         mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
113         mcodesize *= 2;
114         *((s4 *) (mcodebase + mcodelen - 4)) = code;
115 }
116
117
118 /* mcode_adds4 checks code area size and adds instruction                     */
119
120 static void mcode_adds4(s4 code)
121 {
122         s4 *codeptr;
123
124         codeptr = (s4 *) (mcodebase + mcodelen);
125         mcodelen += 4;
126         if (mcodelen <= mcodesize)
127                 *codeptr = code;
128         else
129                 mcode_adds4_increase(code);
130 }
131
132
133 /* desg_increase doubles data area                                            */
134
135 static void dseg_increase() {
136         u1 *newstorage = MNEW (u1, dsegsize * 2);
137         memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
138         MFREE (dsegtop - dsegsize, u1, dsegsize);
139         dsegtop = newstorage;
140         dsegsize *= 2;
141         dsegtop += dsegsize;
142 }
143
144
145 static s4 dseg_adds4_increase(s4 value)
146 {
147         dseg_increase();
148         *((s4 *) (dsegtop - dseglen)) = value;
149         return -dseglen;
150 }
151
152
153 static s4 dseg_adds4(s4 value)
154 {
155         s4 *dataptr;
156
157         dseglen += 4;
158         dataptr = (s4 *) (dsegtop - dseglen);
159         if (dseglen > dsegsize)
160                 return dseg_adds4_increase(value);
161         *dataptr = value;
162         return -dseglen;
163 }
164
165
166 static s4 dseg_adds8_increase(s8 value)
167 {
168         dseg_increase();
169         *((s8 *) (dsegtop - dseglen)) = value;
170         return -dseglen;
171 }
172
173
174 static s4 dseg_adds8(s8 value)
175 {
176         s8 *dataptr;
177
178         dseglen = ALIGN (dseglen + 8, 8);
179         dataptr = (s8 *) (dsegtop - dseglen);
180         if (dseglen > dsegsize)
181                 return dseg_adds8_increase(value);
182         *dataptr = value;
183         return -dseglen;
184 }
185
186
187 static s4 dseg_addfloat_increase(float value)
188 {
189         dseg_increase();
190         *((float *) (dsegtop - dseglen)) = value;
191         return -dseglen;
192 }
193
194
195 static s4 dseg_addfloat(float value)
196 {
197         float *dataptr;
198
199         dseglen += 4;
200         dataptr = (float *) (dsegtop - dseglen);
201         if (dseglen > dsegsize)
202                 return dseg_addfloat_increase(value);
203         *dataptr = value;
204         return -dseglen;
205 }
206
207
208 static s4 dseg_adddouble_increase(double value)
209 {
210         dseg_increase();
211         *((double *) (dsegtop - dseglen)) = value;
212         return -dseglen;
213 }
214
215
216 static s4 dseg_adddouble(double value)
217 {
218         double *dataptr;
219
220         dseglen = ALIGN (dseglen + 8, 8);
221         dataptr = (double *) (dsegtop - dseglen);
222         if (dseglen > dsegsize)
223                 return dseg_adddouble_increase(value);
224         *dataptr = value;
225         return -dseglen;
226 }
227
228
229 #if POINTERSIZE==8
230 #define dseg_addaddress(value)      dseg_adds8((s8)(value))
231 #else
232 #define dseg_addaddress(value)      dseg_adds4((s4)(value))
233 #endif
234
235
236 static s4 dseg_addtarget(basicblock *target)
237 {
238         mcodereference *cr = DNEW(mcodereference);
239
240         dseglen = ALIGN (dseglen + sizeof(void*), sizeof(void*));
241         if (dseglen > dsegsize)
242                 dseg_increase();
243
244         cr -> incode = false;
245         cr -> msourcepos = -dseglen;
246         cr -> target = target;
247         
248         list_addlast (&mcodereferences, cr);
249
250         return -dseglen;
251 }
252
253
254 static void mcode_addreference(basicblock *target)
255 {
256         mcodereference *cr = DNEW(mcodereference);
257         
258         cr -> incode = true;
259         cr -> msourcepos = mcodelen;
260         cr -> target = target;
261         
262         list_addlast (&mcodereferences, cr);
263 }
264
265
266
267 static void mcode_blockstart (basicblock *b)
268 {
269         b -> mpc = mcodelen;
270 }
271
272
273
274 static void gen_resolvebranch(void* mcodepiece, s4 sourcepos, s4 targetpos);
275
276 static void mcode_finish()
277 {
278         mcodereference *cr;
279
280         count_code_len += mcodelen;
281         count_data_len += dseglen;
282
283         dseglen = ALIGN(dseglen, MAX_ALIGN);
284
285         method->mcodelength = mcodelen + dseglen;
286         method->mcode = CNEW(u1, mcodelen + dseglen);
287
288         memcpy ( method->mcode, dsegtop - dseglen, dseglen);
289         memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
290
291         method -> entrypoint = (u1*) (method->mcode + dseglen);
292
293                 cr = list_first (&mcodereferences);
294         while (cr != NULL) {
295
296                 if (cr->incode) {  /* branch resolving */
297                         gen_resolvebranch ( ((u1*)(method->entrypoint)) + cr->msourcepos, 
298                                     cr->msourcepos,
299                                         cr->target->mpc);
300                         }
301                 else {             /* jump table resolving */
302                         void **p;
303                         p = (void**) ( ((u1*)(method->entrypoint)) + cr->msourcepos);
304
305                         *p = ((u1*)(method->entrypoint)) + cr->target->mpc;
306                         }
307
308                 cr = list_next (&mcodereferences, cr);
309                 }
310
311 #ifdef CACHE_FLUSH_BLOCK
312         synchronize_caches(method->mcode, (mcodelen>>2));
313 #endif
314         
315 }
316
317
318 static void dseg_display()
319 {
320         int i;
321         printf ("  --- dump of datasegment\n");
322         for (i = dseglen - 4; i >= 0 ; i -= 4) {
323                 printf ("%6x: %8x\n", i, (int)(*((s4*)(dsegtop - i))));
324                 }
325 }