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 5186 2006-07-28 13:24:43Z twisti $
45 #include "mm/memory.h"
46 #include "vm/jit/codegen-common.h"
49 /* dseg_finish *****************************************************************
51 Fills the data segment with the values stored.
53 *******************************************************************************/
55 void dseg_finish(jitdata *jd)
61 /* get required compiler data */
66 /* process all data segment entries */
68 for (de = cd->dseg; de != NULL; de = de->next) {
71 *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
75 *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
79 *((float *) (code->entrypoint + de->disp)) = de->val.f;
83 *((double *) (code->entrypoint + de->disp)) = de->val.d;
87 *((void **) (code->entrypoint + de->disp)) = de->val.a;
94 static s4 dseg_find_s4(codegendata *cd, s4 value)
98 /* search all data segment entries for a matching entry */
100 for (de = cd->dseg; de != NULL; de = de->next) {
101 if (IS_INT_TYPE(de->type))
102 if (de->flags & DSEG_FLAG_READONLY)
103 if (de->val.i == value)
107 /* no matching entry was found */
113 static s4 dseg_find_s8(codegendata *cd, s8 value)
117 /* search all data segment entries for a matching entry */
119 for (de = cd->dseg; de != NULL; de = de->next) {
120 if (IS_LNG_TYPE(de->type))
121 if (de->flags & DSEG_FLAG_READONLY)
122 if (de->val.l == value)
126 /* no matching entry was found */
132 static s4 dseg_find_float(codegendata *cd, float value)
136 /* search all data segment entries for a matching entry */
138 for (de = cd->dseg; de != NULL; de = de->next) {
139 if (IS_FLT_TYPE(de->type))
140 if (de->flags & DSEG_FLAG_READONLY)
141 if (de->val.f == value)
145 /* no matching entry was found */
151 static s4 dseg_find_double(codegendata *cd, double value)
155 /* search all data segment entries for a matching entry */
157 for (de = cd->dseg; de != NULL; de = de->next) {
158 if (IS_DBL_TYPE(de->type))
159 if (de->flags & DSEG_FLAG_READONLY)
160 if (de->val.d == value)
164 /* no matching entry was found */
170 static s4 dseg_find_address(codegendata *cd, void *value)
174 /* search all data segment entries for a matching entry */
176 for (de = cd->dseg; de != NULL; de = de->next) {
177 if (IS_ADR_TYPE(de->type))
178 if (de->flags & DSEG_FLAG_READONLY)
179 if (de->val.a == value)
183 /* no matching entry was found */
189 /* dseg_add_s4_intern **********************************************************
191 Internal function to add an s4 value to the data segment.
193 *******************************************************************************/
195 static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
199 /* Increase data segment size, which is also the displacement into
204 /* allocate new entry */
206 de = DNEW(dsegentry);
210 de->disp = -(cd->dseglen);
214 /* insert into the chain */
222 /* dseg_add_unique_s4 **********************************************************
224 Adds uniquely an s4 value to the data segment.
226 *******************************************************************************/
228 s4 dseg_add_unique_s4(codegendata *cd, s4 value)
232 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
238 /* dseg_add_s4 *****************************************************************
240 Adds an s4 value to the data segment. It tries to reuse previously
243 *******************************************************************************/
245 s4 dseg_add_s4(codegendata *cd, s4 value)
249 /* search the data segment if the value is already stored */
251 disp = dseg_find_s4(cd, value);
256 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
262 /* dseg_add_s8_intern **********************************************************
264 Internal function to add an s8 value to the data segment.
266 *******************************************************************************/
268 static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
272 /* Increase data segment size, which is also the displacement into
275 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
277 /* allocate new entry */
279 de = DNEW(dsegentry);
283 de->disp = -(cd->dseglen);
287 /* insert into the chain */
295 /* dseg_add_unique_s8 **********************************************************
297 Adds uniquely an s8 value to the data segment.
299 *******************************************************************************/
301 s4 dseg_add_unique_s8(codegendata *cd, s8 value)
305 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
311 /* dseg_add_s8 *****************************************************************
313 Adds an s8 value to the data segment. It tries to reuse previously
316 *******************************************************************************/
318 s4 dseg_add_s8(codegendata *cd, s8 value)
322 /* search the data segment if the value is already stored */
324 disp = dseg_find_s8(cd, value);
329 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
335 /* dseg_add_float_intern *******************************************************
337 Internal function to add a float value to the data segment.
339 *******************************************************************************/
341 static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
345 /* Increase data segment size, which is also the displacement into
350 /* allocate new entry */
352 de = DNEW(dsegentry);
356 de->disp = -(cd->dseglen);
360 /* insert into the chain */
368 /* dseg_add_unique_float *******************************************************
370 Adds uniquely an float value to the data segment.
372 *******************************************************************************/
374 s4 dseg_add_unique_float(codegendata *cd, float value)
378 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
384 /* dseg_add_float **************************************************************
386 Adds an float value to the data segment. It tries to reuse
387 previously added values.
389 *******************************************************************************/
391 s4 dseg_add_float(codegendata *cd, float value)
395 /* search the data segment if the value is already stored */
397 disp = dseg_find_float(cd, value);
402 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
408 /* dseg_add_double_intern ******************************************************
410 Internal function to add a double value to the data segment.
412 *******************************************************************************/
414 static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
418 /* Increase data segment size, which is also the displacement into
421 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
423 /* allocate new entry */
425 de = DNEW(dsegentry);
429 de->disp = -(cd->dseglen);
433 /* insert into the chain */
441 /* dseg_add_unique_double ******************************************************
443 Adds uniquely a double value to the data segment.
445 *******************************************************************************/
447 s4 dseg_add_unique_double(codegendata *cd, double value)
451 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
457 /* dseg_add_double *************************************************************
459 Adds a double value to the data segment. It tries to reuse
460 previously added values.
462 *******************************************************************************/
464 s4 dseg_add_double(codegendata *cd, double value)
468 /* search the data segment if the value is already stored */
470 disp = dseg_find_double(cd, value);
475 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
481 /* dseg_add_address_intern *****************************************************
483 Internal function to add an address pointer to the data segment.
485 *******************************************************************************/
487 static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
491 /* Increase data segment size, which is also the displacement into
494 #if SIZEOF_VOID_P == 8
495 cd->dseglen = ALIGN(cd->dseglen + 8, 8);
500 /* allocate new entry */
502 de = DNEW(dsegentry);
506 de->disp = -(cd->dseglen);
510 /* insert into the chain */
518 /* dseg_add_unique_address *****************************************************
520 Adds uniquely an address value to the data segment.
522 *******************************************************************************/
524 s4 dseg_add_unique_address(codegendata *cd, void *value)
528 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
534 /* dseg_add_address ************************************************************
536 Adds an address value to the data segment. It tries to reuse
537 previously added values.
539 *******************************************************************************/
541 s4 dseg_add_address(codegendata *cd, void *value)
545 /* search the data segment if the value is already stored */
547 disp = dseg_find_address(cd, value);
552 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
558 /* dseg_add_target *************************************************************
562 *******************************************************************************/
564 void dseg_add_target(codegendata *cd, basicblock *target)
570 jr->tablepos = dseg_add_unique_address(cd, NULL);
572 jr->next = cd->jumpreferences;
574 cd->jumpreferences = jr;
578 /* dseg_addlinenumbertablesize *************************************************
582 *******************************************************************************/
584 void dseg_addlinenumbertablesize(codegendata *cd)
586 #if SIZEOF_VOID_P == 8
587 /* 4-byte ALIGNMENT PADDING */
589 dseg_add_unique_s4(cd, 0);
592 cd->linenumbertablesizepos = dseg_add_unique_address(cd, NULL);
593 cd->linenumbertablestartpos = dseg_add_unique_address(cd, NULL);
595 #if SIZEOF_VOID_P == 8
596 /* 4-byte ALIGNMENT PADDING */
598 dseg_add_unique_s4(cd, 0);
603 /* dseg_addlinenumber **********************************************************
605 Add a line number reference.
608 cd.............current codegen data
609 linenumber.....number of line that starts with the given mcodeptr
610 mcodeptr.......start mcodeptr of line
612 *******************************************************************************/
614 void dseg_addlinenumber(codegendata *cd, u2 linenumber)
618 lr = DNEW(linenumberref);
620 lr->linenumber = linenumber;
622 lr->targetmpc = cd->mcodeptr - cd->mcodebase;
623 lr->next = cd->linenumberreferences;
625 cd->linenumberreferences = lr;
629 /* dseg_addlinenumber_inline_start *********************************************
631 Add a marker to the line number table indicating the start of an inlined
632 method body. (see doc/inlining_stacktrace.txt)
635 cd.............current codegen data
636 iptr...........the ICMD_INLINE_START instruction
637 mcodeptr.......start mcodeptr of inlined body
639 *******************************************************************************/
641 void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
644 insinfo_inline *insinfo;
647 lr = DNEW(linenumberref);
649 lr->linenumber = (-2); /* marks start of inlined method */
651 lr->targetmpc = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
652 lr->next = cd->linenumberreferences;
654 cd->linenumberreferences = lr;
656 insinfo = (insinfo_inline *) iptr->target;
658 insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
662 /* dseg_addlinenumber_inline_end ***********************************************
664 Add a marker to the line number table indicating the end of an inlined
665 method body. (see doc/inlining_stacktrace.txt)
668 cd.............current codegen data
669 iptr...........the ICMD_INLINE_END instruction
672 iptr->method must point to the inlined callee.
674 *******************************************************************************/
676 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
680 insinfo_inline *insinfo;
682 insinfo = (insinfo_inline *) iptr->target;
686 lr = DNEW(linenumberref);
688 /* special entry containing the methodinfo * */
689 lr->linenumber = (-3) - iptr->line;
691 lr->targetmpc = (ptrint) insinfo->method;
692 lr->next = cd->linenumberreferences;
695 lr = DNEW(linenumberref);
697 /* end marker with PC of start of body */
698 lr->linenumber = (-1);
700 lr->targetmpc = insinfo->startmpc;
703 cd->linenumberreferences = lr;
707 /* dseg_createlinenumbertable **************************************************
709 Creates a line number table in the data segment from the created
710 entries in linenumberreferences.
712 *******************************************************************************/
714 void dseg_createlinenumbertable(codegendata *cd)
718 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
719 lr->tablepos = dseg_add_unique_address(cd, NULL);
721 if (cd->linenumbertab == 0)
722 cd->linenumbertab = lr->tablepos;
724 #if SIZEOF_VOID_P == 8
725 /* This is for alignment and easier usage. */
726 (void) dseg_add_unique_s8(cd, lr->linenumber);
728 (void) dseg_add_unique_s4(cd, lr->linenumber);
734 /* dseg_adddata ****************************************************************
736 Adds a data segment reference to the codegendata.
738 *******************************************************************************/
740 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
741 void dseg_adddata(codegendata *cd)
747 dr->datapos = cd->mcodeptr - cd->mcodebase;
748 dr->next = cd->datareferences;
750 cd->datareferences = dr;
755 /* dseg_resolve_datareferences *************************************************
757 Resolve data segment references.
759 *******************************************************************************/
761 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
762 void dseg_resolve_datareferences(jitdata *jd)
768 /* get required compiler data */
773 /* data segment references resolving */
775 for (dr = cd->datareferences; dr != NULL; dr = dr->next)
776 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
781 /* dseg_display ****************************************************************
783 Displays the content of the methods' data segment.
785 *******************************************************************************/
788 void dseg_display(jitdata *jd)
795 /* get required compiler data */
800 s4ptr = (s4 *) (ptrint) code->mcode;
802 printf(" --- dump of datasegment\n");
804 for (i = cd->dseglen; i > 0 ; i -= 4) {
805 #if SIZEOF_VOID_P == 8
806 printf("0x%016lx: -%6x (%6d): %8x\n",
807 (ptrint) s4ptr, i, i, (s4) *s4ptr);
809 printf("0x%08x: -%6x (%6d): %8x\n",
810 (ptrint) s4ptr, i, i, (s4) *s4ptr);
815 printf(" --- begin of data segment: %p\n", (void *) s4ptr);
817 #endif /* !defined(NDEBUG) */
821 * These are local overrides for various environment variables in Emacs.
822 * Please do not remove this and leave it at the end of the file, where
823 * Emacs will automagically detect them.
824 * ---------------------------------------------------------------------
827 * indent-tabs-mode: t
831 * vim:noexpandtab:sw=4:ts=4: