31
31
#include < libevmasm/ConstantOptimiser.h>
32
32
#include < libevmasm/GasMeter.h>
33
33
34
+ #include < libsolutil/JSON.h>
35
+
34
36
#include < liblangutil/Exceptions.h>
35
37
36
38
#include < json/json.h>
@@ -227,6 +229,216 @@ string Assembly::toStringInHex(u256 _value)
227
229
return hexStr.str ();
228
230
}
229
231
232
+ AssemblyItem Assembly::loadItemFromJSON (Json::Value const & _json)
233
+ {
234
+ std::string name = _json[" name" ].isString () ? _json[" name" ].asString () : " " ;
235
+ int begin = _json[" begin" ].isInt () ? _json[" begin" ].asInt () : -1 ;
236
+ int end = _json[" end" ].isInt () ? _json[" end" ].asInt () : -1 ;
237
+ int source = _json[" source" ].isInt () ? _json[" source" ].asInt () : -1 ;
238
+ std::string value = _json[" value" ].isString () ? _json[" value" ].asString () : " " ;
239
+ std::string jumpType = _json[" jumpType" ].isString () ? _json[" jumpType" ].asString () : " " ;
240
+ solAssert (!name.empty (), " " );
241
+
242
+ auto updateUsedTags = [&](u256 const & data) {
243
+ auto tag = static_cast <unsigned >(data);
244
+ if (this ->m_usedTags <= tag)
245
+ this ->m_usedTags = tag + 1 ;
246
+ };
247
+
248
+ auto updateImmutables = [&](string const & _immutableName) -> h256 {
249
+ h256 hash (util::keccak256 (value));
250
+ this ->m_immutables [hash] = _immutableName;
251
+ return hash;
252
+ };
253
+
254
+ auto updateLibraries = [&](string const & _libraryName) -> h256 {
255
+ h256 hash (util::keccak256 (_libraryName));
256
+ this ->m_libraries [hash] = _libraryName;
257
+ return hash;
258
+ };
259
+
260
+ SourceLocation location;
261
+ location.start = begin;
262
+ location.end = end;
263
+ location.sourceIndex = source;
264
+ if (c_instructions.find (name) != c_instructions.end ())
265
+ {
266
+ AssemblyItem item{c_instructions.at (name), location};
267
+ if (!value.empty ())
268
+ item.setJumpType (value);
269
+ return item;
270
+ }
271
+ else
272
+ {
273
+ u256 data;
274
+ if (name == " PUSH" )
275
+ {
276
+ if (!value.empty ())
277
+ data = u256 (" 0x" + value);
278
+ AssemblyItem item{AssemblyItemType::Push, data, location};
279
+ if (!jumpType.empty ())
280
+ item.setJumpType (jumpType);
281
+ return item;
282
+ }
283
+ else if (name == " PUSH tag" )
284
+ {
285
+ if (!value.empty ())
286
+ data = u256 (" 0x" + value);
287
+ updateUsedTags (data);
288
+ return {AssemblyItemType::PushString, data, location};
289
+ }
290
+ else if (name == " PUSH [ErrorTag]" )
291
+ return {AssemblyItemType::PushTag, data, location};
292
+ else if (name == " PUSH [tag]" )
293
+ {
294
+ if (!value.empty ())
295
+ data = u256 (value);
296
+ updateUsedTags (data);
297
+ return {AssemblyItemType::PushTag, data, location};
298
+ }
299
+ else if (name == " PUSH [$]" )
300
+ {
301
+ if (!value.empty ())
302
+ data = u256 (" 0x" + value);
303
+ return {AssemblyItemType::PushSub, data, location};
304
+ }
305
+ else if (name == " PUSH #[$]" )
306
+ {
307
+ if (!value.empty ())
308
+ data = u256 (" 0x" + value);
309
+ return {AssemblyItemType::PushSubSize, data, location};
310
+ }
311
+ else if (name == " PUSHSIZE" )
312
+ return {AssemblyItemType::PushProgramSize, data, location};
313
+ else if (name == " PUSHLIB" )
314
+ {
315
+ h256 hash = updateLibraries (value);
316
+ return {AssemblyItemType::PushLibraryAddress, hash, location};
317
+ }
318
+ else if (name == " PUSHDEPLOYADDRESS" )
319
+ return {AssemblyItemType::PushDeployTimeAddress, data, location};
320
+ else if (name == " PUSHIMMUTABLE" )
321
+ {
322
+ h256 hash = updateImmutables (value);
323
+ return {AssemblyItemType::PushImmutable, hash, location};
324
+ }
325
+ else if (name == " ASSIGNIMMUTABLE" )
326
+ {
327
+ h256 hash = updateImmutables (value);
328
+ return {AssemblyItemType::AssignImmutable, hash, location};
329
+ }
330
+ else if (name == " tag" )
331
+ {
332
+ if (!value.empty ())
333
+ data = u256 (value);
334
+ return {AssemblyItemType::Tag, data, location};
335
+ }
336
+ else if (name == " PUSH data" )
337
+ {
338
+ if (!value.empty ())
339
+ data = u256 (" 0x" + value);
340
+ return {AssemblyItemType::PushData, data, location};
341
+ }
342
+ else if (name == " VERBATIM" )
343
+ {
344
+ AssemblyItem item (fromHex (value), 0 , 0 );
345
+ item.setLocation (location);
346
+ return item;
347
+ }
348
+ else
349
+ assertThrow (false , InvalidOpcode, " " );
350
+ }
351
+ }
352
+
353
+ vector<Json::Value> Assembly::assemblyItemAsJSON (AssemblyItem const & _item, int _sourceIndex) const
354
+ {
355
+ vector<Json::Value> result;
356
+
357
+ switch (_item.type ())
358
+ {
359
+ case Operation:
360
+ result.emplace_back (createJsonValue (
361
+ instructionInfo (_item.instruction ()).name ,
362
+ _sourceIndex,
363
+ _item.location ().start ,
364
+ _item.location ().end ,
365
+ _item.getJumpTypeAsString ()));
366
+ break ;
367
+ case Push:
368
+ result.emplace_back (createJsonValue (
369
+ " PUSH" ,
370
+ _sourceIndex,
371
+ _item.location ().start ,
372
+ _item.location ().end ,
373
+ toStringInHex (_item.data ()),
374
+ _item.getJumpTypeAsString ()));
375
+ break ;
376
+ case PushString:
377
+ result.emplace_back (createJsonValue (
378
+ " PUSH tag" , _sourceIndex, _item.location ().start , _item.location ().end , m_strings.at (h256 (_item.data ()))));
379
+ break ;
380
+ case PushTag:
381
+ if (_item.data () == 0 )
382
+ result.emplace_back (
383
+ createJsonValue (" PUSH [ErrorTag]" , _sourceIndex, _item.location ().start , _item.location ().end , " " ));
384
+ else
385
+ result.emplace_back (createJsonValue (
386
+ " PUSH [tag]" , _sourceIndex, _item.location ().start , _item.location ().end , toString (_item.data ())));
387
+ break ;
388
+ case PushSub:
389
+ result.emplace_back (createJsonValue (
390
+ " PUSH [$]" , _sourceIndex, _item.location ().start , _item.location ().end , toString (h256 (_item.data ()))));
391
+ break ;
392
+ case PushSubSize:
393
+ result.emplace_back (createJsonValue (
394
+ " PUSH #[$]" , _sourceIndex, _item.location ().start , _item.location ().end , toString (h256 (_item.data ()))));
395
+ break ;
396
+ case PushProgramSize:
397
+ result.emplace_back (createJsonValue (" PUSHSIZE" , _sourceIndex, _item.location ().start , _item.location ().end ));
398
+ break ;
399
+ case PushLibraryAddress:
400
+ result.emplace_back (createJsonValue (
401
+ " PUSHLIB" , _sourceIndex, _item.location ().start , _item.location ().end , m_libraries.at (h256 (_item.data ()))));
402
+ break ;
403
+ case PushDeployTimeAddress:
404
+ result.emplace_back (
405
+ createJsonValue (" PUSHDEPLOYADDRESS" , _sourceIndex, _item.location ().start , _item.location ().end ));
406
+ break ;
407
+ case PushImmutable:
408
+ result.emplace_back (createJsonValue (
409
+ " PUSHIMMUTABLE" ,
410
+ _sourceIndex,
411
+ _item.location ().start ,
412
+ _item.location ().end ,
413
+ m_immutables.at (h256 (_item.data ()))));
414
+ break ;
415
+ case AssignImmutable:
416
+ result.emplace_back (createJsonValue (
417
+ " ASSIGNIMMUTABLE" ,
418
+ _sourceIndex,
419
+ _item.location ().start ,
420
+ _item.location ().end ,
421
+ m_immutables.at (h256 (_item.data ()))));
422
+ break ;
423
+ case Tag:
424
+ result.emplace_back (
425
+ createJsonValue (" tag" , _sourceIndex, _item.location ().start , _item.location ().end , toString (_item.data ())));
426
+ result.emplace_back (createJsonValue (" JUMPDEST" , _sourceIndex, _item.location ().start , _item.location ().end ));
427
+ break ;
428
+ case PushData:
429
+ result.emplace_back (createJsonValue (
430
+ " PUSH data" , _sourceIndex, _item.location ().start , _item.location ().end , toStringInHex (_item.data ())));
431
+ break ;
432
+ case VerbatimBytecode:
433
+ result.emplace_back (createJsonValue (
434
+ " VERBATIM" , _sourceIndex, _item.location ().start , _item.location ().end , toHex (_item.verbatimData ())));
435
+ break ;
436
+ default :
437
+ assertThrow (false , InvalidOpcode, " " );
438
+ }
439
+ return result;
440
+ }
441
+
230
442
Json::Value Assembly::assemblyJSON (map<string, unsigned > const & _sourceIndices) const
231
443
{
232
444
Json::Value root;
@@ -235,96 +447,17 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices)
235
447
for (AssemblyItem const & i: m_items)
236
448
{
237
449
int sourceIndex = -1 ;
238
- if (i.location ().sourceName )
450
+ if (i.location ().sourceIndex .has_value ())
451
+ sourceIndex = i.location ().sourceIndex .value ();
452
+ else if (i.location ().sourceName )
239
453
{
240
454
auto iter = _sourceIndices.find (*i.location ().sourceName );
241
455
if (iter != _sourceIndices.end ())
242
456
sourceIndex = static_cast <int >(iter->second );
243
457
}
244
458
245
- switch (i.type ())
246
- {
247
- case Operation:
248
- collection.append (
249
- createJsonValue (
250
- instructionInfo (i.instruction ()).name ,
251
- sourceIndex,
252
- i.location ().start ,
253
- i.location ().end ,
254
- i.getJumpTypeAsString ())
255
- );
256
- break ;
257
- case Push:
258
- collection.append (
259
- createJsonValue (" PUSH" , sourceIndex, i.location ().start , i.location ().end , toStringInHex (i.data ()), i.getJumpTypeAsString ()));
260
- break ;
261
- case PushString:
262
- collection.append (
263
- createJsonValue (" PUSH tag" , sourceIndex, i.location ().start , i.location ().end , m_strings.at (h256 (i.data ()))));
264
- break ;
265
- case PushTag:
266
- if (i.data () == 0 )
267
- collection.append (
268
- createJsonValue (" PUSH [ErrorTag]" , sourceIndex, i.location ().start , i.location ().end , " " ));
269
- else
270
- collection.append (
271
- createJsonValue (" PUSH [tag]" , sourceIndex, i.location ().start , i.location ().end , toString (i.data ())));
272
- break ;
273
- case PushSub:
274
- collection.append (
275
- createJsonValue (" PUSH [$]" , sourceIndex, i.location ().start , i.location ().end , toString (h256 (i.data ()))));
276
- break ;
277
- case PushSubSize:
278
- collection.append (
279
- createJsonValue (" PUSH #[$]" , sourceIndex, i.location ().start , i.location ().end , toString (h256 (i.data ()))));
280
- break ;
281
- case PushProgramSize:
282
- collection.append (
283
- createJsonValue (" PUSHSIZE" , sourceIndex, i.location ().start , i.location ().end ));
284
- break ;
285
- case PushLibraryAddress:
286
- collection.append (
287
- createJsonValue (" PUSHLIB" , sourceIndex, i.location ().start , i.location ().end , m_libraries.at (h256 (i.data ())))
288
- );
289
- break ;
290
- case PushDeployTimeAddress:
291
- collection.append (
292
- createJsonValue (" PUSHDEPLOYADDRESS" , sourceIndex, i.location ().start , i.location ().end )
293
- );
294
- break ;
295
- case PushImmutable:
296
- collection.append (createJsonValue (
297
- " PUSHIMMUTABLE" ,
298
- sourceIndex,
299
- i.location ().start ,
300
- i.location ().end ,
301
- m_immutables.at (h256 (i.data ()))
302
- ));
303
- break ;
304
- case AssignImmutable:
305
- collection.append (createJsonValue (
306
- " ASSIGNIMMUTABLE" ,
307
- sourceIndex,
308
- i.location ().start ,
309
- i.location ().end ,
310
- m_immutables.at (h256 (i.data ()))
311
- ));
312
- break ;
313
- case Tag:
314
- collection.append (
315
- createJsonValue (" tag" , sourceIndex, i.location ().start , i.location ().end , toString (i.data ())));
316
- collection.append (
317
- createJsonValue (" JUMPDEST" , sourceIndex, i.location ().start , i.location ().end ));
318
- break ;
319
- case PushData:
320
- collection.append (createJsonValue (" PUSH data" , sourceIndex, i.location ().start , i.location ().end , toStringInHex (i.data ())));
321
- break ;
322
- case VerbatimBytecode:
323
- collection.append (createJsonValue (" VERBATIM" , sourceIndex, i.location ().start , i.location ().end , toHex (i.verbatimData ())));
324
- break ;
325
- default :
326
- assertThrow (false , InvalidOpcode, " " );
327
- }
459
+ for (Json::Value const & item: assemblyItemAsJSON (i, sourceIndex))
460
+ collection.append (item);
328
461
}
329
462
330
463
if (!m_data.empty () || !m_subs.empty ())
@@ -342,12 +475,54 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices)
342
475
}
343
476
}
344
477
345
- if (m_auxiliaryData.size () > 0 )
478
+ if (! m_auxiliaryData.empty () )
346
479
root[" .auxdata" ] = toHex (m_auxiliaryData);
347
480
348
481
return root;
349
482
}
350
483
484
+ void Assembly::addAssemblyItemsFromJSON (Json::Value const & _code)
485
+ {
486
+ solAssert (_code.isArray (), " " );
487
+ for (auto const & it: _code)
488
+ this ->m_items .emplace_back (loadItemFromJSON (it));
489
+
490
+ for (auto current = this ->m_items .begin (); current != this ->m_items .end (); ++current)
491
+ {
492
+ auto const next = std::next (current);
493
+ if (
494
+ current->type () == AssemblyItemType::Tag &&
495
+ next->type () == AssemblyItemType::Operation &&
496
+ next->instruction () == Instruction::JUMPDEST
497
+ )
498
+ this ->m_items .erase (next);
499
+ }
500
+ }
501
+
502
+ bool Assembly::loadFromAssemblyJSON (Json::Value const & _json)
503
+ {
504
+ solAssert (_json[" .code" ].isArray (), " " );
505
+ addAssemblyItemsFromJSON (_json[" .code" ]);
506
+ if (_json[" .auxdata" ].isString ())
507
+ this ->m_auxiliaryData = fromHex (_json[" .auxdata" ].asString ());
508
+ Json::Value const & data = _json[" .data" ];
509
+ for (Json::ValueConstIterator itr = data.begin (); itr != data.end (); itr++)
510
+ {
511
+ solAssert (itr.key ().isString (), " " );
512
+ std::string key = itr.key ().asString ();
513
+ Json::Value const & code = data[key];
514
+ if (code.isString ())
515
+ this ->m_data [h256 (fromHex (key))] = fromHex (code.asString ());
516
+ else
517
+ {
518
+ shared_ptr<Assembly> subassembly = make_shared<Assembly>();
519
+ subassembly->loadFromAssemblyJSON (code);
520
+ this ->m_subs .emplace_back (subassembly);
521
+ }
522
+ }
523
+ return true ;
524
+ }
525
+
351
526
AssemblyItem Assembly::namedTag (string const & _name, size_t _params, size_t _returns, optional<uint64_t > _sourceID)
352
527
{
353
528
assertThrow (!_name.empty (), AssemblyException, " Empty named tag." );
@@ -402,7 +577,6 @@ Assembly& Assembly::optimise(bool _enable, EVMVersion _evmVersion, bool _isCreat
402
577
return *this ;
403
578
}
404
579
405
-
406
580
Assembly& Assembly::optimise (OptimiserSettings const & _settings)
407
581
{
408
582
optimiseInternal (_settings, {});
0 commit comments