aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen/CompilerUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen/CompilerUtils.cpp')
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp34
1 files changed, 24 insertions, 10 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 79aef7b0..4af7d905 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -78,6 +78,20 @@ void CompilerUtils::toSizeAfterFreeMemoryPointer()
m_context << Instruction::SWAP1;
}
+void CompilerUtils::revertWithStringData(Type const& _argumentType)
+{
+ solAssert(_argumentType.isImplicitlyConvertibleTo(*Type::fromElementaryTypeName("string memory")), "");
+ fetchFreeMemoryPointer();
+ m_context << (u256(FixedHash<4>::Arith(FixedHash<4>(dev::keccak256("Error(string)")))) << (256 - 32));
+ m_context << Instruction::DUP2 << Instruction::MSTORE;
+ m_context << u256(4) << Instruction::ADD;
+ // Stack: <string data> <mem pos of encoding start>
+ abiEncode({_argumentType.shared_from_this()}, {make_shared<ArrayType>(DataLocation::Memory, true)});
+ toSizeAfterFreeMemoryPointer();
+ m_context << Instruction::REVERT;
+ m_context.adjustStackOffset(_argumentType.sizeOnStack());
+}
+
unsigned CompilerUtils::loadFromMemory(
unsigned _offset,
Type const& _type,
@@ -670,19 +684,17 @@ void CompilerUtils::convertType(
// clear for conversion to longer bytes
solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested.");
FixedBytesType const& targetType = dynamic_cast<FixedBytesType const&>(_targetType);
- if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded)
+ if (typeOnStack.numBytes() == 0 || targetType.numBytes() == 0)
+ m_context << Instruction::POP << u256(0);
+ else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded)
{
- if (typeOnStack.numBytes() == 0)
- m_context << Instruction::POP << u256(0);
- else
- {
- m_context << ((u256(1) << (256 - typeOnStack.numBytes() * 8)) - 1);
- m_context << Instruction::NOT << Instruction::AND;
- }
+ int bytes = min(typeOnStack.numBytes(), targetType.numBytes());
+ m_context << ((u256(1) << (256 - bytes * 8)) - 1);
+ m_context << Instruction::NOT << Instruction::AND;
}
}
- }
break;
+ }
case Type::Category::Enum:
solAssert(_targetType == _typeOnStack || targetTypeCategory == Type::Category::Integer, "");
if (enumOverflowCheckPending)
@@ -691,6 +703,7 @@ void CompilerUtils::convertType(
solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
if (_asPartOfArgumentDecoding)
+ // TODO: error message?
m_context.appendConditionalRevert();
else
m_context.appendConditionalInvalid();
@@ -783,8 +796,9 @@ void CompilerUtils::convertType(
bytesConstRef data(value);
if (targetTypeCategory == Type::Category::FixedBytes)
{
+ int const numBytes = dynamic_cast<FixedBytesType const&>(_targetType).numBytes();
solAssert(data.size() <= 32, "");
- m_context << h256::Arith(h256(data, h256::AlignLeft));
+ m_context << (h256::Arith(h256(data, h256::AlignLeft)) & (~(u256(-1) >> (8 * numBytes))));
}
else if (targetTypeCategory == Type::Category::Array)
{