mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Do not copy reference types to memory in-place.
This commit is contained in:
+19
-57
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user