mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #6965 from sifmelcara/6881-preparation
Clean up and refactor array element access related code
This commit is contained in:
		
						commit
						9a707ea6e9
					
				| @ -414,7 +414,8 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( | ||||
| 		fromArrayType.isByteArray() || | ||||
| 		*fromArrayType.baseType() == *TypeProvider::uint256() || | ||||
| 		*fromArrayType.baseType() == FixedBytesType(32), | ||||
| 	""); | ||||
| 		"" | ||||
| 	); | ||||
| 	solAssert(fromArrayType.calldataStride() == toArrayType.memoryStride(), ""); | ||||
| 
 | ||||
| 	solAssert( | ||||
|  | ||||
| @ -1055,28 +1055,27 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b | ||||
| 	switch (location) | ||||
| 	{ | ||||
| 	case DataLocation::Memory: | ||||
| 		// stack: <base_ref> <index>
 | ||||
| 		if (!_arrayType.isByteArray()) | ||||
| 			m_context << u256(_arrayType.memoryHeadSize()) << Instruction::MUL; | ||||
| 		if (_arrayType.isDynamicallySized()) | ||||
| 			m_context << u256(32) << Instruction::ADD; | ||||
| 		if (_keepReference) | ||||
| 			m_context << Instruction::DUP2; | ||||
| 		m_context << Instruction::ADD; | ||||
| 		break; | ||||
| 	case DataLocation::CallData: | ||||
| 		if (!_arrayType.isByteArray()) | ||||
| 		{ | ||||
| 			if (location == DataLocation::CallData) | ||||
| 			{ | ||||
| 				if (_arrayType.baseType()->isDynamicallyEncoded()) | ||||
| 					m_context << u256(0x20); | ||||
| 				else | ||||
| 					m_context << _arrayType.baseType()->calldataEncodedSize(); | ||||
| 			} | ||||
| 			if (_arrayType.baseType()->isDynamicallyEncoded()) | ||||
| 				m_context << u256(0x20); | ||||
| 			else | ||||
| 				m_context << u256(_arrayType.memoryHeadSize()); | ||||
| 				m_context << _arrayType.baseType()->calldataEncodedSize(); | ||||
| 			m_context << Instruction::MUL; | ||||
| 		} | ||||
| 		// stack: <base_ref> <index * size>
 | ||||
| 
 | ||||
| 		if (location == DataLocation::Memory && _arrayType.isDynamicallySized()) | ||||
| 			m_context << u256(32) << Instruction::ADD; | ||||
| 
 | ||||
| 		if (_keepReference) | ||||
| 			m_context << Instruction::DUP2; | ||||
| 
 | ||||
| 		m_context << Instruction::ADD; | ||||
| 		break; | ||||
| 	case DataLocation::Storage: | ||||
| @ -1132,6 +1131,50 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck) const | ||||
| { | ||||
| 	solAssert(_arrayType.location() == DataLocation::CallData, ""); | ||||
| 	if (_arrayType.baseType()->isDynamicallyEncoded()) | ||||
| 	{ | ||||
| 		// stack layout: <base_ref> <length> <index>
 | ||||
| 		ArrayUtils(m_context).accessIndex(_arrayType, _doBoundsCheck, true); | ||||
| 		// stack layout: <base_ref> <ptr_to_tail>
 | ||||
| 
 | ||||
| 		CompilerUtils(m_context).accessCalldataTail(*_arrayType.baseType()); | ||||
| 		// stack layout: <tail_ref> [length]
 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		ArrayUtils(m_context).accessIndex(_arrayType, _doBoundsCheck); | ||||
| 		if (_arrayType.baseType()->isValueType()) | ||||
| 		{ | ||||
| 			solAssert(_arrayType.baseType()->storageBytes() <= 32, ""); | ||||
| 			if ( | ||||
| 				!_arrayType.isByteArray() && | ||||
| 				_arrayType.baseType()->storageBytes() < 32 && | ||||
| 				m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) | ||||
| 			) | ||||
| 			{ | ||||
| 				m_context << u256(32); | ||||
| 				CompilerUtils(m_context).abiDecodeV2({_arrayType.baseType()}, false); | ||||
| 			} | ||||
| 			else | ||||
| 				CompilerUtils(m_context).loadFromMemoryDynamic( | ||||
| 					*_arrayType.baseType(), | ||||
| 					true, | ||||
| 					!_arrayType.isByteArray(), | ||||
| 					false | ||||
| 				); | ||||
| 		} | ||||
| 		else | ||||
| 			solAssert( | ||||
| 				_arrayType.baseType()->category() == Type::Category::Struct || | ||||
| 				_arrayType.baseType()->category() == Type::Category::Array, | ||||
| 				"Invalid statically sized non-value base type on array access." | ||||
| 			); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ArrayUtils::incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPosition, unsigned _storageOffsetPosition) const | ||||
| { | ||||
| 	solAssert(_byteSize < 32, ""); | ||||
|  | ||||
| @ -104,6 +104,10 @@ public: | ||||
| 	/// Stack post (storage): [reference] storage_slot byte_offset
 | ||||
| 	/// Stack post: [reference] memory/calldata_offset
 | ||||
| 	void accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck = true, bool _keepReference = false) const; | ||||
| 	/// Access calldata array's element and put it on stack.
 | ||||
| 	/// Stack pre: reference [length] index
 | ||||
| 	/// Stack post: value
 | ||||
| 	void accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck = true) const; | ||||
| 
 | ||||
| private: | ||||
| 	/// Adds the given number of bytes to a storage byte offset counter and also increments
 | ||||
|  | ||||
| @ -816,7 +816,12 @@ void CompilerUtils::convertType( | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract || targetTypeCategory == Type::Category::Address, ""); | ||||
| 			solAssert( | ||||
| 				targetTypeCategory == Type::Category::Integer || | ||||
| 				targetTypeCategory == Type::Category::Contract || | ||||
| 				targetTypeCategory == Type::Category::Address, | ||||
| 				"" | ||||
| 			); | ||||
| 			IntegerType addressType(160); | ||||
| 			IntegerType const& targetType = targetTypeCategory == Type::Category::Integer | ||||
| 				? dynamic_cast<IntegerType const&>(_targetType) : addressType; | ||||
| @ -923,7 +928,6 @@ void CompilerUtils::convertType( | ||||
| 				// stack: <mem start> <source ref> (variably sized) <length> <mem data pos>
 | ||||
| 				if (targetType.baseType()->isValueType()) | ||||
| 				{ | ||||
| 					solAssert(typeOnStack.baseType()->isValueType(), ""); | ||||
| 					copyToStackTop(2 + stackSize, stackSize); | ||||
| 					ArrayUtils(m_context).copyArrayToMemory(typeOnStack); | ||||
| 				} | ||||
| @ -957,10 +961,11 @@ void CompilerUtils::convertType( | ||||
| 		} | ||||
| 		case DataLocation::CallData: | ||||
| 			solAssert( | ||||
| 					targetType.isByteArray() && | ||||
| 					typeOnStack.isByteArray() && | ||||
| 					typeOnStack.location() == DataLocation::CallData, | ||||
| 				"Invalid conversion to calldata type."); | ||||
| 				targetType.isByteArray() && | ||||
| 				typeOnStack.isByteArray() && | ||||
| 				typeOnStack.location() == DataLocation::CallData, | ||||
| 				"Invalid conversion to calldata type." | ||||
| 			); | ||||
| 			break; | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| @ -54,7 +54,13 @@ class StackHeightChecker | ||||
| public: | ||||
| 	explicit StackHeightChecker(CompilerContext const& _context): | ||||
| 		m_context(_context), stackHeight(m_context.stackHeight()) {} | ||||
| 	void check() { solAssert(m_context.stackHeight() == stackHeight, std::string("I sense a disturbance in the stack: ") + to_string(m_context.stackHeight()) + " vs " + to_string(stackHeight)); } | ||||
| 	void check() | ||||
| 	{ | ||||
| 		solAssert( | ||||
| 			m_context.stackHeight() == stackHeight, | ||||
| 			std::string("I sense a disturbance in the stack: ") + to_string(m_context.stackHeight()) + " vs " + to_string(stackHeight) | ||||
| 		); | ||||
| 	} | ||||
| private: | ||||
| 	CompilerContext const& m_context; | ||||
| 	unsigned stackHeight; | ||||
| @ -893,9 +899,9 @@ bool ContractCompiler::visit(VariableDeclarationStatement const& _variableDeclar | ||||
| 
 | ||||
| 	// Local variable slots are reserved when their declaration is visited,
 | ||||
| 	// and freed in the end of their scope.
 | ||||
| 	for (auto _decl: _variableDeclarationStatement.declarations()) | ||||
| 		if (_decl) | ||||
| 			appendStackVariableInitialisation(*_decl); | ||||
| 	for (auto decl: _variableDeclarationStatement.declarations()) | ||||
| 		if (decl) | ||||
| 			appendStackVariableInitialisation(*decl); | ||||
| 
 | ||||
| 	StackHeightChecker checker(m_context); | ||||
| 	if (Expression const* expression = _variableDeclarationStatement.initialValue()) | ||||
|  | ||||
| @ -1588,45 +1588,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) | ||||
| 			setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArray()); | ||||
| 			break; | ||||
| 		case DataLocation::CallData: | ||||
| 			if (arrayType.baseType()->isDynamicallyEncoded()) | ||||
| 			{ | ||||
| 				// stack layout: <base_ref> <length> <index>
 | ||||
| 				ArrayUtils(m_context).accessIndex(arrayType, true, true); | ||||
| 				// stack layout: <base_ref> <ptr_to_tail>
 | ||||
| 
 | ||||
| 				CompilerUtils(m_context).accessCalldataTail(*arrayType.baseType()); | ||||
| 				// stack layout: <tail_ref> [length]
 | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ArrayUtils(m_context).accessIndex(arrayType, true); | ||||
| 				if (arrayType.baseType()->isValueType()) | ||||
| 				{ | ||||
| 					solAssert(arrayType.baseType()->storageBytes() <= 32, ""); | ||||
| 					if ( | ||||
| 						!arrayType.isByteArray() && | ||||
| 						arrayType.baseType()->storageBytes() < 32 && | ||||
| 						m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) | ||||
| 					) | ||||
| 					{ | ||||
| 						m_context << u256(32); | ||||
| 						CompilerUtils(m_context).abiDecodeV2({arrayType.baseType()}, false); | ||||
| 					} | ||||
| 					else | ||||
| 						CompilerUtils(m_context).loadFromMemoryDynamic( | ||||
| 							*arrayType.baseType(), | ||||
| 							true, | ||||
| 							!arrayType.isByteArray(), | ||||
| 							false | ||||
| 						); | ||||
| 				} | ||||
| 				else | ||||
| 					solAssert( | ||||
| 						arrayType.baseType()->category() == Type::Category::Struct || | ||||
| 						arrayType.baseType()->category() == Type::Category::Array, | ||||
| 						"Invalid statically sized non-value base type on array access." | ||||
| 					); | ||||
| 			} | ||||
| 			ArrayUtils(m_context).accessCallDataArrayElement(arrayType); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user