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