* src/vm/method.h (vm/jit/code.h): Added.
[cacao.git] / src / vm / jit / dseg.c
1 /* src/vm/jit/dseg.c - data segment handling stuff
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28             Andreas  Krall
29
30    Changes: Christian Thalinger
31             Joseph Wenninger
32                         Edwin Steiner
33
34    $Id: dseg.c 4699 2006-03-28 14:52:32Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42
43 #include "vm/types.h"
44
45 #include "mm/memory.h"
46 #include "vm/jit/codegen-common.h"
47
48
49 /* desg_increase ***************************************************************
50
51    Doubles data area.
52
53 *******************************************************************************/
54
55 void dseg_increase(codegendata *cd)
56 {
57         u1 *newstorage;
58
59         newstorage = DMNEW(u1, cd->dsegsize * 2);
60
61         MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
62                   cd->dsegsize);
63
64         cd->dsegtop   = newstorage;
65         cd->dsegsize *= 2;
66         cd->dsegtop  += cd->dsegsize;
67 }
68
69
70 s4 dseg_adds4_increase(codegendata *cd, s4 value)
71 {
72         dseg_increase(cd);
73
74         *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
75
76         return -(cd->dseglen);
77 }
78
79
80 s4 dseg_adds4(codegendata *cd, s4 value)
81 {
82         s4 *dataptr;
83
84         cd->dseglen += 4;
85         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
86
87         if (cd->dseglen > cd->dsegsize)
88                 return dseg_adds4_increase(cd, value);
89
90         *dataptr = value;
91
92         return -(cd->dseglen);
93 }
94
95
96 s4 dseg_adds8_increase(codegendata *cd, s8 value)
97 {
98         dseg_increase(cd);
99
100         *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
101
102         return -(cd->dseglen);
103 }
104
105
106 s4 dseg_adds8(codegendata *cd, s8 value)
107 {
108         s8 *dataptr;
109
110         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
111         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
112
113         if (cd->dseglen > cd->dsegsize)
114                 return dseg_adds8_increase(cd, value);
115
116         *dataptr = value;
117
118         return -(cd->dseglen);
119 }
120
121
122 s4 dseg_addfloat_increase(codegendata *cd, float value)
123 {
124         dseg_increase(cd);
125
126         *((float *) (cd->dsegtop - cd->dseglen)) = value;
127
128         return -(cd->dseglen);
129 }
130
131
132 s4 dseg_addfloat(codegendata *cd, float value)
133 {
134         float *dataptr;
135
136         cd->dseglen += 4;
137         dataptr = (float *) (cd->dsegtop - cd->dseglen);
138
139         if (cd->dseglen > cd->dsegsize)
140                 return dseg_addfloat_increase(cd, value);
141
142         *dataptr = value;
143
144         return -(cd->dseglen);
145 }
146
147
148 s4 dseg_adddouble_increase(codegendata *cd, double value)
149 {
150         dseg_increase(cd);
151
152         *((double *) (cd->dsegtop - cd->dseglen)) = value;
153
154         return -(cd->dseglen);
155 }
156
157
158 s4 dseg_adddouble(codegendata *cd, double value)
159 {
160         double *dataptr;
161
162         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
163         dataptr = (double *) (cd->dsegtop - cd->dseglen);
164
165         if (cd->dseglen > cd->dsegsize)
166                 return dseg_adddouble_increase(cd, value);
167
168         *dataptr = value;
169
170         return -(cd->dseglen);
171 }
172
173
174 void dseg_addtarget(codegendata *cd, basicblock *target)
175 {
176         jumpref *jr;
177
178         jr = DNEW(jumpref);
179
180         jr->tablepos = dseg_addaddress(cd, NULL);
181         jr->target   = target;
182         jr->next     = cd->jumpreferences;
183
184         cd->jumpreferences = jr;
185 }
186
187
188 /* dseg_addlinenumbertablesize *************************************************
189
190    XXX
191
192 *******************************************************************************/
193
194 void dseg_addlinenumbertablesize(codegendata *cd)
195 {
196 #if SIZEOF_VOID_P == 8
197         /* 4-byte ALIGNMENT PADDING */
198
199         dseg_adds4(cd, 0);
200 #endif
201
202         cd->linenumbertablesizepos  = dseg_addaddress(cd, NULL);
203         cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
204
205 #if SIZEOF_VOID_P == 8
206         /* 4-byte ALIGNMENT PADDING */
207
208         dseg_adds4(cd, 0);
209 #endif
210 }
211
212
213 /* dseg_addlinenumber **********************************************************
214
215    Add a line number reference.
216
217    IN:
218       cd.............current codegen data
219       linenumber.....number of line that starts with the given mcodeptr
220       mcodeptr.......start mcodeptr of line
221
222 *******************************************************************************/
223
224 void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
225 {
226         linenumberref *lr;
227
228         lr = DNEW(linenumberref);
229
230         lr->linenumber = linenumber;
231         lr->tablepos   = 0;
232         lr->targetmpc  = mcodeptr - cd->mcodebase;
233         lr->next       = cd->linenumberreferences;
234
235         cd->linenumberreferences = lr;
236 }
237
238
239 /* dseg_addlinenumber_inline_start *********************************************
240
241    Add a marker to the line number table indicating the start of an inlined
242    method body. (see doc/inlining_stacktrace.txt)
243
244    IN:
245       cd.............current codegen data
246       iptr...........the ICMD_INLINE_START instruction
247       mcodeptr.......start mcodeptr of inlined body
248
249 *******************************************************************************/
250
251 void dseg_addlinenumber_inline_start(codegendata *cd, 
252                                                                          instruction *iptr, 
253                                                                          u1 *mcodeptr)
254 {
255         linenumberref *lr;
256
257         lr = DNEW(linenumberref);
258
259         lr->linenumber = (-2); /* marks start of inlined method */
260         lr->tablepos   = 0;
261         lr->targetmpc  = mcodeptr - cd->mcodebase;
262         lr->next       = cd->linenumberreferences;
263
264         cd->linenumberreferences = lr;
265
266         iptr->target = mcodeptr; /* store for corresponding INLINE_END */
267 }
268
269
270 /* dseg_addlinenumber_inline_end ***********************************************
271
272    Add a marker to the line number table indicating the end of an inlined
273    method body. (see doc/inlining_stacktrace.txt)
274
275    IN:
276       cd.............current codegen data
277       iptr...........the ICMD_INLINE_END instruction
278
279    Note:
280       iptr->method must point to the inlined callee.
281
282 *******************************************************************************/
283
284 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
285 {
286         linenumberref *lr;
287         linenumberref *prev;
288         instruction *inlinestart;
289
290         /* get the pointer to the corresponding ICMD_INLINE_START */
291         inlinestart = (instruction *)iptr->target;
292
293         assert(inlinestart);
294         assert(iptr->method);
295
296         lr = DNEW(linenumberref);
297
298         /* special entry containing the methodinfo * */
299         lr->linenumber = (-3) - iptr->line;
300         lr->tablepos   = 0;
301         lr->targetmpc  = (ptrint) iptr->method;
302         lr->next       = cd->linenumberreferences;
303
304         prev = lr;
305         lr = DNEW(linenumberref);
306
307         /* end marker with PC of start of body */
308         lr->linenumber = (-1);
309         lr->tablepos   = 0;
310         lr->targetmpc  = (u1*)inlinestart->target - cd->mcodebase;
311         lr->next       = prev;
312
313         cd->linenumberreferences = lr;
314 }
315
316
317 /* dseg_createlinenumbertable **************************************************
318
319    Creates a line number table in the data segment from the created
320    entries in linenumberreferences.
321
322 *******************************************************************************/
323
324 void dseg_createlinenumbertable(codegendata *cd)
325 {
326         linenumberref *lr;
327
328         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
329                 lr->tablepos = dseg_addaddress(cd, NULL);
330
331                 if (cd->linenumbertab == 0)
332                         cd->linenumbertab = lr->tablepos;
333
334                 dseg_addaddress(cd, lr->linenumber);
335         }
336 }
337
338
339 /* dseg_adddata ****************************************************************
340
341    Adds a data segment reference to the codegendata.
342
343 *******************************************************************************/
344
345 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
346 void dseg_adddata(codegendata *cd, u1 *mcodeptr)
347 {
348         dataref *dr;
349
350         dr = DNEW(dataref);
351
352         dr->datapos = mcodeptr - cd->mcodebase;
353         dr->next    = cd->datareferences;
354
355         cd->datareferences = dr;
356 }
357 #endif
358
359
360 /* dseg_resolve_datareferences *************************************************
361
362    Resolve data segment references.
363
364 *******************************************************************************/
365
366 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
367 void dseg_resolve_datareferences(jitdata *jd)
368 {
369         codeinfo    *code;
370         codegendata *cd;
371         dataref     *dr;
372
373         /* get required compiler data */
374
375         code = jd->code;
376         cd   = jd->cd;
377
378         /* data segment references resolving */
379
380         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
381                 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
382 }
383 #endif
384
385
386 /* dseg_display ****************************************************************
387
388    Displays the content of the methods' data segment.
389
390 *******************************************************************************/
391
392 #if !defined(NDEBUG)
393 void dseg_display(jitdata *jd)
394 {
395         codeinfo    *code;
396         codegendata *cd;
397         s4          *s4ptr;
398         s4           i;
399         
400         /* get required compiler data */
401
402         code = jd->code;
403         cd   = jd->cd;
404
405         s4ptr = (s4 *) (ptrint) code->mcode;
406
407         printf("  --- dump of datasegment\n");
408
409         for (i = cd->dseglen; i > 0 ; i -= 4) {
410 #if SIZEOF_VOID_P == 8
411                 printf("0x%016lx:   -%6x (%6d): %8x\n",
412                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
413 #else
414                 printf("0x%08x:   -%6x (%6d): %8x\n",
415                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
416 #endif
417                 s4ptr++;
418         }
419
420         printf("  --- begin of data segment: %p\n", (void *) s4ptr);
421 }
422 #endif /* !defined(NDEBUG) */
423
424
425 /*
426  * These are local overrides for various environment variables in Emacs.
427  * Please do not remove this and leave it at the end of the file, where
428  * Emacs will automagically detect them.
429  * ---------------------------------------------------------------------
430  * Local variables:
431  * mode: c
432  * indent-tabs-mode: t
433  * c-basic-offset: 4
434  * tab-width: 4
435  * End:
436  * vim:noexpandtab:sw=4:ts=4:
437  */