aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp56
1 files changed, 56 insertions, 0 deletions
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<ReferenceType const*>(&_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<StructType const*>(&_type))
+ for (auto const& member: structType->getMembers())
+ appendStackVariableInitialisation(*member.type, true);
+ else if (auto arrayType = dynamic_cast<ArrayType const*>(&_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);