diff options
author | Lefteris Karapetsas <lefteris@refu.co> | 2015-02-01 09:41:14 +0800 |
---|---|---|
committer | Lefteris Karapetsas <lefteris@refu.co> | 2015-02-01 09:41:14 +0800 |
commit | 82bcb7e33a4a00be8145588615c0d7a812fd4ce2 (patch) | |
tree | d4940591385832188eb1ebefa002bb7601bf9d6b /ExpressionCompiler.cpp | |
parent | ec7a9bf919c393b10a91f0bc77fe2932c66a0c6d (diff) | |
download | dexon-solidity-82bcb7e33a4a00be8145588615c0d7a812fd4ce2.tar.gz dexon-solidity-82bcb7e33a4a00be8145588615c0d7a812fd4ce2.tar.zst dexon-solidity-82bcb7e33a4a00be8145588615c0d7a812fd4ce2.zip |
Code generation for mapping state variable accessor
- Work in progress
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 75 |
1 files changed, 67 insertions, 8 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 7d58ea2e..edd04256 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -823,26 +823,85 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ return length; } -unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, - Expression const& _expression, unsigned _memoryOffset) +unsigned ExpressionCompiler::appendTypeCopyToMemory(Type const& _expectedType, TypePointer const& _type, + Location const& _location, unsigned _memoryOffset) { - _expression.accept(*this); - appendTypeConversion(*_expression.getType(), _expectedType, true); + appendTypeConversion(*_type, _expectedType, true); unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); if (c_numBytes == 0 || c_numBytes > 32) BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_sourceLocation(_location) << errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; bool const c_padToWords = true; return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); } +unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, + Expression const& _expression, + unsigned _memoryOffset) +{ + _expression.accept(*this); + return appendTypeCopyToMemory(_expectedType, _expression.getType(), _expression.getLocation(), _memoryOffset); +} + void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) { - m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); - solAssert(m_currentLValue.isInStorage(), ""); - m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true); + auto mappingType = dynamic_cast<const MappingType*>(_varDecl.getType().get()); + unsigned sizeOnStack; + if (mappingType != nullptr) + { + // this copies from Compiler::visit(FunctionDefinition..) for argument reading + unsigned parameterSize = mappingType->getKeyType()->getSizeOnStack(); + m_context.adjustStackOffset(parameterSize); + m_context.addVariable(_varDecl, parameterSize); + // this copies from ExpressionCompiler::visit(IndexAccess .. ) for mapping access + TypePointer const& keyType = mappingType->getKeyType(); + unsigned length = appendTypeCopyToMemory(*keyType, mappingType->getValueType(), Location()); + solAssert(length == 32, "Mapping key has to take 32 bytes in memory (for now)."); + // @todo move this once we actually use memory + length += CompilerUtils(m_context).storeInMemory(length); + m_context << u256(length) << u256(0) << eth::Instruction::SHA3; + + m_currentLValue = LValue(m_context, LValue::STORAGE, *mappingType->getValueType()); + m_currentLValue.retrieveValue(mappingType->getValueType(), Location(), true); + + unsigned const c_argumentsSize = keyType->getSizeOnStack(); + unsigned const c_returnValuesSize = mappingType->getValueType()->getSizeOnStack(); + unsigned const c_localVariablesSize = 0; + + vector<int> stackLayout; + stackLayout.push_back(c_returnValuesSize); // target of return address + stackLayout += vector<int>(c_argumentsSize, -1); // discard all arguments + for (unsigned i = 0; i < c_returnValuesSize; ++i) + stackLayout.push_back(i); + stackLayout += vector<int>(c_localVariablesSize, -1); + + while (stackLayout.back() != int(stackLayout.size() - 1)) + if (stackLayout.back() < 0) + { + m_context << eth::Instruction::POP; + stackLayout.pop_back(); + } + else + { + m_context << eth::swapInstruction(stackLayout.size() - stackLayout.back() - 1); + swap(stackLayout[stackLayout.back()], stackLayout.back()); + } + //@todo assert that everything is in place now + + m_context << eth::Instruction::JUMP; + } + else + { + m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); + solAssert(m_currentLValue.isInStorage(), ""); + m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true); + sizeOnStack = _varDecl.getType()->getSizeOnStack(); + solAssert(sizeOnStack <= 15, "Stack too deep."); + m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP; + } + } ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, |