Implement inline arrays.

This commit is contained in:
chriseth 2020-07-20 14:37:19 +02:00
parent ac95e98b2b
commit 50a54fa8aa
4 changed files with 57 additions and 7 deletions

View File

@ -1620,26 +1620,45 @@ string YulUtilFunctions::zeroComplexMemoryArrayFunction(ArrayType const& _type)
}); });
} }
string YulUtilFunctions::allocateMemoryArrayFunction(ArrayType const& _type)
{
string functionName = "allocate_memory_array_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(length) -> memPtr {
let allocSize := <allocSize>(length)
memPtr := <alloc>(allocSize)
<?dynamic>
mstore(memPtr, length)
</dynamic>
}
)")
("functionName", functionName)
("alloc", allocationFunction())
("allocSize", arrayAllocationSizeFunction(_type))
("dynamic", _type.isDynamicallySized())
.render();
});
}
string YulUtilFunctions::allocateAndInitializeMemoryArrayFunction(ArrayType const& _type) string YulUtilFunctions::allocateAndInitializeMemoryArrayFunction(ArrayType const& _type)
{ {
string functionName = "allocate_and_zero_memory_array_" + _type.identifier(); string functionName = "allocate_and_zero_memory_array_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"( return Whiskers(R"(
function <functionName>(length) -> memPtr { function <functionName>(length) -> memPtr {
let allocSize := <allocSize>(length) memPtr := <allocArray>(length)
memPtr := <alloc>(allocSize)
let dataStart := memPtr let dataStart := memPtr
let dataSize := allocSize let dataSize := <allocSize>(length)
<?dynamic> <?dynamic>
dataStart := add(dataStart, 32) dataStart := add(dataStart, 32)
dataSize := sub(dataSize, 32) dataSize := sub(dataSize, 32)
mstore(memPtr, length)
</dynamic> </dynamic>
<zeroArrayFunction>(dataStart, dataSize) <zeroArrayFunction>(dataStart, dataSize)
} }
)") )")
("functionName", functionName) ("functionName", functionName)
("alloc", allocationFunction()) ("allocArray", allocateMemoryArrayFunction(_type))
("allocSize", arrayAllocationSizeFunction(_type)) ("allocSize", arrayAllocationSizeFunction(_type))
("zeroArrayFunction", zeroMemoryArrayFunction(_type)) ("zeroArrayFunction", zeroMemoryArrayFunction(_type))
("dynamic", _type.isDynamicallySized()) ("dynamic", _type.isDynamicallySized())

View File

@ -282,6 +282,12 @@ public:
/// signature: (dataStart, dataSizeInBytes) -> /// signature: (dataStart, dataSizeInBytes) ->
std::string zeroComplexMemoryArrayFunction(ArrayType const& _type); std::string zeroComplexMemoryArrayFunction(ArrayType const& _type);
/// @returns the name of a function that allocates a memory array.
/// For dynamic arrays it adds space for length and stores it.
/// The contents of the data area are unspecified.
/// signature: (length) -> memPtr
std::string allocateMemoryArrayFunction(ArrayType const& _type);
/// @returns the name of a function that allocates and zeroes a memory array. /// @returns the name of a function that allocates and zeroes a memory array.
/// For dynamic arrays it adds space for length and stores it. /// For dynamic arrays it adds space for length and stores it.
/// signature: (length) -> memPtr /// signature: (length) -> memPtr

View File

@ -311,7 +311,31 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment)
bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
{ {
if (_tuple.isInlineArray()) if (_tuple.isInlineArray())
solUnimplementedAssert(false, ""); {
auto const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
define(_tuple) <<
m_utils.allocateMemoryArrayFunction(arrayType) <<
"(" <<
_tuple.components().size() <<
")\n";
string mpos = IRVariable(_tuple).part("mpos").name();
Type const& baseType = *arrayType.baseType();
for (size_t i = 0; i < _tuple.components().size(); i++)
{
Expression const& component = *_tuple.components()[i];
component.accept(*this);
IRVariable converted = convert(component, baseType);
m_code <<
m_utils.writeToMemoryFunction(baseType) <<
"(" <<
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
", " <<
converted.name() <<
")\n";
}
}
else else
{ {
bool willBeWrittenTo = _tuple.annotation().willBeWrittenTo; bool willBeWrittenTo = _tuple.annotation().willBeWrittenTo;

View File

@ -4,6 +4,7 @@ contract C {
return [4][0]; return [4][0];
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// f() -> 4 // f() -> 4