From cb052611cf1c50aa095efc92e098d6ce986b93d6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 28 Sep 2021 15:39:18 +0200 Subject: [PATCH] Fix signextend for user defined value types. --- libsolidity/codegen/LValue.cpp | 21 ++++++++++++--------- libsolidity/codegen/YulUtilFunctions.cpp | 15 +++++++++------ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 01befb8a4..2ff69e4ac 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -227,27 +227,30 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const m_context << Instruction::POP << Instruction::SLOAD; else { + Type const* type = m_dataType; + if (type->category() == Type::Category::UserDefinedValueType) + type = type->encodingType(); bool cleaned = false; m_context << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1 << 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. 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; } else if ( - m_dataType->category() == Type::Category::Integer && - dynamic_cast(*m_dataType).isSigned() + type->category() == Type::Category::Integer && + dynamic_cast(*type).isSigned() ) { - m_context << u256(m_dataType->storageBytes() - 1) << Instruction::SIGNEXTEND; + m_context << u256(type->storageBytes() - 1) << Instruction::SIGNEXTEND; cleaned = true; } - else if (FunctionType const* fun = dynamic_cast(m_dataType)) + else if (FunctionType const* fun = dynamic_cast(type)) { if (fun->kind() == FunctionType::Kind::External) { @@ -263,8 +266,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const } if (!cleaned) { - solAssert(m_dataType->sizeOnStack() == 1, ""); - m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << Instruction::AND; + solAssert(type->sizeOnStack() == 1, ""); + m_context << ((u256(0x1) << (8 * type->storageBytes())) - 1) << Instruction::AND; } } } diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index ea3dd4526..7f6f48e26 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2912,9 +2912,12 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type) )"); templ("functionName", functionName); - unsigned storageBytes = _type.storageBytes(); - if (IntegerType const* type = dynamic_cast(&_type)) - if (type->isSigned() && storageBytes != 32) + Type const* encodingType = &_type; + if (_type.category() == Type::Category::UserDefinedValueType) + encodingType = _type.encodingType(); + unsigned storageBytes = encodingType->storageBytes(); + if (IntegerType const* intType = dynamic_cast(encodingType)) + if (intType->isSigned() && storageBytes != 32) { templ("cleaned", "signextend(" + to_string(storageBytes - 1) + ", value)"); return templ.render(); @@ -2922,10 +2925,10 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type) bool leftAligned = false; if ( - _type.category() != Type::Category::Function || - dynamic_cast(_type).kind() == FunctionType::Kind::External + encodingType->category() != Type::Category::Function || + dynamic_cast(*encodingType).kind() == FunctionType::Kind::External ) - leftAligned = _type.leftAligned(); + leftAligned = encodingType->leftAligned(); if (storageBytes == 32) templ("cleaned", "value");