* Removed all Id tags.
[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 #if SIZEOF_VOID_P == 8
597         /* 4-byte ALIGNMENT PADDING */
598
599         dseg_add_unique_s4(cd, 0);
600 #endif
601
602         cd->linenumbertablesizepos  = dseg_add_unique_address(cd, NULL);
603         cd->linenumbertablestartpos = dseg_add_unique_address(cd, NULL);
604
605 #if SIZEOF_VOID_P == 8
606         /* 4-byte ALIGNMENT PADDING */
607
608         dseg_add_unique_s4(cd, 0);
609 #endif
610 }
611
612
613 /* dseg_addlinenumber **********************************************************
614
615    Add a line number reference.
616
617    IN:
618       cd.............current codegen data
619       linenumber.....number of line that starts with the given mcodeptr
620       mcodeptr.......start mcodeptr of line
621
622 *******************************************************************************/
623
624 void dseg_addlinenumber(codegendata *cd, u2 linenumber)
625 {
626         linenumberref *lr;
627
628         lr = DNEW(linenumberref);
629
630         lr->linenumber = linenumber;
631         lr->tablepos   = 0;
632         lr->targetmpc  = cd->mcodeptr - cd->mcodebase;
633         lr->next       = cd->linenumberreferences;
634
635         cd->linenumberreferences = lr;
636 }
637
638
639 /* dseg_addlinenumber_inline_start *********************************************
640
641    Add a marker to the line number table indicating the start of an inlined
642    method body. (see doc/inlining_stacktrace.txt)
643
644    IN:
645       cd.............current codegen data
646       iptr...........the ICMD_INLINE_BODY instruction
647       mcodeptr.......start mcodeptr of inlined body
648
649 *******************************************************************************/
650
651 void dseg_addlinenumber_inline_start(codegendata *cd, instruction *iptr)
652 {
653         linenumberref *lr;
654         insinfo_inline *insinfo;
655         ptrint mpc;
656
657         lr = DNEW(linenumberref);
658
659         lr->linenumber = (-2); /* marks start of inlined method */
660         lr->tablepos   = 0;
661         lr->targetmpc  = (mpc = (u1 *) cd->mcodeptr - cd->mcodebase);
662         lr->next       = cd->linenumberreferences;
663
664         cd->linenumberreferences = lr;
665
666         insinfo = iptr->sx.s23.s3.inlineinfo;
667
668         insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
669 }
670
671
672 /* dseg_addlinenumber_inline_end ***********************************************
673
674    Add a marker to the line number table indicating the end of an inlined
675    method body. (see doc/inlining_stacktrace.txt)
676
677    IN:
678       cd.............current codegen data
679       iptr...........the ICMD_INLINE_END instruction
680
681    Note:
682       iptr->method must point to the inlined callee.
683
684 *******************************************************************************/
685
686 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
687 {
688         linenumberref *lr;
689         linenumberref *prev;
690         insinfo_inline *insinfo;
691
692         insinfo = iptr->sx.s23.s3.inlineinfo;
693
694         assert(insinfo);
695
696         lr = DNEW(linenumberref);
697
698         /* special entry containing the methodinfo * */
699         lr->linenumber = (-3) - iptr->line;
700         lr->tablepos   = 0;
701         lr->targetmpc  = (ptrint) insinfo->method;
702         lr->next       = cd->linenumberreferences;
703
704         prev = lr;
705         lr = DNEW(linenumberref);
706
707         /* end marker with PC of start of body */
708         lr->linenumber = (-1);
709         lr->tablepos   = 0;
710         lr->targetmpc  = insinfo->startmpc;
711         lr->next       = prev;
712
713         cd->linenumberreferences = lr;
714 }
715
716
717 /* dseg_createlinenumbertable **************************************************
718
719    Creates a line number table in the data segment from the created
720    entries in linenumberreferences.
721
722 *******************************************************************************/
723
724 void dseg_createlinenumbertable(codegendata *cd)
725 {
726         linenumberref *lr;
727
728         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
729                 lr->tablepos = dseg_add_unique_address(cd, NULL);
730
731                 if (cd->linenumbertab == 0)
732                         cd->linenumbertab = lr->tablepos;
733
734 #if SIZEOF_VOID_P == 8
735                 /* This is for alignment and easier usage. */
736                 (void) dseg_add_unique_s8(cd, lr->linenumber);
737 #else
738                 (void) dseg_add_unique_s4(cd, lr->linenumber);
739 #endif
740         }
741 }
742
743
744 /* dseg_get_linenumber_from_pc_intern ******************************************
745
746    This function search the line number table for the line
747    corresponding to a given pc. The function recurses for inlined
748    methods.
749
750 *******************************************************************************/
751
752 static s4 dseg_get_linenumber_from_pc_intern(methodinfo **pm, linenumbertable_entry *lntentry, s4 lntsize, u1 *pc)
753 {
754         linenumbertable_entry *lntinline;     /* special entry for inlined method */
755
756         for (; lntsize > 0; lntsize--, lntentry--) {
757                 /* Note: In case of inlining this may actually compare the pc
758                    against a methodinfo *, yielding a non-sensical
759                    result. This is no problem, however, as we ignore such
760                    entries in the switch below. This way we optimize for the
761                    common case (ie. a real pc in lntentry->pc). */
762
763                 if (pc >= lntentry->pc) {
764                         /* did we reach the current line? */
765
766                         if ((s4) lntentry->line >= 0)
767                                 return (s4) lntentry->line;
768
769                         /* we found a special inline entry (see
770                            doc/inlining_stacktrace.txt for details */
771
772                         switch (lntentry->line) {
773                         case -1: 
774                                 /* begin of inlined method (ie. INLINE_END
775                                    instruction) */
776
777                                 lntinline = --lntentry;/* get entry with methodinfo * */
778                                 lntentry--;            /* skip the special entry      */
779                                 lntsize -= 2;
780
781                                 /* search inside the inlined method */
782
783                                 if (dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize,
784                                                                                                            pc))
785                                 {
786                                         /* the inlined method contained the pc */
787
788                                         *pm = (methodinfo *) lntinline->pc;
789
790                                         assert(lntinline->line <= -3);
791
792                                         return (-3) - lntinline->line;
793                                 }
794
795                                 /* pc was not in inlined method, continue search.
796                                    Entries inside the inlined method will be skipped
797                                    because their lntentry->pc is higher than pc.  */
798                                 break;
799
800                         case -2: 
801                                 /* end of inlined method */
802
803                                 return 0;
804
805                                 /* default: is only reached for an -3-line entry after
806                                    a skipped -2 entry. We can safely ignore it and
807                                    continue searching.  */
808                         }
809                 }
810         }
811
812         /* not found, return 0 */
813
814         return 0;
815 }
816
817
818 /* dseg_get_linenumber_from_pc *************************************************
819
820    A wrapper for dseg_get_linenumber_from_pc_intern, so we don't have
821    to evaluate the method header on every call.
822
823 *******************************************************************************/
824
825 s4 dseg_get_linenumber_from_pc(methodinfo **pm, u1 *pv, u1 *pc)
826 {
827         ptrint                 lntsize;     /* size of line number table          */
828         u1                    *lntstart;    /* start of line number table         */
829         linenumbertable_entry *lntentry;    /* points to last entry in the table  */
830         s4                     linenumber;
831
832 #if defined(__S390__)
833         pc = (u1 *)((intptr_t)pc & 0x7FFFFFFF);
834 #endif
835
836         /* get size of line number table */
837
838         lntsize  = *((ptrint *) (pv + LineNumberTableSize));
839         lntstart = *((u1 **)    (pv + LineNumberTableStart));
840
841         /* Subtract the size of the line number entry of the structure,
842            since the line number table start points to the pc. */
843
844         lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
845
846         /* get the line number */
847
848         linenumber = dseg_get_linenumber_from_pc_intern(pm, lntentry, lntsize, pc);
849
850         return linenumber;
851 }
852
853
854 /* dseg_adddata ****************************************************************
855
856    Adds a data segment reference to the codegendata.
857
858 *******************************************************************************/
859
860 #if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
861 void dseg_adddata(codegendata *cd)
862 {
863         dataref *dr;
864
865         dr = DNEW(dataref);
866
867         dr->datapos = cd->mcodeptr - cd->mcodebase;
868         dr->next    = cd->datareferences;
869
870         cd->datareferences = dr;
871 }
872 #endif
873
874
875 /* dseg_resolve_datareferences *************************************************
876
877    Resolve data segment references.
878
879 *******************************************************************************/
880
881 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
882 void dseg_resolve_datareferences(jitdata *jd)
883 {
884         codeinfo    *code;
885         codegendata *cd;
886         dataref     *dr;
887
888         /* get required compiler data */
889
890         code = jd->code;
891         cd   = jd->cd;
892
893         /* data segment references resolving */
894
895         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
896                 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
897 }
898 #endif
899
900
901 /* dseg_display ****************************************************************
902
903    Displays the content of the methods' data segment.
904
905 *******************************************************************************/
906
907 #if !defined(NDEBUG)
908 void dseg_display(jitdata *jd)
909 {
910         codeinfo    *code;
911         codegendata *cd;
912         dsegentry   *de;
913         imm_union   val;
914
915         /* get required compiler data */
916
917         code = jd->code;
918         cd   = jd->cd;
919
920         if (opt_debugcolor)
921                 printf("\033[34m");     /* blue */
922
923         printf("  --- dump of datasegment\n");
924
925         /* process all data segment entries */
926
927         for (de = cd->dseg; de != NULL; de = de->next) {
928 #if SIZEOF_VOID_P == 8
929                 printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
930 #else
931                 printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
932 #endif
933
934                 printf("    %6x (%6d): ", de->disp, de->disp);
935
936                 /* We read the values from the data segment as some values,
937                    like the line number table, have been written directly to
938                    the data segment. */
939
940                 switch (de->type) {
941                 case TYPE_INT:
942                         val.i = *((s4 *) (code->entrypoint + de->disp));
943                         printf("(INT) %d (0x%08x)", val.i, val.i);
944                         break;
945
946                 case TYPE_LNG:
947                         val.l = *((s8 *) (code->entrypoint + de->disp));
948 #if SIZEOF_VOID_P == 8
949                         printf("(LNG) %ld (0x%016lx)", val.l, val.l);
950 #else
951                         printf("(LNG) %lld (0x%016llx)", val.l, val.l);
952 #endif
953                         break;
954
955                 case TYPE_FLT:
956                         val.f = *((float *) (code->entrypoint + de->disp));
957                         printf("(FLT) %g (0x%08x)", val.f, val.i);
958                         break;
959
960                 case TYPE_DBL:
961                         val.d = *((double *) (code->entrypoint + de->disp));
962 #if SIZEOF_VOID_P == 8
963                         printf("(DBL) %g (0x%016lx)", val.d, val.l);
964 #else
965                         printf("(DBL) %g (0x%016llx)", val.d, val.l);
966 #endif
967                         break;
968
969                 case TYPE_ADR:
970                         val.a = *((void **) (code->entrypoint + de->disp));
971 #if SIZEOF_VOID_P == 8
972                         printf("(ADR) %016lx", (ptrint) val.a);
973 #else
974                         printf("(ADR) %08x", (ptrint) val.a);
975 #endif
976                         break;
977                 }
978
979                 printf("\n");
980         }
981
982         printf("  --- begin of data segment: ");
983 #if SIZEOF_VOID_P == 8
984         printf("0x%016lx\n", (ptrint) code->entrypoint);
985 #else
986         printf("0x%08x\n", (ptrint) code->entrypoint);
987 #endif
988
989         if (opt_debugcolor)
990                 printf("\033[m");
991 }
992 #endif /* !defined(NDEBUG) */
993
994
995 /*
996  * These are local overrides for various environment variables in Emacs.
997  * Please do not remove this and leave it at the end of the file, where
998  * Emacs will automagically detect them.
999  * ---------------------------------------------------------------------
1000  * Local variables:
1001  * mode: c
1002  * indent-tabs-mode: t
1003  * c-basic-offset: 4
1004  * tab-width: 4
1005  * End:
1006  * vim:noexpandtab:sw=4:ts=4:
1007  */