-redesigned appendTypeConversion function

This commit is contained in:
liana 2015-01-27 12:55:40 +01:00
parent ef885d0212
commit 6ba82b1427

View File

@ -636,11 +636,11 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
// conversion from string to hash. no need to clean the high bit // conversion from string to hash. no need to clean the high bit
// only to shift right because of opposite alignment // only to shift right because of opposite alignment
IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType); IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType);
StaticStringType const& sourceStringType = dynamic_cast<StaticStringType const&>(_typeOnStack); StaticStringType const& typeOnStack = dynamic_cast<StaticStringType const&>(_typeOnStack);
if (targetIntegerType.isHash()) if (targetIntegerType.isHash())
{ {
solAssert(targetIntegerType.getNumBits() == sourceStringType.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 - sourceStringType.getNumBytes() * 8) << m_context << (u256(1) << 256 - typeOnStack.getNumBytes() * 8) <<
eth::Instruction::SWAP1 << eth::Instruction::DIV; eth::Instruction::SWAP1 << eth::Instruction::DIV;
} }
} }
@ -650,43 +650,45 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings //@todo clear lower-order bytes if we allow explicit conversion to shorter strings
} }
} }
else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER)
{
// conversion from hash to string. no need to clean the high bit
// only to shift left because of opposite alignment
StaticStringType const& targetStringType = dynamic_cast<StaticStringType const&>(_targetType);
IntegerType const& sourceIntegerType = dynamic_cast<IntegerType const&>(_typeOnStack);
if (sourceIntegerType.isHash())
{
solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
m_context << (u256(1) << 256 - sourceIntegerType.getNumBits()) << eth::Instruction::MUL;
}
}
else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
stackTypeCategory == Type::Category::INTEGER_CONSTANT) stackTypeCategory == Type::Category::INTEGER_CONSTANT)
{ {
solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, ""); if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER)
IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
? dynamic_cast<IntegerType const&>(_targetType) : addressType;
if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
{ {
IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack); // conversion from hash to string. no need to clean the high bit
// We know that the stack is clean, we only have to clean for a narrowing conversion // only to shift left because of opposite alignment
// where cleanup is forced. StaticStringType const& targetStringType = dynamic_cast<StaticStringType const&>(_targetType);
if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded) IntegerType const& typeOnStack = dynamic_cast<IntegerType const&>(_typeOnStack);
appendHighBitsCleanup(targetType); if (typeOnStack.isHash())
} {
else solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
m_context << (u256(1) << 256 - typeOnStack.getNumBits()) << eth::Instruction::MUL;
}
} else
{ {
IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType; IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
// Widening: clean up according to source type width IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
// Non-widening and force: clean up according to target type bits ? dynamic_cast<IntegerType const&>(_targetType) : addressType;
if (targetType.getNumBits() > typeOnStack.getNumBits()) if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
appendHighBitsCleanup(typeOnStack); {
else if (_cleanupNeeded) IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
appendHighBitsCleanup(targetType); // We know that the stack is clean, we only have to clean for a narrowing conversion
// where cleanup is forced.
if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
appendHighBitsCleanup(targetType);
}
else
{
IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
? 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())
appendHighBitsCleanup(typeOnStack);
else if (_cleanupNeeded)
appendHighBitsCleanup(targetType);
}
} }
} }
else if (_typeOnStack != _targetType) else if (_typeOnStack != _targetType)