MCPcopy Create free account
hub / github.com/argotorg/solidity / copyArrayToStorage

Method copyArrayToStorage

libsolidity/codegen/ArrayUtils.cpp:44–108  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

42using namespace solidity::langutil;
43
44void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType const& _sourceType) const
45{
46 // this copies source to target and also clears target if it was larger
47 // need to leave "target_ref target_byte_off" on the stack at the end
48
49 // stack layout: source_ref [source length] target_ref (top)
50 solAssert(_targetType.location() == DataLocation::Storage, "");
51
52 // TODO unroll loop for small sizes
53
54 bool fromCalldata = _sourceType.location() == DataLocation::CallData;
55 bool haveSourceLengthOnStack = fromCalldata && _sourceType.isDynamicallySized();
56
57 for (unsigned i = _sourceType.sizeOnStack(); i > 0; --i)
58 m_context << swapInstruction(i);
59 // stack: target_ref source_ref [source_length]
60
61 if (_sourceType.baseType()->category() == Type::Category::Array)
62 {
63 // TODO: This limitation can now be removed since we use Yul utility functions that handle nested arrays correctly.
64 // The old inline assembly implementation couldn't handle nested calldata dynamic arrays, but the Yul functions
65 // support them through recursive calls. We keep this check temporarily for backward compatibility.
66 auto const& sourceBaseArrayType = dynamic_cast<ArrayType const&>(*_sourceType.baseType());
67 solUnimplementedAssert(
68 !fromCalldata ||
69 !_sourceType.isDynamicallyEncoded() ||
70 !sourceBaseArrayType.isDynamicallySized(),
71 "Copying nested calldata dynamic arrays to storage is not implemented in the old code generator."
72 );
73 }
74 else
75 {
76 // TODO: This limitation can now be removed since we use Yul utility functions that handle non-value types correctly.
77 // The old inline assembly implementation couldn't handle copying arrays of non-value types from memory or calldata to storage,
78 // but the Yul functions support them. We keep this check temporarily for backward compatibility.
79 bool fromMemoryOrCalldata = _sourceType.location() == DataLocation::Memory || _sourceType.location() == DataLocation::CallData;
80 solUnimplementedAssert(
81 _sourceType.baseType()->isValueType() || !fromMemoryOrCalldata,
82 "Copying of type " + _sourceType.toString(false) + " to storage is not supported in legacy (only supported by the IR pipeline). " +
83 "Hint: try compiling with `--via-ir` (CLI) or the equivalent `viaIR: true` (Standard JSON)."
84 );
85 }
86
87 if (haveSourceLengthOnStack)
88 {
89 // stack: target_ref source_ref source_length
90 m_context << Instruction::SWAP1;
91 // stack: target_ref source_length source_ref
92 m_context << Instruction::DUP3;
93 // stack: target_ref source_length source_ref target_ref
94 }
95 else
96 {
97 // stack: target_ref source_ref
98 m_context << Instruction::DUP2;
99 // stack: target_ref source_ref target_ref
100 }
101

Callers 1

storeValueMethod · 0.80

Calls 11

swapInstructionFunction · 0.85
callYulFunctionMethod · 0.80
locationMethod · 0.45
isDynamicallySizedMethod · 0.45
sizeOnStackMethod · 0.45
categoryMethod · 0.45
baseTypeMethod · 0.45
isDynamicallyEncodedMethod · 0.45
isValueTypeMethod · 0.45
toStringMethod · 0.45

Tested by

no test coverage detected