diff options
author | Lefteris Karapetsas <lefteris@refu.co> | 2015-03-11 01:22:19 +0800 |
---|---|---|
committer | Lefteris Karapetsas <lefteris@refu.co> | 2015-03-12 19:53:00 +0800 |
commit | b2fadf6b933e9034d5edb49608329fb0f7d015dd (patch) | |
tree | a0f606a88174cbdb99dcab2d3ee9a23fe47ae8d6 | |
parent | 73ce24ae75554b18a342e1e510f37f99057fdb1d (diff) | |
download | dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar.gz dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar.bz2 dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar.lz dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar.xz dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.tar.zst dexon-solidity-b2fadf6b933e9034d5edb49608329fb0f7d015dd.zip |
Conversion changes after renaming Hash/String to Bytes.
- Almost all end to end tests pass. Still needs a little bit of work
-rw-r--r-- | ExpressionCompiler.cpp | 49 | ||||
-rw-r--r-- | GlobalContext.cpp | 2 | ||||
-rw-r--r-- | LValue.cpp | 8 | ||||
-rw-r--r-- | Types.cpp | 20 |
4 files changed, 47 insertions, 32 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 089ebc32..f00b2d40 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -123,16 +123,20 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con Type::Category stackTypeCategory = _typeOnStack.getCategory(); Type::Category targetTypeCategory = _targetType.getCategory(); - if (stackTypeCategory == Type::Category::FixedBytes) + switch (stackTypeCategory) + { + case Type::Category::FixedBytes: { FixedBytesType const& typeOnStack = dynamic_cast<FixedBytesType const&>(_typeOnStack); if (targetTypeCategory == Type::Category::Integer) { - // conversion from string to bytes. no need to clean the high bit + // conversion from bytes to integer. no need to clean the high bit // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType); - solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); + // solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + if (targetIntegerType.getNumBits() < typeOnStack.getNumBytes() * 8) + appendTypeConversion(IntegerType(typeOnStack.getNumBytes() * 8), _targetType, _cleanupNeeded); } else { @@ -150,21 +154,24 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con } } } - else if (stackTypeCategory == Type::Category::Enum) - solAssert(targetTypeCategory == Type::Category::Integer || - targetTypeCategory == Type::Category::Enum, ""); - else if (stackTypeCategory == Type::Category::Integer || - stackTypeCategory == Type::Category::Contract || - stackTypeCategory == Type::Category::IntegerConstant) - { - if (targetTypeCategory == Type::Category::FixedBytes && stackTypeCategory == Type::Category::Integer) + break; + case Type::Category::Enum: + solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Enum, ""); + break; + case Type::Category::Integer: + case Type::Category::Contract: + case Type::Category::IntegerConstant: + if (targetTypeCategory == Type::Category::FixedBytes) { + solAssert(stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::IntegerConstant, + "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); - IntegerType const& typeOnStack = dynamic_cast<IntegerType const&>(_typeOnStack); - solAssert(typeOnStack.getNumBits() == targetBytesType.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; + if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack)) + if (targetBytesType.getNumBytes() * 8 > typeOnStack->getNumBits()) + appendHighBitsCleanup(*typeOnStack); + m_context << (u256(1) << (256 - targetBytesType.getNumBytes() * 8)) << eth::Instruction::MUL; } else if (targetTypeCategory == Type::Category::Enum) // just clean @@ -174,7 +181,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); IntegerType addressType(0, IntegerType::Modifier::Address); IntegerType const& targetType = targetTypeCategory == Type::Category::Integer - ? dynamic_cast<IntegerType const&>(_targetType) : addressType; + ? dynamic_cast<IntegerType const&>(_targetType) : addressType; if (stackTypeCategory == Type::Category::IntegerConstant) { IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack); @@ -186,7 +193,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con else { IntegerType const& typeOnStack = stackTypeCategory == Type::Category::Integer - ? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType; + ? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType; // Widening: clean up according to source type width // Non-widening and force: clean up according to target type bits if (targetType.getNumBits() > typeOnStack.getNumBits()) @@ -195,10 +202,12 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con appendHighBitsCleanup(targetType); } } - } - else if (_typeOnStack != _targetType) + break; + default: // All other types should not be convertible to non-equal types. - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); + solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + break; + } } bool ExpressionCompiler::visit(Assignment const& _assignment) @@ -773,7 +782,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) // no lvalue, just retrieve the value m_context << eth::Instruction::ADD << eth::Instruction::CALLDATALOAD - << u256(0) << eth::Instruction::BYTE; + << ((u256(1) << (256 - 8)) - 1) << eth::Instruction::AND; break; case ArrayType::Location::Memory: solAssert(false, "Memory lvalues not yet implemented."); diff --git a/GlobalContext.cpp b/GlobalContext.cpp index 7bd9c8df..80cebd76 100644 --- a/GlobalContext.cpp +++ b/GlobalContext.cpp @@ -55,7 +55,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared< make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Location::SHA256, true)), make_shared<MagicVariableDeclaration>("ecrecover", - make_shared<FunctionType>(strings{"bytes32", "bytes1", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)), + make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)), make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true))}) { @@ -246,10 +246,11 @@ void StorageByteArrayElement::retrieveValue(SourceLocation const&, bool _remove) // stack: ref byte_number if (_remove) m_context << eth::Instruction::SWAP1 << eth::Instruction::SLOAD - << eth::Instruction::SWAP1 << eth::Instruction::BYTE; + << eth::Instruction::SWAP1 << eth::Instruction::BYTE ; else m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD << eth::Instruction::DUP2 << eth::Instruction::BYTE; + m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL; } void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, bool _move) const @@ -265,8 +266,9 @@ void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, boo m_context << eth::Instruction::DUP2 << u256(0xff) << eth::Instruction::MUL << eth::Instruction::NOT << eth::Instruction::AND; // stack: value ref (1<<(32-byte_number)) old_full_value_with_cleared_byte - m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP4 << eth::Instruction::MUL - << eth::Instruction::OR; + m_context << eth::Instruction::SWAP1; + m_context << (u256(1) << (256 - 8)) << eth::Instruction::DUP5 << eth::Instruction::DIV + << eth::Instruction::MUL << eth::Instruction::OR; // stack: value ref new_full_value m_context << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; if (_move) @@ -175,14 +175,10 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (_convertTo.getCategory() == Category::FixedBytes) - { - FixedBytesType const& convertTo = dynamic_cast<FixedBytesType const&>(_convertTo); - return (m_bits == convertTo.getNumBytes() * 8); - } return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::Contract || - _convertTo.getCategory() == Category::Enum; + _convertTo.getCategory() == Category::Enum || + _convertTo.getCategory() == Category::FixedBytes; } TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const @@ -284,7 +280,15 @@ IntegerConstantType::IntegerConstantType(Literal const& _literal) bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const { - TypePointer integerType = getIntegerType(); + auto integerType = getIntegerType(); + if (_convertTo.getCategory() == Category::FixedBytes) + { + FixedBytesType const& convertTo = dynamic_cast<FixedBytesType const&>(_convertTo); + if (convertTo.getNumBytes() * 8 >= integerType->getNumBits()) + return true; + return false; + } + return integerType && integerType->isImplicitlyConvertibleTo(_convertTo); } @@ -461,7 +465,7 @@ bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const if (_convertTo.getCategory() == Category::Integer) { IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo); - if (m_bytes * 8 == convertTo.getNumBits()) + if (m_bytes * 8 <= convertTo.getNumBits()) return true; } |