aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-06-25 23:51:01 +0800
committerchriseth <c@ethdev.com>2015-06-27 01:15:00 +0800
commit37e7f1f10d597efb7773417779e32f0533b6ba1b (patch)
tree7ad95be5d1c6f51b3fbad577de4494665c6eb7d3 /ExpressionCompiler.cpp
parent342ca948661a3f2088b3025b5f15c97d3a53f86e (diff)
downloaddexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar.gz
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar.bz2
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar.lz
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar.xz
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.tar.zst
dexon-solidity-37e7f1f10d597efb7773417779e32f0533b6ba1b.zip
Do not copy reference types to memory in-place.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp76
1 files changed, 19 insertions, 57 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index fb10eb83..7ddcc031 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -56,62 +56,6 @@ 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);
@@ -211,6 +155,8 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
TypePointer type = _assignment.getRightHandSide().getType();
if (!_assignment.getType()->dataStoredIn(DataLocation::Storage))
{
+ //@todo we should delay conversion here if RHS is not in memory, LHS is a MemoryItem
+ // and not dynamically-sized.
utils().convertType(*type, *_assignment.getType());
type = _assignment.getType();
}
@@ -827,8 +773,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
_indexAccess.getIndexExpression()->accept(*this);
// stack layout: <base_ref> [<length>] <index>
ArrayUtils(m_context).accessIndex(arrayType);
- if (arrayType.location() == DataLocation::Storage)
+ switch (arrayType.location())
{
+ case DataLocation::Storage:
if (arrayType.isByteArray())
{
solAssert(!arrayType.isString(), "Index access to string is not allowed.");
@@ -836,6 +783,21 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
}
else
setLValueToStorageItem(_indexAccess);
+ break;
+ case DataLocation::Memory:
+ setLValue<MemoryItem>(_indexAccess, *_indexAccess.getType(), !arrayType.isByteArray());
+ break;
+ case DataLocation::CallData:
+ //@todo if we implement this, the value in calldata has to be added to the base offset
+ solAssert(!arrayType.getBaseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
+ if (arrayType.getBaseType()->isValueType())
+ CompilerUtils(m_context).loadFromMemoryDynamic(
+ *arrayType.getBaseType(),
+ true,
+ !arrayType.isByteArray(),
+ false
+ );
+ break;
}
}
else