From 50a54fa8aaf9c0e06ef7bbde0ae93717583ac339 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 20 Jul 2020 14:37:19 +0200 Subject: [PATCH] Implement inline arrays. --- libsolidity/codegen/YulUtilFunctions.cpp | 29 +++++++++++++++---- libsolidity/codegen/YulUtilFunctions.h | 6 ++++ .../codegen/ir/IRGeneratorForStatements.cpp | 26 ++++++++++++++++- .../array/inline_array_singleton.sol | 3 +- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index cab908c18..0bd6b0d3a 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -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 (length) -> memPtr { + let allocSize := (length) + memPtr := (allocSize) + + mstore(memPtr, length) + + } + )") + ("functionName", functionName) + ("alloc", allocationFunction()) + ("allocSize", arrayAllocationSizeFunction(_type)) + ("dynamic", _type.isDynamicallySized()) + .render(); + }); +} + string YulUtilFunctions::allocateAndInitializeMemoryArrayFunction(ArrayType const& _type) { string functionName = "allocate_and_zero_memory_array_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { return Whiskers(R"( function (length) -> memPtr { - let allocSize := (length) - memPtr := (allocSize) + memPtr := (length) let dataStart := memPtr - let dataSize := allocSize + let dataSize := (length) dataStart := add(dataStart, 32) dataSize := sub(dataSize, 32) - mstore(memPtr, length) (dataStart, dataSize) } )") ("functionName", functionName) - ("alloc", allocationFunction()) + ("allocArray", allocateMemoryArrayFunction(_type)) ("allocSize", arrayAllocationSizeFunction(_type)) ("zeroArrayFunction", zeroMemoryArrayFunction(_type)) ("dynamic", _type.isDynamicallySized()) diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 5d9ec805f..19ca72dd0 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -282,6 +282,12 @@ public: /// signature: (dataStart, dataSizeInBytes) -> 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. /// For dynamic arrays it adds space for length and stores it. /// signature: (length) -> memPtr diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 51679571e..0489f3f68 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -311,7 +311,31 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment) bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) { if (_tuple.isInlineArray()) - solUnimplementedAssert(false, ""); + { + auto const& arrayType = dynamic_cast(*_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 { bool willBeWrittenTo = _tuple.annotation().willBeWrittenTo; diff --git a/test/libsolidity/semanticTests/array/inline_array_singleton.sol b/test/libsolidity/semanticTests/array/inline_array_singleton.sol index 5925aba0f..e8373854d 100644 --- a/test/libsolidity/semanticTests/array/inline_array_singleton.sol +++ b/test/libsolidity/semanticTests/array/inline_array_singleton.sol @@ -4,6 +4,7 @@ contract C { return [4][0]; } } - +// ==== +// compileViaYul: also // ---- // f() -> 4