1 /* src/vm/jit/dseg.c - data segment handling stuff
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
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
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
30 Changes: Christian Thalinger
34 $Id: dseg.c 5820 2006-10-24 11:17:30Z twisti $
43 #include "vm/options.h"
46 #include "mm/memory.h"
47 #include "vm/jit/codegen-common.h"
51 /* dseg_finish *****************************************************************
53 Fills the data segment with the values stored.
55 *******************************************************************************/
57 void dseg_finish(jitdata *jd)
63 /* get required compiler data */
68 /* process all data segment entries */
70 for (de = cd->dseg; de != NULL; de = de->next) {
73 *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
77 *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
81 *((float *) (code->entrypoint + de->disp)) = de->val.f;
85 *((double *) (code->entrypoint + de->disp)) = de->val.d;
89 *((void **) (code->entrypoint + de->disp)) = de->val.a;
96 static s4 dseg_find_s4(codegendata *cd, s4 value)
100 /* search all data segment entries for a matching entry */
102 for (de = cd->dseg; de != NULL; de = de->next) {
103 if (IS_INT_TYPE(de->type))
104 if (de->flags & DSEG_FLAG_READONLY)
105 if (de->val.i == value)
109 /* no matching entry was found */
115 static s4 dseg_find_s8(codegendata *cd, s8 value)
119 /* search all data segment entries for a matching entry */
121 for (de = cd->dseg; de != NULL; de = de->next) {
122 if (IS_LNG_TYPE(de->type))
123 if (de->flags & DSEG_FLAG_READONLY)
124 if (de->val.l == value)
128 /* no matching entry was found */
134 static s4 dseg_find_float(codegendata *cd, float value)
138 /* search all data segment entries for a matching entry */
140 for (de = cd->dseg; de != NULL; de = de->next) {
141 if (IS_FLT_TYPE(de->type))
142 if (de->flags & DSEG_FLAG_READONLY)
143 if (de->val.f == value)
147 /* no matching entry was found */
153 static s4 dseg_find_double(codegendata *cd, double value)
157 /* search all data segment entries for a matching entry */
159 for (de = cd->dseg; de != NULL; de = de->next) {
160 if (IS_DBL_TYPE(de->type))
161 if (de->flags & DSEG_FLAG_READONLY)
162 if (de->val.d == value)
166 /* no matching entry was found */
172 static s4 dseg_find_address(codegendata *cd, void *value)
176 /* search all data segment entries for a matching entry */
178 for (de = cd->dseg; de != NULL; de = de->next) {
179 if (IS_ADR_TYPE(de->type))
180 if (de->flags & DSEG_FLAG_READONLY)
181 if (de->val.a == value)
185 /* no matching entry was found */
191 /* dseg_add_s4_intern **********************************************************
193 Internal function to add an s4 value to the data segment.
195 *******************************************************************************/
197 static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
201 /* Increase data segment size, which is also the displacement into
206 /* allocate new entry */
208 de = DNEW(dsegentry);
212 de->disp = -(cd->dseglen);
216 /* insert into the chain */
224 /* dseg_add_unique_s4 **********************************************************
226 Adds uniquely an s4 value to the data segment.
228 *******************************************************************************/
230 s4 dseg_add_unique_s4(codegendata *cd, s4 value)
234 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
240 /* dseg_add_s4 *****************************************************************
242 Adds an s4 value to the data segment. It tries to reuse previously
245 *******************************************************************************/
247 s4 dseg_add_s4(codegendata *cd, s4 value)
251 /* search the data segment if the value is already stored */
253 disp = dseg_find_s4(cd, value);
258 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
264 /* dseg_add_s8_intern **********************************************************
266 Internal function to add an s8 value to the data segment.
268 *******************************************************************************/
270 static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
274 /* Increase data segment size, which is also the displacement into
277 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
279 /* allocate new entry */
281 de = DNEW(dsegentry);
285 de->disp = -(cd->dseglen);
289 /* insert into the chain */
297 /* dseg_add_unique_s8 **********************************************************
299 Adds uniquely an s8 value to the data segment.
301 *******************************************************************************/
303 s4 dseg_add_unique_s8(codegendata *cd, s8 value)
307 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
313 /* dseg_add_s8 *****************************************************************
315 Adds an s8 value to the data segment. It tries to reuse previously
318 *******************************************************************************/
320 s4 dseg_add_s8(codegendata *cd, s8 value)
324 /* search the data segment if the value is already stored */
326 disp = dseg_find_s8(cd, value);
331 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
337 /* dseg_add_float_intern *******************************************************
339 Internal function to add a float value to the data segment.
341 *******************************************************************************/
343 static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
347 /* Increase data segment size, which is also the displacement into
352 /* allocate new entry */
354 de = DNEW(dsegentry);
358 de->disp = -(cd->dseglen);
362 /* insert into the chain */
370 /* dseg_add_unique_float *******************************************************
372 Adds uniquely an float value to the data segment.
374 *******************************************************************************/
376 s4 dseg_add_unique_float(codegendata *cd, float value)
380 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
386 /* dseg_add_float **************************************************************
388 Adds an float value to the data segment. It tries to reuse
389 previously added values.
391 *******************************************************************************/
393 s4 dseg_add_float(codegendata *cd, float value)
397 /* search the data segment if the value is already stored */
399 disp = dseg_find_float(cd, value);
404 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
410 /* dseg_add_double_intern ******************************************************
412 Internal function to add a double value to the data segment.
414 *******************************************************************************/
416 static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
420 /* Increase data segment size, which is also the displacement into
423 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
425 /* allocate new entry */
427 de = DNEW(dsegentry);
431 de->disp = -(cd->dseglen);
435 /* insert into the chain */
443 /* dseg_add_unique_double ******************************************************
445 Adds uniquely a double value to the data segment.
447 *******************************************************************************/
449 s4 dseg_add_unique_double(codegendata *cd, double value)
453 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
459 /* dseg_add_double *************************************************************
461 Adds a double value to the data segment. It tries to reuse
462 previously added values.
464 *******************************************************************************/
466 s4 dseg_add_double(codegendata *cd, double value)
470 /* search the data segment if the value is already stored */
472 disp = dseg_find_double(cd, value);
477 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
483 /* dseg_add_address_intern *****************************************************
485 Internal function to add an address pointer to the data segment.
487 *******************************************************************************/
489 static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
493 /* Increase data segment size, which is also the displacement into
496 #if SIZEOF_VOID_P == 8
497 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
502 /* allocate new entry */
504 de = DNEW(dsegentry);
508 de->disp = -(cd->dseglen);
512 /* insert into the chain */
520 /* dseg_add_unique_address *****************************************************
522 Adds uniquely an address value to the data segment.
524 *******************************************************************************/
526 s4 dseg_add_unique_address(codegendata *cd, void *value)
530 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
536 /* dseg_add_address ************************************************************
538 Adds an address value to the data segment. It tries to reuse
539 previously added values.
541 *******************************************************************************/
543 s4 dseg_add_address(codegendata *cd, void *value)
547 /* search the data segment if the value is already stored */
549 disp = dseg_find_address(cd, value);
554 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
560 /* dseg_add_target *************************************************************
564 *******************************************************************************/
566 void dseg_add_target(codegendata *cd, basicblock *target)
572 jr->tablepos = dseg_add_unique_address(cd, NULL);
574 jr->next = cd->jumpreferences;
576 cd->jumpreferences = jr;
580 /* dseg_addlinenumbertablesize *************************************************
584 *******************************************************************************/
586 void dseg_addlinenumbertablesize(codegendata *cd)
588 #if SIZEOF_VOID_P == 8
589 /* 4-byte ALIGNMENT PADDING */
591 dseg_add_unique_s4(cd, 0);
594 cd->linenumbertablesizepos = dseg_add_unique_address(cd, NULL);
595 cd->linenumbertablestartpos = dseg_add_unique_address(cd, NULL);
597 #if SIZEOF_VOID_P == 8
598 /* 4-byte ALIGNMENT PADDING */
600 dseg_add_unique_s4(cd, 0);
605 /* dseg_addlinenumber **********************************************************
607 Add a line number reference.
610 cd.............current codegen data
611 linenumber.....number of line that starts with the given mcodeptr
612 mcodeptr.......start mcodeptr of line
614 *******************************************************************************/
616 void dseg_addlinenumber(codegendata *cd, u2 linenumber)
620 lr = DNEW(linenumberref);
622 lr->linenumber = linenumber;
624 lr->targetmpc = cd->mcodeptr - cd->mcodebase;
625 lr->next = cd->linenumberreferences;
627 cd->linenumberreferences = lr;
631 /* dseg_addlinenumber_inline_start *********************************************
633 Add a marker to the line number table indicating the start of an inlined
634 method body. (see doc/inlining_stacktrace.txt)
637 cd.............current codegen data
638 iptr...........the ICMD_INLINE_START instruction
639 mcodeptr.......start mcodeptr of inlined body
641 *******************************************************************************/
643 void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
646 insinfo_inline *insinfo;
649 lr = DNEW(linenumberref);
651 lr->linenumber = (-2); /* marks start of inlined method */
653 lr->targetmpc = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
654 lr->next = cd->linenumberreferences;
656 cd->linenumberreferences = lr;
659 insinfo = (insinfo_inline *) iptr->target;
662 insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
666 /* dseg_addlinenumber_inline_end ***********************************************
668 Add a marker to the line number table indicating the end of an inlined
669 method body. (see doc/inlining_stacktrace.txt)
672 cd.............current codegen data
673 iptr...........the ICMD_INLINE_END instruction
676 iptr->method must point to the inlined callee.
678 *******************************************************************************/
680 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
684 insinfo_inline *insinfo;
687 insinfo = (insinfo_inline *) iptr->target;
692 lr = DNEW(linenumberref);
694 /* special entry containing the methodinfo * */
695 lr->linenumber = (-3) - iptr->line;
697 lr->targetmpc = (ptrint) insinfo->method;
698 lr->next = cd->linenumberreferences;
701 lr = DNEW(linenumberref);
703 /* end marker with PC of start of body */
704 lr->linenumber = (-1);
706 lr->targetmpc = insinfo->startmpc;
709 cd->linenumberreferences = lr;
713 /* dseg_createlinenumbertable **************************************************
715 Creates a line number table in the data segment from the created
716 entries in linenumberreferences.
718 *******************************************************************************/
720 void dseg_createlinenumbertable(codegendata *cd)
724 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
725 lr->tablepos = dseg_add_unique_address(cd, NULL);
727 if (cd->linenumbertab == 0)
728 cd->linenumbertab = lr->tablepos;
730 #if SIZEOF_VOID_P == 8
731 /* This is for alignment and easier usage. */
732 (void) dseg_add_unique_s8(cd, lr->linenumber);
734 (void) dseg_add_unique_s4(cd, lr->linenumber);
740 /* dseg_adddata ****************************************************************
742 Adds a data segment reference to the codegendata.
744 *******************************************************************************/
746 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
747 void dseg_adddata(codegendata *cd)
753 dr->datapos = cd->mcodeptr - cd->mcodebase;
754 dr->next = cd->datareferences;
756 cd->datareferences = dr;
761 /* dseg_resolve_datareferences *************************************************
763 Resolve data segment references.
765 *******************************************************************************/
767 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
768 void dseg_resolve_datareferences(jitdata *jd)
774 /* get required compiler data */
779 /* data segment references resolving */
781 for (dr = cd->datareferences; dr != NULL; dr = dr->next)
782 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
787 /* dseg_display ****************************************************************
789 Displays the content of the methods' data segment.
791 *******************************************************************************/
794 void dseg_display(jitdata *jd)
801 /* get required compiler data */
807 printf("\033[34m"); /* blue */
809 printf(" --- dump of datasegment\n");
811 /* process all data segment entries */
813 for (de = cd->dseg; de != NULL; de = de->next) {
814 #if SIZEOF_VOID_P == 8
815 printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
817 printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
820 printf(" %6x (%6d): ", de->disp, de->disp);
822 /* We read the values from the data segment as some values,
823 like the line number table, have been written directly to
828 val.i = *((s4 *) (code->entrypoint + de->disp));
829 printf("(INT) %d (0x%08x)", val.i, val.i);
833 val.l = *((s8 *) (code->entrypoint + de->disp));
834 #if SIZEOF_VOID_P == 8
835 printf("(LNG) %ld (0x%016lx)", val.l, val.l);
837 printf("(LNG) %lld (0x%016llx)", val.l, val.l);
842 val.f = *((float *) (code->entrypoint + de->disp));
843 printf("(FLT) %g (0x%08x)", val.f, val.i);
847 val.d = *((double *) (code->entrypoint + de->disp));
848 #if SIZEOF_VOID_P == 8
849 printf("(DBL) %g (0x%016lx)", val.d, val.l);
851 printf("(DBL) %g (0x%016llx)", val.d, val.l);
856 val.a = *((void **) (code->entrypoint + de->disp));
857 #if SIZEOF_VOID_P == 8
858 printf("(ADR) %016lx", (ptrint) val.a);
860 printf("(ADR) %08x", (ptrint) val.a);
868 printf(" --- begin of data segment: ");
869 #if SIZEOF_VOID_P == 8
870 printf("0x%016lx\n", (ptrint) code->entrypoint);
872 printf("0x%08x\n", (ptrint) code->entrypoint);
878 #endif /* !defined(NDEBUG) */
882 * These are local overrides for various environment variables in Emacs.
883 * Please do not remove this and leave it at the end of the file, where
884 * Emacs will automagically detect them.
885 * ---------------------------------------------------------------------
888 * indent-tabs-mode: t
892 * vim:noexpandtab:sw=4:ts=4: