1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/***************************************************************************/
6/* ILFormatter.h */
7/***************************************************************************/
8
9#include "stdafx.h"
10#include <cor.h>
11#include <debugmacros.h> // for ASSERTE
12#include "ilformatter.h"
13#include "outstring.h"
14#include "opinfo.h"
15
16/***************************************************************************/
17void ILFormatter::init(IMetaDataImport* aMeta, const BYTE* aStart,
18 const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh) {
19 this->~ILFormatter(); // clean out old stuff
20
21 meta = aMeta;
22 start = aStart;
23 limit = aLimit;
24 if (maxStack == 0) maxStack++;
25 stackStart = stackCur = new StackEntry[maxStack];
26 stackEnd = stackStart + maxStack;
27 targetStart = targetCur = targetEnd = 0;
28 if (eh != 0) {
29 COR_ILMETHOD_SECT_EH_CLAUSE_FAT buff;
30 const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clause;
31 for(unsigned i = 0; i < eh->EHCount(); i++) {
32 clause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)eh->EHClause(i, &buff);
33 // is it a regular catch clause ?
34 if ((clause->GetFlags() & (COR_ILEXCEPTION_CLAUSE_FINALLY | COR_ILEXCEPTION_CLAUSE_FAULT)) == 0)
35 setTarget(clause->GetHandlerOffset(), 1);
36 if(clause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER)
37 setTarget(clause->GetFilterOffset(), 1);
38 }
39 }
40}
41
42/***************************************************************************/
43inline size_t ILFormatter::stackDepth() {
44 return(stackCur - stackStart);
45}
46
47/***************************************************************************/
48inline void ILFormatter::pushAndClear(OutString* val, int prec) {
49 if (stackCur >= stackEnd) {
50 _ASSERTE(!"Stack Overflow (can be ignored)");
51 return; // Ignore overflow in free build
52 }
53 stackCur->val.swap(*val);
54 val->clear();
55 stackCur->prec = prec;
56 stackCur++;
57}
58
59/***************************************************************************/
60inline OutString* ILFormatter::top() {
61 if (stackDepth() == 0) {
62 _ASSERTE(!"Stack underflow (can be ignored)");
63 stackStart->val.clear();
64 stackStart->val << "<UNDERFLOW ERROR>";
65 return (&stackStart->val);
66 }
67 return(&stackCur[-1].val);
68}
69
70/***************************************************************************/
71inline OutString* ILFormatter::pop(int prec) {
72 if (stackDepth() == 0) {
73 _ASSERTE(!"Stack underflow (can be ignored)");
74 stackStart->val.clear();
75 stackStart->val << "<UNDERFLOW ERROR>";
76 return (&stackStart->val);
77 }
78 --stackCur;
79 if (stackCur->prec < prec) {
80 stackCur->val.prepend('(');
81 stackCur->val << ')';
82 }
83 return(&stackCur->val);
84}
85
86/***************************************************************************/
87inline void ILFormatter::popN(size_t num) {
88 if (stackCur-stackStart < (SSIZE_T)num) {
89 _ASSERTE(!"Stack underflow (can be ignored)");
90 stackCur = stackStart;
91 return;
92 }
93 stackCur -= num;
94}
95
96/***************************************************************************/
97void ILFormatter::setStackAsTarget(size_t ilOffset) {
98
99 Target*ptr = targetStart;
100 for(;;) {
101 if (ptr >= targetCur)
102 return;
103 if (ptr->ilOffset == ilOffset)
104 break;
105 ptr++;
106 }
107
108 for(size_t i = 0; i < ptr->stackDepth; i++) {
109 stackStart[i].val.clear();
110 stackStart[i].val << "@STK" << (unsigned)i;
111 }
112 stackCur = stackStart + ptr->stackDepth;
113}
114
115/***************************************************************************/
116void ILFormatter::setTarget(size_t ilOffset, size_t depth) {
117 if (depth == 0)
118 return;
119
120 if (targetCur >= targetEnd) {
121 Target* targetOld = targetStart;
122 size_t oldLen = targetCur-targetStart;
123 targetStart = new Target[oldLen+10];
124 targetEnd = &targetStart[oldLen+10];
125 targetCur = &targetStart[oldLen];
126 memcpy(targetStart, targetOld, sizeof(Target)*oldLen);
127 delete [] targetOld;
128 }
129 targetCur->ilOffset = ilOffset;
130 targetCur->stackDepth = depth;
131 targetCur++;
132}
133
134/***************************************************************************/
135void ILFormatter::spillStack(OutString* out) {
136
137 for(unsigned i = 0; i < stackDepth(); i++) {
138 // don't bother spilling something already spilled.
139 if (memcmp(stackStart[i].val.val(), "@STK", 4) != 0)
140 *out << "@STK" << i << " = " << stackStart[i].val.val() << "\n";
141 stackStart[i].val.clear();
142 stackStart[i].val << "@STK" << i ;
143 }
144}
145
146/***************************************************************************/
147const BYTE* ILFormatter::formatInstr(const BYTE* instrPtr, OutString* out) {
148
149 _ASSERTE(start < instrPtr && instrPtr < limit);
150 OpArgsVal arg;
151 OpInfo op;
152 instrPtr = op.fetch(instrPtr, &arg);
153 *out << op.getName();
154 if (op.getArgsInfo() != InlineNone)
155 *out << ' ';
156 formatInstrArgs(op, arg, out, instrPtr - start);
157 return(instrPtr);
158}
159
160/***************************************************************************/
161void ILFormatter::formatArgs(unsigned numArgs, OutString* out) {
162
163 *out << '(';
164 if (numArgs > stackDepth()) {
165 _ASSERTE(!"Underflow error");
166 *out << "<UNDERFLOW ERROR>";
167 }
168 else {
169 popN(numArgs);
170 for(unsigned i = 0; i < numArgs; i++) {
171 if (i != 0) *out << ", ";
172 *out << stackCur[i].val.val();
173 }
174 }
175 *out << ')';
176}
177
178/***************************************************************************/
179void ILFormatter::formatInstrArgs(OpInfo op, OpArgsVal arg, OutString* out, size_t curILOffset) {
180
181 MDUTF8CSTR typeName=0;
182 HRESULT hr = S_OK;
183 switch(op.getArgsInfo() & PrimaryMask) {
184 case InlineNone:
185 break;
186 case InlineVar:
187 *out << arg.i;
188 break;
189 case InlineI:
190 case InlineRVA:
191 out->hex(arg.i, 0, OutString::put0x);
192 break;
193 case InlineR:
194 *out << arg.r;
195 break;
196 case InlineBrTarget: {
197 _ASSERTE(curILOffset != INVALID_IL_OFFSET);
198 size_t target = curILOffset + arg.i;
199 setTarget(target, stackDepth());
200 *out << "IL_"; out->hex(static_cast<unsigned __int64>(target), 4, OutString::zeroFill);
201 } break;
202 case InlineI8:
203 out->hex(arg.i, 0, OutString::put0x);
204 break;
205 case InlineString: {
206 ULONG numChars;
207 wchar_t str[84];
208
209 hr = meta->GetUserString(arg.i, str, 80, &numChars);
210 _ASSERTE(SUCCEEDED(hr));
211 if (numChars < 80)
212 str[numChars] = 0;
213 wcscpy_s(&str[79], 4, W("..."));
214 *out << '"';
215 wchar_t* ptr = str;
216 while(*ptr != 0) {
217 if (*ptr == '\n')
218 *out << "\\n";
219 else if (*ptr == '"')
220 *out << "\\\"";
221 else if (*ptr < 0x20 || * ptr >= 0x80) {
222 *out << '\\';
223 out->hex(*ptr, 4, OutString::zeroFill);
224 }
225 else
226 *out << char(*ptr);
227 ptr++;
228 }
229 *out << '"';
230 } break;
231 case InlineMethod:
232 case InlineField:
233 case InlineTok: {
234 // Get the typeName if possible
235 mdToken mdType = mdTypeDefNil;
236 if (TypeFromToken(arg.i) == mdtMethodDef)
237 hr = meta->GetMethodProps(mdMethodDef(arg.i), &mdType, 0, 0, 0, 0, 0, 0, 0, 0);
238 else if (TypeFromToken(arg.i) == mdtMemberRef)
239 hr = meta->GetMemberRefProps(mdMemberRef(arg.i), &mdType, 0, 0, 0, 0, 0);
240 else if (TypeFromToken(arg.i) == mdtFieldDef)
241 hr = meta->GetFieldProps(mdMethodDef(arg.i), &mdType, 0, 0, 0, 0, 0, 0, 0, 0, 0);
242 if (SUCCEEDED(hr) && mdType != mdTypeDefNil) {
243 hr = meta->GetNameFromToken(mdType, &typeName);
244 }
245 }
246 // FALL THROUGH
247 case InlineType: {
248 // FIX handle case if (TypeFromToken(arg.i) == mdtTypeSpec)
249 MDUTF8CSTR name;
250 hr = meta->GetNameFromToken(arg.i, &name);
251 if (SUCCEEDED(hr)) {
252 if (typeName) {
253 const char* lastDot = strrchr(typeName, '.');
254 if (lastDot) typeName = lastDot + 1;
255 *out << typeName << "::";
256 }
257 *out << name;
258 }
259 else {
260 *out << "TOK<";
261 out->hex(arg.i, 0, OutString::put0x);
262 *out << '>';
263 }
264 } break;
265 case InlineSig:
266 *out << "SIG<";
267 out->hex(arg.i, 0, OutString::put0x);
268 *out << '>';
269 break;
270 case InlineSwitch: {
271 _ASSERTE(curILOffset != INVALID_IL_OFFSET);
272 unsigned count = arg.switch_.count;
273 unsigned i;
274 for (i = 0; i < count; i++) {
275 size_t target = curILOffset + GET_UNALIGNED_VAL32(&arg.switch_.targets[i]);
276 setTarget(target, stackDepth()-1);
277 *out << "IL_"; out->hex(static_cast<unsigned __int64>(target), 4, OutString::zeroFill);
278 if (i < count)
279 *out << ' ';
280 }
281 } break;
282 case InlinePhi: {
283 unsigned count = arg.phi.count;
284 unsigned i;
285 for (i = 0; i < count; i++) {
286 *out << GET_UNALIGNED_VAL32(&arg.phi.vars[i]);
287 if (i < count)
288 *out << ' ';
289 }
290 } break;
291 default:
292 _ASSERTE(!"BadType");
293 }
294}
295
296#ifdef _PREFAST_
297#pragma warning(push)
298#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
299#endif
300/***************************************************************************/
301const BYTE* ILFormatter::formatStatement(const BYTE* instrPtr, OutString* out) {
302
303 OutString result;
304 OpInfo op;
305 OutString *lhs, *rhs, *idx;
306 const char* name;
307 int prec = 0;
308
309 // set stack as it would be if it was begin jumped to
310 setStackAsTarget(instrPtr - start);
311
312 while(instrPtr < limit) {
313 OpArgsVal inlineArg;
314 instrPtr = op.fetch(instrPtr, &inlineArg);
315
316 switch(op.getOpcode()) {
317 case CEE_UNALIGNED:
318 case CEE_TAILCALL:
319 case CEE_VOLATILE:
320 // for now just skip these
321 break;
322
323 case CEE_LDARGA_S:
324 case CEE_LDARGA:
325 result << "&";
326 goto DO_LDARG;
327
328 case CEE_LDARG_0:
329 case CEE_LDARG_1:
330 case CEE_LDARG_2:
331 case CEE_LDARG_3:
332 inlineArg.i = op.getOpcode() - CEE_LDARG_0;
333 goto DO_LDARG;
334
335 case CEE_LDARG:
336 case CEE_LDARG_S:
337 DO_LDARG:
338 name = "arg";
339 DO_LDARG_LDLOC:
340 result << name << inlineArg.i;
341 prec = 0x1000;
342 goto DO_PUSH;
343 DO_PUSH:
344 pushAndClear(&result, prec); // also clears result!
345 break;
346
347 case CEE_LDLOCA_S:
348 case CEE_LDLOCA:
349 result << "&";
350 goto DO_LDLOC;
351
352 case CEE_LDLOC_0:
353 case CEE_LDLOC_1:
354 case CEE_LDLOC_2:
355 case CEE_LDLOC_3:
356 inlineArg.i = op.getOpcode() - CEE_LDLOC_0;
357 goto DO_LDLOC;
358
359 case CEE_LDLOC:
360 case CEE_LDLOC_S:
361 DO_LDLOC:
362 name = "loc";
363 goto DO_LDARG_LDLOC;
364
365 case CEE_STARG:
366 case CEE_STARG_S:
367 name = "arg";
368 DO_STARG_STLOC:
369 lhs = pop(0x10);
370 result << name << inlineArg.i << " = " << lhs->val();
371 DO_STMT:
372 spillStack(out);
373 *out << result.val() << '\n';
374 // if flow of control does not fall through,
375 // assume the stack is empty
376 if (op.getFlow() == FLOW_BRANCH || op.getFlow() == FLOW_RETURN ||
377 op.getFlow() == FLOW_THROW) {
378 popN(stackDepth());
379 }
380 return(instrPtr);
381
382 case CEE_STLOC_0:
383 case CEE_STLOC_1:
384 case CEE_STLOC_2:
385 case CEE_STLOC_3:
386 inlineArg.i = op.getOpcode() - CEE_STLOC_0;
387 goto DO_STLOC;
388
389 case CEE_STLOC:
390 case CEE_STLOC_S:
391 DO_STLOC:
392 name = "loc";
393 goto DO_STARG_STLOC;
394
395 case CEE_LDC_I4_M1:
396 case CEE_LDC_I4_0:
397 case CEE_LDC_I4_1:
398 case CEE_LDC_I4_2:
399 case CEE_LDC_I4_3:
400 case CEE_LDC_I4_4:
401 case CEE_LDC_I4_5:
402 case CEE_LDC_I4_6:
403 case CEE_LDC_I4_7:
404 case CEE_LDC_I4_8:
405 inlineArg.i = op.getOpcode() - CEE_LDC_I4_0;
406 // FALL THROUGH
407 case CEE_LDC_I4:
408 case CEE_LDC_I4_S:
409 result << inlineArg.i;
410 prec = 0x1000;
411 goto DO_PUSH;
412
413 case CEE_LDC_I8:
414 result.hex(inlineArg.i8);
415 prec = 0x1000;
416 goto DO_PUSH;
417
418 case CEE_LDC_R4:
419 case CEE_LDC_R8:
420 result << inlineArg.r;
421 prec = 0x1000;
422 goto DO_PUSH;
423
424 case CEE_LDNULL:
425 result << "null";
426 prec = 0x1000;
427 goto DO_PUSH;
428
429 case CEE_LDSTR:
430 formatInstrArgs(op, inlineArg, &result);
431 prec = 0x1000;
432 goto DO_PUSH;
433
434 case CEE_BEQ:
435 case CEE_BEQ_S:
436 name = "=="; prec = 0x40; goto DO_BR_BINOP;
437 case CEE_BGE:
438 case CEE_BGE_S:
439 name = ">="; prec = 0x40; goto DO_BR_BINOP;
440 case CEE_BGE_UN:
441 case CEE_BGE_UN_S:
442 name = ">=un"; prec = 0x40; goto DO_BR_BINOP;
443
444 case CEE_BGT:
445 case CEE_BGT_S:
446 name = ">"; prec = 0x40; goto DO_BR_BINOP;
447 case CEE_BGT_UN:
448 case CEE_BGT_UN_S:
449 name = ">un"; prec = 0x40; goto DO_BR_BINOP;
450 case CEE_BLE:
451 case CEE_BLE_S:
452 name = "<="; prec = 0x40; goto DO_BR_BINOP;
453 case CEE_BLE_UN:
454 case CEE_BLE_UN_S:
455 name = "<=un"; prec = 0x40; goto DO_BR_BINOP;
456 case CEE_BLT:
457 case CEE_BLT_S:
458 name = "<"; prec = 0x40; goto DO_BR_BINOP;
459 case CEE_BLT_UN:
460 case CEE_BLT_UN_S:
461 name = "<un"; prec = 0x40; goto DO_BR_BINOP;
462 case CEE_BNE_UN:
463 case CEE_BNE_UN_S:
464 name = "!=un"; prec = 0x40; goto DO_BR_BINOP;
465 DO_BR_BINOP:
466 rhs = pop(prec);
467 lhs = pop(prec-1);
468 result << "if (" << lhs->val() << ' ' << name << ' ' << rhs->val() << ") ";
469 goto DO_BR;
470
471 case CEE_LEAVE_S:
472 case CEE_LEAVE:
473 while (stackDepth() > 0) {
474 lhs = pop();
475 *lhs << '\n' << result; // put the result in front of anything else
476 result.swap(*lhs);
477 }
478 /* fall through */
479 case CEE_BR_S:
480 case CEE_BR:
481 DO_BR: {
482 size_t target = (instrPtr - start) + inlineArg.i;
483 setTarget(target, stackDepth());
484 result << "goto IL_"; result.hex(static_cast<unsigned __int64>(target), 4, OutString::zeroFill);
485 } goto DO_STMT;
486
487 case CEE_BRFALSE_S:
488 case CEE_BRFALSE:
489 name = "!";
490 goto DO_BR_UNOP;
491 case CEE_BRTRUE_S:
492 case CEE_BRTRUE:
493 name = "";
494 DO_BR_UNOP:
495 lhs = pop();
496 result << "if (" << name << lhs->val() << ") ";
497 goto DO_BR;
498
499 case CEE_OR:
500 name = "|"; prec = 0x20; goto DO_BINOP;
501 case CEE_XOR:
502 name = "^"; prec = 0x20; goto DO_BINOP;
503 case CEE_AND:
504 name = "&"; prec = 0x30; goto DO_BINOP;
505 case CEE_SHL:
506 name = "<<"; prec = 0x50; goto DO_BINOP;
507 case CEE_SHR:
508 name = ">>"; prec = 0x50; goto DO_BINOP;
509 case CEE_SHR_UN:
510 name = ">>un"; prec = 0x50; goto DO_BINOP;
511 case CEE_CEQ:
512 name = "=="; prec = 0x40; goto DO_BINOP;
513 case CEE_CGT:
514 name = ">"; prec = 0x40; goto DO_BINOP;
515 case CEE_CGT_UN:
516 name = ">un"; prec = 0x40; goto DO_BINOP;
517 case CEE_CLT:
518 name = "<"; prec = 0x40; goto DO_BINOP;
519 case CEE_CLT_UN:
520 name = "<un"; prec = 0x40; goto DO_BINOP;
521 case CEE_ADD:
522 name = "+"; prec = 0x60; goto DO_BINOP;
523 case CEE_ADD_OVF:
524 name = "+ovf"; prec = 0x60; goto DO_BINOP;
525 case CEE_ADD_OVF_UN:
526 name = "+ovf.un";prec = 0x60; goto DO_BINOP;
527 case CEE_SUB:
528 name = "-"; prec = 0x60; goto DO_BINOP;
529 case CEE_SUB_OVF:
530 name = "-ovf"; prec = 0x60; goto DO_BINOP;
531 case CEE_SUB_OVF_UN:
532 name = "-ovf.un";prec = 0x60; goto DO_BINOP;
533 case CEE_MUL:
534 name = "*"; prec = 0x70; goto DO_BINOP;
535 case CEE_MUL_OVF:
536 name = "*ovf"; prec = 0x70; goto DO_BINOP;
537 case CEE_MUL_OVF_UN:
538 name = "*ovf.un";prec = 0x70; goto DO_BINOP;
539 case CEE_DIV:
540 name = "/"; prec = 0x70; goto DO_BINOP;
541 case CEE_DIV_UN:
542 name = "/un"; prec = 0x70; goto DO_BINOP;
543 case CEE_REM:
544 name = "%"; prec = 0x70; goto DO_BINOP;
545 case CEE_REM_UN:
546 name = "%un"; prec = 0x70; goto DO_BINOP;
547 DO_BINOP:
548 rhs = pop(prec);
549 lhs = pop(prec-1);
550 result << lhs->val() << ' ' << name << ' ' << rhs->val();
551 goto DO_PUSH;
552
553 case CEE_NOT:
554 name = "~"; prec = 0x80; goto DO_UNOP;
555 case CEE_NEG:
556 name = "-"; prec = 0x80; goto DO_UNOP;
557 DO_UNOP:
558 lhs = pop(prec-1);
559 result << name << lhs->val();
560 goto DO_PUSH;
561
562 case CEE_RET:
563 _ASSERTE(stackDepth() <= 1);
564 result << "return";
565 if (stackDepth() > 0) {
566 lhs = pop();
567 result << ' ' << lhs->val();
568 }
569 goto DO_STMT;
570
571 case CEE_POP:
572 lhs = pop();
573 result.swap(*lhs);
574 goto DO_STMT;
575
576 case CEE_DUP:
577 spillStack(out);
578 lhs = top();
579 result << lhs->val();
580 prec = 0x1000; // spillstack makes them temps, so they have high prec
581 goto DO_PUSH;
582
583 case CEE_LDFLDA:
584 name = "&";
585 goto DO_LDFLD_LDFLDA;
586 case CEE_LDFLD:
587 name = "";
588 DO_LDFLD_LDFLDA:
589 prec = 0x110;
590 lhs = pop(prec-1);
591 result << name << lhs->val() << '.';
592 formatInstrArgs(op, inlineArg, &result);
593 goto DO_PUSH;
594
595 case CEE_LDSFLDA:
596 name = "&";
597 goto DO_LDSFLD_LDSFLDA;
598 case CEE_LDSFLD:
599 name = "";
600 DO_LDSFLD_LDSFLDA:
601 prec = 0x1000;
602 result << name;
603 formatInstrArgs(op, inlineArg, &result);
604 goto DO_PUSH;
605
606 case CEE_STFLD:
607 rhs = pop(0x10);
608 lhs = pop(0x110-1);
609 result << lhs->val() << '.';
610 formatInstrArgs(op, inlineArg, &result);
611 result << " = " << rhs->val();
612 goto DO_STMT;
613
614 case CEE_STSFLD:
615 rhs = pop(0x20);
616 formatInstrArgs(op, inlineArg, &result);
617 result << " = " << rhs->val();
618 goto DO_STMT;
619
620 case CEE_CALLI:
621 lhs = pop();
622 result << "CALLI<" << lhs->val() << '>';
623 goto DO_CALL;
624
625 case CEE_NEWOBJ:
626 result << "new ";
627 // FALL THROUGH
628 case CEE_CALL:
629 case CEE_CALLVIRT: {
630 formatInstrArgs(op, inlineArg, &result);
631
632 DO_CALL:
633 // Get the signature stuff
634 PCCOR_SIGNATURE sig;
635 ULONG cSig;
636 HRESULT hr;
637 if (TypeFromToken(inlineArg.i) == mdtMethodDef)
638 hr = meta->GetMethodProps(mdMethodDef(inlineArg.i), 0, 0, 0, 0, 0, &sig, &cSig, 0, 0);
639 else if (TypeFromToken(inlineArg.i) == mdtMemberRef)
640 hr = meta->GetMemberRefProps(mdMemberRef(inlineArg.i), 0, 0, 0, 0, &sig, &cSig);
641 else
642 hr = meta->GetSigFromToken(mdSignature(inlineArg.i), &sig, &cSig);
643 _ASSERTE(SUCCEEDED(hr));
644 unsigned callConv = CorSigUncompressData(sig);
645 unsigned hasThis = callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS;
646 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
647 {
648 CorSigUncompressData(sig);
649 }
650 unsigned numArgs = CorSigUncompressData(sig);
651 while(*sig == ELEMENT_TYPE_CMOD_REQD || *sig == ELEMENT_TYPE_CMOD_OPT) {
652 sig++;
653 CorSigUncompressToken(sig);
654 }
655
656 formatArgs(numArgs, &result);
657 if (hasThis && op.getOpcode() != CEE_NEWOBJ) {
658 lhs = pop(0x90);
659 result.swap(*lhs);
660 result << '.' << lhs->val();
661 }
662 prec = 0x1000;
663 if (op.getOpcode() == CEE_NEWOBJ || *sig != ELEMENT_TYPE_VOID)
664 goto DO_PUSH;
665 } goto DO_STMT;
666
667 case CEE_LDELEM_I1:
668 case CEE_LDELEM_I2:
669 case CEE_LDELEM_I4:
670 case CEE_LDELEM_I8:
671 case CEE_LDELEM_REF:
672 case CEE_LDELEM_R4:
673 case CEE_LDELEM_R8:
674 case CEE_LDELEM_U1:
675 case CEE_LDELEM_U2:
676 case CEE_LDELEM_I:
677 rhs = pop(0x100);
678 lhs = pop();
679 result << lhs->val() << '[' << rhs->val() << ']';
680 prec = 0x100;
681 goto DO_PUSH;
682
683 case CEE_STELEM_I1:
684 case CEE_STELEM_I2:
685 case CEE_STELEM_I4:
686 case CEE_STELEM_I8:
687 case CEE_STELEM_REF:
688 case CEE_STELEM_R4:
689 case CEE_STELEM_R8:
690 case CEE_STELEM_I:
691 rhs = pop(0x100);
692 idx = pop();
693 lhs = pop(0x20);
694 result << lhs->val() << '[' << idx->val() << "] = " << rhs->val();
695 goto DO_STMT;
696
697 case CEE_LDIND_I1: name = "I1"; goto DO_LDIND;
698 case CEE_LDIND_I2: name = "I2"; goto DO_LDIND;
699 case CEE_LDIND_I4: name = "I4"; goto DO_LDIND;
700 case CEE_LDIND_I8: name = "I8"; goto DO_LDIND;
701 case CEE_LDIND_I: name = "I"; goto DO_LDIND;
702 case CEE_LDIND_R4: name = "R4"; goto DO_LDIND;
703 case CEE_LDIND_R8: name = "R8"; goto DO_LDIND;
704 case CEE_LDIND_U1: name = "U1"; goto DO_LDIND;
705 case CEE_LDIND_U2: name = "U2"; goto DO_LDIND;
706 case CEE_LDIND_REF: name = "REF";goto DO_LDIND;
707 DO_LDIND:
708 prec = 0x90;
709 lhs = pop(prec);
710 result << name << "(*" << lhs->val() << ')';
711 goto DO_PUSH;
712
713 case CEE_STIND_I1: name = "I1"; goto DO_STIND;
714 case CEE_STIND_I2: name = "I2"; goto DO_STIND;
715 case CEE_STIND_I4: name = "I4"; goto DO_STIND;
716 case CEE_STIND_I8: name = "I8"; goto DO_STIND;
717 case CEE_STIND_REF: name = "REF";goto DO_STIND;
718 case CEE_STIND_R4: name = "R4"; goto DO_STIND;
719 case CEE_STIND_R8: name = "R8"; goto DO_STIND;
720 DO_STIND:
721 rhs = pop();
722 lhs = pop(0x90);
723 result << '*' << lhs->val() << " = " << name << '(' << rhs->val() << ')';
724 goto DO_STMT;
725
726 case CEE_LDVIRTFTN:
727 case CEE_ARGLIST:
728 case CEE_BREAK:
729 case CEE_ENDFILTER:
730 case CEE_CPBLK:
731 case CEE_INITBLK:
732 case CEE_LDOBJ:
733 case CEE_CPOBJ:
734 case CEE_STOBJ:
735 case CEE_INITOBJ:
736 case CEE_LOCALLOC:
737 case CEE_NOP:
738 case CEE_SWITCH:
739 case CEE_CASTCLASS:
740 case CEE_ISINST:
741 case CEE_LDLEN:
742 case CEE_JMP:
743 case CEE_NEWARR:
744 case CEE_THROW:
745 case CEE_RETHROW:
746 case CEE_LDELEM_U4:
747 case CEE_LDIND_U4:
748 case CEE_LDELEMA:
749 case CEE_ENDFINALLY:
750 case CEE_STIND_I:
751 case CEE_CKFINITE:
752 case CEE_MKREFANY:
753 case CEE_REFANYTYPE:
754 case CEE_REFANYVAL:
755 case CEE_CONV_I1:
756 case CEE_CONV_I2:
757 case CEE_CONV_I4:
758 case CEE_CONV_I8:
759 case CEE_CONV_R4:
760 case CEE_CONV_R8:
761 case CEE_CONV_R_UN:
762 case CEE_CONV_OVF_I_UN:
763 case CEE_CONV_OVF_I1_UN:
764 case CEE_CONV_OVF_I2_UN:
765 case CEE_CONV_OVF_I4_UN:
766 case CEE_CONV_OVF_I8_UN:
767 case CEE_CONV_OVF_U_UN:
768 case CEE_CONV_OVF_U1_UN:
769 case CEE_CONV_OVF_U2_UN:
770 case CEE_CONV_OVF_U4_UN:
771 case CEE_CONV_OVF_U8_UN:
772 case CEE_CONV_OVF_I1:
773 case CEE_CONV_OVF_I2:
774 case CEE_CONV_OVF_I4:
775 case CEE_CONV_OVF_I8:
776 case CEE_CONV_OVF_U1:
777 case CEE_CONV_OVF_U2:
778 case CEE_CONV_OVF_U4:
779 case CEE_CONV_OVF_U8:
780 case CEE_CONV_U4:
781 case CEE_CONV_U8:
782 case CEE_CONV_U2:
783 case CEE_CONV_U1:
784 case CEE_CONV_I:
785 case CEE_CONV_OVF_I:
786 case CEE_CONV_OVF_U:
787 case CEE_CONV_U:
788 case CEE_BOX:
789 case CEE_LDELEM:
790 case CEE_STELEM:
791 case CEE_UNBOX_ANY:
792 case CEE_UNBOX:
793 case CEE_LDFTN:
794 case CEE_LDTOKEN:
795 case CEE_SIZEOF:
796 default:
797 result << op.getName();
798 if (op.getArgsInfo() != InlineNone) {
799 result << '<';
800 formatInstrArgs(op, inlineArg, &result, instrPtr-start);
801 result << '>';
802 }
803
804 _ASSERTE(op.getNumPop() >= 0);
805 if (op.getNumPop() > 0)
806 formatArgs(op.getNumPop(), &result);
807
808 prec = 0x1000;
809 _ASSERTE(op.getNumPush() == 0 || op.getNumPush() == 1);
810 if (op.getNumPush() > 0)
811 goto DO_PUSH;
812 goto DO_STMT;
813 }
814 }
815 return(instrPtr);
816}
817#ifdef _PREFAST_
818#pragma warning(pop)
819#endif
820
821
822