CNF: Silence pointer fix-up message unless gc debugging is enabled
[ghc.git] / rts / Disassembler.c
1 /* -----------------------------------------------------------------------------
2 * Bytecode disassembler
3 *
4 * Copyright (c) 1994-2002.
5 *
6 * $RCSfile: Disassembler.c,v $
7 * $Revision: 1.29 $
8 * $Date: 2004/09/03 15:28:19 $
9 * ---------------------------------------------------------------------------*/
10
11 #if defined(DEBUG)
12
13 #include "PosixSource.h"
14 #include "Rts.h"
15 #include "RtsAPI.h"
16 #include "rts/Bytecodes.h"
17
18 #include "RtsUtils.h"
19 #include "Schedule.h"
20 #include "Printer.h"
21 #include "Disassembler.h"
22 #include "Interpreter.h"
23
24 /* --------------------------------------------------------------------------
25 * Disassembler
26 * ------------------------------------------------------------------------*/
27
28 int
29 disInstr ( StgBCO *bco, int pc )
30 {
31 int i;
32 StgWord16 instr;
33
34 StgWord16* instrs = (StgWord16*)(bco->instrs->payload);
35
36 StgArrBytes* literal_arr = bco->literals;
37 StgWord* literals = (StgWord*)(&literal_arr->payload[0]);
38
39 StgMutArrPtrs* ptrs_arr = bco->ptrs;
40 StgPtr* ptrs = (StgPtr*)(&ptrs_arr->payload[0]);
41
42 instr = instrs[pc++];
43 if (instr & bci_FLAG_LARGE_ARGS) {
44 debugBelch ("LARGE ");
45 }
46
47 #define BCO_NEXT instrs[pc++]
48 #define BCO_NEXT_32 (pc += 2)
49 #define BCO_READ_NEXT_32 (BCO_NEXT_32, (((StgWord) instrs[pc-2]) << 16) \
50 + ( (StgWord) instrs[pc-1]))
51 #define BCO_NEXT_64 (pc += 4)
52 #define BCO_READ_NEXT_64 (BCO_NEXT_64, (((StgWord) instrs[pc-4]) << 48) \
53 + (((StgWord) instrs[pc-3]) << 32) \
54 + (((StgWord) instrs[pc-2]) << 16) \
55 + ( (StgWord) instrs[pc-1]))
56 #if WORD_SIZE_IN_BITS == 32
57 #define BCO_NEXT_WORD BCO_NEXT_32
58 #define BCO_READ_NEXT_WORD BCO_READ_NEXT_32
59 #elif WORD_SIZE_IN_BITS == 64
60 #define BCO_NEXT_WORD BCO_NEXT_64
61 #define BCO_READ_NEXT_WORD BCO_READ_NEXT_64
62 #else
63 #error Cannot cope with WORD_SIZE_IN_BITS being nether 32 nor 64
64 #endif
65 #define BCO_GET_LARGE_ARG ((instr & bci_FLAG_LARGE_ARGS) ? BCO_READ_NEXT_WORD : BCO_NEXT)
66
67 switch (instr & 0xff) {
68 case bci_BRK_FUN:
69 debugBelch ("BRK_FUN " ); printPtr( ptrs[instrs[pc]] );
70 debugBelch (" %d ", instrs[pc+1]); printPtr( ptrs[instrs[pc+2]] );
71 debugBelch(" %s\n", ((CostCentre*)(literals[instrs[pc+3]]))->label);
72 pc += 4;
73 break;
74 case bci_SWIZZLE:
75 debugBelch("SWIZZLE stkoff %d by %d\n",
76 instrs[pc], (signed int)instrs[pc+1]);
77 pc += 2; break;
78 case bci_CCALL:
79 debugBelch("CCALL marshaller at 0x%" FMT_Word "\n",
80 literals[instrs[pc]] );
81 pc += 1; break;
82 case bci_STKCHECK: {
83 StgWord stk_words_reqd = BCO_GET_LARGE_ARG + 1;
84 debugBelch("STKCHECK %" FMT_Word "\n", (W_)stk_words_reqd );
85 break;
86 }
87 case bci_PUSH_L:
88 debugBelch("PUSH_L %d\n", instrs[pc] );
89 pc += 1; break;
90 case bci_PUSH_LL:
91 debugBelch("PUSH_LL %d %d\n", instrs[pc], instrs[pc+1] );
92 pc += 2; break;
93 case bci_PUSH_LLL:
94 debugBelch("PUSH_LLL %d %d %d\n", instrs[pc], instrs[pc+1],
95 instrs[pc+2] );
96 pc += 3; break;
97 case bci_PUSH_G:
98 debugBelch("PUSH_G " ); printPtr( ptrs[instrs[pc]] );
99 debugBelch("\n" );
100 pc += 1; break;
101
102 case bci_PUSH_ALTS:
103 debugBelch("PUSH_ALTS " ); printPtr( ptrs[instrs[pc]] );
104 debugBelch("\n");
105 pc += 1; break;
106 case bci_PUSH_ALTS_P:
107 debugBelch("PUSH_ALTS_P " ); printPtr( ptrs[instrs[pc]] );
108 debugBelch("\n");
109 pc += 1; break;
110 case bci_PUSH_ALTS_N:
111 debugBelch("PUSH_ALTS_N " ); printPtr( ptrs[instrs[pc]] );
112 debugBelch("\n");
113 pc += 1; break;
114 case bci_PUSH_ALTS_F:
115 debugBelch("PUSH_ALTS_F " ); printPtr( ptrs[instrs[pc]] );
116 debugBelch("\n");
117 pc += 1; break;
118 case bci_PUSH_ALTS_D:
119 debugBelch("PUSH_ALTS_D " ); printPtr( ptrs[instrs[pc]] );
120 debugBelch("\n");
121 pc += 1; break;
122 case bci_PUSH_ALTS_L:
123 debugBelch("PUSH_ALTS_L " ); printPtr( ptrs[instrs[pc]] );
124 debugBelch("\n");
125 pc += 1; break;
126 case bci_PUSH_ALTS_V:
127 debugBelch("PUSH_ALTS_V " ); printPtr( ptrs[instrs[pc]] );
128 debugBelch("\n");
129 pc += 1; break;
130
131 case bci_PUSH_UBX:
132 debugBelch("PUSH_UBX ");
133 for (i = 0; i < instrs[pc+1]; i++)
134 debugBelch("0x%" FMT_Word " ", literals[i + instrs[pc]] );
135 debugBelch("\n");
136 pc += 2; break;
137 case bci_PUSH_APPLY_N:
138 debugBelch("PUSH_APPLY_N\n");
139 break;
140 case bci_PUSH_APPLY_V:
141 debugBelch("PUSH_APPLY_V\n");
142 break;
143 case bci_PUSH_APPLY_F:
144 debugBelch("PUSH_APPLY_F\n");
145 break;
146 case bci_PUSH_APPLY_D:
147 debugBelch("PUSH_APPLY_D\n");
148 break;
149 case bci_PUSH_APPLY_L:
150 debugBelch("PUSH_APPLY_L\n");
151 break;
152 case bci_PUSH_APPLY_P:
153 debugBelch("PUSH_APPLY_P\n");
154 break;
155 case bci_PUSH_APPLY_PP:
156 debugBelch("PUSH_APPLY_PP\n");
157 break;
158 case bci_PUSH_APPLY_PPP:
159 debugBelch("PUSH_APPLY_PPP\n");
160 break;
161 case bci_PUSH_APPLY_PPPP:
162 debugBelch("PUSH_APPLY_PPPP\n");
163 break;
164 case bci_PUSH_APPLY_PPPPP:
165 debugBelch("PUSH_APPLY_PPPPP\n");
166 break;
167 case bci_PUSH_APPLY_PPPPPP:
168 debugBelch("PUSH_APPLY_PPPPPP\n");
169 break;
170 case bci_SLIDE:
171 debugBelch("SLIDE %d down by %d\n", instrs[pc], instrs[pc+1] );
172 pc += 2; break;
173 case bci_ALLOC_AP:
174 debugBelch("ALLOC_AP %d words\n", instrs[pc] );
175 pc += 1; break;
176 case bci_ALLOC_AP_NOUPD:
177 debugBelch("ALLOC_AP_NOUPD %d words\n", instrs[pc] );
178 pc += 1; break;
179 case bci_ALLOC_PAP:
180 debugBelch("ALLOC_PAP %d arity, %d words\n",
181 instrs[pc], instrs[pc+1] );
182 pc += 2; break;
183 case bci_MKAP:
184 debugBelch("MKAP %d words, %d stkoff\n", instrs[pc+1],
185 instrs[pc] );
186 pc += 2; break;
187 case bci_MKPAP:
188 debugBelch("MKPAP %d words, %d stkoff\n", instrs[pc+1],
189 instrs[pc] );
190 pc += 2; break;
191 case bci_UNPACK:
192 debugBelch("UNPACK %d\n", instrs[pc] );
193 pc += 1; break;
194 case bci_PACK:
195 debugBelch("PACK %d words with itbl ", instrs[pc+1] );
196 printPtr( (StgPtr)literals[instrs[pc]] );
197 debugBelch("\n");
198 pc += 2; break;
199
200 case bci_TESTLT_I: {
201 unsigned int discr = BCO_NEXT;
202 int failto = BCO_GET_LARGE_ARG;
203 debugBelch("TESTLT_I %" FMT_Int ", fail to %d\n", literals[discr], failto);
204 break;
205 }
206 case bci_TESTEQ_I:
207 debugBelch("TESTEQ_I %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
208 instrs[pc+1]);
209 pc += 2; break;
210
211 case bci_TESTLT_F:
212 debugBelch("TESTLT_F %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
213 instrs[pc+1]);
214 pc += 2; break;
215 case bci_TESTEQ_F:
216 debugBelch("TESTEQ_F %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
217 instrs[pc+1]);
218 pc += 2; break;
219
220 case bci_TESTLT_D:
221 debugBelch("TESTLT_D %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
222 instrs[pc+1]);
223 pc += 2; break;
224 case bci_TESTEQ_D:
225 debugBelch("TESTEQ_D %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
226 instrs[pc+1]);
227 pc += 2; break;
228
229 case bci_TESTLT_P:
230 debugBelch("TESTLT_P %d, fail to %d\n", instrs[pc],
231 instrs[pc+1]);
232 pc += 2; break;
233 case bci_TESTEQ_P:
234 debugBelch("TESTEQ_P %d, fail to %d\n", instrs[pc],
235 instrs[pc+1]);
236 pc += 2; break;
237 case bci_CASEFAIL:
238 debugBelch("CASEFAIL\n" );
239 break;
240 case bci_JMP:
241 debugBelch("JMP to %d\n", instrs[pc]);
242 pc += 1; break;
243
244 case bci_ENTER:
245 debugBelch("ENTER\n");
246 break;
247
248 case bci_RETURN:
249 debugBelch("RETURN\n" );
250 break;
251 case bci_RETURN_P:
252 debugBelch("RETURN_P\n" );
253 break;
254 case bci_RETURN_N:
255 debugBelch("RETURN_N\n" );
256 break;
257 case bci_RETURN_F:
258 debugBelch("RETURN_F\n" );
259 break;
260 case bci_RETURN_D:
261 debugBelch("RETURN_D\n" );
262 break;
263 case bci_RETURN_L:
264 debugBelch("RETURN_L\n" );
265 break;
266 case bci_RETURN_V:
267 debugBelch("RETURN_V\n" );
268 break;
269
270 default:
271 barf("disInstr: unknown opcode %u", (unsigned int) instr);
272 }
273 return pc;
274 }
275
276
277 /* Something of a kludge .. how do we know where the end of the insn
278 array is, since it isn't recorded anywhere? Answer: the first
279 short is the number of bytecodes which follow it.
280 See ByteCodeGen.linkBCO.insns_arr for construction ...
281 */
282 void disassemble( StgBCO *bco )
283 {
284 uint32_t i, j;
285 StgWord16* instrs = (StgWord16*)(bco->instrs->payload);
286 StgMutArrPtrs* ptrs = bco->ptrs;
287 uint32_t nbcs = (uint32_t)(bco->instrs->bytes / sizeof(StgWord16));
288 uint32_t pc = 1;
289
290 debugBelch("BCO\n" );
291 pc = 0;
292 while (pc < nbcs) {
293 debugBelch("\t%2d: ", pc );
294 pc = disInstr ( bco, pc );
295 }
296
297 debugBelch("INSTRS:\n " );
298 j = 16;
299 for (i = 0; i < nbcs; i++) {
300 debugBelch("%3d ", (int)instrs[i] );
301 j--;
302 if (j == 0) { j = 16; debugBelch("\n "); };
303 }
304 debugBelch("\n");
305
306 debugBelch("PTRS:\n " );
307 j = 8;
308 for (i = 0; i < ptrs->ptrs; i++) {
309 debugBelch("%8p ", ptrs->payload[i] );
310 j--;
311 if (j == 0) { j = 8; debugBelch("\n "); };
312 }
313 debugBelch("\n");
314
315 debugBelch("\n");
316 }
317
318 #endif /* DEBUG */