From e5ae5955b97009233fc46ac04070073750240698 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 24 Jun 2015 17:25:36 +0200 Subject: Initialisation of memory types. --- ExpressionCompiler.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'ExpressionCompiler.cpp') diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 7d6ed346..fb10eb83 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -56,6 +56,62 @@ void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration c StorageItem(m_context, _varDecl).storeValue(*_varDecl.getType(), _varDecl.getLocation(), true); } +void ExpressionCompiler::appendStackVariableInitialisation(Type const& _type, bool _toMemory) +{ + CompilerUtils utils(m_context); + auto const* referenceType = dynamic_cast(&_type); + if (!referenceType || referenceType->location() == DataLocation::Storage) + { + for (size_t i = 0; i < _type.getSizeOnStack(); ++i) + m_context << u256(0); + if (_toMemory) + utils.storeInMemoryDynamic(_type); + return; + } + solAssert(referenceType->location() == DataLocation::Memory, ""); + if (!_toMemory) + { + // allocate memory + utils.fetchFreeMemoryPointer(); + m_context << eth::Instruction::DUP1 << u256(max(32u, _type.getCalldataEncodedSize())); + m_context << eth::Instruction::ADD; + utils.storeFreeMemoryPointer(); + m_context << eth::Instruction::DUP1; + } + + if (auto structType = dynamic_cast(&_type)) + for (auto const& member: structType->getMembers()) + appendStackVariableInitialisation(*member.type, true); + else if (auto arrayType = dynamic_cast(&_type)) + { + if (arrayType->isDynamicallySized()) + { + // zero length + m_context << u256(0); + CompilerUtils(m_context).storeInMemoryDynamic(IntegerType(256)); + } + else if (arrayType->getLength() > 0) + { + m_context << arrayType->getLength() << eth::Instruction::SWAP1; + // stack: items_to_do memory_pos + auto repeat = m_context.newTag(); + m_context << repeat; + appendStackVariableInitialisation(*arrayType->getBaseType(), true); + m_context << eth::Instruction::SWAP1 << u256(1) << eth::Instruction::SWAP1; + m_context << eth::Instruction::SUB << eth::Instruction::SWAP1; + m_context << eth::Instruction::DUP2; + m_context.appendConditionalJumpTo(repeat); + m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + } + } + else + solAssert(false, "Requested initialisation for unknown type: " + _type.toString()); + + if (!_toMemory) + // remove the updated memory pointer + m_context << eth::Instruction::POP; +} + void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) { CompilerContext::LocationSetter locationSetter(m_context, _varDecl); -- cgit v1.2.3