Fix signextend for user defined value types.

This commit is contained in:
chriseth 2021-09-28 15:39:18 +02:00
parent 7b7e38768c
commit cb052611cf
2 changed files with 21 additions and 15 deletions

View File

@ -227,27 +227,30 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
m_context << Instruction::POP << Instruction::SLOAD; m_context << Instruction::POP << Instruction::SLOAD;
else else
{ {
Type const* type = m_dataType;
if (type->category() == Type::Category::UserDefinedValueType)
type = type->encodingType();
bool cleaned = false; bool cleaned = false;
m_context m_context
<< Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1 << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1
<< u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV; << u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
if (m_dataType->category() == Type::Category::FixedPoint) if (type->category() == Type::Category::FixedPoint)
// implementation should be very similar to the integer case. // implementation should be very similar to the integer case.
solUnimplemented("Not yet implemented - FixedPointType."); solUnimplemented("Not yet implemented - FixedPointType.");
if (m_dataType->leftAligned()) if (type->leftAligned())
{ {
CompilerUtils(m_context).leftShiftNumberOnStack(256 - 8 * m_dataType->storageBytes()); CompilerUtils(m_context).leftShiftNumberOnStack(256 - 8 * type->storageBytes());
cleaned = true; cleaned = true;
} }
else if ( else if (
m_dataType->category() == Type::Category::Integer && type->category() == Type::Category::Integer &&
dynamic_cast<IntegerType const&>(*m_dataType).isSigned() dynamic_cast<IntegerType const&>(*type).isSigned()
) )
{ {
m_context << u256(m_dataType->storageBytes() - 1) << Instruction::SIGNEXTEND; m_context << u256(type->storageBytes() - 1) << Instruction::SIGNEXTEND;
cleaned = true; cleaned = true;
} }
else if (FunctionType const* fun = dynamic_cast<decltype(fun)>(m_dataType)) else if (FunctionType const* fun = dynamic_cast<decltype(fun)>(type))
{ {
if (fun->kind() == FunctionType::Kind::External) if (fun->kind() == FunctionType::Kind::External)
{ {
@ -263,8 +266,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
} }
if (!cleaned) if (!cleaned)
{ {
solAssert(m_dataType->sizeOnStack() == 1, ""); solAssert(type->sizeOnStack() == 1, "");
m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << Instruction::AND; m_context << ((u256(0x1) << (8 * type->storageBytes())) - 1) << Instruction::AND;
} }
} }
} }

View File

@ -2912,9 +2912,12 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type)
)"); )");
templ("functionName", functionName); templ("functionName", functionName);
unsigned storageBytes = _type.storageBytes(); Type const* encodingType = &_type;
if (IntegerType const* type = dynamic_cast<IntegerType const*>(&_type)) if (_type.category() == Type::Category::UserDefinedValueType)
if (type->isSigned() && storageBytes != 32) encodingType = _type.encodingType();
unsigned storageBytes = encodingType->storageBytes();
if (IntegerType const* intType = dynamic_cast<IntegerType const*>(encodingType))
if (intType->isSigned() && storageBytes != 32)
{ {
templ("cleaned", "signextend(" + to_string(storageBytes - 1) + ", value)"); templ("cleaned", "signextend(" + to_string(storageBytes - 1) + ", value)");
return templ.render(); return templ.render();
@ -2922,10 +2925,10 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type)
bool leftAligned = false; bool leftAligned = false;
if ( if (
_type.category() != Type::Category::Function || encodingType->category() != Type::Category::Function ||
dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::External dynamic_cast<FunctionType const&>(*encodingType).kind() == FunctionType::Kind::External
) )
leftAligned = _type.leftAligned(); leftAligned = encodingType->leftAligned();
if (storageBytes == 32) if (storageBytes == 32)
templ("cleaned", "value"); templ("cleaned", "value");