diff options
author | chriseth <chris@ethereum.org> | 2018-11-14 02:33:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-14 02:33:35 +0800 |
commit | 1d4f565a64988a3400847d2655ca24f73f234bc6 (patch) | |
tree | caaa6c26e307513505349b50ca4f2a8a9506752b /libsolidity/codegen/ABIFunctions.cpp | |
parent | 59dbf8f1085b8b92e8b7eb0ce380cbeb642e97eb (diff) | |
parent | 91b6b8a88e76016e0324036cb7a7f9300a1e2439 (diff) | |
download | dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.gz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.bz2 dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.lz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.xz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.zst dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.zip |
Merge pull request #5416 from ethereum/develop
Merge develop into release for 0.5.0
Diffstat (limited to 'libsolidity/codegen/ABIFunctions.cpp')
-rw-r--r-- | libsolidity/codegen/ABIFunctions.cpp | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 3e3aa0ae..bd29b382 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -17,7 +17,7 @@ /** * @author Christian <chris@ethereum.org> * @date 2017 - * Routines that generate JULIA code related to ABI encoding, decoding and type conversions. + * Routines that generate Yul code related to ABI encoding, decoding and type conversions. */ #include <libsolidity/codegen/ABIFunctions.h> @@ -49,7 +49,7 @@ string ABIFunctions::tupleEncoder( if (_encodeAsLibraryTypes) functionName += "_library"; - return createFunction(functionName, [&]() { + return createExternallyUsedFunction(functionName, [&]() { solAssert(!_givenTypes.empty(), ""); // Note that the values are in reverse due to the difference in calling semantics. @@ -113,7 +113,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) solAssert(!_types.empty(), ""); - return createFunction(functionName, [&]() { + return createExternallyUsedFunction(functionName, [&]() { TypePointers decodingTypes; for (auto const& t: _types) decodingTypes.emplace_back(t->decodingType()); @@ -176,13 +176,13 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) }); } -string ABIFunctions::requestedFunctions() +pair<string, set<string>> ABIFunctions::requestedFunctions() { string result; for (auto const& f: m_requestedFunctions) result += f.second; m_requestedFunctions.clear(); - return result; + return make_pair(result, std::move(m_externallyUsedFunctions)); } string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) @@ -197,6 +197,9 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) templ("functionName", functionName); switch (_type.category()) { + case Type::Category::Address: + templ("body", "cleaned := " + cleanupFunction(IntegerType(160)) + "(value)"); + break; case Type::Category::Integer: { IntegerType const& type = dynamic_cast<IntegerType const&>(_type); @@ -228,7 +231,8 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) if (type.numBytes() == 32) templ("body", "cleaned := value"); else if (type.numBytes() == 0) - templ("body", "cleaned := 0"); + // This is disallowed in the type system. + solAssert(false, ""); else { size_t numBits = type.numBytes() * 8; @@ -238,8 +242,14 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) break; } case Type::Category::Contract: - templ("body", "cleaned := " + cleanupFunction(IntegerType(160, IntegerType::Modifier::Address)) + "(value)"); + { + AddressType addressType(dynamic_cast<ContractType const&>(_type).isPayable() ? + StateMutability::Payable : + StateMutability::NonPayable + ); + templ("body", "cleaned := " + cleanupFunction(addressType) + "(value)"); break; + } case Type::Category::Enum: { size_t members = dynamic_cast<EnumType const&>(_type).numberOfMembers(); @@ -283,6 +293,12 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) auto fromCategory = _from.category(); switch (fromCategory) { + case Type::Category::Address: + body = + Whiskers("converted := <convert>(value)") + ("convert", conversionFunction(IntegerType(160), _to)) + .render(); + break; case Type::Category::Integer: case Type::Category::RationalNumber: case Type::Category::Contract: @@ -313,16 +329,19 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) .render(); } else if (toCategory == Type::Category::FixedPoint) - { solUnimplemented("Not yet implemented - FixedPointType."); - } + else if (toCategory == Type::Category::Address) + body = + Whiskers("converted := <convert>(value)") + ("convert", conversionFunction(_from, IntegerType(160))) + .render(); else { solAssert( toCategory == Type::Category::Integer || toCategory == Type::Category::Contract, ""); - IntegerType const addressType(160, IntegerType::Modifier::Address); + IntegerType const addressType(160); IntegerType const& to = toCategory == Type::Category::Integer ? dynamic_cast<IntegerType const&>(_to) : @@ -374,6 +393,11 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) ("shift", shiftRightFunction(256 - from.numBytes() * 8)) ("convert", conversionFunction(IntegerType(from.numBytes() * 8), _to)) .render(); + else if (toCategory == Type::Category::Address) + body = + Whiskers("converted := <convert>(value)") + ("convert", conversionFunction(_from, IntegerType(160))) + .render(); else { // clear for conversion to longer bytes @@ -409,7 +433,7 @@ string ABIFunctions::conversionFunction(Type const& _from, Type const& _to) solAssert(false, ""); } - solAssert(!body.empty(), ""); + solAssert(!body.empty(), _from.canonicalName() + " to " + _to.canonicalName()); templ("body", body); return templ.render(); }); @@ -471,13 +495,8 @@ string ABIFunctions::abiEncodingFunction( bool _fromStack ) { - solUnimplementedAssert( - _to.mobileType() && - _to.mobileType()->interfaceType(_encodeAsLibraryTypes) && - _to.mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + _to.toString() + "\" not yet implemented." - ); - TypePointer toInterface = _to.mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer toInterface = _to.fullEncodingType(_encodeAsLibraryTypes, true, false); + solUnimplementedAssert(toInterface, "Encoding type \"" + _to.toString() + "\" not yet implemented."); Type const& to = *toInterface; if (_from.category() == Type::Category::StringLiteral) @@ -886,13 +905,8 @@ string ABIFunctions::abiEncodingFunctionStruct( solAssert(member.type, ""); if (!member.type->canLiveOutsideStorage()) continue; - solUnimplementedAssert( - member.type->mobileType() && - member.type->mobileType()->interfaceType(_encodeAsLibraryTypes) && - member.type->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + member.type->toString() + "\" not yet implemented." - ); - auto memberTypeTo = member.type->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer memberTypeTo = member.type->fullEncodingType(_encodeAsLibraryTypes, true, false); + solUnimplementedAssert(memberTypeTo, "Encoding type \"" + member.type->toString() + "\" not yet implemented."); auto memberTypeFrom = _from.memberType(member.name); solAssert(memberTypeFrom, ""); bool dynamicMember = memberTypeTo->isDynamicallyEncoded(); @@ -989,7 +1003,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( )"); templ("functionName", functionName); - // TODO this can make use of CODECOPY for large strings once we have that in JULIA + // TODO this can make use of CODECOPY for large strings once we have that in Yul size_t words = (value.size() + 31) / 32; templ("overallSize", to_string(32 + words * 32)); templ("length", to_string(value.size())); @@ -1188,7 +1202,8 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) solAssert(_type.dataStoredIn(DataLocation::CallData), ""); if (!_type.isDynamicallySized()) solAssert(_type.length() < u256("0xffffffffffffffff"), ""); - solAssert(!_type.baseType()->isDynamicallyEncoded(), ""); + if (_type.baseType()->isDynamicallyEncoded()) + solUnimplemented("Calldata arrays with non-value base types are not yet supported by Solidity."); solAssert(_type.baseType()->calldataEncodedSize() < u256("0xffffffffffffffff"), ""); string functionName = @@ -1682,6 +1697,13 @@ string ABIFunctions::createFunction(string const& _name, function<string ()> con return _name; } +string ABIFunctions::createExternallyUsedFunction(string const& _name, function<string ()> const& _creator) +{ + string name = createFunction(_name, _creator); + m_externallyUsedFunctions.insert(name); + return name; +} + size_t ABIFunctions::headSize(TypePointers const& _targetTypes) { size_t headSize = 0; |