mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge remote-tracking branch 'ethereum/develop' into sol_overloadingFunctions
Conflicts: libsolidity/Types.cpp
This commit is contained in:
		
						commit
						c7b428fdb1
					
				| @ -27,7 +27,6 @@ endif() | |||||||
| 
 | 
 | ||||||
| target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) | target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) | ||||||
| target_link_libraries(${EXECUTABLE} evmcore) | target_link_libraries(${EXECUTABLE} evmcore) | ||||||
| target_link_libraries(${EXECUTABLE} devcore) |  | ||||||
| target_link_libraries(${EXECUTABLE} devcrypto) | target_link_libraries(${EXECUTABLE} devcrypto) | ||||||
| 
 | 
 | ||||||
| install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) | install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) | ||||||
|  | |||||||
| @ -83,6 +83,7 @@ public: | |||||||
| 	/// Converts an offset relative to the current stack height to a value that can be used later
 | 	/// Converts an offset relative to the current stack height to a value that can be used later
 | ||||||
| 	/// with baseToCurrentStackOffset to point to the same stack element.
 | 	/// with baseToCurrentStackOffset to point to the same stack element.
 | ||||||
| 	unsigned currentToBaseStackOffset(unsigned _offset) const; | 	unsigned currentToBaseStackOffset(unsigned _offset) const; | ||||||
|  | 	/// @returns pair of slot and byte offset of the value inside this slot.
 | ||||||
| 	std::pair<u256, unsigned> getStorageLocationOfVariable(Declaration const& _declaration) const; | 	std::pair<u256, unsigned> getStorageLocationOfVariable(Declaration const& _declaration) const; | ||||||
| 
 | 
 | ||||||
| 	/// Appends a JUMPI instruction to a new tag and @returns the tag
 | 	/// Appends a JUMPI instruction to a new tag and @returns the tag
 | ||||||
|  | |||||||
| @ -157,8 +157,12 @@ void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) | |||||||
| 
 | 
 | ||||||
| void CompilerUtils::popStackElement(Type const& _type) | void CompilerUtils::popStackElement(Type const& _type) | ||||||
| { | { | ||||||
| 	unsigned const size = _type.getSizeOnStack(); | 	popStackSlots(_type.getSizeOnStack()); | ||||||
| 	for (unsigned i = 0; i < size; ++i) | } | ||||||
|  | 
 | ||||||
|  | void CompilerUtils::popStackSlots(size_t _amount) | ||||||
|  | { | ||||||
|  | 	for (size_t i = 0; i < _amount; ++i) | ||||||
| 		m_context << eth::Instruction::POP; | 		m_context << eth::Instruction::POP; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -79,6 +79,8 @@ public: | |||||||
| 	void copyToStackTop(unsigned _stackDepth, unsigned _itemSize); | 	void copyToStackTop(unsigned _stackDepth, unsigned _itemSize); | ||||||
| 	/// Removes the current value from the top of the stack.
 | 	/// Removes the current value from the top of the stack.
 | ||||||
| 	void popStackElement(Type const& _type); | 	void popStackElement(Type const& _type); | ||||||
|  | 	/// Removes element from the top of the stack _amount times.
 | ||||||
|  | 	void popStackSlots(size_t _amount); | ||||||
| 
 | 
 | ||||||
| 	template <class T> | 	template <class T> | ||||||
| 	static unsigned getSizeOnStack(std::vector<T> const& _variables); | 	static unsigned getSizeOnStack(std::vector<T> const& _variables); | ||||||
|  | |||||||
| @ -60,57 +60,82 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& | |||||||
| 	CompilerContext::LocationSetter locationSetter(m_context, _varDecl); | 	CompilerContext::LocationSetter locationSetter(m_context, _varDecl); | ||||||
| 	FunctionType accessorType(_varDecl); | 	FunctionType accessorType(_varDecl); | ||||||
| 
 | 
 | ||||||
| 	unsigned length = 0; |  | ||||||
| 	TypePointers const& paramTypes = accessorType.getParameterTypes(); | 	TypePointers const& paramTypes = accessorType.getParameterTypes(); | ||||||
| 	// move arguments to memory
 |  | ||||||
| 	for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) |  | ||||||
| 		length += CompilerUtils(m_context).storeInMemory(length, *paramType, true); |  | ||||||
| 
 | 
 | ||||||
| 	// retrieve the position of the variable
 | 	// retrieve the position of the variable
 | ||||||
| 	auto const& location = m_context.getStorageLocationOfVariable(_varDecl); | 	auto const& location = m_context.getStorageLocationOfVariable(_varDecl); | ||||||
| 	m_context << location.first; | 	m_context << location.first << u256(location.second); | ||||||
| 
 | 
 | ||||||
| 	TypePointer returnType = _varDecl.getType(); | 	TypePointer returnType = _varDecl.getType(); | ||||||
| 	for (TypePointer const& paramType: paramTypes) | 
 | ||||||
|  | 	for (size_t i = 0; i < paramTypes.size(); ++i) | ||||||
| 	{ | 	{ | ||||||
| 		// move offset to memory
 | 		if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get())) | ||||||
| 		CompilerUtils(m_context).storeInMemory(length); | 		{ | ||||||
| 		unsigned argLen = paramType->getCalldataEncodedSize(); | 			// pop offset
 | ||||||
| 		length -= argLen; | 			m_context << eth::Instruction::POP; | ||||||
| 		m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; | 			// move storage offset to memory.
 | ||||||
| 
 | 			CompilerUtils(m_context).storeInMemory(32); | ||||||
| 		returnType = dynamic_cast<MappingType const&>(*returnType).getValueType(); | 			// move key to memory.
 | ||||||
|  | 			CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i, 1); | ||||||
|  | 			CompilerUtils(m_context).storeInMemory(0); | ||||||
|  | 			m_context << u256(64) << u256(0) << eth::Instruction::SHA3; | ||||||
|  | 			// push offset
 | ||||||
|  | 			m_context << u256(0); | ||||||
|  | 			returnType = mappingType->getValueType(); | ||||||
|  | 		} | ||||||
|  | 		else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get())) | ||||||
|  | 		{ | ||||||
|  | 			// pop offset
 | ||||||
|  | 			m_context << eth::Instruction::POP; | ||||||
|  | 			CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i + 1, 1); | ||||||
|  | 			ArrayUtils(m_context).accessIndex(*arrayType); | ||||||
|  | 			returnType = arrayType->getBaseType(); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			solAssert(false, "Index access is allowed only for \"mapping\" and \"array\" types."); | ||||||
|  | 	} | ||||||
|  | 	// remove index arguments.
 | ||||||
|  | 	if (paramTypes.size() == 1) | ||||||
|  | 		m_context << eth::Instruction::SWAP2 << eth::Instruction::POP << eth::Instruction::SWAP1; | ||||||
|  | 	else if (paramTypes.size() >= 2) | ||||||
|  | 	{ | ||||||
|  | 		m_context << eth::swapInstruction(paramTypes.size()); | ||||||
|  | 		m_context << eth::Instruction::POP; | ||||||
|  | 		m_context << eth::swapInstruction(paramTypes.size()); | ||||||
|  | 		CompilerUtils(m_context).popStackSlots(paramTypes.size() - 1); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	unsigned retSizeOnStack = 0; | 	unsigned retSizeOnStack = 0; | ||||||
| 	solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); | 	solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); | ||||||
| 	if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) | 	if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) | ||||||
| 	{ | 	{ | ||||||
|  | 		// remove offset
 | ||||||
|  | 		m_context << eth::Instruction::POP; | ||||||
| 		auto const& names = accessorType.getReturnParameterNames(); | 		auto const& names = accessorType.getReturnParameterNames(); | ||||||
| 		auto const& types = accessorType.getReturnParameterTypes(); | 		auto const& types = accessorType.getReturnParameterTypes(); | ||||||
| 		// struct
 | 		// struct
 | ||||||
| 		for (size_t i = 0; i < names.size(); ++i) | 		for (size_t i = 0; i < names.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| 			if (types[i]->getCategory() == Type::Category::Mapping) | 			if (types[i]->getCategory() == Type::Category::Mapping || types[i]->getCategory() == Type::Category::Array) | ||||||
| 				continue; | 				continue; | ||||||
| 			pair<u256, unsigned> const& offsets = structType->getStorageOffsetsOfMember(names[i]); | 			pair<u256, unsigned> const& offsets = structType->getStorageOffsetsOfMember(names[i]); | ||||||
| 			m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second); | 			m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second); | ||||||
| 			StorageItem(m_context, *types[i]).retrieveValue(SourceLocation(), true); | 			StorageItem(m_context, *types[i]).retrieveValue(SourceLocation(), true); | ||||||
| 			solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); | 			solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 is not yet implemented."); | ||||||
| 			m_context << eth::Instruction::SWAP1; | 			m_context << eth::Instruction::SWAP1; | ||||||
| 			retSizeOnStack += types[i]->getSizeOnStack(); | 			retSizeOnStack += types[i]->getSizeOnStack(); | ||||||
| 		} | 		} | ||||||
|  | 		// remove slot
 | ||||||
| 		m_context << eth::Instruction::POP; | 		m_context << eth::Instruction::POP; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		// simple value
 | 		// simple value
 | ||||||
| 		solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); | 		solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); | ||||||
| 		m_context << u256(location.second); |  | ||||||
| 		StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); | 		StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); | ||||||
| 		retSizeOnStack = returnType->getSizeOnStack(); | 		retSizeOnStack = returnType->getSizeOnStack(); | ||||||
| 	} | 	} | ||||||
| 	solAssert(retSizeOnStack <= 15, "Stack too deep."); | 	solAssert(retSizeOnStack <= 15, "Stack is too deep."); | ||||||
| 	m_context << eth::dupInstruction(retSizeOnStack + 1); | 	m_context << eth::dupInstruction(retSizeOnStack + 1); | ||||||
| 	m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction); | 	m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction); | ||||||
| } | } | ||||||
| @ -758,7 +783,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) | |||||||
| 		appendTypeMoveToMemory(IntegerType(256)); | 		appendTypeMoveToMemory(IntegerType(256)); | ||||||
| 		m_context << u256(0) << eth::Instruction::SHA3; | 		m_context << u256(0) << eth::Instruction::SHA3; | ||||||
| 		m_context << u256(0); | 		m_context << u256(0); | ||||||
| 		setLValueToStorageItem( _indexAccess); | 		setLValueToStorageItem(_indexAccess); | ||||||
| 	} | 	} | ||||||
| 	else if (baseType.getCategory() == Type::Category::Array) | 	else if (baseType.getCategory() == Type::Category::Array) | ||||||
| 	{ | 	{ | ||||||
| @ -1038,7 +1063,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio | |||||||
| 	else | 	else | ||||||
| 		// send all gas except the amount needed to execute "SUB" and "CALL"
 | 		// send all gas except the amount needed to execute "SUB" and "CALL"
 | ||||||
| 		// @todo this retains too much gas for now, needs to be fine-tuned.
 | 		// @todo this retains too much gas for now, needs to be fine-tuned.
 | ||||||
| 		m_context << u256(50 + (_functionType.valueSet() ? 9000 : 0)) << eth::Instruction::GAS << eth::Instruction::SUB; | 		m_context << u256(50 + (_functionType.valueSet() ? 9000 : 0) + 25000) << eth::Instruction::GAS << eth::Instruction::SUB; | ||||||
| 	m_context << eth::Instruction::CALL; | 	m_context << eth::Instruction::CALL; | ||||||
| 	auto tag = m_context.appendConditionalJump(); | 	auto tag = m_context.appendConditionalJump(); | ||||||
| 	m_context << eth::Instruction::STOP << tag;	// STOP if CALL leaves 0.
 | 	m_context << eth::Instruction::STOP << tag;	// STOP if CALL leaves 0.
 | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								Types.cpp
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Types.cpp
									
									
									
									
									
								
							| @ -1000,15 +1000,26 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal | |||||||
| FunctionType::FunctionType(VariableDeclaration const& _varDecl): | FunctionType::FunctionType(VariableDeclaration const& _varDecl): | ||||||
| 	m_location(Location::External), m_isConstant(true), m_declaration(&_varDecl) | 	m_location(Location::External), m_isConstant(true), m_declaration(&_varDecl) | ||||||
| { | { | ||||||
| 	TypePointers params; | 	TypePointers paramTypes; | ||||||
| 	vector<string> paramNames; | 	vector<string> paramNames; | ||||||
| 	auto returnType = _varDecl.getType(); | 	auto returnType = _varDecl.getType(); | ||||||
| 
 | 
 | ||||||
| 	while (auto mappingType = dynamic_cast<MappingType const*>(returnType.get())) | 	while (true) | ||||||
| 	{ | 	{ | ||||||
| 		params.push_back(mappingType->getKeyType()); | 		if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get())) | ||||||
| 		paramNames.push_back(""); | 		{ | ||||||
| 		returnType = mappingType->getValueType(); | 			paramTypes.push_back(mappingType->getKeyType()); | ||||||
|  | 			paramNames.push_back(""); | ||||||
|  | 			returnType = mappingType->getValueType(); | ||||||
|  | 		} | ||||||
|  | 		else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get())) | ||||||
|  | 		{ | ||||||
|  | 			returnType = arrayType->getBaseType(); | ||||||
|  | 			paramNames.push_back(""); | ||||||
|  | 			paramTypes.push_back(make_shared<IntegerType>(256)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	TypePointers retParams; | 	TypePointers retParams; | ||||||
| @ -1016,7 +1027,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): | |||||||
| 	if (auto structType = dynamic_cast<StructType const*>(returnType.get())) | 	if (auto structType = dynamic_cast<StructType const*>(returnType.get())) | ||||||
| 	{ | 	{ | ||||||
| 		for (auto const& member: structType->getMembers()) | 		for (auto const& member: structType->getMembers()) | ||||||
| 			if (member.type->canLiveOutsideStorage()) | 			if (member.type->getCategory() != Category::Mapping && member.type->getCategory() != Category::Array) | ||||||
| 			{ | 			{ | ||||||
| 				retParamNames.push_back(member.name); | 				retParamNames.push_back(member.name); | ||||||
| 				retParams.push_back(member.type); | 				retParams.push_back(member.type); | ||||||
| @ -1028,7 +1039,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): | |||||||
| 		retParamNames.push_back(""); | 		retParamNames.push_back(""); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	swap(params, m_parameterTypes); | 	swap(paramTypes, m_parameterTypes); | ||||||
| 	swap(paramNames, m_parameterNames); | 	swap(paramNames, m_parameterNames); | ||||||
| 	swap(retParams, m_returnParameterTypes); | 	swap(retParams, m_returnParameterTypes); | ||||||
| 	swap(retParamNames, m_returnParameterNames); | 	swap(retParamNames, m_returnParameterNames); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user