Use https links in user-facing startup and error messages
[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 CostCentre* cc = (CostCentre*)literals[instrs[pc+3]];
72 if (cc) {
73 debugBelch(" %s", cc->label);
74 }
75 debugBelch("\n");
76 pc += 4;
77 break;
78 case bci_SWIZZLE:
79 debugBelch("SWIZZLE stkoff %d by %d\n",
80 instrs[pc], (signed int)instrs[pc+1]);
81 pc += 2; break;
82 case bci_CCALL:
83 debugBelch("CCALL marshaller at 0x%" FMT_Word "\n",
84 literals[instrs[pc]] );
85 pc += 1; break;
86 case bci_STKCHECK: {
87 StgWord stk_words_reqd = BCO_GET_LARGE_ARG + 1;
88 debugBelch("STKCHECK %" FMT_Word "\n", (W_)stk_words_reqd );
89 break;
90 }
91 case bci_PUSH_L:
92 debugBelch("PUSH_L %d\n", instrs[pc] );
93 pc += 1; break;
94 case bci_PUSH_LL:
95 debugBelch("PUSH_LL %d %d\n", instrs[pc], instrs[pc+1] );
96 pc += 2; break;
97 case bci_PUSH_LLL:
98 debugBelch("PUSH_LLL %d %d %d\n", instrs[pc], instrs[pc+1],
99 instrs[pc+2] );
100 pc += 3; break;
101 case bci_PUSH8:
102 debugBelch("PUSH8 %d\n", instrs[pc] );
103 pc += 1; break;
104 case bci_PUSH16:
105 debugBelch("PUSH16 %d\n", instrs[pc] );
106 pc += 1; break;
107 case bci_PUSH32:
108 debugBelch("PUSH32 %d\n", instrs[pc] );
109 pc += 1; break;
110 case bci_PUSH8_W:
111 debugBelch("PUSH8_W %d\n", instrs[pc] );
112 pc += 1; break;
113 case bci_PUSH16_W:
114 debugBelch("PUSH16_W %d\n", instrs[pc] );
115 pc += 1; break;
116 case bci_PUSH32_W:
117 debugBelch("PUSH32_W %d\n", instrs[pc] );
118 pc += 1; break;
119 case bci_PUSH_G:
120 debugBelch("PUSH_G " ); printPtr( ptrs[instrs[pc]] );
121 debugBelch("\n" );
122 pc += 1; break;
123 case bci_PUSH_ALTS:
124 debugBelch("PUSH_ALTS " ); printPtr( ptrs[instrs[pc]] );
125 debugBelch("\n");
126 pc += 1; break;
127 case bci_PUSH_ALTS_P:
128 debugBelch("PUSH_ALTS_P " ); printPtr( ptrs[instrs[pc]] );
129 debugBelch("\n");
130 pc += 1; break;
131 case bci_PUSH_ALTS_N:
132 debugBelch("PUSH_ALTS_N " ); printPtr( ptrs[instrs[pc]] );
133 debugBelch("\n");
134 pc += 1; break;
135 case bci_PUSH_ALTS_F:
136 debugBelch("PUSH_ALTS_F " ); printPtr( ptrs[instrs[pc]] );
137 debugBelch("\n");
138 pc += 1; break;
139 case bci_PUSH_ALTS_D:
140 debugBelch("PUSH_ALTS_D " ); printPtr( ptrs[instrs[pc]] );
141 debugBelch("\n");
142 pc += 1; break;
143 case bci_PUSH_ALTS_L:
144 debugBelch("PUSH_ALTS_L " ); printPtr( ptrs[instrs[pc]] );
145 debugBelch("\n");
146 pc += 1; break;
147 case bci_PUSH_ALTS_V:
148 debugBelch("PUSH_ALTS_V " ); printPtr( ptrs[instrs[pc]] );
149 debugBelch("\n");
150 pc += 1; break;
151 case bci_PUSH_PAD8:
152 debugBelch("PUSH_PAD8\n");
153 pc += 1; break;
154 case bci_PUSH_PAD16:
155 debugBelch("PUSH_PAD16\n");
156 pc += 1; break;
157 case bci_PUSH_PAD32:
158 debugBelch("PUSH_PAD32\n");
159 pc += 1; break;
160 case bci_PUSH_UBX8:
161 debugBelch(
162 "PUSH_UBX8 0x%" FMT_Word8 " ",
163 (StgWord8) literals[instrs[pc]] );
164 debugBelch("\n");
165 pc += 1; break;
166 case bci_PUSH_UBX16:
167 debugBelch(
168 "PUSH_UBX16 0x%" FMT_Word16 " ",
169 (StgWord16) literals[instrs[pc]] );
170 debugBelch("\n");
171 pc += 1; break;
172 case bci_PUSH_UBX32:
173 debugBelch(
174 "PUSH_UBX32 0x%" FMT_Word32 " ",
175 (StgWord32) literals[instrs[pc]] );
176 debugBelch("\n");
177 pc += 1; break;
178 case bci_PUSH_UBX:
179 debugBelch("PUSH_UBX ");
180 for (i = 0; i < instrs[pc+1]; i++)
181 debugBelch("0x%" FMT_Word " ", literals[i + instrs[pc]] );
182 debugBelch("\n");
183 pc += 2; break;
184 case bci_PUSH_APPLY_N:
185 debugBelch("PUSH_APPLY_N\n");
186 break;
187 case bci_PUSH_APPLY_V:
188 debugBelch("PUSH_APPLY_V\n");
189 break;
190 case bci_PUSH_APPLY_F:
191 debugBelch("PUSH_APPLY_F\n");
192 break;
193 case bci_PUSH_APPLY_D:
194 debugBelch("PUSH_APPLY_D\n");
195 break;
196 case bci_PUSH_APPLY_L:
197 debugBelch("PUSH_APPLY_L\n");
198 break;
199 case bci_PUSH_APPLY_P:
200 debugBelch("PUSH_APPLY_P\n");
201 break;
202 case bci_PUSH_APPLY_PP:
203 debugBelch("PUSH_APPLY_PP\n");
204 break;
205 case bci_PUSH_APPLY_PPP:
206 debugBelch("PUSH_APPLY_PPP\n");
207 break;
208 case bci_PUSH_APPLY_PPPP:
209 debugBelch("PUSH_APPLY_PPPP\n");
210 break;
211 case bci_PUSH_APPLY_PPPPP:
212 debugBelch("PUSH_APPLY_PPPPP\n");
213 break;
214 case bci_PUSH_APPLY_PPPPPP:
215 debugBelch("PUSH_APPLY_PPPPPP\n");
216 break;
217 case bci_SLIDE:
218 debugBelch("SLIDE %d down by %d\n", instrs[pc], instrs[pc+1] );
219 pc += 2; break;
220 case bci_ALLOC_AP:
221 debugBelch("ALLOC_AP %d words\n", instrs[pc] );
222 pc += 1; break;
223 case bci_ALLOC_AP_NOUPD:
224 debugBelch("ALLOC_AP_NOUPD %d words\n", instrs[pc] );
225 pc += 1; break;
226 case bci_ALLOC_PAP:
227 debugBelch("ALLOC_PAP %d arity, %d words\n",
228 instrs[pc], instrs[pc+1] );
229 pc += 2; break;
230 case bci_MKAP:
231 debugBelch("MKAP %d words, %d stkoff\n", instrs[pc+1],
232 instrs[pc] );
233 pc += 2; break;
234 case bci_MKPAP:
235 debugBelch("MKPAP %d words, %d stkoff\n", instrs[pc+1],
236 instrs[pc] );
237 pc += 2; break;
238 case bci_UNPACK:
239 debugBelch("UNPACK %d\n", instrs[pc] );
240 pc += 1; break;
241 case bci_PACK:
242 debugBelch("PACK %d words with itbl ", instrs[pc+1] );
243 printPtr( (StgPtr)literals[instrs[pc]] );
244 debugBelch("\n");
245 pc += 2; break;
246
247 case bci_TESTLT_I: {
248 unsigned int discr = BCO_NEXT;
249 int failto = BCO_GET_LARGE_ARG;
250 debugBelch("TESTLT_I %" FMT_Int ", fail to %d\n", literals[discr], failto);
251 break;
252 }
253 case bci_TESTEQ_I:
254 debugBelch("TESTEQ_I %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
255 instrs[pc+1]);
256 pc += 2; break;
257
258 case bci_TESTLT_F:
259 debugBelch("TESTLT_F %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
260 instrs[pc+1]);
261 pc += 2; break;
262 case bci_TESTEQ_F:
263 debugBelch("TESTEQ_F %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
264 instrs[pc+1]);
265 pc += 2; break;
266
267 case bci_TESTLT_D:
268 debugBelch("TESTLT_D %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
269 instrs[pc+1]);
270 pc += 2; break;
271 case bci_TESTEQ_D:
272 debugBelch("TESTEQ_D %" FMT_Int ", fail to %d\n", literals[instrs[pc]],
273 instrs[pc+1]);
274 pc += 2; break;
275
276 case bci_TESTLT_P:
277 debugBelch("TESTLT_P %d, fail to %d\n", instrs[pc],
278 instrs[pc+1]);
279 pc += 2; break;
280 case bci_TESTEQ_P:
281 debugBelch("TESTEQ_P %d, fail to %d\n", instrs[pc],
282 instrs[pc+1]);
283 pc += 2; break;
284 case bci_CASEFAIL:
285 debugBelch("CASEFAIL\n" );
286 break;
287 case bci_JMP:
288 debugBelch("JMP to %d\n", instrs[pc]);
289 pc += 1; break;
290
291 case bci_ENTER:
292 debugBelch("ENTER\n");
293 break;
294
295 case bci_RETURN:
296 debugBelch("RETURN\n" );
297 break;
298 case bci_RETURN_P:
299 debugBelch("RETURN_P\n" );
300 break;
301 case bci_RETURN_N:
302 debugBelch("RETURN_N\n" );
303 break;
304 case bci_RETURN_F:
305 debugBelch("RETURN_F\n" );
306 break;
307 case bci_RETURN_D:
308 debugBelch("RETURN_D\n" );
309 break;
310 case bci_RETURN_L:
311 debugBelch("RETURN_L\n" );
312 break;
313 case bci_RETURN_V:
314 debugBelch("RETURN_V\n" );
315 break;
316
317 default:
318 barf("disInstr: unknown opcode %u", (unsigned int) instr);
319 }
320 return pc;
321 }
322
323
324 /* Something of a kludge .. how do we know where the end of the insn
325 array is, since it isn't recorded anywhere? Answer: the first
326 short is the number of bytecodes which follow it.
327 See ByteCodeGen.linkBCO.insns_arr for construction ...
328 */
329 void disassemble( StgBCO *bco )
330 {
331 uint32_t i, j;
332 StgWord16* instrs = (StgWord16*)(bco->instrs->payload);
333 StgMutArrPtrs* ptrs = bco->ptrs;
334 uint32_t nbcs = (uint32_t)(bco->instrs->bytes / sizeof(StgWord16));
335 uint32_t pc = 1;
336
337 debugBelch("BCO\n" );
338 pc = 0;
339 while (pc < nbcs) {
340 debugBelch("\t%2d: ", pc );
341 pc = disInstr ( bco, pc );
342 }
343
344 debugBelch("INSTRS:\n " );
345 j = 16;
346 for (i = 0; i < nbcs; i++) {
347 debugBelch("%3d ", (int)instrs[i] );
348 j--;
349 if (j == 0) { j = 16; debugBelch("\n "); };
350 }
351 debugBelch("\n");
352
353 debugBelch("PTRS:\n " );
354 j = 8;
355 for (i = 0; i < ptrs->ptrs; i++) {
356 debugBelch("%8p ", ptrs->payload[i] );
357 j--;
358 if (j == 0) { j = 8; debugBelch("\n "); };
359 }
360 debugBelch("\n");
361
362 debugBelch("\n");
363 }
364
365 #endif /* DEBUG */