New ABI encoding for dynamic types.

This commit is contained in:
chriseth 2015-05-08 16:54:39 +02:00
parent 5d2c36603f
commit 69693f17f6

View File

@ -206,16 +206,9 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory) void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory)
{ {
// We do not check the calldata size, everything is zero-padded. // We do not check the calldata size, everything is zero-paddedd
unsigned offset(CompilerUtils::dataStartOffset);
bigint parameterHeadEnd = offset; m_context << u256(CompilerUtils::dataStartOffset);
for (TypePointer const& type: _typeParameters)
parameterHeadEnd += type->isDynamicallySized() ? 32 : type->getCalldataEncodedSize();
solAssert(parameterHeadEnd <= numeric_limits<unsigned>::max(), "Arguments too large.");
unsigned stackHeightOfPreviousDynamicArgument = 0;
ArrayType const* previousDynamicType = nullptr;
for (TypePointer const& type: _typeParameters) for (TypePointer const& type: _typeParameters)
{ {
switch (type->getCategory()) switch (type->getCategory())
@ -223,34 +216,31 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool
case Type::Category::Array: case Type::Category::Array:
if (type->isDynamicallySized()) if (type->isDynamicallySized())
{ {
// put on stack: data_offset length // put on stack: data_pointer length
unsigned newStackHeight = m_context.getStackHeight(); CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory);
if (previousDynamicType) // stack: data_offset next_pointer
{ //@todo once we support nested arrays, this offset needs to be dynamic.
// Retrieve data start offset by adding length to start offset of previous dynamic type m_context << eth::Instruction::SWAP1 << u256(CompilerUtils::dataStartOffset);
unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument; m_context << eth::Instruction::ADD;
solAssert(stackDepth <= 16, "Stack too deep."); // stack: next_pointer data_pointer
m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth); // retrieve length
ArrayUtils(m_context).convertLengthToSize(*previousDynamicType, true); CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory, true);
m_context << eth::Instruction::ADD; // stack: next_pointer length data_pointer
} m_context << eth::Instruction::SWAP2;
else
m_context << u256(parameterHeadEnd);
stackHeightOfPreviousDynamicArgument = newStackHeight;
previousDynamicType = &dynamic_cast<ArrayType const&>(*type);
offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory);
} }
else else
{ {
m_context << u256(offset); // leave the pointer on the stack
offset += type->getCalldataEncodedSize(); m_context << eth::Instruction::DUP1;
m_context << u256(type->getCalldataEncodedSize()) << eth::Instruction::ADD;
} }
break; break;
default: default:
solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString());
offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true); CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, true);
} }
} }
m_context << eth::Instruction::POP;
} }
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)