aboutsummaryrefslogtreecommitdiffstats
path: root/libevmasm/Instruction.cpp
blob: f9bbad2cf321ec9f95c46cf07cc2249e202fd26a (plain) (blame)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
    This file is part of solidity.

    solidity is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    solidity is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Instruction.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "./Instruction.h"

#include <functional>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;

const std::map<std::string, Instruction> dev::solidity::c_instructions =
{
    { "STOP", Instruction::STOP },
    { "ADD", Instruction::ADD },
    { "SUB", Instruction::SUB },
    { "MUL", Instruction::MUL },
    { "DIV", Instruction::DIV },
    { "SDIV", Instruction::SDIV },
    { "MOD", Instruction::MOD },
    { "SMOD", Instruction::SMOD },
    { "EXP", Instruction::EXP },
    { "NOT", Instruction::NOT },
    { "LT", Instruction::LT },
    { "GT", Instruction::GT },
    { "SLT", Instruction::SLT },
    { "SGT", Instruction::SGT },
    { "EQ", Instruction::EQ },
    { "ISZERO", Instruction::ISZERO },
    { "AND", Instruction::AND },
    { "OR", Instruction::OR },
    { "XOR", Instruction::XOR },
    { "BYTE", Instruction::BYTE },
    { "SHL", Instruction::SHL },
    { "SHR", Instruction::SHR },
    { "SAR", Instruction::SAR },
    { "ADDMOD", Instruction::ADDMOD },
    { "MULMOD", Instruction::MULMOD },
    { "SIGNEXTEND", Instruction::SIGNEXTEND },
    { "KECCAK256", Instruction::KECCAK256 },
    { "ADDRESS", Instruction::ADDRESS },
    { "BALANCE", Instruction::BALANCE },
    { "ORIGIN", Instruction::ORIGIN },
    { "CALLER", Instruction::CALLER },
    { "CALLVALUE", Instruction::CALLVALUE },
    { "CALLDATALOAD", Instruction::CALLDATALOAD },
    { "CALLDATASIZE", Instruction::CALLDATASIZE },
    { "CALLDATACOPY", Instruction::CALLDATACOPY },
    { "CODESIZE", Instruction::CODESIZE },
    { "CODECOPY", Instruction::CODECOPY },
    { "GASPRICE", Instruction::GASPRICE },
    { "EXTCODESIZE", Instruction::EXTCODESIZE },
    { "EXTCODECOPY", Instruction::EXTCODECOPY },
    { "RETURNDATASIZE", Instruction::RETURNDATASIZE },
    { "RETURNDATACOPY", Instruction::RETURNDATACOPY },
    { "BLOCKHASH", Instruction::BLOCKHASH },
    { "COINBASE", Instruction::COINBASE },
    { "TIMESTAMP", Instruction::TIMESTAMP },
    { "NUMBER", Instruction::NUMBER },
    { "DIFFICULTY", Instruction::DIFFICULTY },
    { "GASLIMIT", Instruction::GASLIMIT },
    { "POP", Instruction::POP },
    { "MLOAD", Instruction::MLOAD },
    { "MSTORE", Instruction::MSTORE },
    { "MSTORE8", Instruction::MSTORE8 },
    { "SLOAD", Instruction::SLOAD },
    { "SSTORE", Instruction::SSTORE },
    { "JUMP", Instruction::JUMP },
    { "JUMPI", Instruction::JUMPI },
    { "PC", Instruction::PC },
    { "MSIZE", Instruction::MSIZE },
    { "GAS", Instruction::GAS },
    { "JUMPDEST", Instruction::JUMPDEST },
    { "PUSH1", Instruction::PUSH1 },
    { "PUSH2", Instruction::PUSH2 },
    { "PUSH3", Instruction::PUSH3 },
    { "PUSH4", Instruction::PUSH4 },
    { "PUSH5", Instruction::PUSH5 },
    { "PUSH6", Instruction::PUSH6 },
    { "PUSH7", Instruction::PUSH7 },
    { "PUSH8", Instruction::PUSH8 },
    { "PUSH9", Instruction::PUSH9 },
    { "PUSH10", Instruction::PUSH10 },
    { "PUSH11", Instruction::PUSH11 },
    { "PUSH12", Instruction::PUSH12 },
    { "PUSH13", Instruction::PUSH13 },
    { "PUSH14", Instruction::PUSH14 },
    { "PUSH15", Instruction::PUSH15 },
    { "PUSH16", Instruction::PUSH16 },
    { "PUSH17", Instruction::PUSH17 },
    { "PUSH18", Instruction::PUSH18 },
    { "PUSH19", Instruction::PUSH19 },
    { "PUSH20", Instruction::PUSH20 },
    { "PUSH21", Instruction::PUSH21 },
    { "PUSH22", Instruction::PUSH22 },
    { "PUSH23", Instruction::PUSH23 },
    { "PUSH24", Instruction::PUSH24 },
    { "PUSH25", Instruction::PUSH25 },
    { "PUSH26", Instruction::PUSH26 },
    { "PUSH27", Instruction::PUSH27 },
    { "PUSH28", Instruction::PUSH28 },
    { "PUSH29", Instruction::PUSH29 },
    { "PUSH30", Instruction::PUSH30 },
    { "PUSH31", Instruction::PUSH31 },
    { "PUSH32", Instruction::PUSH32 },
    { "DUP1", Instruction::DUP1 },
    { "DUP2", Instruction::DUP2 },
    { "DUP3", Instruction::DUP3 },
    { "DUP4", Instruction::DUP4 },
    { "DUP5", Instruction::DUP5 },
    { "DUP6", Instruction::DUP6 },
    { "DUP7", Instruction::DUP7 },
    { "DUP8", Instruction::DUP8 },
    { "DUP9", Instruction::DUP9 },
    { "DUP10", Instruction::DUP10 },
    { "DUP11", Instruction::DUP11 },
    { "DUP12", Instruction::DUP12 },
    { "DUP13", Instruction::DUP13 },
    { "DUP14", Instruction::DUP14 },
    { "DUP15", Instruction::DUP15 },
    { "DUP16", Instruction::DUP16 },
    { "SWAP1", Instruction::SWAP1 },
    { "SWAP2", Instruction::SWAP2 },
    { "SWAP3", Instruction::SWAP3 },
    { "SWAP4", Instruction::SWAP4 },
    { "SWAP5", Instruction::SWAP5 },
    { "SWAP6", Instruction::SWAP6 },
    { "SWAP7", Instruction::SWAP7 },
    { "SWAP8", Instruction::SWAP8 },
    { "SWAP9", Instruction::SWAP9 },
    { "SWAP10", Instruction::SWAP10 },
    { "SWAP11", Instruction::SWAP11 },
    { "SWAP12", Instruction::SWAP12 },
    { "SWAP13", Instruction::SWAP13 },
    { "SWAP14", Instruction::SWAP14 },
    { "SWAP15", Instruction::SWAP15 },
    { "SWAP16", Instruction::SWAP16 },
    { "LOG0", Instruction::LOG0 },
    { "LOG1", Instruction::LOG1 },
    { "LOG2", Instruction::LOG2 },
    { "LOG3", Instruction::LOG3 },
    { "LOG4", Instruction::LOG4 },
    { "CREATE", Instruction::CREATE },
    { "CALL", Instruction::CALL },
    { "CALLCODE", Instruction::CALLCODE },
    { "STATICCALL", Instruction::STATICCALL },
    { "RETURN", Instruction::RETURN },
    { "DELEGATECALL", Instruction::DELEGATECALL },
    { "CREATE2", Instruction::CREATE2 },
    { "REVERT", Instruction::REVERT },
    { "INVALID", Instruction::INVALID },
    { "SELFDESTRUCT", Instruction::SELFDESTRUCT }
};

static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ //                                                Add, Args, Ret, SideEffects, GasPriceTier
    { Instruction::STOP,        { "STOP",           0, 0, 0, true,  Tier::Zero } },
    { Instruction::ADD,         { "ADD",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SUB,         { "SUB",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::MUL,         { "MUL",            0, 2, 1, false, Tier::Low } },
    { Instruction::DIV,         { "DIV",            0, 2, 1, false, Tier::Low } },
    { Instruction::SDIV,        { "SDIV",           0, 2, 1, false, Tier::Low } },
    { Instruction::MOD,         { "MOD",            0, 2, 1, false, Tier::Low } },
    { Instruction::SMOD,        { "SMOD",           0, 2, 1, false, Tier::Low } },
    { Instruction::EXP,         { "EXP",            0, 2, 1, false, Tier::Special } },
    { Instruction::NOT,         { "NOT",            0, 1, 1, false, Tier::VeryLow } },
    { Instruction::LT,          { "LT",             0, 2, 1, false, Tier::VeryLow } },
    { Instruction::GT,          { "GT",             0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SLT,         { "SLT",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SGT,         { "SGT",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::EQ,          { "EQ",             0, 2, 1, false, Tier::VeryLow } },
    { Instruction::ISZERO,      { "ISZERO",         0, 1, 1, false, Tier::VeryLow } },
    { Instruction::AND,         { "AND",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::OR,          { "OR",             0, 2, 1, false, Tier::VeryLow } },
    { Instruction::XOR,         { "XOR",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::BYTE,        { "BYTE",           0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SHL,     { "SHL",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SHR,     { "SHR",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::SAR,     { "SAR",            0, 2, 1, false, Tier::VeryLow } },
    { Instruction::ADDMOD,      { "ADDMOD",         0, 3, 1, false, Tier::Mid } },
    { Instruction::MULMOD,      { "MULMOD",         0, 3, 1, false, Tier::Mid } },
    { Instruction::SIGNEXTEND,  { "SIGNEXTEND",     0, 2, 1, false, Tier::Low } },
    { Instruction::KECCAK256,   { "KECCAK256",          0, 2, 1, true, Tier::Special } },
    { Instruction::ADDRESS,     { "ADDRESS",        0, 0, 1, false, Tier::Base } },
    { Instruction::BALANCE,     { "BALANCE",        0, 1, 1, false, Tier::Balance } },
    { Instruction::ORIGIN,      { "ORIGIN",         0, 0, 1, false, Tier::Base } },
    { Instruction::CALLER,      { "CALLER",         0, 0, 1, false, Tier::Base } },
    { Instruction::CALLVALUE,   { "CALLVALUE",      0, 0, 1, false, Tier::Base } },
    { Instruction::CALLDATALOAD,{ "CALLDATALOAD",   0, 1, 1, false, Tier::VeryLow } },
    { Instruction::CALLDATASIZE,{ "CALLDATASIZE",   0, 0, 1, false, Tier::Base } },
    { Instruction::CALLDATACOPY,{ "CALLDATACOPY",   0, 3, 0, true, Tier::VeryLow } },
    { Instruction::CODESIZE,    { "CODESIZE",       0, 0, 1, false, Tier::Base } },
    { Instruction::CODECOPY,    { "CODECOPY",       0, 3, 0, true, Tier::VeryLow } },
    { Instruction::GASPRICE,    { "GASPRICE",       0, 0, 1, false, Tier::Base } },
    { Instruction::EXTCODESIZE, { "EXTCODESIZE",    0, 1, 1, false, Tier::ExtCode } },
    { Instruction::EXTCODECOPY, { "EXTCODECOPY",    0, 4, 0, true, Tier::ExtCode } },
    { Instruction::RETURNDATASIZE,  {"RETURNDATASIZE",  0, 0, 1, false, Tier::Base } },
    { Instruction::RETURNDATACOPY,  {"RETURNDATACOPY",  0, 3, 0, true, Tier::VeryLow } },
    { Instruction::BLOCKHASH,   { "BLOCKHASH",      0, 1, 1, false, Tier::Ext } },
    { Instruction::COINBASE,    { "COINBASE",       0, 0, 1, false, Tier::Base } },
    { Instruction::TIMESTAMP,   { "TIMESTAMP",      0, 0, 1, false, Tier::Base } },
    { Instruction::NUMBER,      { "NUMBER",         0, 0, 1, false, Tier::Base } },
    { Instruction::DIFFICULTY,  { "DIFFICULTY",     0, 0, 1, false, Tier::Base } },
    { Instruction::GASLIMIT,    { "GASLIMIT",       0, 0, 1, false, Tier::Base } },
    { Instruction::POP,         { "POP",            0, 1, 0, false, Tier::Base } },
    { Instruction::MLOAD,       { "MLOAD",          0, 1, 1, true, Tier::VeryLow } },
    { Instruction::MSTORE,      { "MSTORE",         0, 2, 0, true, Tier::VeryLow } },
    { Instruction::MSTORE8,     { "MSTORE8",        0, 2, 0, true, Tier::VeryLow } },
    { Instruction::SLOAD,       { "SLOAD",          0, 1, 1, false, Tier::Special } },
    { Instruction::SSTORE,      { "SSTORE",         0, 2, 0, true, Tier::Special } },
    { Instruction::JUMP,        { "JUMP",           0, 1, 0, true, Tier::Mid } },
    { Instruction::JUMPI,       { "JUMPI",          0, 2, 0, true, Tier::High } },
    { Instruction::PC,          { "PC",             0, 0, 1, false, Tier::Base } },
    { Instruction::MSIZE,       { "MSIZE",          0, 0, 1, false, Tier::Base } },
    { Instruction::GAS,         { "GAS",            0, 0, 1, false, Tier::Base } },
    { Instruction::JUMPDEST,    { "JUMPDEST",       0, 0, 0, true, Tier::Special } },
    { Instruction::PUSH1,       { "PUSH1",          1, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH2,       { "PUSH2",          2, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH3,       { "PUSH3",          3, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH4,       { "PUSH4",          4, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH5,       { "PUSH5",          5, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH6,       { "PUSH6",          6, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH7,       { "PUSH7",          7, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH8,       { "PUSH8",          8, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH9,       { "PUSH9",          9, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH10,      { "PUSH10",         10, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH11,      { "PUSH11",         11, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH12,      { "PUSH12",         12, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH13,      { "PUSH13",         13, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH14,      { "PUSH14",         14, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH15,      { "PUSH15",         15, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH16,      { "PUSH16",         16, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH17,      { "PUSH17",         17, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH18,      { "PUSH18",         18, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH19,      { "PUSH19",         19, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH20,      { "PUSH20",         20, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH21,      { "PUSH21",         21, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH22,      { "PUSH22",         22, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH23,      { "PUSH23",         23, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH24,      { "PUSH24",         24, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH25,      { "PUSH25",         25, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH26,      { "PUSH26",         26, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH27,      { "PUSH27",         27, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH28,      { "PUSH28",         28, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH29,      { "PUSH29",         29, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH30,      { "PUSH30",         30, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH31,      { "PUSH31",         31, 0, 1, false, Tier::VeryLow } },
    { Instruction::PUSH32,      { "PUSH32",         32, 0, 1, false, Tier::VeryLow } },
    { Instruction::DUP1,        { "DUP1",           0, 1, 2, false, Tier::VeryLow } },
    { Instruction::DUP2,        { "DUP2",           0, 2, 3, false, Tier::VeryLow } },
    { Instruction::DUP3,        { "DUP3",           0, 3, 4, false, Tier::VeryLow } },
    { Instruction::DUP4,        { "DUP4",           0, 4, 5, false, Tier::VeryLow } },
    { Instruction::DUP5,        { "DUP5",           0, 5, 6, false, Tier::VeryLow } },
    { Instruction::DUP6,        { "DUP6",           0, 6, 7, false, Tier::VeryLow } },
    { Instruction::DUP7,        { "DUP7",           0, 7, 8, false, Tier::VeryLow } },
    { Instruction::DUP8,        { "DUP8",           0, 8, 9, false, Tier::VeryLow } },
    { Instruction::DUP9,        { "DUP9",           0, 9, 10, false, Tier::VeryLow } },
    { Instruction::DUP10,       { "DUP10",          0, 10, 11, false, Tier::VeryLow } },
    { Instruction::DUP11,       { "DUP11",          0, 11, 12, false, Tier::VeryLow } },
    { Instruction::DUP12,       { "DUP12",          0, 12, 13, false, Tier::VeryLow } },
    { Instruction::DUP13,       { "DUP13",          0, 13, 14, false, Tier::VeryLow } },
    { Instruction::DUP14,       { "DUP14",          0, 14, 15, false, Tier::VeryLow } },
    { Instruction::DUP15,       { "DUP15",          0, 15, 16, false, Tier::VeryLow } },
    { Instruction::DUP16,       { "DUP16",          0, 16, 17, false, Tier::VeryLow } },
    { Instruction::SWAP1,       { "SWAP1",          0, 2, 2, false, Tier::VeryLow } },
    { Instruction::SWAP2,       { "SWAP2",          0, 3, 3, false, Tier::VeryLow } },
    { Instruction::SWAP3,       { "SWAP3",          0, 4, 4, false, Tier::VeryLow } },
    { Instruction::SWAP4,       { "SWAP4",          0, 5, 5, false, Tier::VeryLow } },
    { Instruction::SWAP5,       { "SWAP5",          0, 6, 6, false, Tier::VeryLow } },
    { Instruction::SWAP6,       { "SWAP6",          0, 7, 7, false, Tier::VeryLow } },
    { Instruction::SWAP7,       { "SWAP7",          0, 8, 8, false, Tier::VeryLow } },
    { Instruction::SWAP8,       { "SWAP8",          0, 9, 9, false, Tier::VeryLow } },
    { Instruction::SWAP9,       { "SWAP9",          0, 10, 10, false, Tier::VeryLow } },
    { Instruction::SWAP10,      { "SWAP10",         0, 11, 11, false, Tier::VeryLow } },
    { Instruction::SWAP11,      { "SWAP11",         0, 12, 12, false, Tier::VeryLow } },
    { Instruction::SWAP12,      { "SWAP12",         0, 13, 13, false, Tier::VeryLow } },
    { Instruction::SWAP13,      { "SWAP13",         0, 14, 14, false, Tier::VeryLow } },
    { Instruction::SWAP14,      { "SWAP14",         0, 15, 15, false, Tier::VeryLow } },
    { Instruction::SWAP15,      { "SWAP15",         0, 16, 16, false, Tier::VeryLow } },
    { Instruction::SWAP16,      { "SWAP16",         0, 17, 17, false, Tier::VeryLow } },
    { Instruction::LOG0,        { "LOG0",           0, 2, 0, true, Tier::Special } },
    { Instruction::LOG1,        { "LOG1",           0, 3, 0, true, Tier::Special } },
    { Instruction::LOG2,        { "LOG2",           0, 4, 0, true, Tier::Special } },
    { Instruction::LOG3,        { "LOG3",           0, 5, 0, true, Tier::Special } },
    { Instruction::LOG4,        { "LOG4",           0, 6, 0, true, Tier::Special } },
    { Instruction::CREATE,      { "CREATE",         0, 3, 1, true, Tier::Special } },
    { Instruction::CALL,        { "CALL",           0, 7, 1, true, Tier::Special } },
    { Instruction::CALLCODE,    { "CALLCODE",       0, 7, 1, true, Tier::Special } },
    { Instruction::RETURN,      { "RETURN",         0, 2, 0, true, Tier::Zero } },
    { Instruction::DELEGATECALL,    { "DELEGATECALL",   0, 6, 1, true, Tier::Special } },
    { Instruction::STATICCALL,  { "STATICCALL",     0, 6, 1, true, Tier::Special } },
    { Instruction::CREATE2,     { "CREATE2",        0, 4, 1, true, Tier::Special } },
    { Instruction::REVERT,      { "REVERT",     0, 2, 0, true, Tier::Zero } },
    { Instruction::INVALID,     { "INVALID",        0, 0, 0, true, Tier::Zero } },
    { Instruction::SELFDESTRUCT,    { "SELFDESTRUCT",       0, 1, 0, true, Tier::Special } }
};

void dev::solidity::eachInstruction(
    bytes const& _mem,
    function<void(Instruction,u256 const&)> const& _onInstruction
)
{
    for (auto it = _mem.begin(); it < _mem.end(); ++it)
    {
        Instruction instr = Instruction(*it);
        size_t additional = 0;
        if (isValidInstruction(instr))
            additional = instructionInfo(instr).additional;
        u256 data;
        for (size_t i = 0; i < additional; ++i)
        {
            data <<= 8;
            if (++it < _mem.end())
                data |= *it;
        }
        _onInstruction(instr, data);
    }
}

string dev::solidity::disassemble(bytes const& _mem)
{
    stringstream ret;
    eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) {
        if (!isValidInstruction(_instr))
            ret << "0x" << hex << int(_instr) << " ";
        else
        {
            InstructionInfo info = instructionInfo(_instr);
            ret << info.name << " ";
            if (info.additional)
                ret << "0x" << hex << _data << " ";
        }
    });
    return ret.str();
}

InstructionInfo dev::solidity::instructionInfo(Instruction _inst)
{
    try
    {
        return c_instructionInfo.at(_inst);
    }
    catch (...)
    {
        return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, Tier::Invalid});
    }
}

bool dev::solidity::isValidInstruction(Instruction _inst)
{
    return !!c_instructionInfo.count(_inst);
}