diff options
author | Yoichi Hirai <i@yoichihirai.com> | 2016-11-22 00:07:10 +0800 |
---|---|---|
committer | Yoichi Hirai <i@yoichihirai.com> | 2016-11-25 22:45:16 +0800 |
commit | ea628001d5f34ee1d85398a17f93e7c4f55429fe (patch) | |
tree | b1944bbd5938cc56d8fee290ca2817ccf4c58f6f | |
parent | 56d664108614fa8fdf63a02d8f605bf5afcd0837 (diff) | |
download | dexon-solidity-ea628001d5f34ee1d85398a17f93e7c4f55429fe.tar.gz dexon-solidity-ea628001d5f34ee1d85398a17f93e7c4f55429fe.tar.zst dexon-solidity-ea628001d5f34ee1d85398a17f93e7c4f55429fe.zip |
codegen: add an option to CovertType so that it can truncate sign bits
-rw-r--r-- | libsolidity/codegen/CompilerUtils.cpp | 20 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerUtils.h | 2 | ||||
-rw-r--r-- | libsolidity/codegen/LValue.cpp | 10 |
3 files changed, 22 insertions, 10 deletions
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<const IntegerType &>(_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 |