| 420 | } |
| 421 | |
| 422 | void CompilerUtils::encodeToMemory( |
| 423 | TypePointers const& _givenTypes, |
| 424 | TypePointers const& _targetTypes, |
| 425 | bool _padToWordBoundaries, |
| 426 | bool _copyDynamicDataInPlace, |
| 427 | bool _encodeAsLibraryTypes |
| 428 | ) |
| 429 | { |
| 430 | // stack: <v1> <v2> ... <vn> <mem> |
| 431 | bool const encoderV2 = m_context.useABICoderV2(); |
| 432 | TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes; |
| 433 | solAssert(targetTypes.size() == _givenTypes.size()); |
| 434 | for (Type const*& t: targetTypes) |
| 435 | { |
| 436 | Type const* tEncoding = t->fullEncodingType(_encodeAsLibraryTypes, encoderV2, !_padToWordBoundaries); |
| 437 | solUnimplementedAssert(tEncoding, "Encoding type \"" + t->toString() + "\" not yet implemented."); |
| 438 | t = std::move(tEncoding); |
| 439 | } |
| 440 | |
| 441 | if (_givenTypes.empty()) |
| 442 | return; |
| 443 | if (encoderV2) |
| 444 | { |
| 445 | // Use the new Yul-based encoding function |
| 446 | solAssert( |
| 447 | _padToWordBoundaries != _copyDynamicDataInPlace, |
| 448 | "Non-padded and in-place encoding can only be combined." |
| 449 | ); |
| 450 | auto stackHeightBefore = m_context.stackHeight(); |
| 451 | abiEncodeV2(_givenTypes, targetTypes, _encodeAsLibraryTypes, _padToWordBoundaries); |
| 452 | solAssert(stackHeightBefore - m_context.stackHeight() == sizeOnStack(_givenTypes)); |
| 453 | return; |
| 454 | } |
| 455 | |
| 456 | // Stack during operation: |
| 457 | // <v1> <v2> ... <vn> <mem_start> <dyn_head_1> ... <dyn_head_r> <end_of_mem> |
| 458 | // The values dyn_head_n are added during the first loop and they point to the head part |
| 459 | // of the nth dynamic parameter, which is filled once the dynamic parts are processed. |
| 460 | |
| 461 | // store memory start pointer |
| 462 | m_context << Instruction::DUP1; |
| 463 | |
| 464 | unsigned argSize = CompilerUtils::sizeOnStack(_givenTypes); |
| 465 | unsigned stackPos = 0; // advances through the argument values |
| 466 | unsigned dynPointers = 0; // number of dynamic head pointers on the stack |
| 467 | for (size_t i = 0; i < _givenTypes.size(); ++i) |
| 468 | { |
| 469 | Type const* targetType = targetTypes[i]; |
| 470 | solAssert(!!targetType, "Externalable type expected."); |
| 471 | if (targetType->isDynamicallySized() && !_copyDynamicDataInPlace) |
| 472 | { |
| 473 | // leave end_of_mem as dyn head pointer |
| 474 | m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; |
| 475 | dynPointers++; |
| 476 | assertThrow( |
| 477 | (argSize + dynPointers) < m_context.reachableStackDepth(), |
| 478 | StackTooDeepError, |
| 479 | util::stackTooDeepString |
no test coverage detected