* src/vm/jit/alpha/patcher.c (patcher_wrapper): Added return address
[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 4826 2006-04-24 16:06:16Z 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 static 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(codegendata *cd, s4 value)
71 {
72         s4 *dataptr;
73
74         cd->dseglen += 4;
75
76         if (cd->dseglen > cd->dsegsize)
77                 dseg_increase(cd);
78
79         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
80
81         *dataptr = value;
82
83         return -(cd->dseglen);
84 }
85
86
87 s4 dseg_adds8(codegendata *cd, s8 value)
88 {
89         s8 *dataptr;
90
91         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
92
93         if (cd->dseglen > cd->dsegsize)
94                 dseg_increase(cd);
95
96         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
97
98         *dataptr = value;
99
100         return -(cd->dseglen);
101 }
102
103
104 s4 dseg_addfloat(codegendata *cd, float value)
105 {
106         float *dataptr;
107
108         cd->dseglen += 4;
109
110         if (cd->dseglen > cd->dsegsize)
111                 dseg_increase(cd);
112
113         dataptr = (float *) (cd->dsegtop - cd->dseglen);
114
115         *dataptr = value;
116
117         return -(cd->dseglen);
118 }
119
120
121 s4 dseg_adddouble(codegendata *cd, double value)
122 {
123         double *dataptr;
124
125         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
126
127         if (cd->dseglen > cd->dsegsize)
128                 dseg_increase(cd);
129
130         dataptr = (double *) (cd->dsegtop - cd->dseglen);
131
132         *dataptr = value;
133
134         return -(cd->dseglen);
135 }
136
137
138 void dseg_addtarget(codegendata *cd, basicblock *target)
139 {
140         jumpref *jr;
141
142         jr = DNEW(jumpref);
143
144         jr->tablepos = dseg_addaddress(cd, NULL);
145         jr->target   = target;
146         jr->next     = cd->jumpreferences;
147
148         cd->jumpreferences = jr;
149 }
150
151
152 /* dseg_addlinenumbertablesize *************************************************
153
154    XXX
155
156 *******************************************************************************/
157
158 void dseg_addlinenumbertablesize(codegendata *cd)
159 {
160 #if SIZEOF_VOID_P == 8
161         /* 4-byte ALIGNMENT PADDING */
162
163         dseg_adds4(cd, 0);
164 #endif
165
166         cd->linenumbertablesizepos  = dseg_addaddress(cd, NULL);
167         cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
168
169 #if SIZEOF_VOID_P == 8
170         /* 4-byte ALIGNMENT PADDING */
171
172         dseg_adds4(cd, 0);
173 #endif
174 }
175
176
177 /* dseg_addlinenumber **********************************************************
178
179    Add a line number reference.
180
181    IN:
182       cd.............current codegen data
183       linenumber.....number of line that starts with the given mcodeptr
184       mcodeptr.......start mcodeptr of line
185
186 *******************************************************************************/
187
188 void dseg_addlinenumber(codegendata *cd, u2 linenumber)
189 {
190         linenumberref *lr;
191
192         lr = DNEW(linenumberref);
193
194         lr->linenumber = linenumber;
195         lr->tablepos   = 0;
196         lr->targetmpc  = (u1 *) cd->mcodeptr - cd->mcodebase;
197         lr->next       = cd->linenumberreferences;
198
199         cd->linenumberreferences = lr;
200 }
201
202
203 /* dseg_addlinenumber_inline_start *********************************************
204
205    Add a marker to the line number table indicating the start of an inlined
206    method body. (see doc/inlining_stacktrace.txt)
207
208    IN:
209       cd.............current codegen data
210       iptr...........the ICMD_INLINE_START instruction
211       mcodeptr.......start mcodeptr of inlined body
212
213 *******************************************************************************/
214
215 void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
216 {
217         linenumberref *lr;
218         insinfo_inline *insinfo;
219         ptrint mpc;
220
221         lr = DNEW(linenumberref);
222
223         lr->linenumber = (-2); /* marks start of inlined method */
224         lr->tablepos   = 0;
225         lr->targetmpc  = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
226         lr->next       = cd->linenumberreferences;
227
228         cd->linenumberreferences = lr;
229
230         insinfo = (insinfo_inline *) iptr->target;
231
232         insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
233 }
234
235
236 /* dseg_addlinenumber_inline_end ***********************************************
237
238    Add a marker to the line number table indicating the end of an inlined
239    method body. (see doc/inlining_stacktrace.txt)
240
241    IN:
242       cd.............current codegen data
243       iptr...........the ICMD_INLINE_END instruction
244
245    Note:
246       iptr->method must point to the inlined callee.
247
248 *******************************************************************************/
249
250 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
251 {
252         linenumberref *lr;
253         linenumberref *prev;
254         insinfo_inline *insinfo;
255
256         insinfo = (insinfo_inline *) iptr->target;
257
258         assert(insinfo);
259
260         lr = DNEW(linenumberref);
261
262         /* special entry containing the methodinfo * */
263         lr->linenumber = (-3) - iptr->line;
264         lr->tablepos   = 0;
265         lr->targetmpc  = (ptrint) insinfo->method;
266         lr->next       = cd->linenumberreferences;
267
268         prev = lr;
269         lr = DNEW(linenumberref);
270
271         /* end marker with PC of start of body */
272         lr->linenumber = (-1);
273         lr->tablepos   = 0;
274         lr->targetmpc  = insinfo->startmpc;
275         lr->next       = prev;
276
277         cd->linenumberreferences = lr;
278 }
279
280
281 /* dseg_createlinenumbertable **************************************************
282
283    Creates a line number table in the data segment from the created
284    entries in linenumberreferences.
285
286 *******************************************************************************/
287
288 void dseg_createlinenumbertable(codegendata *cd)
289 {
290         linenumberref *lr;
291
292         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
293                 lr->tablepos = dseg_addaddress(cd, NULL);
294
295                 if (cd->linenumbertab == 0)
296                         cd->linenumbertab = lr->tablepos;
297
298                 dseg_addaddress(cd, lr->linenumber);
299         }
300 }
301
302
303 /* dseg_adddata ****************************************************************
304
305    Adds a data segment reference to the codegendata.
306
307 *******************************************************************************/
308
309 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
310 void dseg_adddata(codegendata *cd)
311 {
312         dataref *dr;
313
314         dr = DNEW(dataref);
315
316         dr->datapos = (u1 *) cd->mcodeptr - cd->mcodebase;
317         dr->next    = cd->datareferences;
318
319         cd->datareferences = dr;
320 }
321 #endif
322
323
324 /* dseg_resolve_datareferences *************************************************
325
326    Resolve data segment references.
327
328 *******************************************************************************/
329
330 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
331 void dseg_resolve_datareferences(jitdata *jd)
332 {
333         codeinfo    *code;
334         codegendata *cd;
335         dataref     *dr;
336
337         /* get required compiler data */
338
339         code = jd->code;
340         cd   = jd->cd;
341
342         /* data segment references resolving */
343
344         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
345                 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
346 }
347 #endif
348
349
350 /* dseg_display ****************************************************************
351
352    Displays the content of the methods' data segment.
353
354 *******************************************************************************/
355
356 #if !defined(NDEBUG)
357 void dseg_display(jitdata *jd)
358 {
359         codeinfo    *code;
360         codegendata *cd;
361         s4          *s4ptr;
362         s4           i;
363         
364         /* get required compiler data */
365
366         code = jd->code;
367         cd   = jd->cd;
368
369         s4ptr = (s4 *) (ptrint) code->mcode;
370
371         printf("  --- dump of datasegment\n");
372
373         for (i = cd->dseglen; i > 0 ; i -= 4) {
374 #if SIZEOF_VOID_P == 8
375                 printf("0x%016lx:   -%6x (%6d): %8x\n",
376                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
377 #else
378                 printf("0x%08x:   -%6x (%6d): %8x\n",
379                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
380 #endif
381                 s4ptr++;
382         }
383
384         printf("  --- begin of data segment: %p\n", (void *) s4ptr);
385 }
386 #endif /* !defined(NDEBUG) */
387
388
389 /*
390  * These are local overrides for various environment variables in Emacs.
391  * Please do not remove this and leave it at the end of the file, where
392  * Emacs will automagically detect them.
393  * ---------------------------------------------------------------------
394  * Local variables:
395  * mode: c
396  * indent-tabs-mode: t
397  * c-basic-offset: 4
398  * tab-width: 4
399  * End:
400  * vim:noexpandtab:sw=4:ts=4:
401  */