mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Memory-storage copy.
This commit is contained in:
parent
ee520f6022
commit
2eabaa4716
@ -39,11 +39,6 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
|||||||
|
|
||||||
// stack layout: [source_ref] [source_byte_off] [source length] target_ref target_byte_off (top)
|
// stack layout: [source_ref] [source_byte_off] [source length] target_ref target_byte_off (top)
|
||||||
solAssert(_targetType.location() == DataLocation::Storage, "");
|
solAssert(_targetType.location() == DataLocation::Storage, "");
|
||||||
solAssert(
|
|
||||||
_sourceType.location() == DataLocation::CallData ||
|
|
||||||
_sourceType.location() == DataLocation::Storage,
|
|
||||||
"Given array location not implemented."
|
|
||||||
);
|
|
||||||
|
|
||||||
IntegerType uint256(256);
|
IntegerType uint256(256);
|
||||||
Type const* targetBaseType = _targetType.isByteArray() ? &uint256 : &(*_targetType.getBaseType());
|
Type const* targetBaseType = _targetType.isByteArray() ? &uint256 : &(*_targetType.getBaseType());
|
||||||
@ -52,6 +47,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
|||||||
// TODO unroll loop for small sizes
|
// TODO unroll loop for small sizes
|
||||||
|
|
||||||
bool sourceIsStorage = _sourceType.location() == DataLocation::Storage;
|
bool sourceIsStorage = _sourceType.location() == DataLocation::Storage;
|
||||||
|
bool fromCalldata = _sourceType.location() == DataLocation::CallData;
|
||||||
bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType;
|
bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType;
|
||||||
bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->getStorageBytes() <= 16;
|
bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->getStorageBytes() <= 16;
|
||||||
bool haveByteOffsetTarget = !directCopy && targetBaseType->getStorageBytes() <= 16;
|
bool haveByteOffsetTarget = !directCopy && targetBaseType->getStorageBytes() <= 16;
|
||||||
@ -71,6 +67,13 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
|||||||
// retrieve source length
|
// retrieve source length
|
||||||
if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized())
|
if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized())
|
||||||
retrieveLength(_sourceType); // otherwise, length is already there
|
retrieveLength(_sourceType); // otherwise, length is already there
|
||||||
|
if (_sourceType.location() == DataLocation::Memory && _sourceType.isDynamicallySized())
|
||||||
|
{
|
||||||
|
// increment source pointer to point to data
|
||||||
|
m_context << eth::Instruction::SWAP1 << u256(0x20);
|
||||||
|
m_context << eth::Instruction::ADD << eth::Instruction::SWAP1;
|
||||||
|
}
|
||||||
|
|
||||||
// stack: target_ref source_ref source_length
|
// stack: target_ref source_ref source_length
|
||||||
m_context << eth::Instruction::DUP3;
|
m_context << eth::Instruction::DUP3;
|
||||||
// stack: target_ref source_ref source_length target_ref
|
// stack: target_ref source_ref source_length target_ref
|
||||||
@ -164,9 +167,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
|||||||
StorageItem(m_context, *sourceBaseType).retrieveValue(SourceLocation(), true);
|
StorageItem(m_context, *sourceBaseType).retrieveValue(SourceLocation(), true);
|
||||||
}
|
}
|
||||||
else if (sourceBaseType->isValueType())
|
else if (sourceBaseType->isValueType())
|
||||||
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, true, true, false);
|
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false);
|
||||||
else
|
else
|
||||||
solAssert(false, "Copying of unknown type requested: " + sourceBaseType->toString());
|
solAssert(false, "Copying of type " + _sourceType.toString(false) + " to storage not yet supported.");
|
||||||
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] <source_value>...
|
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] <source_value>...
|
||||||
solAssert(
|
solAssert(
|
||||||
2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16,
|
2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16,
|
||||||
@ -419,6 +422,10 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
solAssert(
|
||||||
|
_arrayType.getBaseType()->getCalldataEncodedSize() > 0,
|
||||||
|
"Copying nested dynamic arrays not yet implemented."
|
||||||
|
);
|
||||||
if (!_arrayType.isByteArray())
|
if (!_arrayType.isByteArray())
|
||||||
m_context << _arrayType.getBaseType()->getCalldataEncodedSize() << eth::Instruction::MUL;
|
m_context << _arrayType.getBaseType()->getCalldataEncodedSize() << eth::Instruction::MUL;
|
||||||
else if (_pad)
|
else if (_pad)
|
||||||
@ -485,6 +492,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
|
|||||||
switch (location)
|
switch (location)
|
||||||
{
|
{
|
||||||
case DataLocation::CallData:
|
case DataLocation::CallData:
|
||||||
|
case DataLocation::Memory:
|
||||||
if (!_arrayType.isByteArray())
|
if (!_arrayType.isByteArray())
|
||||||
{
|
{
|
||||||
m_context << eth::Instruction::SWAP1;
|
m_context << eth::Instruction::SWAP1;
|
||||||
@ -494,7 +502,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
|
|||||||
if (_arrayType.getBaseType()->isValueType())
|
if (_arrayType.getBaseType()->isValueType())
|
||||||
CompilerUtils(m_context).loadFromMemoryDynamic(
|
CompilerUtils(m_context).loadFromMemoryDynamic(
|
||||||
*_arrayType.getBaseType(),
|
*_arrayType.getBaseType(),
|
||||||
true,
|
location == DataLocation::CallData,
|
||||||
!_arrayType.isByteArray(),
|
!_arrayType.isByteArray(),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
@ -527,8 +535,6 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
|
|||||||
m_context << eth::Instruction::ADD << u256(0);
|
m_context << eth::Instruction::ADD << u256(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DataLocation::Memory:
|
|
||||||
solAssert(false, "Memory lvalues not yet implemented.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,8 +724,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
|||||||
case DataLocation::Storage:
|
case DataLocation::Storage:
|
||||||
setLValue<StorageArrayLength>(_memberAccess, type);
|
setLValue<StorageArrayLength>(_memberAccess, type);
|
||||||
break;
|
break;
|
||||||
default:
|
case DataLocation::Memory:
|
||||||
solAssert(false, "Unsupported array location.");
|
m_context << eth::Instruction::MLOAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user