summaryrefslogtreecommitdiff
path: root/src/inc/opinfo.h
blob: a68fb63785f8a00d72b1e2977f206d4704109019 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//


/***************************************************************************/
/*                                OpInfo.h                                 */
/***************************************************************************/

/* contains OpInfo, a wrapper that allows you to get useful information
   about IL opcodes, and how to decode them */

/***************************************************************************/

#ifndef OpInfo_h
#define OpInfo_h

#include "openum.h"

	// Decribes the flow of control properties of the instruction
enum OpFlow {
	FLOW_META,			// not a real instuction
	FLOW_CALL,			// a call instruction
	FLOW_BRANCH,			// unconditional branch, does not fall through
	FLOW_COND_BRANCH,	// may fall through
	FLOW_PHI,			
	FLOW_THROW,
	FLOW_BREAK,
	FLOW_RETURN,		
	FLOW_NEXT,			// flows into next instruction (none of the above)
};

	// These are all the possible arguments for the instruction
/****************************************************************************/
union OpArgsVal {
	__int32  i;
	__int64 i8;
	double   r;
	struct {
		unsigned count;
		int* targets;   // targets are pcrelative displacements (little-endian)
		} switch_;
	struct {
		unsigned count;
		unsigned short* vars;
		} phi;
};

/***************************************************************************/

	// OpInfo parses a il instrution into an opcode, and a arg and updates the IP
class OpInfo {
public:
	OpInfo()			  { data = 0; }
	OpInfo(OPCODE opCode) { _ASSERTE(opCode < CEE_COUNT); data = &table[opCode]; } 

		// fetch instruction at 'instrPtr, fills in 'args' returns pointer 
		// to next instruction 
	const unsigned char* fetch(const unsigned char* instrPtr, OpArgsVal* args);	

	const char* getName() 	 	{ return(data->name); }
	OPCODE_FORMAT getArgsInfo()	{ return(OPCODE_FORMAT(data->format & PrimaryMask)); }
	OpFlow 		getFlow()	 	{ return(data->flow); }
	OPCODE 		getOpcode()	 	{ return((OPCODE) (data-table)); }
    int         getNumPop()     { return(data->numPop); }
    int         getNumPush()    { return(data->numPush); }

private:
	struct OpInfoData {
        const char* name;
        OPCODE_FORMAT format  	: 8;
		OpFlow     	flow		: 8;
		int     	numPop		: 3;	// < 0 means depends on instr args
		int       	numPush		: 3;	// < 0 means depends on instr args
        OPCODE      opcode      : 10;  	// This is the same as the index into the table
    };

	static OpInfoData table[];
private:
	OpInfoData* data;
};

#endif