| 35 | using namespace solidity::frontend; |
| 36 | |
| 37 | std::string ABIFunctions::tupleEncoder( |
| 38 | TypePointers const& _givenTypes, |
| 39 | TypePointers _targetTypes, |
| 40 | bool _encodeAsLibraryTypes, |
| 41 | bool _reversed |
| 42 | ) |
| 43 | { |
| 44 | solAssert(_givenTypes.size() == _targetTypes.size(), ""); |
| 45 | EncodingOptions options; |
| 46 | options.encodeAsLibraryTypes = _encodeAsLibraryTypes; |
| 47 | options.encodeFunctionFromStack = true; |
| 48 | options.padded = true; |
| 49 | options.dynamicInplace = false; |
| 50 | |
| 51 | for (Type const*& t: _targetTypes) |
| 52 | { |
| 53 | solAssert(t, ""); |
| 54 | t = t->fullEncodingType(options.encodeAsLibraryTypes, true, !options.padded); |
| 55 | solAssert(t, ""); |
| 56 | } |
| 57 | |
| 58 | std::string functionName = std::string("abi_encode_tuple_"); |
| 59 | for (auto const& t: _givenTypes) |
| 60 | functionName += t->identifier() + "_"; |
| 61 | functionName += "_to_"; |
| 62 | for (auto const& t: _targetTypes) |
| 63 | functionName += t->identifier() + "_"; |
| 64 | functionName += options.toFunctionNameSuffix(); |
| 65 | if (_reversed) |
| 66 | functionName += "_reversed"; |
| 67 | |
| 68 | return createFunction(functionName, [&]() { |
| 69 | // Note that the values are in reverse due to the difference in calling semantics. |
| 70 | Whiskers templ(R"( |
| 71 | function <functionName>(headStart <valueParams>) -> tail { |
| 72 | tail := add(headStart, <headSize>) |
| 73 | <encodeElements> |
| 74 | } |
| 75 | )"); |
| 76 | templ("functionName", functionName); |
| 77 | size_t const headSize_ = headSize(_targetTypes); |
| 78 | templ("headSize", std::to_string(headSize_)); |
| 79 | std::string encodeElements; |
| 80 | size_t headPos = 0; |
| 81 | size_t stackPos = 0; |
| 82 | for (size_t i = 0; i < _givenTypes.size(); ++i) |
| 83 | { |
| 84 | solAssert(_givenTypes[i], ""); |
| 85 | solAssert(_targetTypes[i], ""); |
| 86 | size_t sizeOnStack = _givenTypes[i]->sizeOnStack(); |
| 87 | bool dynamic = _targetTypes[i]->isDynamicallyEncoded(); |
| 88 | Whiskers elementTempl( |
| 89 | dynamic ? |
| 90 | std::string(R"( |
| 91 | mstore(add(headStart, <pos>), sub(tail, headStart)) |
| 92 | tail := <abiEncode>(<values> tail) |
| 93 | )") : |
| 94 | std::string(R"( |
no test coverage detected