From 5b8a77398608689088938454583d284afd58ab50 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 17:54:09 +0100 Subject: codegen: cleanup value types before storing them --- libsolidity/codegen/LValue.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libsolidity') diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 3f1730d1..933c0419 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -221,6 +221,11 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size."); solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size."); + + m_context << Instruction::SWAP2; + CompilerUtils(m_context).convertType(*m_dataType, *m_dataType, true); + m_context << Instruction::SWAP2; + if (m_dataType->storageBytes() == 32) { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size."); -- cgit v1.2.3 From 56d664108614fa8fdf63a02d8f605bf5afcd0837 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 16:41:02 +0100 Subject: codegen: cleanup stored values in a more consistent way --- libsolidity/codegen/LValue.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 933c0419..78854588 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -216,16 +216,14 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const { CompilerUtils utils(m_context); + solAssert(m_dataType, ""); + // stack: value storage_key storage_offset if (m_dataType->isValueType()) { solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size."); solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size."); - m_context << Instruction::SWAP2; - CompilerUtils(m_context).convertType(*m_dataType, *m_dataType, true); - m_context << Instruction::SWAP2; - if (m_dataType->storageBytes() == 32) { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size."); @@ -233,10 +231,23 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::POP; if (!_move) m_context << Instruction::DUP2 << Instruction::SWAP1; + + m_context << Instruction::SWAP1; + utils.convertType(_sourceType, _sourceType, true); + utils.convertType(*m_dataType, *m_dataType, true); + m_context << Instruction::SWAP1; + m_context << Instruction::SSTORE; } else { + if (_sourceType.sizeOnStack() == 1) + { + m_context << Instruction::SWAP2; + utils.convertType(_sourceType, _sourceType, true); + m_context << Instruction::SWAP2; + } + // OR the value into the other values in the storage slot m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier @@ -269,6 +280,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits + utils.convertType(*m_dataType, *m_dataType, true); m_context << (u256(1) << (8 * (32 - m_dataType->storageBytes()))) << Instruction::SWAP1 -- cgit v1.2.3 From ea628001d5f34ee1d85398a17f93e7c4f55429fe Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 17:07:10 +0100 Subject: codegen: add an option to CovertType so that it can truncate sign bits --- libsolidity/codegen/CompilerUtils.cpp | 20 +++++++++++++++++++- libsolidity/codegen/CompilerUtils.h | 2 +- libsolidity/codegen/LValue.cpp | 10 ++-------- 3 files changed, 22 insertions(+), 10 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index fe2b9c7e..21dd2840 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -358,7 +358,7 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function) Instruction::OR; } -void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) +void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded, bool _chopSignBits) { // For a type extension, we need to remove all higher-order bits that we might have ignored in // previous operations. @@ -370,6 +370,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp Type::Category targetTypeCategory = _targetType.category(); bool enumOverflowCheckPending = (targetTypeCategory == Type::Category::Enum || stackTypeCategory == Type::Category::Enum); + bool chopSignBitsPending = _chopSignBits && targetTypeCategory == Type::Category::Integer; + if (chopSignBitsPending) + { + const IntegerType& targetIntegerType = dynamic_cast(_targetType); + chopSignBitsPending = targetIntegerType.isSigned(); + } switch (stackTypeCategory) { @@ -482,6 +488,17 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp cleanHigherOrderBits(typeOnStack); else if (_cleanupNeeded) cleanHigherOrderBits(targetType); + if (chopSignBitsPending) + { + if (typeOnStack.numBits() < 256) + m_context + << (u256(1) << (256 - typeOnStack.numBits())) + << Instruction::SWAP1 + << Instruction::DUP2 + << Instruction::MUL + << Instruction::DIV; + chopSignBitsPending = false; + } } } break; @@ -728,6 +745,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } solAssert(!enumOverflowCheckPending, "enum overflow checking missing."); + solAssert(!chopSignBitsPending, "forgot to chop the sign bits."); } void CompilerUtils::pushZeroValue(Type const& _type) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index ff87124f..977e96d9 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -130,7 +130,7 @@ public: /// if a reference type is converted from calldata or storage to memory. /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be /// necessary. - void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false); + void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false, bool _chopSignBits = false); /// Creates a zero-value for the given type and puts it onto the stack. This might allocate /// memory for memory references. diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 78854588..df74e836 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -234,7 +234,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::SWAP1; utils.convertType(_sourceType, _sourceType, true); - utils.convertType(*m_dataType, *m_dataType, true); + utils.convertType(*m_dataType, *m_dataType, true, true); m_context << Instruction::SWAP1; m_context << Instruction::SSTORE; @@ -280,13 +280,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits - utils.convertType(*m_dataType, *m_dataType, true); - m_context - << (u256(1) << (8 * (32 - m_dataType->storageBytes()))) - << Instruction::SWAP1 - << Instruction::DUP2 - << Instruction::MUL - << Instruction::DIV; + utils.convertType(*m_dataType, *m_dataType, true, true); } m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value -- cgit v1.2.3 From 3fb9625127c869b3d5b4b8e590dc6feb52e4eeec Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 11:31:14 +0100 Subject: codegen: document _chopSignBits parameter of convertType function --- libsolidity/codegen/CompilerUtils.h | 1 + 1 file changed, 1 insertion(+) (limited to 'libsolidity') diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 977e96d9..4baf48ff 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -130,6 +130,7 @@ public: /// if a reference type is converted from calldata or storage to memory. /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be /// necessary. + /// If @a _chopSignBits, the function resets the signed bits out of the width of the signed integer. void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false, bool _chopSignBits = false); /// Creates a zero-value for the given type and puts it onto the stack. This might allocate -- cgit v1.2.3 From 9d25b5601e6e2713e14803777390c2d45be3d51c Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 16:49:54 +0100 Subject: codegen: merge type conversion and cleaning up --- libsolidity/codegen/LValue.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index df74e836..63729d27 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -233,8 +233,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::DUP2 << Instruction::SWAP1; m_context << Instruction::SWAP1; - utils.convertType(_sourceType, _sourceType, true); - utils.convertType(*m_dataType, *m_dataType, true, true); + utils.convertType(_sourceType, *m_dataType, true); m_context << Instruction::SWAP1; m_context << Instruction::SSTORE; @@ -244,7 +243,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc if (_sourceType.sizeOnStack() == 1) { m_context << Instruction::SWAP2; - utils.convertType(_sourceType, _sourceType, true); + utils.convertType(_sourceType, *m_dataType, true); m_context << Instruction::SWAP2; } -- cgit v1.2.3 From fa486f5b44790e5abda28ddb2b798d0b1408269f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 17:03:17 +0100 Subject: codegen: shorten the bit truncation --- libsolidity/codegen/CompilerUtils.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 21dd2840..41559a42 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -492,11 +492,8 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp { if (typeOnStack.numBits() < 256) m_context - << (u256(1) << (256 - typeOnStack.numBits())) - << Instruction::SWAP1 - << Instruction::DUP2 - << Instruction::MUL - << Instruction::DIV; + << ((u256(1) << typeOnStack.numBits()) - 1) + << Instruction::AND; chopSignBitsPending = false; } } -- cgit v1.2.3 From 548b7ce42d1650d18ce71c3d11486ab4d27e6c0f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 15:38:02 +0100 Subject: codegen: storing of non-value types; add some assertions --- libsolidity/codegen/LValue.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 63729d27..23fe2d4e 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -240,13 +240,6 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc } else { - if (_sourceType.sizeOnStack() == 1) - { - m_context << Instruction::SWAP2; - utils.convertType(_sourceType, *m_dataType, true); - m_context << Instruction::SWAP2; - } - // OR the value into the other values in the storage slot m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier @@ -263,6 +256,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc // stack: value storage_ref cleared_value multiplier value if (FunctionType const* fun = dynamic_cast(m_dataType)) { + solAssert(_sourceType == *m_dataType, "function item stored but target is not equal to source"); if (fun->location() == FunctionType::Location::External) // Combine the two-item function type into a single stack slot. utils.combineExternalFunctionType(false); @@ -272,14 +266,17 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc Instruction::AND; } else if (m_dataType->category() == Type::Category::FixedBytes) + { + solAssert(_sourceType.category() == Type::Category::FixedBytes, "source not fixed bytes"); m_context << (u256(0x1) << (256 - 8 * dynamic_cast(*m_dataType).numBytes())) << Instruction::SWAP1 << Instruction::DIV; + } else { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits - utils.convertType(*m_dataType, *m_dataType, true, true); + utils.convertType(_sourceType, *m_dataType, true, true); } m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value -- cgit v1.2.3 From 0be58595036d3411124bc8b39f9d151790d950b4 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 15:50:46 +0100 Subject: codegen: cleanup values to fit in storage bytes --- libsolidity/codegen/CompilerUtils.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libsolidity') diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 41559a42..d5361ac6 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -738,6 +738,10 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp default: // All other types should not be convertible to non-equal types. solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) + m_context + << ((u256(1) << (8 * _targetType.storageBytes())) - 1) + << Instruction::AND; break; } -- cgit v1.2.3