aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoichi Hirai <i@yoichihirai.com>2016-11-22 00:07:10 +0800
committerYoichi Hirai <i@yoichihirai.com>2016-11-25 22:45:16 +0800
commitea628001d5f34ee1d85398a17f93e7c4f55429fe (patch)
treeb1944bbd5938cc56d8fee290ca2817ccf4c58f6f
parent56d664108614fa8fdf63a02d8f605bf5afcd0837 (diff)
downloaddexon-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.cpp20
-rw-r--r--libsolidity/codegen/CompilerUtils.h2
-rw-r--r--libsolidity/codegen/LValue.cpp10
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