diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 075cad1f3..a62251ab1 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1730,7 +1730,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) setLValue(_indexAccess, IRLValue{ *arrayType.baseType(), - IRLValue::Memory{memAddress} + IRLValue::Memory{memAddress, arrayType.isByteArray()} }); break; } @@ -1763,7 +1763,23 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) } } else if (baseType.category() == Type::Category::FixedBytes) - solUnimplementedAssert(false, ""); + { + auto const& fixedBytesType = dynamic_cast(baseType); + solAssert(_indexAccess.indexExpression(), "Index expression expected."); + + IRVariable index{m_context.newYulVariable(), *TypeProvider::uint256()}; + define(index, *_indexAccess.indexExpression()); + m_code << Whiskers(R"( + if iszero(lt(, )) { invalid() } + let := (byte(, )) + )") + ("index", index.name()) + ("length", to_string(fixedBytesType.numBytes())) + ("array", IRVariable(_indexAccess.baseExpression()).name()) + ("shl248", m_utils.shiftLeftFunction(256 - 8)) + ("result", IRVariable(_indexAccess).name()) + .render(); + } else if (baseType.category() == Type::Category::TypeType) { solAssert(baseType.sizeOnStack() == 0, ""); diff --git a/test/libsolidity/semanticTests/array/index_access.sol b/test/libsolidity/semanticTests/array/index_access.sol new file mode 100644 index 000000000..acb33fc46 --- /dev/null +++ b/test/libsolidity/semanticTests/array/index_access.sol @@ -0,0 +1,20 @@ +contract C { + function to_little_endian_64(uint64 value) public pure returns (bytes memory ret) { + ret = new bytes(8); + bytes8 bytesValue = bytes8(value); + // Byteswapping during copying to bytes. + ret[0] = bytesValue[7]; + ret[1] = bytesValue[6]; + ret[2] = bytesValue[5]; + ret[3] = bytesValue[4]; + ret[4] = bytesValue[3]; + ret[5] = bytesValue[2]; + ret[6] = bytesValue[1]; + ret[7] = bytesValue[0]; + } +} +// ==== +// compileViaYul: also +// ---- +// to_little_endian_64(uint64): 0 -> 0x20, 8, 0x00 +// to_little_endian_64(uint64): 0x0102030405060708 -> 0x20, 8, 0x0807060504030201000000000000000000000000000000000000000000000000