558241b71d66f0ae00579af98c1e96d6fa330dcc
[cacao.git] / src / vm / jit / dseg.c
1 /* src/vm/jit/dseg.c - data segment handling stuff
2
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
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             Christian Thalinger
30             Joseph Wenninger
31             Edwin Steiner
32
33    $Id: dseg.c 8298 2007-08-12 18:49:16Z pm $
34
35 */
36
37
38 #include "config.h"
39
40 #include <assert.h>
41
42 #include "vm/types.h"
43
44 #include "mm/memory.h"
45 #include "vm/jit/codegen-common.h"
46 #include "vm/jit/methodheader.h"
47 #include "vmcore/options.h"
48
49
50 /* dseg_finish *****************************************************************
51
52    Fills the data segment with the values stored.
53
54 *******************************************************************************/
55
56 void dseg_finish(jitdata *jd)
57 {
58         codeinfo    *code;
59         codegendata *cd;
60         dsegentry   *de;
61
62         /* get required compiler data */
63
64         code = jd->code;
65         cd   = jd->cd;
66
67         /* process all data segment entries */
68
69         for (de = cd->dseg; de != NULL; de = de->next) {
70                 switch (de->type) {
71                 case TYPE_INT:
72                         *((s4 *)     (code->entrypoint + de->disp)) = de->val.i;
73                         break;
74
75                 case TYPE_LNG:
76                         *((s8 *)     (code->entrypoint + de->disp)) = de->val.l;
77                         break;
78
79                 case TYPE_FLT:
80                         *((float *)  (code->entrypoint + de->disp)) = de->val.f;
81                         break;
82
83                 case TYPE_DBL:
84                         *((double *) (code->entrypoint + de->disp)) = de->val.d;
85                         break;
86
87                 case TYPE_ADR:
88                         *((void **)  (code->entrypoint + de->disp)) = de->val.a;
89                         break;
90                 }
91         }
92 }
93
94
95 static s4 dseg_find_s4(codegendata *cd, s4 value)
96 {
97         dsegentry *de;
98
99         /* search all data segment entries for a matching entry */
100
101         for (de = cd->dseg; de != NULL; de = de->next) {
102                 if (IS_INT_TYPE(de->type))
103                         if (de->flags & DSEG_FLAG_READONLY)
104                                 if (de->val.i == value)
105                                         return de->disp;
106         }
107
108         /* no matching entry was found */
109
110         return 0;
111 }
112
113
114 static s4 dseg_find_s8(codegendata *cd, s8 value)
115 {
116         dsegentry *de;
117
118         /* search all data segment entries for a matching entry */
119
120         for (de = cd->dseg; de != NULL; de = de->next) {
121                 if (IS_LNG_TYPE(de->type))
122                         if (de->flags & DSEG_FLAG_READONLY)
123                                 if (de->val.l == value)
124                                         return de->disp;
125         }
126
127         /* no matching entry was found */
128
129         return 0;
130 }
131
132
133 static s4 dseg_find_float(codegendata *cd, float value)
134 {
135         dsegentry *de;
136         imm_union  val;
137
138         /* we compare the hex value of the float as 0.0 == -0.0 */
139
140         val.f = value;
141
142         /* search all data segment entries for a matching entry */
143
144         for (de = cd->dseg; de != NULL; de = de->next) {
145                 if (IS_FLT_TYPE(de->type))
146                         if (de->flags & DSEG_FLAG_READONLY)
147                                 if (de->val.i == val.i)
148                                         return de->disp;
149         }
150
151         /* no matching entry was found */
152
153         return 0;
154 }
155
156
157 static s4 dseg_find_double(codegendata *cd, double value)
158 {
159         dsegentry *de;
160         imm_union  val;
161
162         /* we compare the hex value of the double as 0.0 == -0.0 */
163
164         val.d = value;
165
166         /* search all data segment entries for a matching entry */
167
168         for (de = cd->dseg; de != NULL; de = de->next) {
169                 if (IS_DBL_TYPE(de->type))
170                         if (de->flags & DSEG_FLAG_READONLY)
171                                 if (de->val.l == val.l)
172                                         return de->disp;
173         }
174
175         /* no matching entry was found */
176
177         return 0;
178 }
179
180
181 static s4 dseg_find_address(codegendata *cd, void *value)
182 {
183         dsegentry *de;
184
185         /* search all data segment entries for a matching entry */
186
187         for (de = cd->dseg; de != NULL; de = de->next) {
188                 if (IS_ADR_TYPE(de->type))
189                         if (de->flags & DSEG_FLAG_READONLY)
190                                 if (de->val.a == value)
191                                         return de->disp;
192         }
193
194         /* no matching entry was found */
195
196         return 0;
197 }
198
199
200 /* dseg_add_s4_intern **********************************************************
201
202    Internal function to add an s4 value to the data segment.
203
204 *******************************************************************************/
205
206 static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
207 {
208         dsegentry *de;
209
210         /* Increase data segment size, which is also the displacement into
211            the data segment. */
212
213         cd->dseglen += 4;
214
215         /* allocate new entry */
216
217         de = DNEW(dsegentry);
218
219         de->type  = TYPE_INT;
220         de->flags = flags;
221         de->disp  = -(cd->dseglen);
222         de->val.i = value;
223         de->next  = cd->dseg;
224
225         /* insert into the chain */
226
227         cd->dseg = de;
228
229         return de->disp;
230 }
231
232
233 /* dseg_add_unique_s4 **********************************************************
234
235    Adds uniquely an s4 value to the data segment.
236
237 *******************************************************************************/
238
239 s4 dseg_add_unique_s4(codegendata *cd, s4 value)
240 {
241         s4 disp;
242
243         disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
244
245         return disp;
246 }
247
248
249 /* dseg_add_s4 *****************************************************************
250
251    Adds an s4 value to the data segment. It tries to reuse previously
252    added values.
253
254 *******************************************************************************/
255
256 s4 dseg_add_s4(codegendata *cd, s4 value)
257 {
258         s4 disp;
259
260         /* search the data segment if the value is already stored */
261
262         disp = dseg_find_s4(cd, value);
263
264         if (disp != 0)
265                 return disp;
266                 
267         disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
268
269         return disp;
270 }
271
272
273 /* dseg_add_s8_intern **********************************************************
274
275    Internal function to add an s8 value to the data segment.
276
277 *******************************************************************************/
278
279 static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
280 {
281         dsegentry *de;
282
283         /* Increase data segment size, which is also the displacement into
284            the data segment. */
285
286         cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
287
288         /* allocate new entry */
289
290         de = DNEW(dsegentry);
291
292         de->type  = TYPE_LNG;
293         de->flags = flags;
294         de->disp  = -(cd->dseglen);
295         de->val.l = value;
296         de->next  = cd->dseg;
297
298         /* insert into the chain */
299
300         cd->dseg = de;
301
302         return de->disp;
303 }
304
305
306 /* dseg_add_unique_s8 **********************************************************
307
308    Adds uniquely an s8 value to the data segment.
309
310 *******************************************************************************/
311
312 s4 dseg_add_unique_s8(codegendata *cd, s8 value)
313 {
314         s4 disp;
315
316         disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
317
318         return disp;
319 }
320
321
322 /* dseg_add_s8 *****************************************************************
323
324    Adds an s8 value to the data segment. It tries to reuse previously
325    added values.
326
327 *******************************************************************************/
328
329 s4 dseg_add_s8(codegendata *cd, s8 value)
330 {
331         s4 disp;
332
333         /* search the data segment if the value is already stored */
334
335         disp = dseg_find_s8(cd, value);
336
337         if (disp != 0)
338                 return disp;
339                 
340         disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
341
342         return disp;
343 }
344
345
346 /* dseg_add_float_intern *******************************************************
347
348    Internal function to add a float value to the data segment.
349
350 *******************************************************************************/
351
352 static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
353 {
354         dsegentry *de;
355                 
356         /* Increase data segment size, which is also the displacement into
357            the data segment. */
358
359         cd->dseglen += 4;
360
361         /* allocate new entry */
362
363         de = DNEW(dsegentry);
364
365         de->type  = TYPE_FLT;
366         de->flags = flags;
367         de->disp  = -(cd->dseglen);
368         de->val.f = value;
369         de->next  = cd->dseg;
370
371         /* insert into the chain */
372
373         cd->dseg = de;
374
375         return de->disp;
376 }
377
378
379 /* dseg_add_unique_float *******************************************************
380
381    Adds uniquely an float value to the data segment.
382
383 *******************************************************************************/
384
385 s4 dseg_add_unique_float(codegendata *cd, float value)
386 {
387         s4 disp;
388
389         disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
390
391         return disp;
392 }
393
394
395 /* dseg_add_float **************************************************************
396
397    Adds an float value to the data segment. It tries to reuse
398    previously added values.
399
400 *******************************************************************************/
401
402 s4 dseg_add_float(codegendata *cd, float value)
403 {
404         s4 disp;
405
406         /* search the data segment if the value is already stored */
407
408         disp = dseg_find_float(cd, value);
409
410         if (disp != 0)
411                 return disp;
412                 
413         disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
414
415         return disp;
416 }
417
418
419 /* dseg_add_double_intern ******************************************************
420
421    Internal function to add a double value to the data segment.
422
423 *******************************************************************************/
424
425 static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
426 {
427         dsegentry *de;
428                 
429         /* Increase data segment size, which is also the displacement into
430            the data segment. */
431
432         cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
433
434         /* allocate new entry */
435
436         de = DNEW(dsegentry);
437
438         de->type  = TYPE_DBL;
439         de->flags = flags;
440         de->disp  = -(cd->dseglen);
441         de->val.d = value;
442         de->next  = cd->dseg;
443
444         /* insert into the chain */
445
446         cd->dseg = de;
447
448         return de->disp;
449 }
450
451
452 /* dseg_add_unique_double ******************************************************
453
454    Adds uniquely a double value to the data segment.
455
456 *******************************************************************************/
457
458 s4 dseg_add_unique_double(codegendata *cd, double value)
459 {
460         s4 disp;
461
462         disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
463
464         return disp;
465 }
466
467
468 /* dseg_add_double *************************************************************
469
470    Adds a double value to the data segment. It tries to reuse
471    previously added values.
472
473 *******************************************************************************/
474
475 s4 dseg_add_double(codegendata *cd, double value)
476 {
477         s4 disp;
478
479         /* search the data segment if the value is already stored */
480
481         disp = dseg_find_double(cd, value);
482
483         if (disp != 0)
484                 return disp;
485                 
486         disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
487
488         return disp;
489 }
490
491
492 /* dseg_add_address_intern *****************************************************
493
494    Internal function to add an address pointer to the data segment.
495
496 *******************************************************************************/
497
498 static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
499 {
500         dsegentry *de;
501
502         /* Increase data segment size, which is also the displacement into
503            the data segment. */
504
505 #if SIZEOF_VOID_P == 8
506         cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
507 #else
508         cd->dseglen += 4;
509 #endif
510
511         /* allocate new entry */
512
513         de = DNEW(dsegentry);
514
515         de->type  = TYPE_ADR;
516         de->flags = flags;
517         de->disp  = -(cd->dseglen);
518         de->val.a = value;
519         de->next  = cd->dseg;
520
521         /* insert into the chain */
522
523         cd->dseg = de;
524
525         return de->disp;
526 }
527
528
529 /* dseg_add_unique_address *****************************************************
530
531    Adds uniquely an address value to the data segment.
532
533 *******************************************************************************/
534
535 s4 dseg_add_unique_address(codegendata *cd, void *value)
536 {
537         s4 disp;
538
539         disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
540
541         return disp;
542 }
543
544
545 /* dseg_add_address ************************************************************
546
547    Adds an address value to the data segment. It tries to reuse
548    previously added values.
549
550 *******************************************************************************/
551
552 s4 dseg_add_address(codegendata *cd, void *value)
553 {
554         s4 disp;
555
556         /* search the data segment if the value is already stored */
557
558         disp = dseg_find_address(cd, value);
559
560         if (disp != 0)
561                 return disp;
562                 
563         disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
564
565         return disp;
566 }
567
568
569 /* dseg_add_target *************************************************************
570
571    XXX
572
573 *******************************************************************************/
574
575 void dseg_add_target(codegendata *cd, basicblock *target)
576 {
577         jumpref *jr;
578
579         jr = DNEW(jumpref);
580
581         jr->tablepos = dseg_add_unique_address(cd, NULL);
582         jr->target   = target;
583         jr->next     = cd->jumpreferences;
584
585         cd->jumpreferences = jr;
586 }
587
588
589 /* dseg_addlinenumbertablesize *************************************************
590
591    XXX
592
593 *******************************************************************************/
594
595 void dseg_addlinenumbertablesize(codegendata *cd)
596 {
597 #if SIZEOF_VOID_P == 8
598         /* 4-byte ALIGNMENT PADDING */
599
600         dseg_add_unique_s4(cd, 0);
601 #endif
602
603         cd->linenumbertablesizepos  = dseg_add_unique_address(cd, NULL);
604         cd->linenumbertablestartpos = dseg_add_unique_address(cd, NULL);
605
606 #if SIZEOF_VOID_P == 8
607         /* 4-byte ALIGNMENT PADDING */
608
609         dseg_add_unique_s4(cd, 0);
610 #endif
611 }
612
613
614 /* dseg_addlinenumber **********************************************************
615
616    Add a line number reference.
617
618    IN:
619       cd.............current codegen data
620       linenumber.....number of line that starts with the given mcodeptr
621       mcodeptr.......start mcodeptr of line
622
623 *******************************************************************************/
624
625 void dseg_addlinenumber(codegendata *cd, u2 linenumber)
626 {
627         linenumberref *lr;
628
629         lr = DNEW(linenumberref);
630
631         lr->linenumber = linenumber;
632         lr->tablepos   = 0;
633         lr->targetmpc  = cd->mcodeptr - cd->mcodebase;
634         lr->next       = cd->linenumberreferences;
635
636         cd->linenumberreferences = lr;
637 }
638
639
640 /* dseg_addlinenumber_inline_start *********************************************
641
642    Add a marker to the line number table indicating the start of an inlined
643    method body. (see doc/inlining_stacktrace.txt)
644
645    IN:
646       cd.............current codegen data
647       iptr...........the ICMD_INLINE_BODY instruction
648       mcodeptr.......start mcodeptr of inlined body
649
650 *******************************************************************************/
651
652 void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
653 {
654         linenumberref *lr;
655         insinfo_inline *insinfo;
656         ptrint mpc;
657
658         lr = DNEW(linenumberref);
659
660         lr->linenumber = (-2); /* marks start of inlined method */
661         lr->tablepos   = 0;
662         lr->targetmpc  = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
663         lr->next       = cd->linenumberreferences;
664
665         cd->linenumberreferences = lr;
666
667         insinfo = iptr->sx.s23.s3.inlineinfo;
668
669         insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
670 }
671
672
673 /* dseg_addlinenumber_inline_end ***********************************************
674
675    Add a marker to the line number table indicating the end of an inlined
676    method body. (see doc/inlining_stacktrace.txt)
677
678    IN:
679       cd.............current codegen data
680       iptr...........the ICMD_INLINE_END instruction
681
682    Note:
683       iptr->method must point to the inlined callee.
684
685 *******************************************************************************/
686
687 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
688 {
689         linenumberref *lr;
690         linenumberref *prev;
691         insinfo_inline *insinfo;
692
693         insinfo = iptr->sx.s23.s3.inlineinfo;
694
695         assert(insinfo);
696
697         lr = DNEW(linenumberref);
698
699         /* special entry containing the methodinfo * */
700         lr->linenumber = (-3) - iptr->line;
701         lr->tablepos   = 0;
702         lr->targetmpc  = (ptrint) insinfo->method;
703         lr->next       = cd->linenumberreferences;
704
705         prev = lr;
706         lr = DNEW(linenumberref);
707
708         /* end marker with PC of start of body */
709         lr->linenumber = (-1);
710         lr->tablepos   = 0;
711         lr->targetmpc  = insinfo->startmpc;
712         lr->next       = prev;
713
714         cd->linenumberreferences = lr;
715 }
716
717
718 /* dseg_createlinenumbertable **************************************************
719
720    Creates a line number table in the data segment from the created
721    entries in linenumberreferences.
722
723 *******************************************************************************/
724
725 void dseg_createlinenumbertable(codegendata *cd)
726 {
727         linenumberref *lr;
728
729         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
730                 lr->tablepos = dseg_add_unique_address(cd, NULL);
731
732                 if (cd->linenumbertab == 0)
733                         cd->linenumbertab = lr->tablepos;
734
735 #if SIZEOF_VOID_P == 8
736                 /* This is for alignment and easier usage. */
737                 (void) dseg_add_unique_s8(cd, lr->linenumber);
738 #else
739                 (void) dseg_add_unique_s4(cd, lr->linenumber);
740 #endif
741         }
742 }
743
744
745 /* dseg_get_linenumber_from_pc_intern ******************************************
746
747    This function search the line number table for the line
748    corresponding to a given pc. The function recurses for inlined
749    methods.
750
751 *******************************************************************************/
752
753 static s4 dseg_get_linenumber_from_pc_intern(methodinfo **pm, linenumbertable_entry *lntentry, s4 lntsize, u1 *pc)
754 {
755         linenumbertable_entry *lntinline;     /* special entry for inlined method */
756
757         for (; lntsize > 0; lntsize--, lntentry--) {
758                 /* Note: In case of inlining this may actually compare the pc
759                    against a methodinfo *, yielding a non-sensical
760                    result. This is no problem, however, as we ignore such
761                    entries in the switch below. This way we optimize for the
762                    common case (ie. a real pc in lntentry->pc). */
763
764                 if (pc >= lntentry->pc) {
765                         /* did we reach the current line? */
766
767                         if ((s4) lntentry->line >= 0)
768                                 return (s4) lntentry->line;
769
770                         /* we found a special inline entry (see
771                            doc/inlining_stacktrace.txt for details */
772
773                         switch (lntentry->line) {
774                         case -1: 
775                                 /* begin of inlined method (ie. INLINE_END
776                                    instruction) */
777
778                                 lntinline = --lntentry;/* get entry with methodinfo * */
779                                 lntentry--;            /* skip the special entry      */
780                                 lntsize -= 2;
781
782                                 /* search inside the inlined method */
783
784                                 if (dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize,
785                                                                                                            pc))
786                                 {
787                                         /* the inlined method contained the pc */
788
789                                         *pm = (methodinfo *) lntinline->pc;
790
791                                         assert(lntinline->line <= -3);
792
793                                         return (-3) - lntinline->line;
794                                 }
795
796                                 /* pc was not in inlined method, continue search.
797                                    Entries inside the inlined method will be skipped
798                                    because their lntentry->pc is higher than pc.  */
799                                 break;
800
801                         case -2: 
802                                 /* end of inlined method */
803
804                                 return 0;
805
806                                 /* default: is only reached for an -3-line entry after
807                                    a skipped -2 entry. We can safely ignore it and
808                                    continue searching.  */
809                         }
810                 }
811         }
812
813         /* not found, return 0 */
814
815         return 0;
816 }
817
818
819 /* dseg_get_linenumber_from_pc *************************************************
820
821    A wrapper for dseg_get_linenumber_from_pc_intern, so we don't have
822    to evaluate the method header on every call.
823
824 *******************************************************************************/
825
826 s4 dseg_get_linenumber_from_pc(methodinfo **pm, u1 *pv, u1 *pc)
827 {
828         ptrint                 lntsize;     /* size of line number table          */
829         u1                    *lntstart;    /* start of line number table         */
830         linenumbertable_entry *lntentry;    /* points to last entry in the table  */
831         s4                     linenumber;
832
833 #if defined(__S390__)
834         pc = (u1 *)((intptr_t)pc & 0x7FFFFFFF);
835 #endif
836
837         /* get size of line number table */
838
839         lntsize  = *((ptrint *) (pv + LineNumberTableSize));
840         lntstart = *((u1 **)    (pv + LineNumberTableStart));
841
842         /* Subtract the size of the line number entry of the structure,
843            since the line number table start points to the pc. */
844
845         lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
846
847         /* get the line number */
848
849         linenumber = dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize, pc);
850
851         return linenumber;
852 }
853
854
855 /* dseg_adddata ****************************************************************
856
857    Adds a data segment reference to the codegendata.
858
859 *******************************************************************************/
860
861 #if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
862 void dseg_adddata(codegendata *cd)
863 {
864         dataref *dr;
865
866         dr = DNEW(dataref);
867
868         dr->datapos = cd->mcodeptr - cd->mcodebase;
869         dr->next    = cd->datareferences;
870
871         cd->datareferences = dr;
872 }
873 #endif
874
875
876 /* dseg_resolve_datareferences *************************************************
877
878    Resolve data segment references.
879
880 *******************************************************************************/
881
882 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
883 void dseg_resolve_datareferences(jitdata *jd)
884 {
885         codeinfo    *code;
886         codegendata *cd;
887         dataref     *dr;
888
889         /* get required compiler data */
890
891         code = jd->code;
892         cd   = jd->cd;
893
894         /* data segment references resolving */
895
896         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
897                 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
898 }
899 #endif
900
901
902 /* dseg_display ****************************************************************
903
904    Displays the content of the methods' data segment.
905
906 *******************************************************************************/
907
908 #if !defined(NDEBUG)
909 void dseg_display(jitdata *jd)
910 {
911         codeinfo    *code;
912         codegendata *cd;
913         dsegentry   *de;
914         imm_union   val;
915
916         /* get required compiler data */
917
918         code = jd->code;
919         cd   = jd->cd;
920
921         if (opt_debugcolor)
922                 printf("\033[34m");     /* blue */
923
924         printf("  --- dump of datasegment\n");
925
926         /* process all data segment entries */
927
928         for (de = cd->dseg; de != NULL; de = de->next) {
929 #if SIZEOF_VOID_P == 8
930                 printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
931 #else
932                 printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
933 #endif
934
935                 printf("    %6x (%6d): ", de->disp, de->disp);
936
937                 /* We read the values from the data segment as some values,
938                    like the line number table, have been written directly to
939                    the data segment. */
940
941                 switch (de->type) {
942                 case TYPE_INT:
943                         val.i = *((s4 *) (code->entrypoint + de->disp));
944                         printf("(INT) %d (0x%08x)", val.i, val.i);
945                         break;
946
947                 case TYPE_LNG:
948                         val.l = *((s8 *) (code->entrypoint + de->disp));
949 #if SIZEOF_VOID_P == 8
950                         printf("(LNG) %ld (0x%016lx)", val.l, val.l);
951 #else
952                         printf("(LNG) %lld (0x%016llx)", val.l, val.l);
953 #endif
954                         break;
955
956                 case TYPE_FLT:
957                         val.f = *((float *) (code->entrypoint + de->disp));
958                         printf("(FLT) %g (0x%08x)", val.f, val.i);
959                         break;
960
961                 case TYPE_DBL:
962                         val.d = *((double *) (code->entrypoint + de->disp));
963 #if SIZEOF_VOID_P == 8
964                         printf("(DBL) %g (0x%016lx)", val.d, val.l);
965 #else
966                         printf("(DBL) %g (0x%016llx)", val.d, val.l);
967 #endif
968                         break;
969
970                 case TYPE_ADR:
971                         val.a = *((void **) (code->entrypoint + de->disp));
972 #if SIZEOF_VOID_P == 8
973                         printf("(ADR) %016lx", (ptrint) val.a);
974 #else
975                         printf("(ADR) %08x", (ptrint) val.a);
976 #endif
977                         break;
978                 }
979
980                 printf("\n");
981         }
982
983         printf("  --- begin of data segment: ");
984 #if SIZEOF_VOID_P == 8
985         printf("0x%016lx\n", (ptrint) code->entrypoint);
986 #else
987         printf("0x%08x\n", (ptrint) code->entrypoint);
988 #endif
989
990         if (opt_debugcolor)
991                 printf("\033[m");
992 }
993 #endif /* !defined(NDEBUG) */
994
995
996 /*
997  * These are local overrides for various environment variables in Emacs.
998  * Please do not remove this and leave it at the end of the file, where
999  * Emacs will automagically detect them.
1000  * ---------------------------------------------------------------------
1001  * Local variables:
1002  * mode: c
1003  * indent-tabs-mode: t
1004  * c-basic-offset: 4
1005  * tab-width: 4
1006  * End:
1007  * vim:noexpandtab:sw=4:ts=4:
1008  */