mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #1193 from chriseth/sol_fixABIArrays
Fixed arrays in ABI.
This commit is contained in:
		
						commit
						de671024b5
					
				
							
								
								
									
										65
									
								
								Compiler.cpp
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								Compiler.cpp
									
									
									
									
									
								
							| @ -205,42 +205,49 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool | ||||
| { | ||||
| 	// We do not check the calldata size, everything is zero-padded.
 | ||||
| 	unsigned offset(CompilerUtils::dataStartOffset); | ||||
| 	bool const c_padToWords = true; | ||||
| 
 | ||||
| 	unsigned dynamicParameterCount = 0; | ||||
| 	bigint parameterHeadEnd = offset; | ||||
| 	for (TypePointer const& type: _typeParameters) | ||||
| 		if (type->isDynamicallySized()) | ||||
| 			dynamicParameterCount++; | ||||
| 	offset += dynamicParameterCount * 32; | ||||
| 	unsigned currentDynamicParameter = 0; | ||||
| 		parameterHeadEnd += type->isDynamicallySized() ? 32 : | ||||
| 			CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); | ||||
| 	solAssert(parameterHeadEnd <= numeric_limits<unsigned>::max(), "Arguments too large."); | ||||
| 
 | ||||
| 	unsigned stackHeightOfPreviousDynamicArgument = 0; | ||||
| 	ArrayType const* previousDynamicType = nullptr; | ||||
| 	for (TypePointer const& type: _typeParameters) | ||||
| 	{ | ||||
| 		switch (type->getCategory()) | ||||
| 		{ | ||||
| 		case Type::Category::Array: | ||||
| 			if (type->isDynamicallySized()) | ||||
| 			{ | ||||
| 			// value on stack: [calldata_offset] (only if we are already in dynamic mode)
 | ||||
| 			if (currentDynamicParameter == 0) | ||||
| 				// switch from static to dynamic
 | ||||
| 				m_context << u256(offset); | ||||
| 			// retrieve length
 | ||||
| 			CompilerUtils(m_context).loadFromMemory( | ||||
| 				CompilerUtils::dataStartOffset + currentDynamicParameter * 32, | ||||
| 				IntegerType(256), !_fromMemory, c_padToWords); | ||||
| 			// stack: offset length
 | ||||
| 			// add 32-byte padding to copy of length
 | ||||
| 			m_context << u256(32) << eth::Instruction::DUP1 << u256(31) | ||||
| 				<< eth::Instruction::DUP4 << eth::Instruction::ADD | ||||
| 				<< eth::Instruction::DIV << eth::Instruction::MUL; | ||||
| 			// stack: offset length padded_length
 | ||||
| 			m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; | ||||
| 			currentDynamicParameter++; | ||||
| 			// stack: offset length next_calldata_offset
 | ||||
| 				// put on stack: data_offset length
 | ||||
| 				unsigned newStackHeight = m_context.getStackHeight(); | ||||
| 				if (previousDynamicType) | ||||
| 				{ | ||||
| 					// Retrieve data start offset by adding length to start offset of previous dynamic type
 | ||||
| 					unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument; | ||||
| 					m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth); | ||||
| 					ArrayUtils(m_context).convertLengthToSize(*previousDynamicType); | ||||
| 					m_context << u256(32) << eth::Instruction::MUL << eth::Instruction::ADD; | ||||
| 				} | ||||
| 		else if (currentDynamicParameter == 0) | ||||
| 			// we can still use static load
 | ||||
| 			offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords); | ||||
| 				else | ||||
| 			CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords); | ||||
| 	if (dynamicParameterCount > 0) | ||||
| 		m_context << eth::Instruction::POP; | ||||
| 					m_context << u256(parameterHeadEnd); | ||||
| 				stackHeightOfPreviousDynamicArgument = newStackHeight; | ||||
| 				previousDynamicType = &dynamic_cast<ArrayType const&>(*type); | ||||
| 				offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				m_context << u256(offset); | ||||
| 				offset += CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); | ||||
| 			offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) | ||||
|  | ||||
							
								
								
									
										13
									
								
								Types.cpp
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Types.cpp
									
									
									
									
									
								
							| @ -570,6 +570,15 @@ bool ArrayType::operator==(Type const& _other) const | ||||
| 	return isDynamicallySized() || getLength()  == other.getLength(); | ||||
| } | ||||
| 
 | ||||
| unsigned ArrayType::getCalldataEncodedSize() const | ||||
| { | ||||
| 	if (isDynamicallySized()) | ||||
| 		return 0; | ||||
| 	bigint size = bigint(getLength()) * (isByteArray() ? 1 : getBaseType()->getCalldataEncodedSize()); | ||||
| 	solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned."); | ||||
| 	return unsigned(size); | ||||
| } | ||||
| 
 | ||||
| u256 ArrayType::getStorageSize() const | ||||
| { | ||||
| 	if (isDynamicallySized()) | ||||
| @ -586,8 +595,8 @@ u256 ArrayType::getStorageSize() const | ||||
| unsigned ArrayType::getSizeOnStack() const | ||||
| { | ||||
| 	if (m_location == Location::CallData) | ||||
| 		// offset, length (stack top)
 | ||||
| 		return 2; | ||||
| 		// offset [length] (stack top)
 | ||||
| 		return 1 + (isDynamicallySized() ? 1 : 0); | ||||
| 	else | ||||
| 		// offset
 | ||||
| 		return 1; | ||||
|  | ||||
							
								
								
									
										1
									
								
								Types.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Types.h
									
									
									
									
									
								
							| @ -302,6 +302,7 @@ public: | ||||
| 	virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; | ||||
| 	virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; | ||||
| 	virtual bool operator==(const Type& _other) const override; | ||||
| 	virtual unsigned getCalldataEncodedSize() const override; | ||||
| 	virtual bool isDynamicallySized() const { return m_hasDynamicLength; } | ||||
| 	virtual u256 getStorageSize() const override; | ||||
| 	virtual unsigned getSizeOnStack() const override; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user