diff options
Diffstat (limited to 'libsolidity/codegen/CompilerUtils.cpp')
-rw-r--r-- | libsolidity/codegen/CompilerUtils.cpp | 78 |
1 files changed, 38 insertions, 40 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 2f45765a..2bdf88e3 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -333,26 +333,19 @@ void CompilerUtils::encodeToMemory( ) { // stack: <v1> <v2> ... <vn> <mem> + bool const encoderV2 = m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2); TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes; solAssert(targetTypes.size() == _givenTypes.size(), ""); for (TypePointer& t: targetTypes) { - solUnimplementedAssert( - t->mobileType() && - t->mobileType()->interfaceType(_encodeAsLibraryTypes) && - t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + t->toString() + "\" not yet implemented." - ); - t = t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer tEncoding = t->fullEncodingType(_encodeAsLibraryTypes, encoderV2, !_padToWordBoundaries); + solUnimplementedAssert(tEncoding, "Encoding type \"" + t->toString() + "\" not yet implemented."); + t = std::move(tEncoding); } if (_givenTypes.empty()) return; - else if ( - _padToWordBoundaries && - !_copyDynamicDataInPlace && - m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) - ) + else if (_padToWordBoundaries && !_copyDynamicDataInPlace && encoderV2) { // Use the new Yul-based encoding function auto stackHeightBefore = m_context.stackHeight(); @@ -363,8 +356,8 @@ void CompilerUtils::encodeToMemory( // Stack during operation: // <v1> <v2> ... <vn> <mem_start> <dyn_head_1> ... <dyn_head_r> <end_of_mem> - // The values dyn_head_i are added during the first loop and they point to the head part - // of the ith dynamic parameter, which is filled once the dynamic parts are processed. + // The values dyn_head_n are added during the first loop and they point to the head part + // of the nth dynamic parameter, which is filled once the dynamic parts are processed. // store memory start pointer m_context << Instruction::DUP1; @@ -664,6 +657,11 @@ void CompilerUtils::convertType( if (targetIntegerType.numBits() < typeOnStack.numBytes() * 8) convertType(IntegerType(typeOnStack.numBytes() * 8), _targetType, _cleanupNeeded); } + else if (targetTypeCategory == Type::Category::Address) + { + solAssert(typeOnStack.numBytes() * 8 == 160, ""); + rightShiftNumberOnStack(256 - 160); + } else { // clear for conversion to longer bytes @@ -697,23 +695,33 @@ void CompilerUtils::convertType( break; case Type::Category::FixedPoint: solUnimplemented("Not yet implemented - FixedPointType."); + case Type::Category::Address: case Type::Category::Integer: case Type::Category::Contract: case Type::Category::RationalNumber: if (targetTypeCategory == Type::Category::FixedBytes) { - solAssert(stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::RationalNumber, - "Invalid conversion to FixedBytesType requested."); + solAssert( + stackTypeCategory == Type::Category::Address || + stackTypeCategory == Type::Category::Integer || + stackTypeCategory == Type::Category::RationalNumber, + "Invalid conversion to FixedBytesType requested." + ); // conversion from bytes to string. no need to clean the high bit // only to shift left because of opposite alignment FixedBytesType const& targetBytesType = dynamic_cast<FixedBytesType const&>(_targetType); if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack)) + { if (targetBytesType.numBytes() * 8 > typeOnStack->numBits()) cleanHigherOrderBits(*typeOnStack); + } + else if (stackTypeCategory == Type::Category::Address) + solAssert(targetBytesType.numBytes() * 8 == 160, ""); leftShiftNumberOnStack(256 - targetBytesType.numBytes() * 8); } else if (targetTypeCategory == Type::Category::Enum) { + solAssert(stackTypeCategory != Type::Category::Address, "Invalid conversion to EnumType requested."); solAssert(_typeOnStack.mobileType(), ""); // just clean convertType(_typeOnStack, *_typeOnStack.mobileType(), true); @@ -740,8 +748,8 @@ void CompilerUtils::convertType( } else { - solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); - IntegerType addressType(160, IntegerType::Modifier::Address); + solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract || targetTypeCategory == Type::Category::Address, ""); + IntegerType addressType(160); IntegerType const& targetType = targetTypeCategory == Type::Category::Integer ? dynamic_cast<IntegerType const&>(_targetType) : addressType; if (stackTypeCategory == Type::Category::RationalNumber) @@ -887,15 +895,6 @@ void CompilerUtils::convertType( typeOnStack.location() == DataLocation::CallData, "Invalid conversion to calldata type."); break; - default: - solAssert( - false, - "Invalid type conversion " + - _typeOnStack.toString(false) + - " to " + - _targetType.toString(false) + - " requested." - ); } break; } @@ -954,20 +953,12 @@ void CompilerUtils::convertType( { TupleType const& sourceTuple = dynamic_cast<TupleType const&>(_typeOnStack); TupleType const& targetTuple = dynamic_cast<TupleType const&>(_targetType); - // fillRight: remove excess values at right side, !fillRight: remove eccess values at left side - bool fillRight = !targetTuple.components().empty() && ( - !targetTuple.components().back() || - targetTuple.components().front() - ); + solAssert(targetTuple.components().size() == sourceTuple.components().size(), ""); unsigned depth = sourceTuple.sizeOnStack(); for (size_t i = 0; i < sourceTuple.components().size(); ++i) { TypePointer sourceType = sourceTuple.components()[i]; - TypePointer targetType; - if (fillRight && i < targetTuple.components().size()) - targetType = targetTuple.components()[i]; - else if (!fillRight && targetTuple.components().size() + i >= sourceTuple.components().size()) - targetType = targetTuple.components()[targetTuple.components().size() - (sourceTuple.components().size() - i)]; + TypePointer targetType = targetTuple.components()[i]; if (!sourceType) { solAssert(!targetType, ""); @@ -1011,10 +1002,8 @@ void CompilerUtils::convertType( m_context << Instruction::ISZERO << Instruction::ISZERO; break; default: - if (stackTypeCategory == Type::Category::Function && targetTypeCategory == Type::Category::Integer) + if (stackTypeCategory == Type::Category::Function && targetTypeCategory == Type::Category::Address) { - IntegerType const& targetType = dynamic_cast<IntegerType const&>(_targetType); - solAssert(targetType.isAddress(), "Function type can only be converted to address."); FunctionType const& typeOnStack = dynamic_cast<FunctionType const&>(_typeOnStack); solAssert(typeOnStack.kind() == FunctionType::Kind::External, "Only external function type can be converted."); @@ -1170,6 +1159,15 @@ void CompilerUtils::popStackSlots(size_t _amount) m_context << Instruction::POP; } +void CompilerUtils::popAndJump(unsigned _toHeight, eth::AssemblyItem const& _jumpTo) +{ + solAssert(m_context.stackHeight() >= _toHeight, ""); + unsigned amount = m_context.stackHeight() - _toHeight; + popStackSlots(amount); + m_context.appendJumpTo(_jumpTo); + m_context.adjustStackOffset(amount); +} + unsigned CompilerUtils::sizeOnStack(vector<shared_ptr<Type const>> const& _variableTypes) { unsigned size = 0; |