1 /* src/vm/jit/dseg.c - data segment handling stuff
3 Copyright (C) 1996-2005, 2006, 2007 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
8 This file is part of CACAO.
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.
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.
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
34 #include "mm/memory.h"
36 #include "vm/jit/codegen-common.h"
37 #include "vm/jit/methodheader.h"
39 #include "vmcore/options.h"
42 /* dseg_finish *****************************************************************
44 Fills the data segment with the values stored.
46 *******************************************************************************/
48 void dseg_finish(jitdata *jd)
54 /* get required compiler data */
59 /* process all data segment entries */
61 for (de = cd->dseg; de != NULL; de = de->next) {
64 *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
68 *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
72 *((float *) (code->entrypoint + de->disp)) = de->val.f;
76 *((double *) (code->entrypoint + de->disp)) = de->val.d;
80 *((void **) (code->entrypoint + de->disp)) = de->val.a;
87 static s4 dseg_find_s4(codegendata *cd, s4 value)
91 /* search all data segment entries for a matching entry */
93 for (de = cd->dseg; de != NULL; de = de->next) {
94 if (IS_INT_TYPE(de->type))
95 if (de->flags & DSEG_FLAG_READONLY)
96 if (de->val.i == value)
100 /* no matching entry was found */
106 static s4 dseg_find_s8(codegendata *cd, s8 value)
110 /* search all data segment entries for a matching entry */
112 for (de = cd->dseg; de != NULL; de = de->next) {
113 if (IS_LNG_TYPE(de->type))
114 if (de->flags & DSEG_FLAG_READONLY)
115 if (de->val.l == value)
119 /* no matching entry was found */
125 static s4 dseg_find_float(codegendata *cd, float value)
130 /* we compare the hex value of the float as 0.0 == -0.0 */
134 /* search all data segment entries for a matching entry */
136 for (de = cd->dseg; de != NULL; de = de->next) {
137 if (IS_FLT_TYPE(de->type))
138 if (de->flags & DSEG_FLAG_READONLY)
139 if (de->val.i == val.i)
143 /* no matching entry was found */
149 static s4 dseg_find_double(codegendata *cd, double value)
154 /* we compare the hex value of the double as 0.0 == -0.0 */
158 /* search all data segment entries for a matching entry */
160 for (de = cd->dseg; de != NULL; de = de->next) {
161 if (IS_DBL_TYPE(de->type))
162 if (de->flags & DSEG_FLAG_READONLY)
163 if (de->val.l == val.l)
167 /* no matching entry was found */
173 static s4 dseg_find_address(codegendata *cd, void *value)
177 /* search all data segment entries for a matching entry */
179 for (de = cd->dseg; de != NULL; de = de->next) {
180 if (IS_ADR_TYPE(de->type))
181 if (de->flags & DSEG_FLAG_READONLY)
182 if (de->val.a == value)
186 /* no matching entry was found */
192 /* dseg_add_s4_intern **********************************************************
194 Internal function to add an s4 value to the data segment.
196 *******************************************************************************/
198 static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
202 /* Increase data segment size, which is also the displacement into
207 /* allocate new entry */
209 de = DNEW(dsegentry);
213 de->disp = -(cd->dseglen);
217 /* insert into the chain */
225 /* dseg_add_unique_s4 **********************************************************
227 Adds uniquely an s4 value to the data segment.
229 *******************************************************************************/
231 s4 dseg_add_unique_s4(codegendata *cd, s4 value)
235 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
241 /* dseg_add_s4 *****************************************************************
243 Adds an s4 value to the data segment. It tries to reuse previously
246 *******************************************************************************/
248 s4 dseg_add_s4(codegendata *cd, s4 value)
252 /* search the data segment if the value is already stored */
254 disp = dseg_find_s4(cd, value);
259 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
265 /* dseg_add_s8_intern **********************************************************
267 Internal function to add an s8 value to the data segment.
269 *******************************************************************************/
271 static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
275 /* Increase data segment size, which is also the displacement into
278 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
280 /* allocate new entry */
282 de = DNEW(dsegentry);
286 de->disp = -(cd->dseglen);
290 /* insert into the chain */
298 /* dseg_add_unique_s8 **********************************************************
300 Adds uniquely an s8 value to the data segment.
302 *******************************************************************************/
304 s4 dseg_add_unique_s8(codegendata *cd, s8 value)
308 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
314 /* dseg_add_s8 *****************************************************************
316 Adds an s8 value to the data segment. It tries to reuse previously
319 *******************************************************************************/
321 s4 dseg_add_s8(codegendata *cd, s8 value)
325 /* search the data segment if the value is already stored */
327 disp = dseg_find_s8(cd, value);
332 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
338 /* dseg_add_float_intern *******************************************************
340 Internal function to add a float value to the data segment.
342 *******************************************************************************/
344 static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
348 /* Increase data segment size, which is also the displacement into
353 /* allocate new entry */
355 de = DNEW(dsegentry);
359 de->disp = -(cd->dseglen);
363 /* insert into the chain */
371 /* dseg_add_unique_float *******************************************************
373 Adds uniquely an float value to the data segment.
375 *******************************************************************************/
377 s4 dseg_add_unique_float(codegendata *cd, float value)
381 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
387 /* dseg_add_float **************************************************************
389 Adds an float value to the data segment. It tries to reuse
390 previously added values.
392 *******************************************************************************/
394 s4 dseg_add_float(codegendata *cd, float value)
398 /* search the data segment if the value is already stored */
400 disp = dseg_find_float(cd, value);
405 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
411 /* dseg_add_double_intern ******************************************************
413 Internal function to add a double value to the data segment.
415 *******************************************************************************/
417 static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
421 /* Increase data segment size, which is also the displacement into
424 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
426 /* allocate new entry */
428 de = DNEW(dsegentry);
432 de->disp = -(cd->dseglen);
436 /* insert into the chain */
444 /* dseg_add_unique_double ******************************************************
446 Adds uniquely a double value to the data segment.
448 *******************************************************************************/
450 s4 dseg_add_unique_double(codegendata *cd, double value)
454 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
460 /* dseg_add_double *************************************************************
462 Adds a double value to the data segment. It tries to reuse
463 previously added values.
465 *******************************************************************************/
467 s4 dseg_add_double(codegendata *cd, double value)
471 /* search the data segment if the value is already stored */
473 disp = dseg_find_double(cd, value);
478 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
484 /* dseg_add_address_intern *****************************************************
486 Internal function to add an address pointer to the data segment.
488 *******************************************************************************/
490 static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
494 /* Increase data segment size, which is also the displacement into
497 #if SIZEOF_VOID_P == 8
498 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
503 /* allocate new entry */
505 de = DNEW(dsegentry);
509 de->disp = -(cd->dseglen);
513 /* insert into the chain */
521 /* dseg_add_unique_address *****************************************************
523 Adds uniquely an address value to the data segment.
525 *******************************************************************************/
527 s4 dseg_add_unique_address(codegendata *cd, void *value)
531 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
537 /* dseg_add_address ************************************************************
539 Adds an address value to the data segment. It tries to reuse
540 previously added values.
542 *******************************************************************************/
544 s4 dseg_add_address(codegendata *cd, void *value)
548 /* search the data segment if the value is already stored */
550 disp = dseg_find_address(cd, value);
555 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
561 /* dseg_add_target *************************************************************
565 *******************************************************************************/
567 void dseg_add_target(codegendata *cd, basicblock *target)
573 jr->tablepos = dseg_add_unique_address(cd, NULL);
575 jr->next = cd->jumpreferences;
577 cd->jumpreferences = jr;
581 /* dseg_adddata ****************************************************************
583 Adds a data segment reference to the codegendata.
585 *******************************************************************************/
587 #if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
588 void dseg_adddata(codegendata *cd)
594 dr->datapos = cd->mcodeptr - cd->mcodebase;
595 dr->next = cd->datareferences;
597 cd->datareferences = dr;
602 /* dseg_resolve_datareferences *************************************************
604 Resolve data segment references.
606 *******************************************************************************/
608 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
609 void dseg_resolve_datareferences(jitdata *jd)
615 /* get required compiler data */
620 /* data segment references resolving */
622 for (dr = cd->datareferences; dr != NULL; dr = dr->next)
623 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
628 /* dseg_display ****************************************************************
630 Displays the content of the methods' data segment.
632 *******************************************************************************/
635 void dseg_display(jitdata *jd)
642 /* get required compiler data */
648 printf("\033[34m"); /* blue */
650 printf(" --- dump of datasegment\n");
652 /* process all data segment entries */
654 for (de = cd->dseg; de != NULL; de = de->next) {
655 #if SIZEOF_VOID_P == 8
656 printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
658 printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
661 printf(" %6x (%6d): ", de->disp, de->disp);
663 /* We read the values from the data segment as some values,
664 like the line number table, have been written directly to
669 val.i = *((s4 *) (code->entrypoint + de->disp));
670 printf("(INT) %d (0x%08x)", val.i, val.i);
674 val.l = *((s8 *) (code->entrypoint + de->disp));
675 #if SIZEOF_VOID_P == 8
676 printf("(LNG) %ld (0x%016lx)", val.l, val.l);
678 printf("(LNG) %lld (0x%016llx)", val.l, val.l);
683 val.f = *((float *) (code->entrypoint + de->disp));
684 printf("(FLT) %g (0x%08x)", val.f, val.i);
688 val.d = *((double *) (code->entrypoint + de->disp));
689 #if SIZEOF_VOID_P == 8
690 printf("(DBL) %g (0x%016lx)", val.d, val.l);
692 printf("(DBL) %g (0x%016llx)", val.d, val.l);
697 val.a = *((void **) (code->entrypoint + de->disp));
698 #if SIZEOF_VOID_P == 8
699 printf("(ADR) %016lx", (ptrint) val.a);
701 printf("(ADR) %08x", (ptrint) val.a);
709 printf(" --- begin of data segment: ");
710 #if SIZEOF_VOID_P == 8
711 printf("0x%016lx\n", (ptrint) code->entrypoint);
713 printf("0x%08x\n", (ptrint) code->entrypoint);
719 #endif /* !defined(NDEBUG) */
723 * These are local overrides for various environment variables in Emacs.
724 * Please do not remove this and leave it at the end of the file, where
725 * Emacs will automagically detect them.
726 * ---------------------------------------------------------------------
729 * indent-tabs-mode: t
733 * vim:noexpandtab:sw=4:ts=4: