mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #14490 from ethereum/purge-using-namespace-std-from-libsolidity-codegen
Purge using namespace std from libsolidity/codegen
This commit is contained in:
		
						commit
						f085572e24
					
				| @ -30,12 +30,11 @@ | |||||||
| 
 | 
 | ||||||
| #include <boost/algorithm/string/join.hpp> | #include <boost/algorithm/string/join.hpp> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::tupleEncoder( | std::string ABIFunctions::tupleEncoder( | ||||||
| 	TypePointers const& _givenTypes, | 	TypePointers const& _givenTypes, | ||||||
| 	TypePointers _targetTypes, | 	TypePointers _targetTypes, | ||||||
| 	bool _encodeAsLibraryTypes, | 	bool _encodeAsLibraryTypes, | ||||||
| @ -56,7 +55,7 @@ string ABIFunctions::tupleEncoder( | |||||||
| 		solAssert(t, ""); | 		solAssert(t, ""); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string functionName = string("abi_encode_tuple_"); | 	std::string functionName = std::string("abi_encode_tuple_"); | ||||||
| 	for (auto const& t: _givenTypes) | 	for (auto const& t: _givenTypes) | ||||||
| 		functionName += t->identifier() + "_"; | 		functionName += t->identifier() + "_"; | ||||||
| 	functionName += "_to_"; | 	functionName += "_to_"; | ||||||
| @ -76,8 +75,8 @@ string ABIFunctions::tupleEncoder( | |||||||
| 		)"); | 		)"); | ||||||
| 		templ("functionName", functionName); | 		templ("functionName", functionName); | ||||||
| 		size_t const headSize_ = headSize(_targetTypes); | 		size_t const headSize_ = headSize(_targetTypes); | ||||||
| 		templ("headSize", to_string(headSize_)); | 		templ("headSize", std::to_string(headSize_)); | ||||||
| 		string encodeElements; | 		std::string encodeElements; | ||||||
| 		size_t headPos = 0; | 		size_t headPos = 0; | ||||||
| 		size_t stackPos = 0; | 		size_t stackPos = 0; | ||||||
| 		for (size_t i = 0; i < _givenTypes.size(); ++i) | 		for (size_t i = 0; i < _givenTypes.size(); ++i) | ||||||
| @ -88,24 +87,24 @@ string ABIFunctions::tupleEncoder( | |||||||
| 			bool dynamic = _targetTypes[i]->isDynamicallyEncoded(); | 			bool dynamic = _targetTypes[i]->isDynamicallyEncoded(); | ||||||
| 			Whiskers elementTempl( | 			Whiskers elementTempl( | ||||||
| 				dynamic ? | 				dynamic ? | ||||||
| 				string(R"( | 				std::string(R"( | ||||||
| 					mstore(add(headStart, <pos>), sub(tail, headStart)) | 					mstore(add(headStart, <pos>), sub(tail, headStart)) | ||||||
| 					tail := <abiEncode>(<values> tail) | 					tail := <abiEncode>(<values> tail) | ||||||
| 				)") : | 				)") : | ||||||
| 				string(R"( | 				std::string(R"( | ||||||
| 					<abiEncode>(<values> add(headStart, <pos>)) | 					<abiEncode>(<values> add(headStart, <pos>)) | ||||||
| 				)") | 				)") | ||||||
| 			); | 			); | ||||||
| 			string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack); | 			std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack); | ||||||
| 			elementTempl("values", values.empty() ? "" : values + ", "); | 			elementTempl("values", values.empty() ? "" : values + ", "); | ||||||
| 			elementTempl("pos", to_string(headPos)); | 			elementTempl("pos", std::to_string(headPos)); | ||||||
| 			elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options)); | 			elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options)); | ||||||
| 			encodeElements += elementTempl.render(); | 			encodeElements += elementTempl.render(); | ||||||
| 			headPos += _targetTypes[i]->calldataHeadSize(); | 			headPos += _targetTypes[i]->calldataHeadSize(); | ||||||
| 			stackPos += sizeOnStack; | 			stackPos += sizeOnStack; | ||||||
| 		} | 		} | ||||||
| 		solAssert(headPos == headSize_, ""); | 		solAssert(headPos == headSize_, ""); | ||||||
| 		string valueParams = | 		std::string valueParams = | ||||||
| 			_reversed ? | 			_reversed ? | ||||||
| 			suffixedVariableNameList("value", stackPos, 0) : | 			suffixedVariableNameList("value", stackPos, 0) : | ||||||
| 			suffixedVariableNameList("value", 0, stackPos); | 			suffixedVariableNameList("value", 0, stackPos); | ||||||
| @ -116,7 +115,7 @@ string ABIFunctions::tupleEncoder( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::tupleEncoderPacked( | std::string ABIFunctions::tupleEncoderPacked( | ||||||
| 	TypePointers const& _givenTypes, | 	TypePointers const& _givenTypes, | ||||||
| 	TypePointers _targetTypes, | 	TypePointers _targetTypes, | ||||||
| 	bool _reversed | 	bool _reversed | ||||||
| @ -135,7 +134,7 @@ string ABIFunctions::tupleEncoderPacked( | |||||||
| 		solAssert(t, ""); | 		solAssert(t, ""); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string functionName = string("abi_encode_tuple_packed_"); | 	std::string functionName = std::string("abi_encode_tuple_packed_"); | ||||||
| 	for (auto const& t: _givenTypes) | 	for (auto const& t: _givenTypes) | ||||||
| 		functionName += t->identifier() + "_"; | 		functionName += t->identifier() + "_"; | ||||||
| 	functionName += "_to_"; | 	functionName += "_to_"; | ||||||
| @ -154,7 +153,7 @@ string ABIFunctions::tupleEncoderPacked( | |||||||
| 			} | 			} | ||||||
| 		)"); | 		)"); | ||||||
| 		templ("functionName", functionName); | 		templ("functionName", functionName); | ||||||
| 		string encodeElements; | 		std::string encodeElements; | ||||||
| 		size_t stackPos = 0; | 		size_t stackPos = 0; | ||||||
| 		for (size_t i = 0; i < _givenTypes.size(); ++i) | 		for (size_t i = 0; i < _givenTypes.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| @ -164,23 +163,23 @@ string ABIFunctions::tupleEncoderPacked( | |||||||
| 			bool dynamic = _targetTypes[i]->isDynamicallyEncoded(); | 			bool dynamic = _targetTypes[i]->isDynamicallyEncoded(); | ||||||
| 			Whiskers elementTempl( | 			Whiskers elementTempl( | ||||||
| 				dynamic ? | 				dynamic ? | ||||||
| 				string(R"( | 				std::string(R"( | ||||||
| 					pos := <abiEncode>(<values> pos) | 					pos := <abiEncode>(<values> pos) | ||||||
| 				)") : | 				)") : | ||||||
| 				string(R"( | 				std::string(R"( | ||||||
| 					<abiEncode>(<values> pos) | 					<abiEncode>(<values> pos) | ||||||
| 					pos := add(pos, <calldataEncodedSize>) | 					pos := add(pos, <calldataEncodedSize>) | ||||||
| 				)") | 				)") | ||||||
| 			); | 			); | ||||||
| 			string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack); | 			std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack); | ||||||
| 			elementTempl("values", values.empty() ? "" : values + ", "); | 			elementTempl("values", values.empty() ? "" : values + ", "); | ||||||
| 			if (!dynamic) | 			if (!dynamic) | ||||||
| 				elementTempl("calldataEncodedSize", to_string(_targetTypes[i]->calldataEncodedSize(false))); | 				elementTempl("calldataEncodedSize", std::to_string(_targetTypes[i]->calldataEncodedSize(false))); | ||||||
| 			elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options)); | 			elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options)); | ||||||
| 			encodeElements += elementTempl.render(); | 			encodeElements += elementTempl.render(); | ||||||
| 			stackPos += sizeOnStack; | 			stackPos += sizeOnStack; | ||||||
| 		} | 		} | ||||||
| 		string valueParams = | 		std::string valueParams = | ||||||
| 			_reversed ? | 			_reversed ? | ||||||
| 			suffixedVariableNameList("value", stackPos, 0) : | 			suffixedVariableNameList("value", stackPos, 0) : | ||||||
| 			suffixedVariableNameList("value", 0, stackPos); | 			suffixedVariableNameList("value", 0, stackPos); | ||||||
| @ -190,9 +189,9 @@ string ABIFunctions::tupleEncoderPacked( | |||||||
| 		return templ.render(); | 		return templ.render(); | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | ||||||
| { | { | ||||||
| 	string functionName = string("abi_decode_tuple_"); | 	std::string functionName = std::string("abi_decode_tuple_"); | ||||||
| 	for (auto const& t: _types) | 	for (auto const& t: _types) | ||||||
| 		functionName += t->identifier(); | 		functionName += t->identifier(); | ||||||
| 	if (_fromMemory) | 	if (_fromMemory) | ||||||
| @ -211,10 +210,10 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | |||||||
| 		)"); | 		)"); | ||||||
| 		templ("functionName", functionName); | 		templ("functionName", functionName); | ||||||
| 		templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short")); | 		templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short")); | ||||||
| 		templ("minimumSize", to_string(headSize(decodingTypes))); | 		templ("minimumSize", std::to_string(headSize(decodingTypes))); | ||||||
| 
 | 
 | ||||||
| 		string decodeElements; | 		std::string decodeElements; | ||||||
| 		vector<string> valueReturnParams; | 		std::vector<std::string> valueReturnParams; | ||||||
| 		size_t headPos = 0; | 		size_t headPos = 0; | ||||||
| 		size_t stackPos = 0; | 		size_t stackPos = 0; | ||||||
| 		for (size_t i = 0; i < _types.size(); ++i) | 		for (size_t i = 0; i < _types.size(); ++i) | ||||||
| @ -224,11 +223,11 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | |||||||
| 			size_t sizeOnStack = _types[i]->sizeOnStack(); | 			size_t sizeOnStack = _types[i]->sizeOnStack(); | ||||||
| 			solAssert(sizeOnStack == decodingTypes[i]->sizeOnStack(), ""); | 			solAssert(sizeOnStack == decodingTypes[i]->sizeOnStack(), ""); | ||||||
| 			solAssert(sizeOnStack > 0, ""); | 			solAssert(sizeOnStack > 0, ""); | ||||||
| 			vector<string> valueNamesLocal; | 			std::vector<std::string> valueNamesLocal; | ||||||
| 			for (size_t j = 0; j < sizeOnStack; j++) | 			for (size_t j = 0; j < sizeOnStack; j++) | ||||||
| 			{ | 			{ | ||||||
| 				valueNamesLocal.emplace_back("value" + to_string(stackPos)); | 				valueNamesLocal.emplace_back("value" + std::to_string(stackPos)); | ||||||
| 				valueReturnParams.emplace_back("value" + to_string(stackPos)); | 				valueReturnParams.emplace_back("value" + std::to_string(stackPos)); | ||||||
| 				stackPos++; | 				stackPos++; | ||||||
| 			} | 			} | ||||||
| 			Whiskers elementTempl(R"( | 			Whiskers elementTempl(R"( | ||||||
| @ -247,7 +246,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | |||||||
| 			elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset")); | 			elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset")); | ||||||
| 			elementTempl("load", _fromMemory ? "mload" : "calldataload"); | 			elementTempl("load", _fromMemory ? "mload" : "calldataload"); | ||||||
| 			elementTempl("values", boost::algorithm::join(valueNamesLocal, ", ")); | 			elementTempl("values", boost::algorithm::join(valueNamesLocal, ", ")); | ||||||
| 			elementTempl("pos", to_string(headPos)); | 			elementTempl("pos", std::to_string(headPos)); | ||||||
| 			elementTempl("abiDecode", abiDecodingFunction(*_types[i], _fromMemory, true)); | 			elementTempl("abiDecode", abiDecodingFunction(*_types[i], _fromMemory, true)); | ||||||
| 			decodeElements += elementTempl.render(); | 			decodeElements += elementTempl.render(); | ||||||
| 			headPos += decodingTypes[i]->calldataHeadSize(); | 			headPos += decodingTypes[i]->calldataHeadSize(); | ||||||
| @ -260,9 +259,9 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const | std::string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const | ||||||
| { | { | ||||||
| 	string suffix; | 	std::string suffix; | ||||||
| 	if (!padded) | 	if (!padded) | ||||||
| 		suffix += "_nonPadded"; | 		suffix += "_nonPadded"; | ||||||
| 	if (dynamicInplace) | 	if (dynamicInplace) | ||||||
| @ -274,7 +273,7 @@ string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const | |||||||
| 	return suffix; | 	return suffix; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunction( | std::string ABIFunctions::abiEncodingFunction( | ||||||
| 	Type const& _from, | 	Type const& _from, | ||||||
| 	Type const& _to, | 	Type const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| @ -349,7 +348,7 @@ string ABIFunctions::abiEncodingFunction( | |||||||
| 	solAssert(_from.sizeOnStack() == 1, ""); | 	solAssert(_from.sizeOnStack() == 1, ""); | ||||||
| 	solAssert(to.isValueType(), ""); | 	solAssert(to.isValueType(), ""); | ||||||
| 	solAssert(to.calldataEncodedSize() == 32, ""); | 	solAssert(to.calldataEncodedSize() == 32, ""); | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -376,7 +375,7 @@ string ABIFunctions::abiEncodingFunction( | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			string cleanupConvert; | 			std::string cleanupConvert; | ||||||
| 			if (_from == to) | 			if (_from == to) | ||||||
| 				cleanupConvert = m_utils.cleanupFunction(_from) + "(value)"; | 				cleanupConvert = m_utils.cleanupFunction(_from) + "(value)"; | ||||||
| 			else | 			else | ||||||
| @ -389,21 +388,21 @@ string ABIFunctions::abiEncodingFunction( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction( | std::string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction( | ||||||
| 	Type const& _givenType, | 	Type const& _givenType, | ||||||
| 	Type const& _targetType, | 	Type const& _targetType, | ||||||
| 	ABIFunctions::EncodingOptions const& _options | 	ABIFunctions::EncodingOptions const& _options | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encodeUpdatedPos_" + | 		"abi_encodeUpdatedPos_" + | ||||||
| 		_givenType.identifier() + | 		_givenType.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| 		_targetType.identifier() + | 		_targetType.identifier() + | ||||||
| 		_options.toFunctionNameSuffix(); | 		_options.toFunctionNameSuffix(); | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| 		string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options)); | 		std::string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options)); | ||||||
| 		string encoder = abiEncodingFunction(_givenType, _targetType, _options); | 		std::string encoder = abiEncodingFunction(_givenType, _targetType, _options); | ||||||
| 		Type const* targetEncoding = _targetType.fullEncodingType(_options.encodeAsLibraryTypes, true, false); | 		Type const* targetEncoding = _targetType.fullEncodingType(_options.encodeAsLibraryTypes, true, false); | ||||||
| 		solAssert(targetEncoding, ""); | 		solAssert(targetEncoding, ""); | ||||||
| 		if (targetEncoding->isDynamicallyEncoded()) | 		if (targetEncoding->isDynamicallyEncoded()) | ||||||
| @ -435,7 +434,7 @@ string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( | std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( | ||||||
| 	Type const& _from, | 	Type const& _from, | ||||||
| 	Type const& _to, | 	Type const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| @ -461,7 +460,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( | |||||||
| 		"" | 		"" | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -522,13 +521,13 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionSimpleArray( | std::string ABIFunctions::abiEncodingFunctionSimpleArray( | ||||||
| 	ArrayType const& _from, | 	ArrayType const& _from, | ||||||
| 	ArrayType const& _to, | 	ArrayType const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -548,7 +547,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( | |||||||
| 		EncodingOptions subOptions(_options); | 		EncodingOptions subOptions(_options); | ||||||
| 		subOptions.encodeFunctionFromStack = false; | 		subOptions.encodeFunctionFromStack = false; | ||||||
| 		subOptions.padded = true; | 		subOptions.padded = true; | ||||||
| 		string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions)); | 		std::string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions)); | ||||||
| 		Whiskers templ( | 		Whiskers templ( | ||||||
| 			usesTail ? | 			usesTail ? | ||||||
| 			R"( | 			R"( | ||||||
| @ -632,13 +631,13 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionMemoryByteArray( | std::string ABIFunctions::abiEncodingFunctionMemoryByteArray( | ||||||
| 	ArrayType const& _from, | 	ArrayType const& _from, | ||||||
| 	ArrayType const& _to, | 	ArrayType const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -669,13 +668,13 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionCompactStorageArray( | std::string ABIFunctions::abiEncodingFunctionCompactStorageArray( | ||||||
| 	ArrayType const& _from, | 	ArrayType const& _from, | ||||||
| 	ArrayType const& _to, | 	ArrayType const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -791,13 +790,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( | |||||||
| 				templ("useSpill", "1"); | 				templ("useSpill", "1"); | ||||||
| 			else | 			else | ||||||
| 				templ("useSpill", "0"); | 				templ("useSpill", "0"); | ||||||
| 			templ("itemsPerSlot", to_string(itemsPerSlot)); | 			templ("itemsPerSlot", std::to_string(itemsPerSlot)); | ||||||
| 			templ("stride", toCompactHexWithPrefix(_to.calldataStride())); | 			templ("stride", toCompactHexWithPrefix(_to.calldataStride())); | ||||||
| 
 | 
 | ||||||
| 			EncodingOptions subOptions(_options); | 			EncodingOptions subOptions(_options); | ||||||
| 			subOptions.encodeFunctionFromStack = false; | 			subOptions.encodeFunctionFromStack = false; | ||||||
| 			subOptions.padded = true; | 			subOptions.padded = true; | ||||||
| 			string encodeToMemoryFun = abiEncodingFunction( | 			std::string encodeToMemoryFun = abiEncodingFunction( | ||||||
| 				*_from.baseType(), | 				*_from.baseType(), | ||||||
| 				*_to.baseType(), | 				*_to.baseType(), | ||||||
| 				subOptions | 				subOptions | ||||||
| @ -820,13 +819,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionStruct( | std::string ABIFunctions::abiEncodingFunctionStruct( | ||||||
| 	StructType const& _from, | 	StructType const& _from, | ||||||
| 	StructType const& _to, | 	StructType const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -867,7 +866,7 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 		templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : ""); | 		templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : ""); | ||||||
| 		u256 previousSlotOffset(-1); | 		u256 previousSlotOffset(-1); | ||||||
| 		u256 encodingOffset = 0; | 		u256 encodingOffset = 0; | ||||||
| 		vector<map<string, string>> members; | 		std::vector<std::map<std::string, std::string>> members; | ||||||
| 		for (auto const& member: _to.members(nullptr)) | 		for (auto const& member: _to.members(nullptr)) | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(member.type, ""); | 			solAssert(member.type, ""); | ||||||
| @ -890,7 +889,7 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 					solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), ""); | 					solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), ""); | ||||||
| 					u256 storageSlotOffset; | 					u256 storageSlotOffset; | ||||||
| 					size_t intraSlotOffset; | 					size_t intraSlotOffset; | ||||||
| 					tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name); | 					std::tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name); | ||||||
| 					if (memberTypeFrom->isValueType()) | 					if (memberTypeFrom->isValueType()) | ||||||
| 					{ | 					{ | ||||||
| 						if (storageSlotOffset != previousSlotOffset) | 						if (storageSlotOffset != previousSlotOffset) | ||||||
| @ -910,13 +909,13 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 				} | 				} | ||||||
| 				case DataLocation::Memory: | 				case DataLocation::Memory: | ||||||
| 				{ | 				{ | ||||||
| 					string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name)); | 					std::string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name)); | ||||||
| 					members.back()["retrieveValue"] = "mload(add(value, " + sourceOffset + "))"; | 					members.back()["retrieveValue"] = "mload(add(value, " + sourceOffset + "))"; | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 				case DataLocation::CallData: | 				case DataLocation::CallData: | ||||||
| 				{ | 				{ | ||||||
| 					string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name)); | 					std::string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name)); | ||||||
| 					members.back()["retrieveValue"] = calldataAccessFunction(*memberTypeFrom) + "(value, add(value, " + sourceOffset + "))"; | 					members.back()["retrieveValue"] = calldataAccessFunction(*memberTypeFrom) + "(value, add(value, " + sourceOffset + "))"; | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| @ -929,10 +928,10 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 			// Like with arrays, struct members are always padded.
 | 			// Like with arrays, struct members are always padded.
 | ||||||
| 			subOptions.padded = true; | 			subOptions.padded = true; | ||||||
| 
 | 
 | ||||||
| 			string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions)); | 			std::string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions)); | ||||||
| 			members.back()["memberValues"] = memberValues; | 			members.back()["memberValues"] = memberValues; | ||||||
| 
 | 
 | ||||||
| 			string encode; | 			std::string encode; | ||||||
| 			if (_options.dynamicInplace) | 			if (_options.dynamicInplace) | ||||||
| 				encode = Whiskers{"pos := <encode>(<memberValues>, pos)"} | 				encode = Whiskers{"pos := <encode>(<memberValues>, pos)"} | ||||||
| 					("encode", abiEncodeAndReturnUpdatedPosFunction(*memberTypeFrom, *memberTypeTo, subOptions)) | 					("encode", abiEncodeAndReturnUpdatedPosFunction(*memberTypeFrom, *memberTypeTo, subOptions)) | ||||||
| @ -942,7 +941,7 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 			{ | 			{ | ||||||
| 				Whiskers encodeTempl( | 				Whiskers encodeTempl( | ||||||
| 					dynamicMember ? | 					dynamicMember ? | ||||||
| 					string(R"( | 					std::string(R"( | ||||||
| 						mstore(add(pos, <encodingOffset>), sub(tail, pos)) | 						mstore(add(pos, <encodingOffset>), sub(tail, pos)) | ||||||
| 						tail := <abiEncode>(<memberValues>, tail) | 						tail := <abiEncode>(<memberValues>, tail) | ||||||
| 					)") : | 					)") : | ||||||
| @ -966,7 +965,7 @@ string ABIFunctions::abiEncodingFunctionStruct( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionStringLiteral( | std::string ABIFunctions::abiEncodingFunctionStringLiteral( | ||||||
| 	Type const& _from, | 	Type const& _from, | ||||||
| 	Type const& _to, | 	Type const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| @ -974,7 +973,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | |||||||
| { | { | ||||||
| 	solAssert(_from.category() == Type::Category::StringLiteral, ""); | 	solAssert(_from.category() == Type::Category::StringLiteral, ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -982,7 +981,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | |||||||
| 		_options.toFunctionNameSuffix(); | 		_options.toFunctionNameSuffix(); | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| 		auto const& strType = dynamic_cast<StringLiteralType const&>(_from); | 		auto const& strType = dynamic_cast<StringLiteralType const&>(_from); | ||||||
| 		string const& value = strType.value(); | 		std::string const& value = strType.value(); | ||||||
| 		solAssert(_from.sizeOnStack() == 0, ""); | 		solAssert(_from.sizeOnStack() == 0, ""); | ||||||
| 
 | 
 | ||||||
| 		if (_to.isDynamicallySized()) | 		if (_to.isDynamicallySized()) | ||||||
| @ -998,12 +997,12 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | |||||||
| 			templ("functionName", functionName); | 			templ("functionName", functionName); | ||||||
| 
 | 
 | ||||||
| 			// TODO this can make use of CODECOPY for large strings once we have that in Yul
 | 			// TODO this can make use of CODECOPY for large strings once we have that in Yul
 | ||||||
| 			templ("length", to_string(value.size())); | 			templ("length", std::to_string(value.size())); | ||||||
| 			templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options)); | 			templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options)); | ||||||
| 			if (_options.padded) | 			if (_options.padded) | ||||||
| 				templ("overallSize", to_string(((value.size() + 31) / 32) * 32)); | 				templ("overallSize", std::to_string(((value.size() + 31) / 32) * 32)); | ||||||
| 			else | 			else | ||||||
| 				templ("overallSize", to_string(value.size())); | 				templ("overallSize", std::to_string(value.size())); | ||||||
| 			templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value)); | 			templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value)); | ||||||
| 			return templ.render(); | 			return templ.render(); | ||||||
| 		} | 		} | ||||||
| @ -1023,7 +1022,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiEncodingFunctionFunctionType( | std::string ABIFunctions::abiEncodingFunctionFunctionType( | ||||||
| 	FunctionType const& _from, | 	FunctionType const& _from, | ||||||
| 	Type const& _to, | 	Type const& _to, | ||||||
| 	EncodingOptions const& _options | 	EncodingOptions const& _options | ||||||
| @ -1036,7 +1035,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( | |||||||
| 		"Invalid function type conversion requested" | 		"Invalid function type conversion requested" | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_encode_" + | 		"abi_encode_" + | ||||||
| 		_from.identifier() + | 		_from.identifier() + | ||||||
| 		"_to_" + | 		"_to_" + | ||||||
| @ -1069,7 +1068,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( | |||||||
| 		}); | 		}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack) | std::string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack) | ||||||
| { | { | ||||||
| 	// The decoding function has to perform bounds checks unless it decodes a value type.
 | 	// The decoding function has to perform bounds checks unless it decodes a value type.
 | ||||||
| 	// Conversely, bounds checks have to be performed before the decoding function
 | 	// Conversely, bounds checks have to be performed before the decoding function
 | ||||||
| @ -1104,7 +1103,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo | |||||||
| 		return abiDecodingFunctionValueType(_type, _fromMemory); | 		return abiDecodingFunctionValueType(_type, _fromMemory); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory) | std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory) | ||||||
| { | { | ||||||
| 	Type const* decodingType = _type.decodingType(); | 	Type const* decodingType = _type.decodingType(); | ||||||
| 	solAssert(decodingType, ""); | 	solAssert(decodingType, ""); | ||||||
| @ -1113,7 +1112,7 @@ string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromM | |||||||
| 	solAssert(!decodingType->isDynamicallyEncoded(), ""); | 	solAssert(!decodingType->isDynamicallyEncoded(), ""); | ||||||
| 	solAssert(decodingType->calldataEncodedSize() == 32, ""); | 	solAssert(decodingType->calldataEncodedSize() == 32, ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : ""); | 		(_fromMemory ? "_fromMemory" : ""); | ||||||
| @ -1134,17 +1133,17 @@ string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromM | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory) | std::string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : ""); | 		(_fromMemory ? "_fromMemory" : ""); | ||||||
| 
 | 
 | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| 		string load = _fromMemory ? "mload" : "calldataload"; | 		std::string load = _fromMemory ? "mload" : "calldataload"; | ||||||
| 		Whiskers templ( | 		Whiskers templ( | ||||||
| 			R"( | 			R"( | ||||||
| 				// <readableTypeName>
 | 				// <readableTypeName>
 | ||||||
| @ -1166,14 +1165,14 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory) | std::string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | ||||||
| 	if (_type.isByteArrayOrString()) | 	if (_type.isByteArrayOrString()) | ||||||
| 		return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory); | 		return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory); | ||||||
| 	solAssert(_type.calldataStride() > 0, ""); | 	solAssert(_type.calldataStride() > 0, ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_available_length_" + | 		"abi_decode_available_length_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : ""); | 		(_fromMemory ? "_fromMemory" : ""); | ||||||
| @ -1224,7 +1223,7 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) | std::string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | ||||||
| 	if (!_type.isDynamicallySized()) | 	if (!_type.isDynamicallySized()) | ||||||
| @ -1232,7 +1231,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) | |||||||
| 	solAssert(_type.calldataStride() > 0, ""); | 	solAssert(_type.calldataStride() > 0, ""); | ||||||
| 	solAssert(_type.calldataStride() < u256("0xffffffffffffffff"), ""); | 	solAssert(_type.calldataStride() < u256("0xffffffffffffffff"), ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier(); | 		_type.identifier(); | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| @ -1273,12 +1272,12 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory) | std::string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | 	solAssert(_type.dataStoredIn(DataLocation::Memory), ""); | ||||||
| 	solAssert(_type.isByteArrayOrString(), ""); | 	solAssert(_type.isByteArrayOrString(), ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_available_length_" + | 		"abi_decode_available_length_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : ""); | 		(_fromMemory ? "_fromMemory" : ""); | ||||||
| @ -1302,10 +1301,10 @@ string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type) | std::string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier(); | 		_type.identifier(); | ||||||
| 
 | 
 | ||||||
| @ -1321,15 +1320,15 @@ string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type) | |||||||
| 		w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short")); | 		w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short")); | ||||||
| 		w("functionName", functionName); | 		w("functionName", functionName); | ||||||
| 		w("readableTypeName", _type.toString(true)); | 		w("readableTypeName", _type.toString(true)); | ||||||
| 		w("minimumSize", to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true))); | 		w("minimumSize", std::to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true))); | ||||||
| 		return w.render(); | 		return w.render(); | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory) | std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory) | ||||||
| { | { | ||||||
| 	solAssert(!_type.dataStoredIn(DataLocation::CallData), ""); | 	solAssert(!_type.dataStoredIn(DataLocation::CallData), ""); | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : ""); | 		(_fromMemory ? "_fromMemory" : ""); | ||||||
| @ -1356,7 +1355,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr | |||||||
| 		solAssert(_type.memoryDataSize() < u256("0xffffffffffffffff"), ""); | 		solAssert(_type.memoryDataSize() < u256("0xffffffffffffffff"), ""); | ||||||
| 		templ("memorySize", toCompactHexWithPrefix(_type.memoryDataSize())); | 		templ("memorySize", toCompactHexWithPrefix(_type.memoryDataSize())); | ||||||
| 		size_t headPos = 0; | 		size_t headPos = 0; | ||||||
| 		vector<map<string, string>> members; | 		std::vector<std::map<std::string, std::string>> members; | ||||||
| 		for (auto const& member: _type.members(nullptr)) | 		for (auto const& member: _type.members(nullptr)) | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(member.type, ""); | 			solAssert(member.type, ""); | ||||||
| @ -1376,7 +1375,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr | |||||||
| 			// TODO add test
 | 			// TODO add test
 | ||||||
| 			memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset")); | 			memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset")); | ||||||
| 			memberTempl("load", _fromMemory ? "mload" : "calldataload"); | 			memberTempl("load", _fromMemory ? "mload" : "calldataload"); | ||||||
| 			memberTempl("pos", to_string(headPos)); | 			memberTempl("pos", std::to_string(headPos)); | ||||||
| 			memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name))); | 			memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name))); | ||||||
| 			memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false)); | 			memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false)); | ||||||
| 
 | 
 | ||||||
| @ -1391,11 +1390,11 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack) | std::string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack) | ||||||
| { | { | ||||||
| 	solAssert(_type.kind() == FunctionType::Kind::External, ""); | 	solAssert(_type.kind() == FunctionType::Kind::External, ""); | ||||||
| 
 | 
 | ||||||
| 	string functionName = | 	std::string functionName = | ||||||
| 		"abi_decode_" + | 		"abi_decode_" + | ||||||
| 		_type.identifier() + | 		_type.identifier() + | ||||||
| 		(_fromMemory ? "_fromMemory" : "") + | 		(_fromMemory ? "_fromMemory" : "") + | ||||||
| @ -1430,10 +1429,10 @@ string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::calldataAccessFunction(Type const& _type) | std::string ABIFunctions::calldataAccessFunction(Type const& _type) | ||||||
| { | { | ||||||
| 	solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), ""); | 	solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), ""); | ||||||
| 	string functionName = "calldata_access_" + _type.identifier(); | 	std::string functionName = "calldata_access_" + _type.identifier(); | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| 		if (_type.isDynamicallyEncoded()) | 		if (_type.isDynamicallyEncoded()) | ||||||
| 		{ | 		{ | ||||||
| @ -1477,7 +1476,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type) | |||||||
| 		} | 		} | ||||||
| 		else if (_type.isValueType()) | 		else if (_type.isValueType()) | ||||||
| 		{ | 		{ | ||||||
| 			string decodingFunction; | 			std::string decodingFunction; | ||||||
| 			if (auto const* functionType = dynamic_cast<FunctionType const*>(&_type)) | 			if (auto const* functionType = dynamic_cast<FunctionType const*>(&_type)) | ||||||
| 				decodingFunction = abiDecodingFunctionFunctionType(*functionType, false, false); | 				decodingFunction = abiDecodingFunctionFunctionType(*functionType, false, false); | ||||||
| 			else | 			else | ||||||
| @ -1510,9 +1509,9 @@ string ABIFunctions::calldataAccessFunction(Type const& _type) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options) | std::string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options) | ||||||
| { | { | ||||||
| 	string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix(); | 	std::string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix(); | ||||||
| 	return createFunction(functionName, [&]() { | 	return createFunction(functionName, [&]() { | ||||||
| 		if (_type.isDynamicallySized() && !_options.dynamicInplace) | 		if (_type.isDynamicallySized() && !_options.dynamicInplace) | ||||||
| 			return Whiskers(R"( | 			return Whiskers(R"( | ||||||
| @ -1534,7 +1533,7 @@ string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string ABIFunctions::createFunction(string const& _name, function<string ()> const& _creator) | std::string ABIFunctions::createFunction(std::string const& _name, std::function<std::string ()> const& _creator) | ||||||
| { | { | ||||||
| 	return m_functionCollector.createFunction(_name, _creator); | 	return m_functionCollector.createFunction(_name, _creator); | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,7 +36,6 @@ | |||||||
| #include <libevmasm/Instruction.h> | #include <libevmasm/Instruction.h> | ||||||
| #include <liblangutil/Exceptions.h> | #include <liblangutil/Exceptions.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -314,7 +313,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord | |||||||
| 		if (!_sourceType.isByteArrayOrString()) | 		if (!_sourceType.isByteArrayOrString()) | ||||||
| 			convertLengthToSize(_sourceType); | 			convertLengthToSize(_sourceType); | ||||||
| 
 | 
 | ||||||
| 		string routine = "calldatacopy(target, source, len)\n"; | 		std::string routine = "calldatacopy(target, source, len)\n"; | ||||||
| 		if (_padToWordBoundaries) | 		if (_padToWordBoundaries) | ||||||
| 			routine += R"( | 			routine += R"( | ||||||
| 				// Set padding suffix to zero
 | 				// Set padding suffix to zero
 | ||||||
| @ -890,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const | |||||||
| 			sstore(ref, slot_value) | 			sstore(ref, slot_value) | ||||||
| 		})"); | 		})"); | ||||||
| 		code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()); | 		code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()); | ||||||
| 		code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop))); | 		code("emptyArrayPop", std::to_string(unsigned(util::PanicCode::EmptyArrayPop))); | ||||||
| 		m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"}); | 		m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"}); | ||||||
| 		m_context << Instruction::POP << Instruction::POP << Instruction::POP; | 		m_context << Instruction::POP << Instruction::POP << Instruction::POP; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -26,13 +26,12 @@ | |||||||
| #include <libsolidity/codegen/ContractCompiler.h> | #include <libsolidity/codegen/ContractCompiler.h> | ||||||
| #include <libevmasm/Assembly.h> | #include <libevmasm/Assembly.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| 
 | 
 | ||||||
| void Compiler::compileContract( | void Compiler::compileContract( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers, | 	std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers, | ||||||
| 	bytes const& _metadata | 	bytes const& _metadata | ||||||
| ) | ) | ||||||
| { | { | ||||||
|  | |||||||
| @ -55,7 +55,6 @@ | |||||||
| #undef SOL_OUTPUT_ASM | #undef SOL_OUTPUT_ASM | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| @ -68,7 +67,7 @@ void CompilerContext::addStateVariable( | |||||||
| 	unsigned _byteOffset | 	unsigned _byteOffset | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	m_stateVariables[&_declaration] = make_pair(_storageOffset, _byteOffset); | 	m_stateVariables[&_declaration] = std::make_pair(_storageOffset, _byteOffset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CompilerContext::addImmutable(VariableDeclaration const& _variable) | void CompilerContext::addImmutable(VariableDeclaration const& _variable) | ||||||
| @ -88,14 +87,14 @@ size_t CompilerContext::immutableMemoryOffset(VariableDeclaration const& _variab | |||||||
| 	return m_immutableVariables.at(&_variable); | 	return m_immutableVariables.at(&_variable); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| vector<string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable) | std::vector<std::string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable) | ||||||
| { | { | ||||||
| 	string baseName = to_string(_variable.id()); | 	std::string baseName = std::to_string(_variable.id()); | ||||||
| 	solAssert(_variable.annotation().type->sizeOnStack() > 0, ""); | 	solAssert(_variable.annotation().type->sizeOnStack() > 0, ""); | ||||||
| 	if (_variable.annotation().type->sizeOnStack() == 1) | 	if (_variable.annotation().type->sizeOnStack() == 1) | ||||||
| 		return {baseName}; | 		return {baseName}; | ||||||
| 	vector<string> names; | 	std::vector<std::string> names; | ||||||
| 	auto collectSlotNames = [&](string const& _baseName, Type const* type, auto const& _recurse) -> void { | 	auto collectSlotNames = [&](std::string const& _baseName, Type const* type, auto const& _recurse) -> void { | ||||||
| 		for (auto const& [slot, type]: type->stackItems()) | 		for (auto const& [slot, type]: type->stackItems()) | ||||||
| 			if (type) | 			if (type) | ||||||
| 				_recurse(_baseName + " " + slot, type, _recurse); | 				_recurse(_baseName + " " + slot, type, _recurse); | ||||||
| @ -121,10 +120,10 @@ void CompilerContext::startFunction(Declaration const& _function) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CompilerContext::callLowLevelFunction( | void CompilerContext::callLowLevelFunction( | ||||||
| 	string const& _name, | 	std::string const& _name, | ||||||
| 	unsigned _inArgs, | 	unsigned _inArgs, | ||||||
| 	unsigned _outArgs, | 	unsigned _outArgs, | ||||||
| 	function<void(CompilerContext&)> const& _generator | 	std::function<void(CompilerContext&)> const& _generator | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	evmasm::AssemblyItem retTag = pushNewTag(); | 	evmasm::AssemblyItem retTag = pushNewTag(); | ||||||
| @ -138,7 +137,7 @@ void CompilerContext::callLowLevelFunction( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CompilerContext::callYulFunction( | void CompilerContext::callYulFunction( | ||||||
| 	string const& _name, | 	std::string const& _name, | ||||||
| 	unsigned _inArgs, | 	unsigned _inArgs, | ||||||
| 	unsigned _outArgs | 	unsigned _outArgs | ||||||
| ) | ) | ||||||
| @ -152,10 +151,10 @@ void CompilerContext::callYulFunction( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag( | evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag( | ||||||
| 	string const& _name, | 	std::string const& _name, | ||||||
| 	unsigned _inArgs, | 	unsigned _inArgs, | ||||||
| 	unsigned _outArgs, | 	unsigned _outArgs, | ||||||
| 	function<void(CompilerContext&)> const& _generator | 	std::function<void(CompilerContext&)> const& _generator | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	auto it = m_lowLevelFunctions.find(_name); | 	auto it = m_lowLevelFunctions.find(_name); | ||||||
| @ -174,10 +173,10 @@ void CompilerContext::appendMissingLowLevelFunctions() | |||||||
| { | { | ||||||
| 	while (!m_lowLevelFunctionGenerationQueue.empty()) | 	while (!m_lowLevelFunctionGenerationQueue.empty()) | ||||||
| 	{ | 	{ | ||||||
| 		string name; | 		std::string name; | ||||||
| 		unsigned inArgs; | 		unsigned inArgs; | ||||||
| 		unsigned outArgs; | 		unsigned outArgs; | ||||||
| 		function<void(CompilerContext&)> generator; | 		std::function<void(CompilerContext&)> generator; | ||||||
| 		tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front(); | 		tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front(); | ||||||
| 		m_lowLevelFunctionGenerationQueue.pop(); | 		m_lowLevelFunctionGenerationQueue.pop(); | ||||||
| 
 | 
 | ||||||
| @ -195,7 +194,7 @@ void CompilerContext::appendYulUtilityFunctions(OptimiserSettings const& _optimi | |||||||
| 	solAssert(!m_appendYulUtilityFunctionsRan, "requestedYulFunctions called more than once."); | 	solAssert(!m_appendYulUtilityFunctionsRan, "requestedYulFunctions called more than once."); | ||||||
| 	m_appendYulUtilityFunctionsRan = true; | 	m_appendYulUtilityFunctionsRan = true; | ||||||
| 
 | 
 | ||||||
| 	string code = m_yulFunctionCollector.requestedFunctions(); | 	std::string code = m_yulFunctionCollector.requestedFunctions(); | ||||||
| 	if (!code.empty()) | 	if (!code.empty()) | ||||||
| 	{ | 	{ | ||||||
| 		appendInlineAssembly( | 		appendInlineAssembly( | ||||||
| @ -233,7 +232,7 @@ void CompilerContext::removeVariable(Declaration const& _declaration) | |||||||
| 
 | 
 | ||||||
| void CompilerContext::removeVariablesAboveStackHeight(unsigned _stackHeight) | void CompilerContext::removeVariablesAboveStackHeight(unsigned _stackHeight) | ||||||
| { | { | ||||||
| 	vector<Declaration const*> toRemove; | 	std::vector<Declaration const*> toRemove; | ||||||
| 	for (auto _var: m_localVariables) | 	for (auto _var: m_localVariables) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(!_var.second.empty(), ""); | 		solAssert(!_var.second.empty(), ""); | ||||||
| @ -250,14 +249,14 @@ unsigned CompilerContext::numberOfLocalVariables() const | |||||||
| 	return static_cast<unsigned>(m_localVariables.size()); | 	return static_cast<unsigned>(m_localVariables.size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const | std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const | ||||||
| { | { | ||||||
| 	auto ret = m_otherCompilers.find(&_contract); | 	auto ret = m_otherCompilers.find(&_contract); | ||||||
| 	solAssert(ret != m_otherCompilers.end(), "Compiled contract not found."); | 	solAssert(ret != m_otherCompilers.end(), "Compiled contract not found."); | ||||||
| 	return ret->second->assemblyPtr(); | 	return ret->second->assemblyPtr(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const | std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const | ||||||
| { | { | ||||||
| 	auto ret = m_otherCompilers.find(&_contract); | 	auto ret = m_otherCompilers.find(&_contract); | ||||||
| 	solAssert(ret != m_otherCompilers.end(), "Compiled contract not found."); | 	solAssert(ret != m_otherCompilers.end(), "Compiled contract not found."); | ||||||
| @ -320,7 +319,7 @@ unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const | |||||||
| 	return static_cast<unsigned>(m_asm->deposit()) - _offset - 1; | 	return static_cast<unsigned>(m_asm->deposit()) - _offset - 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const | std::pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const | ||||||
| { | { | ||||||
| 	auto it = m_stateVariables.find(&_declaration); | 	auto it = m_stateVariables.find(&_declaration); | ||||||
| 	solAssert(it != m_stateVariables.end(), "Variable not found in storage."); | 	solAssert(it != m_stateVariables.end(), "Variable not found in storage."); | ||||||
| @ -349,13 +348,13 @@ CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code) | |||||||
| 	return *this; | 	return *this; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CompilerContext& CompilerContext::appendRevert(string const& _message) | CompilerContext& CompilerContext::appendRevert(std::string const& _message) | ||||||
| { | { | ||||||
| 	appendInlineAssembly("{ " + revertReasonIfDebug(_message) + " }"); | 	appendInlineAssembly("{ " + revertReasonIfDebug(_message) + " }"); | ||||||
| 	return *this; | 	return *this; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, string const& _message) | CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, std::string const& _message) | ||||||
| { | { | ||||||
| 	if (_forwardReturnData && m_evmVersion.supportsReturndata()) | 	if (_forwardReturnData && m_evmVersion.supportsReturndata()) | ||||||
| 		appendInlineAssembly(R"({ | 		appendInlineAssembly(R"({ | ||||||
| @ -372,24 +371,24 @@ CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnDat | |||||||
| 
 | 
 | ||||||
| void CompilerContext::resetVisitedNodes(ASTNode const* _node) | void CompilerContext::resetVisitedNodes(ASTNode const* _node) | ||||||
| { | { | ||||||
| 	stack<ASTNode const*> newStack; | 	std::stack<ASTNode const*> newStack; | ||||||
| 	newStack.push(_node); | 	newStack.push(_node); | ||||||
| 	std::swap(m_visitedNodes, newStack); | 	std::swap(m_visitedNodes, newStack); | ||||||
| 	updateSourceLocation(); | 	updateSourceLocation(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CompilerContext::appendInlineAssembly( | void CompilerContext::appendInlineAssembly( | ||||||
| 	string const& _assembly, | 	std::string const& _assembly, | ||||||
| 	vector<string> const& _localVariables, | 	std::vector<std::string> const& _localVariables, | ||||||
| 	set<string> const& _externallyUsedFunctions, | 	std::set<std::string> const& _externallyUsedFunctions, | ||||||
| 	bool _system, | 	bool _system, | ||||||
| 	OptimiserSettings const& _optimiserSettings, | 	OptimiserSettings const& _optimiserSettings, | ||||||
| 	string _sourceName | 	std::string _sourceName | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	unsigned startStackHeight = stackHeight(); | 	unsigned startStackHeight = stackHeight(); | ||||||
| 
 | 
 | ||||||
| 	set<yul::YulString> externallyUsedIdentifiers; | 	std::set<yul::YulString> externallyUsedIdentifiers; | ||||||
| 	for (auto const& fun: _externallyUsedFunctions) | 	for (auto const& fun: _externallyUsedFunctions) | ||||||
| 		externallyUsedIdentifiers.insert(yul::YulString(fun)); | 		externallyUsedIdentifiers.insert(yul::YulString(fun)); | ||||||
| 	for (auto const& var: _localVariables) | 	for (auto const& var: _localVariables) | ||||||
| @ -438,19 +437,19 @@ void CompilerContext::appendInlineAssembly( | |||||||
| 	ErrorReporter errorReporter(errors); | 	ErrorReporter errorReporter(errors); | ||||||
| 	langutil::CharStream charStream(_assembly, _sourceName); | 	langutil::CharStream charStream(_assembly, _sourceName); | ||||||
| 	yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); | 	yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); | ||||||
| 	optional<langutil::SourceLocation> locationOverride; | 	std::optional<langutil::SourceLocation> locationOverride; | ||||||
| 	if (!_system) | 	if (!_system) | ||||||
| 		locationOverride = m_asm->currentSourceLocation(); | 		locationOverride = m_asm->currentSourceLocation(); | ||||||
| 	shared_ptr<yul::Block> parserResult = | 	std::shared_ptr<yul::Block> parserResult = | ||||||
| 		yul::Parser(errorReporter, dialect, std::move(locationOverride)) | 		yul::Parser(errorReporter, dialect, std::move(locationOverride)) | ||||||
| 		.parse(charStream); | 		.parse(charStream); | ||||||
| #ifdef SOL_OUTPUT_ASM | #ifdef SOL_OUTPUT_ASM | ||||||
| 	cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; | 	cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	auto reportError = [&](string const& _context) | 	auto reportError = [&](std::string const& _context) | ||||||
| 	{ | 	{ | ||||||
| 		string message = | 		std::string message = | ||||||
| 			"Error parsing/analyzing inline assembly block:\n" + | 			"Error parsing/analyzing inline assembly block:\n" + | ||||||
| 			_context + "\n" | 			_context + "\n" | ||||||
| 			"------------------ Input: -----------------\n" + | 			"------------------ Input: -----------------\n" + | ||||||
| @ -483,7 +482,7 @@ void CompilerContext::appendInlineAssembly( | |||||||
| 	{ | 	{ | ||||||
| 		yul::Object obj; | 		yul::Object obj; | ||||||
| 		obj.code = parserResult; | 		obj.code = parserResult; | ||||||
| 		obj.analysisInfo = make_shared<yul::AsmAnalysisInfo>(analysisInfo); | 		obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(analysisInfo); | ||||||
| 
 | 
 | ||||||
| 		solAssert(!dialect.providesObjectAccess()); | 		solAssert(!dialect.providesObjectAccess()); | ||||||
| 		optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); | 		optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); | ||||||
| @ -493,7 +492,7 @@ void CompilerContext::appendInlineAssembly( | |||||||
| 			// Store as generated sources, but first re-parse to update the source references.
 | 			// Store as generated sources, but first re-parse to update the source references.
 | ||||||
| 			solAssert(m_generatedYulUtilityCode.empty(), ""); | 			solAssert(m_generatedYulUtilityCode.empty(), ""); | ||||||
| 			m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code); | 			m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code); | ||||||
| 			string code = yul::AsmPrinter{dialect}(*obj.code); | 			std::string code = yul::AsmPrinter{dialect}(*obj.code); | ||||||
| 			langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); | 			langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); | ||||||
| 			obj.code = yul::Parser(errorReporter, dialect).parse(charStream); | 			obj.code = yul::Parser(errorReporter, dialect).parse(charStream); | ||||||
| 			*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); | 			*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); | ||||||
| @ -548,7 +547,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ | |||||||
| 		_optimiserSettings.optimizeStackAllocation, | 		_optimiserSettings.optimizeStackAllocation, | ||||||
| 		_optimiserSettings.yulOptimiserSteps, | 		_optimiserSettings.yulOptimiserSteps, | ||||||
| 		_optimiserSettings.yulOptimiserCleanupSteps, | 		_optimiserSettings.yulOptimiserCleanupSteps, | ||||||
| 		isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment), | 		isCreation? std::nullopt : std::make_optional(_optimiserSettings.expectedExecutionsPerDeployment), | ||||||
| 		_externalIdentifiers | 		_externalIdentifiers | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| @ -558,11 +557,11 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string CompilerContext::revertReasonIfDebug(string const& _message) | std::string CompilerContext::revertReasonIfDebug(std::string const& _message) | ||||||
| { | { | ||||||
| 	return YulUtilFunctions::revertReasonIfDebugBody( | 	return YulUtilFunctions::revertReasonIfDebugBody( | ||||||
| 		m_revertStrings, | 		m_revertStrings, | ||||||
| 		"mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")", | 		"mload(" + std::to_string(CompilerUtils::freeMemoryPointer) + ")", | ||||||
| 		_message | 		_message | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| @ -590,14 +589,14 @@ evmasm::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel( | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// some name that cannot clash with yul function names.
 | 		// some name that cannot clash with yul function names.
 | ||||||
| 		string labelName = "@" + _declaration.name() + "_" + to_string(_declaration.id()); | 		std::string labelName = "@" + _declaration.name() + "_" + std::to_string(_declaration.id()); | ||||||
| 		evmasm::AssemblyItem tag = _context.namedTag( | 		evmasm::AssemblyItem tag = _context.namedTag( | ||||||
| 			labelName, | 			labelName, | ||||||
| 			params, | 			params, | ||||||
| 			returns, | 			returns, | ||||||
| 			_declaration.id() | 			_declaration.id() | ||||||
| 		); | 		); | ||||||
| 		m_entryLabels.insert(make_pair(&_declaration, tag)); | 		m_entryLabels.insert(std::make_pair(&_declaration, tag)); | ||||||
| 		m_functionsToCompile.push(&_declaration); | 		m_functionsToCompile.push(&_declaration); | ||||||
| 		return tag.tag(); | 		return tag.tag(); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -33,7 +33,6 @@ | |||||||
| #include <libsolutil/Whiskers.h> | #include <libsolutil/Whiskers.h> | ||||||
| #include <libsolutil/StackTooDeepString.h> | #include <libsolutil/StackTooDeepString.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -105,9 +104,9 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CompilerUtils::revertWithError( | void CompilerUtils::revertWithError( | ||||||
| 	string const& _signature, | 	std::string const& _signature, | ||||||
| 	vector<Type const*> const& _parameterTypes, | 	std::vector<Type const*> const& _parameterTypes, | ||||||
| 	vector<Type const*> const& _argumentTypes | 	std::vector<Type const*> const& _argumentTypes | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	fetchFreeMemoryPointer(); | 	fetchFreeMemoryPointer(); | ||||||
| @ -215,7 +214,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound | |||||||
| 		m_context << Instruction::DUP1; | 		m_context << Instruction::DUP1; | ||||||
| 		storeStringData(bytesConstRef(str->value())); | 		storeStringData(bytesConstRef(str->value())); | ||||||
| 		if (_padToWordBoundaries) | 		if (_padToWordBoundaries) | ||||||
| 			m_context << u256(max<size_t>(32, ((str->value().size() + 31) / 32) * 32)); | 			m_context << u256(std::max<size_t>(32, ((str->value().size() + 31) / 32) * 32)); | ||||||
| 		else | 		else | ||||||
| 			m_context << u256(str->value().size()); | 			m_context << u256(str->value().size()); | ||||||
| 		m_context << Instruction::ADD; | 		m_context << Instruction::ADD; | ||||||
| @ -264,7 +263,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem | |||||||
| 	Whiskers templ(R"({ | 	Whiskers templ(R"({ | ||||||
| 		if lt(len, <encodedSize>) { <revertString> } | 		if lt(len, <encodedSize>) { <revertString> } | ||||||
| 	})"); | 	})"); | ||||||
| 	templ("encodedSize", to_string(encodedSize)); | 	templ("encodedSize", std::to_string(encodedSize)); | ||||||
| 	templ("revertString", m_context.revertReasonIfDebug("Calldata too short")); | 	templ("revertString", m_context.revertReasonIfDebug("Calldata too short")); | ||||||
| 	m_context.appendInlineAssembly(templ.render(), {"len"}); | 	m_context.appendInlineAssembly(templ.render(), {"len"}); | ||||||
| 
 | 
 | ||||||
| @ -320,7 +319,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem | |||||||
| 						mstore(dst, array_length) | 						mstore(dst, array_length) | ||||||
| 						dst := add(dst, 0x20) | 						dst := add(dst, 0x20) | ||||||
| 					})"); | 					})"); | ||||||
| 					templ("item_size", to_string(arrayType.calldataStride())); | 					templ("item_size", std::to_string(arrayType.calldataStride())); | ||||||
| 					// TODO add test
 | 					// TODO add test
 | ||||||
| 					templ("revertStringPointer", m_context.revertReasonIfDebug("ABI memory decoding: invalid data pointer")); | 					templ("revertStringPointer", m_context.revertReasonIfDebug("ABI memory decoding: invalid data pointer")); | ||||||
| 					templ("revertStringStart", m_context.revertReasonIfDebug("ABI memory decoding: invalid data start")); | 					templ("revertStringStart", m_context.revertReasonIfDebug("ABI memory decoding: invalid data start")); | ||||||
| @ -374,7 +373,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem | |||||||
| 					m_context.appendInlineAssembly(Whiskers(R"({ | 					m_context.appendInlineAssembly(Whiskers(R"({ | ||||||
| 						if or( | 						if or( | ||||||
| 							gt(array_length, 0x100000000), | 							gt(array_length, 0x100000000), | ||||||
| 							gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end) | 							gt(add(data_ptr, mul(array_length, )" + std::to_string(arrayType.calldataStride()) + R"()), input_end) | ||||||
| 						) { <revertString> } | 						) { <revertString> } | ||||||
| 					})") | 					})") | ||||||
| 					("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data pointer")) | 					("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data pointer")) | ||||||
| @ -618,7 +617,7 @@ void CompilerUtils::abiEncodeV2( | |||||||
| 
 | 
 | ||||||
| 	// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
 | 	// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
 | ||||||
| 
 | 
 | ||||||
| 	string encoderName = | 	std::string encoderName = | ||||||
| 		_padToWordBoundaries ? | 		_padToWordBoundaries ? | ||||||
| 		m_context.abiFunctions().tupleEncoderReversed(_givenTypes, _targetTypes, _encodeAsLibraryTypes) : | 		m_context.abiFunctions().tupleEncoderReversed(_givenTypes, _targetTypes, _encodeAsLibraryTypes) : | ||||||
| 		m_context.abiFunctions().tupleEncoderPackedReversed(_givenTypes, _targetTypes); | 		m_context.abiFunctions().tupleEncoderPackedReversed(_givenTypes, _targetTypes); | ||||||
| @ -631,7 +630,7 @@ void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromM | |||||||
| 	m_context << Instruction::DUP2 << Instruction::ADD; | 	m_context << Instruction::DUP2 << Instruction::ADD; | ||||||
| 	m_context << Instruction::SWAP1; | 	m_context << Instruction::SWAP1; | ||||||
| 	// stack: <end> <start>
 | 	// stack: <end> <start>
 | ||||||
| 	string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory); | 	std::string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory); | ||||||
| 	m_context.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes)); | 	m_context.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -646,7 +645,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) | |||||||
| 			calldatacopy(memptr, calldatasize(), size) | 			calldatacopy(memptr, calldatasize(), size) | ||||||
| 			memptr := add(memptr, size) | 			memptr := add(memptr, size) | ||||||
| 		})"); | 		})"); | ||||||
| 		templ("element_size", to_string(_type.memoryStride())); | 		templ("element_size", std::to_string(_type.memoryStride())); | ||||||
| 		m_context.appendInlineAssembly(templ.render(), {"length", "memptr"}); | 		m_context.appendInlineAssembly(templ.render(), {"length", "memptr"}); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| @ -842,7 +841,7 @@ void CompilerUtils::convertType( | |||||||
| 				m_context << Instruction::POP << u256(0); | 				m_context << Instruction::POP << u256(0); | ||||||
| 			else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) | 			else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) | ||||||
| 			{ | 			{ | ||||||
| 				unsigned bytes = min(typeOnStack.numBytes(), targetType.numBytes()); | 				unsigned bytes = std::min(typeOnStack.numBytes(), targetType.numBytes()); | ||||||
| 				m_context << ((u256(1) << (256 - bytes * 8)) - 1); | 				m_context << ((u256(1) << (256 - bytes * 8)) - 1); | ||||||
| 				m_context << Instruction::NOT << Instruction::AND; | 				m_context << Instruction::NOT << Instruction::AND; | ||||||
| 			} | 			} | ||||||
| @ -960,7 +959,7 @@ void CompilerUtils::convertType( | |||||||
| 	case Type::Category::StringLiteral: | 	case Type::Category::StringLiteral: | ||||||
| 	{ | 	{ | ||||||
| 		auto const& literalType = dynamic_cast<StringLiteralType const&>(_typeOnStack); | 		auto const& literalType = dynamic_cast<StringLiteralType const&>(_typeOnStack); | ||||||
| 		string const& value = literalType.value(); | 		std::string const& value = literalType.value(); | ||||||
| 		bytesConstRef data(value); | 		bytesConstRef data(value); | ||||||
| 		if (targetTypeCategory == Type::Category::FixedBytes) | 		if (targetTypeCategory == Type::Category::FixedBytes) | ||||||
| 		{ | 		{ | ||||||
| @ -1186,7 +1185,7 @@ void CompilerUtils::convertType( | |||||||
| 					for (auto const& member: typeOnStack->members(nullptr)) | 					for (auto const& member: typeOnStack->members(nullptr)) | ||||||
| 					{ | 					{ | ||||||
| 						solAssert(!member.type->containsNestedMapping()); | 						solAssert(!member.type->containsNestedMapping()); | ||||||
| 						pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name); | 						std::pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name); | ||||||
| 						_context << offsets.first << Instruction::DUP3 << Instruction::ADD; | 						_context << offsets.first << Instruction::DUP3 << Instruction::ADD; | ||||||
| 						_context << u256(offsets.second); | 						_context << u256(offsets.second); | ||||||
| 						StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true); | 						StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true); | ||||||
| @ -1268,7 +1267,7 @@ void CompilerUtils::convertType( | |||||||
| 				if (sourceSize > 0 || targetSize > 0) | 				if (sourceSize > 0 || targetSize > 0) | ||||||
| 				{ | 				{ | ||||||
| 					// Move it back into its place.
 | 					// Move it back into its place.
 | ||||||
| 					for (unsigned j = 0; j < min(sourceSize, targetSize); ++j) | 					for (unsigned j = 0; j < std::min(sourceSize, targetSize); ++j) | ||||||
| 						m_context << | 						m_context << | ||||||
| 							swapInstruction(depth + targetSize - sourceSize) << | 							swapInstruction(depth + targetSize - sourceSize) << | ||||||
| 							Instruction::POP; | 							Instruction::POP; | ||||||
| @ -1375,7 +1374,7 @@ void CompilerUtils::pushZeroValue(Type const& _type) | |||||||
| 		[type](CompilerContext& _context) { | 		[type](CompilerContext& _context) { | ||||||
| 			CompilerUtils utils(_context); | 			CompilerUtils utils(_context); | ||||||
| 
 | 
 | ||||||
| 			utils.allocateMemory(max<u256>(32u, type->memoryDataSize())); | 			utils.allocateMemory(std::max<u256>(32u, type->memoryDataSize())); | ||||||
| 			_context << Instruction::DUP1; | 			_context << Instruction::DUP1; | ||||||
| 
 | 
 | ||||||
| 			if (auto structType = dynamic_cast<StructType const*>(type)) | 			if (auto structType = dynamic_cast<StructType const*>(type)) | ||||||
| @ -1493,7 +1492,7 @@ void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _ | |||||||
| 	m_context.adjustStackOffset(static_cast<int>(amount)); | 	m_context.adjustStackOffset(static_cast<int>(amount)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes) | unsigned CompilerUtils::sizeOnStack(std::vector<Type const*> const& _variableTypes) | ||||||
| { | { | ||||||
| 	unsigned size = 0; | 	unsigned size = 0; | ||||||
| 	for (Type const* type: _variableTypes) | 	for (Type const* type: _variableTypes) | ||||||
| @ -1509,7 +1508,7 @@ void CompilerUtils::computeHashStatic() | |||||||
| 
 | 
 | ||||||
| void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation) | void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation) | ||||||
| { | { | ||||||
| 	string which = _creation ? "Creation" : "Runtime"; | 	std::string which = _creation ? "Creation" : "Runtime"; | ||||||
| 	m_context.callLowLevelFunction( | 	m_context.callLowLevelFunction( | ||||||
| 		"$copyContract" + which + "CodeToMemory_" + contract.type()->identifier(), | 		"$copyContract" + which + "CodeToMemory_" + contract.type()->identifier(), | ||||||
| 		1, | 		1, | ||||||
| @ -1517,7 +1516,7 @@ void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, | |||||||
| 		[&contract, _creation](CompilerContext& _context) | 		[&contract, _creation](CompilerContext& _context) | ||||||
| 		{ | 		{ | ||||||
| 			// copy the contract's code into memory
 | 			// copy the contract's code into memory
 | ||||||
| 			shared_ptr<evmasm::Assembly> assembly = | 			std::shared_ptr<evmasm::Assembly> assembly = | ||||||
| 				_creation ? | 				_creation ? | ||||||
| 				_context.compiledContract(contract) : | 				_context.compiledContract(contract) : | ||||||
| 				_context.compiledContractRuntime(contract); | 				_context.compiledContractRuntime(contract); | ||||||
|  | |||||||
| @ -55,7 +55,6 @@ | |||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <limits> | #include <limits> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -80,7 +79,7 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		solAssert( | 		solAssert( | ||||||
| 			m_context.stackHeight() == stackHeight, | 			m_context.stackHeight() == stackHeight, | ||||||
| 			std::string("I sense a disturbance in the stack: ") + to_string(m_context.stackHeight()) + " vs " + to_string(stackHeight) | 			std::string("I sense a disturbance in the stack: ") + std::to_string(m_context.stackHeight()) + " vs " + std::to_string(stackHeight) | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| private: | private: | ||||||
| @ -92,7 +91,7 @@ private: | |||||||
| 
 | 
 | ||||||
| void ContractCompiler::compileContract( | void ContractCompiler::compileContract( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers | 	std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | ||||||
| @ -111,7 +110,7 @@ void ContractCompiler::compileContract( | |||||||
| 
 | 
 | ||||||
| size_t ContractCompiler::compileConstructor( | size_t ContractCompiler::compileConstructor( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers | 	std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | ||||||
| @ -126,7 +125,7 @@ size_t ContractCompiler::compileConstructor( | |||||||
| 
 | 
 | ||||||
| void ContractCompiler::initializeContext( | void ContractCompiler::initializeContext( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers | 	std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2); | 	m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2); | ||||||
| @ -187,7 +186,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont | |||||||
| 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | ||||||
| 	m_context << deployRoutine; | 	m_context << deployRoutine; | ||||||
| 
 | 
 | ||||||
| 	solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered"); | 	solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered"); | ||||||
| 
 | 
 | ||||||
| 	ContractType contractType(_contract); | 	ContractType contractType(_contract); | ||||||
| 	auto const& immutables = contractType.immutableVariables(); | 	auto const& immutables = contractType.immutableVariables(); | ||||||
| @ -231,7 +230,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) | |||||||
| 
 | 
 | ||||||
| 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | 	CompilerContext::LocationSetter locationSetter(m_context, _contract); | ||||||
| 
 | 
 | ||||||
| 	solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered"); | 	solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered"); | ||||||
| 	m_context.pushSubroutineSize(m_context.runtimeSub()); | 	m_context.pushSubroutineSize(m_context.runtimeSub()); | ||||||
| 	m_context.pushSubroutineOffset(m_context.runtimeSub()); | 	m_context.pushSubroutineOffset(m_context.runtimeSub()); | ||||||
| 	// This code replaces the address added by appendDeployTimeAddress().
 | 	// This code replaces the address added by appendDeployTimeAddress().
 | ||||||
| @ -324,8 +323,8 @@ void ContractCompiler::appendDelegatecallCheck() | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ContractCompiler::appendInternalSelector( | void ContractCompiler::appendInternalSelector( | ||||||
| 	map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints, | 	std::map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints, | ||||||
| 	vector<FixedHash<4>> const& _ids, | 	std::vector<FixedHash<4>> const& _ids, | ||||||
| 	evmasm::AssemblyItem const& _notFoundTag, | 	evmasm::AssemblyItem const& _notFoundTag, | ||||||
| 	size_t _runs | 	size_t _runs | ||||||
| ) | ) | ||||||
| @ -369,11 +368,11 @@ void ContractCompiler::appendInternalSelector( | |||||||
| 		m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT; | 		m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT; | ||||||
| 		evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()}; | 		evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()}; | ||||||
| 		// Here, we have funid >= pivot
 | 		// Here, we have funid >= pivot
 | ||||||
| 		vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()}; | 		std::vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()}; | ||||||
| 		appendInternalSelector(_entryPoints, larger, _notFoundTag, _runs); | 		appendInternalSelector(_entryPoints, larger, _notFoundTag, _runs); | ||||||
| 		m_context << lessTag; | 		m_context << lessTag; | ||||||
| 		// Here, we have funid < pivot
 | 		// Here, we have funid < pivot
 | ||||||
| 		vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)}; | 		std::vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)}; | ||||||
| 		appendInternalSelector(_entryPoints, smaller, _notFoundTag, _runs); | 		appendInternalSelector(_entryPoints, smaller, _notFoundTag, _runs); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| @ -411,8 +410,8 @@ bool hasPayableFunctions(ContractDefinition const& _contract) | |||||||
| 
 | 
 | ||||||
| void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract) | void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions(); | 	std::map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions(); | ||||||
| 	map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints; | 	std::map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints; | ||||||
| 
 | 
 | ||||||
| 	if (_contract.isLibrary()) | 	if (_contract.isLibrary()) | ||||||
| 	{ | 	{ | ||||||
| @ -448,7 +447,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac | |||||||
| 		CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true, false); | 		CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true, false); | ||||||
| 
 | 
 | ||||||
| 		// stack now is: <can-call-non-view-functions>? <funhash>
 | 		// stack now is: <can-call-non-view-functions>? <funhash>
 | ||||||
| 		vector<FixedHash<4>> sortedIDs; | 		std::vector<FixedHash<4>> sortedIDs; | ||||||
| 		for (auto const& it: interfaceFunctions) | 		for (auto const& it: interfaceFunctions) | ||||||
| 		{ | 		{ | ||||||
| 			callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag()); | 			callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag()); | ||||||
| @ -572,7 +571,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete | |||||||
| void ContractCompiler::registerStateVariables(ContractDefinition const& _contract) | void ContractCompiler::registerStateVariables(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	for (auto const& var: ContractType(_contract).stateVariables()) | 	for (auto const& var: ContractType(_contract).stateVariables()) | ||||||
| 		m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var)); | 		m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ContractCompiler::registerImmutableVariables(ContractDefinition const& _contract) | void ContractCompiler::registerImmutableVariables(ContractDefinition const& _contract) | ||||||
| @ -645,7 +644,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) | |||||||
| 	m_breakTags.clear(); | 	m_breakTags.clear(); | ||||||
| 	m_continueTags.clear(); | 	m_continueTags.clear(); | ||||||
| 	m_currentFunction = &_function; | 	m_currentFunction = &_function; | ||||||
| 	m_modifierDepth = numeric_limits<unsigned>::max(); | 	m_modifierDepth = std::numeric_limits<unsigned>::max(); | ||||||
| 	m_scopeStackHeight.clear(); | 	m_scopeStackHeight.clear(); | ||||||
| 	m_context.setModifierDepth(0); | 	m_context.setModifierDepth(0); | ||||||
| 
 | 
 | ||||||
| @ -662,10 +661,10 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) | |||||||
| 	unsigned const c_argumentsSize = CompilerUtils::sizeOnStack(_function.parameters()); | 	unsigned const c_argumentsSize = CompilerUtils::sizeOnStack(_function.parameters()); | ||||||
| 	unsigned const c_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters()); | 	unsigned const c_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters()); | ||||||
| 
 | 
 | ||||||
| 	vector<int> stackLayout; | 	std::vector<int> stackLayout; | ||||||
| 	if (!_function.isConstructor() && !_function.isFallback()) | 	if (!_function.isConstructor() && !_function.isFallback()) | ||||||
| 		stackLayout.push_back(static_cast<int>(c_returnValuesSize)); // target of return address
 | 		stackLayout.push_back(static_cast<int>(c_returnValuesSize)); // target of return address
 | ||||||
| 	stackLayout += vector<int>(c_argumentsSize, -1); // discard all arguments
 | 	stackLayout += std::vector<int>(c_argumentsSize, -1); // discard all arguments
 | ||||||
| 	for (size_t i = 0; i < c_returnValuesSize; ++i) | 	for (size_t i = 0; i < c_returnValuesSize; ++i) | ||||||
| 		stackLayout.push_back(static_cast<int>(i)); | 		stackLayout.push_back(static_cast<int>(i)); | ||||||
| 
 | 
 | ||||||
| @ -684,7 +683,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) | |||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			m_context << swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u); | 			m_context << swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u); | ||||||
| 			swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back()); | 			std::swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back()); | ||||||
| 		} | 		} | ||||||
| 	for (size_t i = 0; i < stackLayout.size(); ++i) | 	for (size_t i = 0; i < stackLayout.size(); ++i) | ||||||
| 		if (stackLayout[i] != static_cast<int>(i)) | 		if (stackLayout[i] != static_cast<int>(i)) | ||||||
| @ -790,7 +789,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) | |||||||
| 					unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable); | 					unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable); | ||||||
| 					if (!ref->second.suffix.empty()) | 					if (!ref->second.suffix.empty()) | ||||||
| 					{ | 					{ | ||||||
| 						string const& suffix = ref->second.suffix; | 						std::string const& suffix = ref->second.suffix; | ||||||
| 						if (variable->type()->dataStoredIn(DataLocation::Storage)) | 						if (variable->type()->dataStoredIn(DataLocation::Storage)) | ||||||
| 						{ | 						{ | ||||||
| 							solAssert(suffix == "offset" || suffix == "slot", ""); | 							solAssert(suffix == "offset" || suffix == "slot", ""); | ||||||
| @ -865,7 +864,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) | |||||||
| 			// lvalue context
 | 			// lvalue context
 | ||||||
| 			auto variable = dynamic_cast<VariableDeclaration const*>(decl); | 			auto variable = dynamic_cast<VariableDeclaration const*>(decl); | ||||||
| 			unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1; | 			unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1; | ||||||
| 			string const& suffix = ref->second.suffix; | 			std::string const& suffix = ref->second.suffix; | ||||||
| 			if (variable->type()->dataStoredIn(DataLocation::Storage)) | 			if (variable->type()->dataStoredIn(DataLocation::Storage)) | ||||||
| 			{ | 			{ | ||||||
| 				solAssert( | 				solAssert( | ||||||
| @ -928,7 +927,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) | |||||||
| 	yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get(); | 	yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get(); | ||||||
| 
 | 
 | ||||||
| 	// Only used in the scope below, but required to live outside to keep the
 | 	// Only used in the scope below, but required to live outside to keep the
 | ||||||
| 	// shared_ptr's alive
 | 	// std::shared_ptr's alive
 | ||||||
| 	yul::Object object = {}; | 	yul::Object object = {}; | ||||||
| 
 | 
 | ||||||
| 	// The optimiser cannot handle external references
 | 	// The optimiser cannot handle external references
 | ||||||
| @ -941,8 +940,8 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) | |||||||
| 		solAssert(dialect, ""); | 		solAssert(dialect, ""); | ||||||
| 
 | 
 | ||||||
| 		// Create a modifiable copy of the code and analysis
 | 		// Create a modifiable copy of the code and analysis
 | ||||||
| 		object.code = make_shared<yul::Block>(yul::ASTCopier().translate(*code)); | 		object.code = std::make_shared<yul::Block>(yul::ASTCopier().translate(*code)); | ||||||
| 		object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); | 		object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); | ||||||
| 
 | 
 | ||||||
| 		m_context.optimizeYul(object, *dialect, m_optimiserSettings); | 		m_context.optimizeYul(object, *dialect, m_optimiserSettings); | ||||||
| 
 | 
 | ||||||
| @ -989,10 +988,10 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement) | |||||||
| 		TryCatchClause const& successClause = *_tryStatement.clauses().front(); | 		TryCatchClause const& successClause = *_tryStatement.clauses().front(); | ||||||
| 		if (successClause.parameters()) | 		if (successClause.parameters()) | ||||||
| 		{ | 		{ | ||||||
| 			vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type}; | 			std::vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type}; | ||||||
| 			if (auto tupleType = dynamic_cast<TupleType const*>(exprTypes.front())) | 			if (auto tupleType = dynamic_cast<TupleType const*>(exprTypes.front())) | ||||||
| 				exprTypes = tupleType->components(); | 				exprTypes = tupleType->components(); | ||||||
| 			vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters(); | 			std::vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters(); | ||||||
| 			solAssert(exprTypes.size() == params.size(), ""); | 			solAssert(exprTypes.size() == params.size(), ""); | ||||||
| 			for (size_t i = 0; i < exprTypes.size(); ++i) | 			for (size_t i = 0; i < exprTypes.size(); ++i) | ||||||
| 				solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], ""); | 				solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], ""); | ||||||
| @ -1008,7 +1007,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement) | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _catchClauses) | void ContractCompiler::handleCatch(std::vector<ASTPointer<TryCatchClause>> const& _catchClauses) | ||||||
| { | { | ||||||
| 	// Stack is empty.
 | 	// Stack is empty.
 | ||||||
| 	ASTPointer<TryCatchClause> error{}; | 	ASTPointer<TryCatchClause> error{}; | ||||||
| @ -1285,7 +1284,7 @@ bool ContractCompiler::visit(Return const& _return) | |||||||
| 	if (Expression const* expression = _return.expression()) | 	if (Expression const* expression = _return.expression()) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer."); | 		solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer."); | ||||||
| 		vector<ASTPointer<VariableDeclaration>> const& returnParameters = | 		std::vector<ASTPointer<VariableDeclaration>> const& returnParameters = | ||||||
| 			_return.annotation().functionReturnParameters->parameters(); | 			_return.annotation().functionReturnParameters->parameters(); | ||||||
| 		TypePointers types; | 		TypePointers types; | ||||||
| 		for (auto const& retVariable: returnParameters) | 		for (auto const& retVariable: returnParameters) | ||||||
| @ -1432,7 +1431,7 @@ void ContractCompiler::appendModifierOrFunctionCode() | |||||||
| 	solAssert(m_currentFunction, ""); | 	solAssert(m_currentFunction, ""); | ||||||
| 	unsigned stackSurplus = 0; | 	unsigned stackSurplus = 0; | ||||||
| 	Block const* codeBlock = nullptr; | 	Block const* codeBlock = nullptr; | ||||||
| 	vector<VariableDeclaration const*> addedVariables; | 	std::vector<VariableDeclaration const*> addedVariables; | ||||||
| 
 | 
 | ||||||
| 	m_modifierDepth++; | 	m_modifierDepth++; | ||||||
| 	m_context.setModifierDepth(m_modifierDepth); | 	m_context.setModifierDepth(m_modifierDepth); | ||||||
|  | |||||||
| @ -43,7 +43,6 @@ | |||||||
| #include <numeric> | #include <numeric> | ||||||
| #include <utility> | #include <utility> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -242,7 +241,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& | |||||||
| 			if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i])) | 			if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i])) | ||||||
| 				if (!arrayType->isByteArrayOrString()) | 				if (!arrayType->isByteArrayOrString()) | ||||||
| 					continue; | 					continue; | ||||||
| 			pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); | 			std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); | ||||||
| 			m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second); | 			m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second); | ||||||
| 			Type const* memberType = structType->memberType(names[i]); | 			Type const* memberType = structType->memberType(names[i]); | ||||||
| 			StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true); | 			StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true); | ||||||
| @ -370,7 +369,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) | |||||||
| 		ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); | 		ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); | ||||||
| 
 | 
 | ||||||
| 		solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); | 		solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); | ||||||
| 		utils().allocateMemory(max(u256(32u), arrayType.memoryDataSize())); | 		utils().allocateMemory(std::max(u256(32u), arrayType.memoryDataSize())); | ||||||
| 		m_context << Instruction::DUP1; | 		m_context << Instruction::DUP1; | ||||||
| 
 | 
 | ||||||
| 		for (auto const& component: _tuple.components()) | 		for (auto const& component: _tuple.components()) | ||||||
| @ -383,7 +382,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		vector<unique_ptr<LValue>> lvalues; | 		std::vector<std::unique_ptr<LValue>> lvalues; | ||||||
| 		for (auto const& component: _tuple.components()) | 		for (auto const& component: _tuple.components()) | ||||||
| 			if (component) | 			if (component) | ||||||
| 			{ | 			{ | ||||||
| @ -395,13 +394,13 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (_tuple.annotation().willBeWrittenTo) | 			else if (_tuple.annotation().willBeWrittenTo) | ||||||
| 				lvalues.push_back(unique_ptr<LValue>()); | 				lvalues.push_back(std::unique_ptr<LValue>()); | ||||||
| 		if (_tuple.annotation().willBeWrittenTo) | 		if (_tuple.annotation().willBeWrittenTo) | ||||||
| 		{ | 		{ | ||||||
| 			if (_tuple.components().size() == 1) | 			if (_tuple.components().size() == 1) | ||||||
| 				m_currentLValue = std::move(lvalues[0]); | 				m_currentLValue = std::move(lvalues[0]); | ||||||
| 			else | 			else | ||||||
| 				m_currentLValue = make_unique<TupleObject>(m_context, std::move(lvalues)); | 				m_currentLValue = std::make_unique<TupleObject>(m_context, std::move(lvalues)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return false; | 	return false; | ||||||
| @ -524,7 +523,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) | |||||||
| 			m_context << u256(0) << Instruction::SUB; | 			m_context << u256(0) << Instruction::SUB; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator()))); | 		solAssert(false, "Invalid unary operator: " + std::string(TokenTraits::toString(_unaryOperation.getOperator()))); | ||||||
| 	} | 	} | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| @ -659,14 +658,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 
 | 
 | ||||||
| 	TypePointers parameterTypes = functionType->parameterTypes(); | 	TypePointers parameterTypes = functionType->parameterTypes(); | ||||||
| 
 | 
 | ||||||
| 	vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments(); | 	std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments(); | ||||||
| 
 | 
 | ||||||
| 	if (functionCallKind == FunctionCallKind::StructConstructorCall) | 	if (functionCallKind == FunctionCallKind::StructConstructorCall) | ||||||
| 	{ | 	{ | ||||||
| 		TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type); | 		TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type); | ||||||
| 		auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); | 		auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); | ||||||
| 
 | 
 | ||||||
| 		utils().allocateMemory(max(u256(32u), structType.memoryDataSize())); | 		utils().allocateMemory(std::max(u256(32u), structType.memoryDataSize())); | ||||||
| 		m_context << Instruction::DUP1; | 		m_context << Instruction::DUP1; | ||||||
| 
 | 
 | ||||||
| 		for (unsigned i = 0; i < arguments.size(); ++i) | 		for (unsigned i = 0; i < arguments.size(); ++i) | ||||||
| @ -992,7 +991,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 		case FunctionType::Kind::Error: | 		case FunctionType::Kind::Error: | ||||||
| 		{ | 		{ | ||||||
| 			_functionCall.expression().accept(*this); | 			_functionCall.expression().accept(*this); | ||||||
| 			vector<Type const*> argumentTypes; | 			std::vector<Type const*> argumentTypes; | ||||||
| 			for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments()) | 			for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments()) | ||||||
| 			{ | 			{ | ||||||
| 				arg->accept(*this); | 				arg->accept(*this); | ||||||
| @ -1060,7 +1059,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 		case FunctionType::Kind::RIPEMD160: | 		case FunctionType::Kind::RIPEMD160: | ||||||
| 		{ | 		{ | ||||||
| 			_functionCall.expression().accept(*this); | 			_functionCall.expression().accept(*this); | ||||||
| 			static map<FunctionType::Kind, u256> const contractAddresses{ | 			static std::map<FunctionType::Kind, u256> const contractAddresses{ | ||||||
| 				{FunctionType::Kind::ECRecover, 1}, | 				{FunctionType::Kind::ECRecover, 1}, | ||||||
| 				{FunctionType::Kind::SHA256, 2}, | 				{FunctionType::Kind::SHA256, 2}, | ||||||
| 				{FunctionType::Kind::RIPEMD160, 3} | 				{FunctionType::Kind::RIPEMD160, 3} | ||||||
| @ -1151,8 +1150,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 		case FunctionType::Kind::BytesConcat: | 		case FunctionType::Kind::BytesConcat: | ||||||
| 		{ | 		{ | ||||||
| 			_functionCall.expression().accept(*this); | 			_functionCall.expression().accept(*this); | ||||||
| 			vector<Type const*> argumentTypes; | 			std::vector<Type const*> argumentTypes; | ||||||
| 			vector<Type const*> targetTypes; | 			std::vector<Type const*> targetTypes; | ||||||
| 			for (auto const& argument: arguments) | 			for (auto const& argument: arguments) | ||||||
| 			{ | 			{ | ||||||
| 				argument->accept(*this); | 				argument->accept(*this); | ||||||
| @ -1416,7 +1415,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 				// stack: <memory pointer> <selector>
 | 				// stack: <memory pointer> <selector>
 | ||||||
| 
 | 
 | ||||||
| 				// load current memory, mask and combine the selector
 | 				// load current memory, mask and combine the selector
 | ||||||
| 				string mask = formatNumber((u256(-1) >> 32)); | 				std::string mask = formatNumber((u256(-1) >> 32)); | ||||||
| 				m_context.appendInlineAssembly(R"({ | 				m_context.appendInlineAssembly(R"({ | ||||||
| 					let data_start := add(mem_ptr, 0x20) | 					let data_start := add(mem_ptr, 0x20) | ||||||
| 					let data := mload(data_start) | 					let data := mload(data_start) | ||||||
| @ -1476,7 +1475,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions) | |||||||
| 	// Desired Stack: [salt], [gas], [value]
 | 	// Desired Stack: [salt], [gas], [value]
 | ||||||
| 	enum Option { Salt, Gas, Value }; | 	enum Option { Salt, Gas, Value }; | ||||||
| 
 | 
 | ||||||
| 	vector<Option> presentOptions; | 	std::vector<Option> presentOptions; | ||||||
| 	FunctionType const& funType = dynamic_cast<FunctionType const&>( | 	FunctionType const& funType = dynamic_cast<FunctionType const&>( | ||||||
| 		*_functionCallOptions.expression().annotation().type | 		*_functionCallOptions.expression().annotation().type | ||||||
| 	); | 	); | ||||||
| @ -1486,7 +1485,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions) | |||||||
| 
 | 
 | ||||||
| 	for (size_t i = 0; i < _functionCallOptions.options().size(); ++i) | 	for (size_t i = 0; i < _functionCallOptions.options().size(); ++i) | ||||||
| 	{ | 	{ | ||||||
| 		string const& name = *_functionCallOptions.names()[i]; | 		std::string const& name = *_functionCallOptions.names()[i]; | ||||||
| 		Type const* requiredType = TypeProvider::uint256(); | 		Type const* requiredType = TypeProvider::uint256(); | ||||||
| 		Option newOption; | 		Option newOption; | ||||||
| 		if (name == "salt") | 		if (name == "salt") | ||||||
| @ -1818,7 +1817,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | |||||||
| 			); | 			); | ||||||
| 			m_context << Instruction::EXTCODEHASH; | 			m_context << Instruction::EXTCODEHASH; | ||||||
| 		} | 		} | ||||||
| 		else if ((set<string>{"send", "transfer"}).count(member)) | 		else if ((std::set<std::string>{"send", "transfer"}).count(member)) | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, ""); | 			solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, ""); | ||||||
| 			utils().convertType( | 			utils().convertType( | ||||||
| @ -1827,7 +1826,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | |||||||
| 				true | 				true | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 		else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member)) | 		else if ((std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}).count(member)) | ||||||
| 			utils().convertType( | 			utils().convertType( | ||||||
| 				*_memberAccess.expression().annotation().type, | 				*_memberAccess.expression().annotation().type, | ||||||
| 				*TypeProvider::address(), | 				*TypeProvider::address(), | ||||||
| @ -1910,7 +1909,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | |||||||
| 				Whiskers(R"({ | 				Whiskers(R"({ | ||||||
| 					mstore(start, sub(end, add(start, 0x20))) | 					mstore(start, sub(end, add(start, 0x20))) | ||||||
| 					mstore(<free>, and(add(end, 31), not(31))) | 					mstore(<free>, and(add(end, 31), not(31))) | ||||||
| 				})")("free", to_string(CompilerUtils::freeMemoryPointer)).render(), | 				})")("free", std::to_string(CompilerUtils::freeMemoryPointer)).render(), | ||||||
| 				{"start", "end"} | 				{"start", "end"} | ||||||
| 			); | 			); | ||||||
| 			m_context << Instruction::POP; | 			m_context << Instruction::POP; | ||||||
| @ -1946,7 +1945,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | |||||||
| 				solAssert(false, "min/max not available for the given type."); | 				solAssert(false, "min/max not available for the given type."); | ||||||
| 
 | 
 | ||||||
| 		} | 		} | ||||||
| 		else if ((set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member)) | 		else if ((std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member)) | ||||||
| 		{ | 		{ | ||||||
| 			// no-op
 | 			// no-op
 | ||||||
| 		} | 		} | ||||||
| @ -1961,7 +1960,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | |||||||
| 		{ | 		{ | ||||||
| 		case DataLocation::Storage: | 		case DataLocation::Storage: | ||||||
| 		{ | 		{ | ||||||
| 			pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member); | 			std::pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member); | ||||||
| 			m_context << offsets.first << Instruction::ADD << u256(offsets.second); | 			m_context << offsets.first << Instruction::ADD << u256(offsets.second); | ||||||
| 			setLValueToStorageItem(_memberAccess); | 			setLValueToStorageItem(_memberAccess); | ||||||
| 			break; | 			break; | ||||||
| @ -2454,7 +2453,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons | |||||||
| 	IntegerType const& type = dynamic_cast<IntegerType const&>(_type); | 	IntegerType const& type = dynamic_cast<IntegerType const&>(_type); | ||||||
| 	if (m_context.arithmetic() == Arithmetic::Checked) | 	if (m_context.arithmetic() == Arithmetic::Checked) | ||||||
| 	{ | 	{ | ||||||
| 		string functionName; | 		std::string functionName; | ||||||
| 		switch (_operator) | 		switch (_operator) | ||||||
| 		{ | 		{ | ||||||
| 		case Token::Add: | 		case Token::Add: | ||||||
| @ -2620,7 +2619,7 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons | |||||||
| 
 | 
 | ||||||
| void ExpressionCompiler::appendExternalFunctionCall( | void ExpressionCompiler::appendExternalFunctionCall( | ||||||
| 	FunctionType const& _functionType, | 	FunctionType const& _functionType, | ||||||
| 	vector<ASTPointer<Expression const>> const& _arguments, | 	std::vector<ASTPointer<Expression const>> const& _arguments, | ||||||
| 	bool _tryCall | 	bool _tryCall | ||||||
| ) | ) | ||||||
| { | { | ||||||
|  | |||||||
| @ -30,7 +30,6 @@ | |||||||
| 
 | 
 | ||||||
| #include <libsolutil/StackTooDeepString.h> | #include <libsolutil/StackTooDeepString.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::evmasm; | using namespace solidity::evmasm; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -410,7 +409,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc | |||||||
| 					if (sourceType.location() == DataLocation::Storage) | 					if (sourceType.location() == DataLocation::Storage) | ||||||
| 					{ | 					{ | ||||||
| 						// stack layout: source_ref target_ref
 | 						// stack layout: source_ref target_ref
 | ||||||
| 						pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name); | 						std::pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name); | ||||||
| 						m_context << offsets.first << Instruction::DUP3 << Instruction::ADD; | 						m_context << offsets.first << Instruction::DUP3 << Instruction::ADD; | ||||||
| 						m_context << u256(offsets.second); | 						m_context << u256(offsets.second); | ||||||
| 						// stack: source_ref target_ref source_member_ref source_member_off
 | 						// stack: source_ref target_ref source_member_ref source_member_off
 | ||||||
| @ -427,7 +426,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc | |||||||
| 						// stack layout: source_ref target_ref source_value...
 | 						// stack layout: source_ref target_ref source_value...
 | ||||||
| 					} | 					} | ||||||
| 					unsigned stackSize = sourceMemberType->sizeOnStack(); | 					unsigned stackSize = sourceMemberType->sizeOnStack(); | ||||||
| 					pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); | 					std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); | ||||||
| 					m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD; | 					m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD; | ||||||
| 					m_context << u256(offsets.second); | 					m_context << u256(offsets.second); | ||||||
| 					// stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off
 | 					// stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off
 | ||||||
| @ -469,7 +468,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const | |||||||
| 			Type const* memberType = member.type; | 			Type const* memberType = member.type; | ||||||
| 			if (memberType->category() == Type::Category::Mapping) | 			if (memberType->category() == Type::Category::Mapping) | ||||||
| 				continue; | 				continue; | ||||||
| 			pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); | 			std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name); | ||||||
| 			m_context | 			m_context | ||||||
| 				<< offsets.first << Instruction::DUP3 << Instruction::ADD | 				<< offsets.first << Instruction::DUP3 << Instruction::ADD | ||||||
| 				<< u256(offsets.second); | 				<< u256(offsets.second); | ||||||
| @ -592,7 +591,7 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc | |||||||
| 	// We will assign from right to left to optimize stack layout.
 | 	// We will assign from right to left to optimize stack layout.
 | ||||||
| 	for (size_t i = 0; i < m_lvalues.size(); ++i) | 	for (size_t i = 0; i < m_lvalues.size(); ++i) | ||||||
| 	{ | 	{ | ||||||
| 		unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1]; | 		std::unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1]; | ||||||
| 		Type const* valType = valueTypes[valueTypes.size() - i - 1]; | 		Type const* valType = valueTypes[valueTypes.size() - i - 1]; | ||||||
| 		unsigned stackHeight = m_context.stackHeight(); | 		unsigned stackHeight = m_context.stackHeight(); | ||||||
| 		solAssert(!valType == !lvalue, ""); | 		solAssert(!valType == !lvalue, ""); | ||||||
|  | |||||||
| @ -26,44 +26,43 @@ | |||||||
| #include <libsolutil/Whiskers.h> | #include <libsolutil/Whiskers.h> | ||||||
| #include <libsolutil/StringUtils.h> | #include <libsolutil/StringUtils.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| 
 | 
 | ||||||
| string MultiUseYulFunctionCollector::requestedFunctions() | std::string MultiUseYulFunctionCollector::requestedFunctions() | ||||||
| { | { | ||||||
| 	string result = std::move(m_code); | 	std::string result = std::move(m_code); | ||||||
| 	m_code.clear(); | 	m_code.clear(); | ||||||
| 	m_requestedFunctions.clear(); | 	m_requestedFunctions.clear(); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string MultiUseYulFunctionCollector::createFunction(string const& _name, function<string ()> const& _creator) | std::string MultiUseYulFunctionCollector::createFunction(std::string const& _name, std::function<std::string()> const& _creator) | ||||||
| { | { | ||||||
| 	if (!m_requestedFunctions.count(_name)) | 	if (!m_requestedFunctions.count(_name)) | ||||||
| 	{ | 	{ | ||||||
| 		m_requestedFunctions.insert(_name); | 		m_requestedFunctions.insert(_name); | ||||||
| 		string fun = _creator(); | 		std::string fun = _creator(); | ||||||
| 		solAssert(!fun.empty(), ""); | 		solAssert(!fun.empty(), ""); | ||||||
| 		solAssert(fun.find("function " + _name + "(") != string::npos, "Function not properly named."); | 		solAssert(fun.find("function " + _name + "(") != std::string::npos, "Function not properly named."); | ||||||
| 		m_code += std::move(fun); | 		m_code += std::move(fun); | ||||||
| 	} | 	} | ||||||
| 	return _name; | 	return _name; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string MultiUseYulFunctionCollector::createFunction( | std::string MultiUseYulFunctionCollector::createFunction( | ||||||
| 	string const& _name, | 	std::string const& _name, | ||||||
| 	function<string(vector<string>&, vector<string>&)> const& _creator | 	std::function<std::string(std::vector<std::string>&, std::vector<std::string>&)> const& _creator | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	solAssert(!_name.empty(), ""); | 	solAssert(!_name.empty(), ""); | ||||||
| 	if (!m_requestedFunctions.count(_name)) | 	if (!m_requestedFunctions.count(_name)) | ||||||
| 	{ | 	{ | ||||||
| 		m_requestedFunctions.insert(_name); | 		m_requestedFunctions.insert(_name); | ||||||
| 		vector<string> arguments; | 		std::vector<std::string> arguments; | ||||||
| 		vector<string> returnParameters; | 		std::vector<std::string> returnParameters; | ||||||
| 		string body = _creator(arguments, returnParameters); | 		std::string body = _creator(arguments, returnParameters); | ||||||
| 		solAssert(!body.empty(), ""); | 		solAssert(!body.empty(), ""); | ||||||
| 
 | 
 | ||||||
| 		m_code += Whiskers(R"( | 		m_code += Whiskers(R"( | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -24,7 +24,6 @@ | |||||||
| 
 | 
 | ||||||
| #include <libyul/AsmPrinter.h> | #include <libyul/AsmPrinter.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity::langutil; | using namespace solidity::langutil; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| @ -41,110 +40,110 @@ YulArity YulArity::fromType(FunctionType const& _functionType) | |||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl) | std::string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl) | ||||||
| { | { | ||||||
| 	if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl)) | 	if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl)) | ||||||
| 		solAssert(!function->isConstructor()); | 		solAssert(!function->isConstructor()); | ||||||
| 
 | 
 | ||||||
| 	return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id()); | 	return "external_fun_" + _functionOrVarDecl.name() + "_" + std::to_string(_functionOrVarDecl.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::function(FunctionDefinition const& _function) | std::string IRNames::function(FunctionDefinition const& _function) | ||||||
| { | { | ||||||
| 	if (_function.isConstructor()) | 	if (_function.isConstructor()) | ||||||
| 		return constructor(*_function.annotation().contract); | 		return constructor(*_function.annotation().contract); | ||||||
| 
 | 
 | ||||||
| 	return "fun_" + _function.name() + "_" + to_string(_function.id()); | 	return "fun_" + _function.name() + "_" + std::to_string(_function.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::function(VariableDeclaration const& _varDecl) | std::string IRNames::function(VariableDeclaration const& _varDecl) | ||||||
| { | { | ||||||
| 	return "getter_fun_" + _varDecl.name() + "_" + to_string(_varDecl.id()); | 	return "getter_fun_" + _varDecl.name() + "_" + std::to_string(_varDecl.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation) | std::string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation) | ||||||
| { | { | ||||||
| 	// This uses the ID of the modifier invocation because it has to be unique
 | 	// This uses the ID of the modifier invocation because it has to be unique
 | ||||||
| 	// for each invocation.
 | 	// for each invocation.
 | ||||||
| 	solAssert(!_modifierInvocation.name().path().empty(), ""); | 	solAssert(!_modifierInvocation.name().path().empty(), ""); | ||||||
| 	string const& modifierName = _modifierInvocation.name().path().back(); | 	std::string const& modifierName = _modifierInvocation.name().path().back(); | ||||||
| 	solAssert(!modifierName.empty(), ""); | 	solAssert(!modifierName.empty(), ""); | ||||||
| 	return "modifier_" + modifierName + "_" + to_string(_modifierInvocation.id()); | 	return "modifier_" + modifierName + "_" + std::to_string(_modifierInvocation.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::functionWithModifierInner(FunctionDefinition const& _function) | std::string IRNames::functionWithModifierInner(FunctionDefinition const& _function) | ||||||
| { | { | ||||||
| 	return "fun_" + _function.name() + "_" + to_string(_function.id()) + "_inner"; | 	return "fun_" + _function.name() + "_" + std::to_string(_function.id()) + "_inner"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::creationObject(ContractDefinition const& _contract) | std::string IRNames::creationObject(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	return _contract.name() + "_" + toString(_contract.id()); | 	return _contract.name() + "_" + toString(_contract.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::deployedObject(ContractDefinition const& _contract) | std::string IRNames::deployedObject(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	return _contract.name() + "_" + toString(_contract.id()) + "_deployed"; | 	return _contract.name() + "_" + toString(_contract.id()) + "_deployed"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::internalDispatch(YulArity const& _arity) | std::string IRNames::internalDispatch(YulArity const& _arity) | ||||||
| { | { | ||||||
| 	return "dispatch_internal" | 	return "dispatch_internal" | ||||||
| 		"_in_" + to_string(_arity.in) + | 		"_in_" + std::to_string(_arity.in) + | ||||||
| 		"_out_" + to_string(_arity.out); | 		"_out_" + std::to_string(_arity.out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::constructor(ContractDefinition const& _contract) | std::string IRNames::constructor(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	return "constructor_" + _contract.name() + "_" + to_string(_contract.id()); | 	return "constructor_" + _contract.name() + "_" + std::to_string(_contract.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::libraryAddressImmutable() | std::string IRNames::libraryAddressImmutable() | ||||||
| { | { | ||||||
| 	return "library_deploy_address"; | 	return "library_deploy_address"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::constantValueFunction(VariableDeclaration const& _constant) | std::string IRNames::constantValueFunction(VariableDeclaration const& _constant) | ||||||
| { | { | ||||||
| 	solAssert(_constant.isConstant(), ""); | 	solAssert(_constant.isConstant(), ""); | ||||||
| 	return "constant_" + _constant.name() + "_" + to_string(_constant.id()); | 	return "constant_" + _constant.name() + "_" + std::to_string(_constant.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::localVariable(VariableDeclaration const& _declaration) | std::string IRNames::localVariable(VariableDeclaration const& _declaration) | ||||||
| { | { | ||||||
| 	return "var_" + _declaration.name() + '_' + std::to_string(_declaration.id()); | 	return "var_" + _declaration.name() + '_' + std::to_string(_declaration.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::localVariable(Expression const& _expression) | std::string IRNames::localVariable(Expression const& _expression) | ||||||
| { | { | ||||||
| 	return "expr_" + to_string(_expression.id()); | 	return "expr_" + std::to_string(_expression.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::trySuccessConditionVariable(Expression const& _expression) | std::string IRNames::trySuccessConditionVariable(Expression const& _expression) | ||||||
| { | { | ||||||
| 	auto annotation = dynamic_cast<FunctionCallAnnotation const*>(&_expression.annotation()); | 	auto annotation = dynamic_cast<FunctionCallAnnotation const*>(&_expression.annotation()); | ||||||
| 	solAssert(annotation, ""); | 	solAssert(annotation, ""); | ||||||
| 	solAssert(annotation->tryCall, "Parameter must be a FunctionCall with tryCall-annotation set."); | 	solAssert(annotation->tryCall, "Parameter must be a FunctionCall with tryCall-annotation set."); | ||||||
| 
 | 
 | ||||||
| 	return "trySuccessCondition_" + to_string(_expression.id()); | 	return "trySuccessCondition_" + std::to_string(_expression.id()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::tupleComponent(size_t _i) | std::string IRNames::tupleComponent(size_t _i) | ||||||
| { | { | ||||||
| 	return "component_" + to_string(_i + 1); | 	return "component_" + std::to_string(_i + 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRNames::zeroValue(Type const& _type, string const& _variableName) | std::string IRNames::zeroValue(Type const& _type, std::string const& _variableName) | ||||||
| { | { | ||||||
| 	return "zero_" + _type.identifier() + _variableName; | 	return "zero_" + _type.identifier() + _variableName; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context) | std::string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context) | ||||||
| { | { | ||||||
| 	solAssert(_location.sourceName, ""); | 	solAssert(_location.sourceName, ""); | ||||||
| 	_context.markSourceUsed(*_location.sourceName); | 	_context.markSourceUsed(*_location.sourceName); | ||||||
| 
 | 
 | ||||||
| 	string debugInfo = AsmPrinter::formatSourceLocation( | 	std::string debugInfo = AsmPrinter::formatSourceLocation( | ||||||
| 		_location, | 		_location, | ||||||
| 		_context.sourceIndices(), | 		_context.sourceIndices(), | ||||||
| 		_context.debugInfoSelection(), | 		_context.debugInfoSelection(), | ||||||
| @ -154,7 +153,7 @@ string dispenseLocationComment(langutil::SourceLocation const& _location, IRGene | |||||||
| 	return debugInfo.empty() ? "" : "/// " + debugInfo; | 	return debugInfo.empty() ? "" : "/// " + debugInfo; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context) | std::string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context) | ||||||
| { | { | ||||||
| 	return dispenseLocationComment(_node.location(), _context); | 	return dispenseLocationComment(_node.location(), _context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -32,14 +32,13 @@ | |||||||
| 
 | 
 | ||||||
| #include <range/v3/view/map.hpp> | #include <range/v3/view/map.hpp> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| 
 | 
 | ||||||
| string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function) | std::string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function) | ||||||
| { | { | ||||||
| 	string name = IRNames::function(_function); | 	std::string name = IRNames::function(_function); | ||||||
| 
 | 
 | ||||||
| 	if (!m_functions.contains(name)) | 	if (!m_functions.contains(name)) | ||||||
| 		m_functionGenerationQueue.insert(&_function); | 		m_functionGenerationQueue.insert(&_function); | ||||||
| @ -121,12 +120,12 @@ void IRGenerationContext::addStateVariable( | |||||||
| 	unsigned _byteOffset | 	unsigned _byteOffset | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	m_stateVariables[&_declaration] = make_pair(std::move(_storageOffset), _byteOffset); | 	m_stateVariables[&_declaration] = std::make_pair(std::move(_storageOffset), _byteOffset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerationContext::newYulVariable() | std::string IRGenerationContext::newYulVariable() | ||||||
| { | { | ||||||
| 	return "_" + to_string(++m_varCounter); | 	return "_" + std::to_string(++m_varCounter); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch) | void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch) | ||||||
|  | |||||||
| @ -43,18 +43,18 @@ | |||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <variant> | #include <variant> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| using namespace solidity::langutil; | using namespace solidity::langutil; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
|  | using namespace std::string_literals; | ||||||
| 
 | 
 | ||||||
| namespace | namespace | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| void verifyCallGraph( | void verifyCallGraph( | ||||||
| 	set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables, | 	std::set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables, | ||||||
| 	set<FunctionDefinition const*> _generatedFunctions | 	std::set<FunctionDefinition const*> _generatedFunctions | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	for (auto const& expectedCallable: _expectedCallables) | 	for (auto const& expectedCallable: _expectedCallables) | ||||||
| @ -73,47 +73,47 @@ void verifyCallGraph( | |||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables( | std::set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables( | ||||||
| 	CallGraph const& _graph | 	CallGraph const& _graph | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables; | 	std::set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables; | ||||||
| 	for (CallGraph::Node const& reachableNode: _graph.edges | ranges::views::keys) | 	for (CallGraph::Node const& reachableNode: _graph.edges | ranges::views::keys) | ||||||
| 		if (holds_alternative<CallableDeclaration const*>(reachableNode)) | 		if (std::holds_alternative<CallableDeclaration const*>(reachableNode)) | ||||||
| 			reachableCallables.emplace(get<CallableDeclaration const*>(reachableNode)); | 			reachableCallables.emplace(std::get<CallableDeclaration const*>(reachableNode)); | ||||||
| 
 | 
 | ||||||
| 	return reachableCallables; | 	return reachableCallables; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::run( | std::string IRGenerator::run( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	bytes const& _cborMetadata, | 	bytes const& _cborMetadata, | ||||||
| 	map<ContractDefinition const*, string_view const> const& _otherYulSources | 	std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	return yul::reindent(generate(_contract, _cborMetadata, _otherYulSources)); | 	return yul::reindent(generate(_contract, _cborMetadata, _otherYulSources)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generate( | std::string IRGenerator::generate( | ||||||
| 	ContractDefinition const& _contract, | 	ContractDefinition const& _contract, | ||||||
| 	bytes const& _cborMetadata, | 	bytes const& _cborMetadata, | ||||||
| 	map<ContractDefinition const*, string_view const> const& _otherYulSources | 	std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> string | 	auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> std::string | ||||||
| 	{ | 	{ | ||||||
| 		std::string subObjectsSources; | 		std::string subObjectsSources; | ||||||
| 		for (ContractDefinition const* subObject: subObjects) | 		for (ContractDefinition const* subObject: subObjects) | ||||||
| 			subObjectsSources += _otherYulSources.at(subObject); | 			subObjectsSources += _otherYulSources.at(subObject); | ||||||
| 		return subObjectsSources; | 		return subObjectsSources; | ||||||
| 	}; | 	}; | ||||||
| 	auto formatUseSrcMap = [](IRGenerationContext const& _context) -> string | 	auto formatUseSrcMap = [](IRGenerationContext const& _context) -> std::string | ||||||
| 	{ | 	{ | ||||||
| 		return joinHumanReadable( | 		return joinHumanReadable( | ||||||
| 			ranges::views::transform(_context.usedSourceNames(), [_context](string const& _sourceName) { | 			ranges::views::transform(_context.usedSourceNames(), [_context](std::string const& _sourceName) { | ||||||
| 				return to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName); | 				return std::to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName); | ||||||
| 			}), | 			}), | ||||||
| 			", " | 			", " | ||||||
| 		); | 		); | ||||||
| @ -162,7 +162,7 @@ string IRGenerator::generate( | |||||||
| 
 | 
 | ||||||
| 	FunctionDefinition const* constructor = _contract.constructor(); | 	FunctionDefinition const* constructor = _contract.constructor(); | ||||||
| 	t("callValueCheck", !constructor || !constructor->isPayable() ? callValueCheck() : ""); | 	t("callValueCheck", !constructor || !constructor->isPayable() ? callValueCheck() : ""); | ||||||
| 	vector<string> constructorParams; | 	std::vector<std::string> constructorParams; | ||||||
| 	if (constructor && !constructor->parameters().empty()) | 	if (constructor && !constructor->parameters().empty()) | ||||||
| 	{ | 	{ | ||||||
| 		for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i) | 		for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i) | ||||||
| @ -178,7 +178,7 @@ string IRGenerator::generate( | |||||||
| 
 | 
 | ||||||
| 	t("deploy", deployCode(_contract)); | 	t("deploy", deployCode(_contract)); | ||||||
| 	generateConstructors(_contract); | 	generateConstructors(_contract); | ||||||
| 	set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions(); | 	std::set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions(); | ||||||
| 	InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract); | 	InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract); | ||||||
| 
 | 
 | ||||||
| 	t("functions", m_context.functionCollector().requestedFunctions()); | 	t("functions", m_context.functionCollector().requestedFunctions()); | ||||||
| @ -201,7 +201,7 @@ string IRGenerator::generate( | |||||||
| 	t("sourceLocationCommentDeployed", dispenseLocationComment(_contract)); | 	t("sourceLocationCommentDeployed", dispenseLocationComment(_contract)); | ||||||
| 	t("library_address", IRNames::libraryAddressImmutable()); | 	t("library_address", IRNames::libraryAddressImmutable()); | ||||||
| 	t("dispatch", dispatchRoutine(_contract)); | 	t("dispatch", dispatchRoutine(_contract)); | ||||||
| 	set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions(); | 	std::set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions(); | ||||||
| 	generateInternalDispatchFunctions(_contract); | 	generateInternalDispatchFunctions(_contract); | ||||||
| 	t("deployedFunctions", m_context.functionCollector().requestedFunctions()); | 	t("deployedFunctions", m_context.functionCollector().requestedFunctions()); | ||||||
| 	t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated())); | 	t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated())); | ||||||
| @ -222,16 +222,16 @@ string IRGenerator::generate( | |||||||
| 	return t.render(); | 	return t.render(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generate(Block const& _block) | std::string IRGenerator::generate(Block const& _block) | ||||||
| { | { | ||||||
| 	IRGeneratorForStatements generator(m_context, m_utils); | 	IRGeneratorForStatements generator(m_context, m_utils); | ||||||
| 	generator.generate(_block); | 	generator.generate(_block); | ||||||
| 	return generator.code(); | 	return generator.code(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions() | std::set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions() | ||||||
| { | { | ||||||
| 	set<FunctionDefinition const*> functions; | 	std::set<FunctionDefinition const*> functions; | ||||||
| 
 | 
 | ||||||
| 	while (!m_context.functionGenerationQueueEmpty()) | 	while (!m_context.functionGenerationQueueEmpty()) | ||||||
| 	{ | 	{ | ||||||
| @ -256,7 +256,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin | |||||||
| 	InternalDispatchMap internalDispatchMap = m_context.consumeInternalDispatchMap(); | 	InternalDispatchMap internalDispatchMap = m_context.consumeInternalDispatchMap(); | ||||||
| 	for (YulArity const& arity: internalDispatchMap | ranges::views::keys) | 	for (YulArity const& arity: internalDispatchMap | ranges::views::keys) | ||||||
| 	{ | 	{ | ||||||
| 		string funName = IRNames::internalDispatch(arity); | 		std::string funName = IRNames::internalDispatch(arity); | ||||||
| 		m_context.functionCollector().createFunction(funName, [&]() { | 		m_context.functionCollector().createFunction(funName, [&]() { | ||||||
| 			Whiskers templ(R"( | 			Whiskers templ(R"( | ||||||
| 				<sourceLocationComment> | 				<sourceLocationComment> | ||||||
| @ -278,7 +278,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin | |||||||
| 			templ("in", suffixedVariableNameList("in_", 0, arity.in)); | 			templ("in", suffixedVariableNameList("in_", 0, arity.in)); | ||||||
| 			templ("out", suffixedVariableNameList("out_", 0, arity.out)); | 			templ("out", suffixedVariableNameList("out_", 0, arity.out)); | ||||||
| 
 | 
 | ||||||
| 			vector<map<string, string>> cases; | 			std::vector<std::map<std::string, std::string>> cases; | ||||||
| 			for (FunctionDefinition const* function: internalDispatchMap.at(arity)) | 			for (FunctionDefinition const* function: internalDispatchMap.at(arity)) | ||||||
| 			{ | 			{ | ||||||
| 				solAssert(function, ""); | 				solAssert(function, ""); | ||||||
| @ -291,8 +291,8 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin | |||||||
| 				solAssert(function->id() != 0, "Unexpected function ID: 0"); | 				solAssert(function->id() != 0, "Unexpected function ID: 0"); | ||||||
| 				solAssert(m_context.functionCollector().contains(IRNames::function(*function)), ""); | 				solAssert(m_context.functionCollector().contains(IRNames::function(*function)), ""); | ||||||
| 
 | 
 | ||||||
| 				cases.emplace_back(map<string, string>{ | 				cases.emplace_back(std::map<std::string, std::string>{ | ||||||
| 					{"funID", to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))}, | 					{"funID", std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))}, | ||||||
| 					{"name", IRNames::function(*function)} | 					{"name", IRNames::function(*function)} | ||||||
| 				}); | 				}); | ||||||
| 			} | 			} | ||||||
| @ -311,9 +311,9 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin | |||||||
| 	return internalDispatchMap; | 	return internalDispatchMap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateFunction(FunctionDefinition const& _function) | std::string IRGenerator::generateFunction(FunctionDefinition const& _function) | ||||||
| { | { | ||||||
| 	string functionName = IRNames::function(_function); | 	std::string functionName = IRNames::function(_function); | ||||||
| 	return m_context.functionCollector().createFunction(functionName, [&]() { | 	return m_context.functionCollector().createFunction(functionName, [&]() { | ||||||
| 		m_context.resetLocalVariables(); | 		m_context.resetLocalVariables(); | ||||||
| 		Whiskers t(R"( | 		Whiskers t(R"( | ||||||
| @ -326,7 +326,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) | |||||||
| 		)"); | 		)"); | ||||||
| 
 | 
 | ||||||
| 		if (m_context.debugInfoSelection().astID) | 		if (m_context.debugInfoSelection().astID) | ||||||
| 			t("astIDComment", "/// @ast-id " + to_string(_function.id()) + "\n"); | 			t("astIDComment", "/// @ast-id " + std::to_string(_function.id()) + "\n"); | ||||||
| 		else | 		else | ||||||
| 			t("astIDComment", ""); | 			t("astIDComment", ""); | ||||||
| 		t("sourceLocationComment", dispenseLocationComment(_function)); | 		t("sourceLocationComment", dispenseLocationComment(_function)); | ||||||
| @ -336,12 +336,12 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) | |||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		t("functionName", functionName); | 		t("functionName", functionName); | ||||||
| 		vector<string> params; | 		std::vector<std::string> params; | ||||||
| 		for (auto const& varDecl: _function.parameters()) | 		for (auto const& varDecl: _function.parameters()) | ||||||
| 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 		t("params", joinHumanReadable(params)); | 		t("params", joinHumanReadable(params)); | ||||||
| 		vector<string> retParams; | 		std::vector<std::string> retParams; | ||||||
| 		string retInit; | 		std::string retInit; | ||||||
| 		for (auto const& varDecl: _function.returnParameters()) | 		for (auto const& varDecl: _function.returnParameters()) | ||||||
| 		{ | 		{ | ||||||
| 			retParams += m_context.addLocalVariable(*varDecl).stackSlots(); | 			retParams += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| @ -358,14 +358,14 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) | |||||||
| 			for (size_t i = 0; i < _function.modifiers().size(); ++i) | 			for (size_t i = 0; i < _function.modifiers().size(); ++i) | ||||||
| 			{ | 			{ | ||||||
| 				ModifierInvocation const& modifier = *_function.modifiers().at(i); | 				ModifierInvocation const& modifier = *_function.modifiers().at(i); | ||||||
| 				string next = | 				std::string next = | ||||||
| 					i + 1 < _function.modifiers().size() ? | 					i + 1 < _function.modifiers().size() ? | ||||||
| 					IRNames::modifierInvocation(*_function.modifiers().at(i + 1)) : | 					IRNames::modifierInvocation(*_function.modifiers().at(i + 1)) : | ||||||
| 					IRNames::functionWithModifierInner(_function); | 					IRNames::functionWithModifierInner(_function); | ||||||
| 				generateModifier(modifier, _function, next); | 				generateModifier(modifier, _function, next); | ||||||
| 			} | 			} | ||||||
| 			t("body", | 			t("body", | ||||||
| 				(retParams.empty() ? string{} : joinHumanReadable(retParams) + " := ") + | 				(retParams.empty() ? std::string{} : joinHumanReadable(retParams) + " := ") + | ||||||
| 				IRNames::modifierInvocation(*_function.modifiers().at(0)) + | 				IRNames::modifierInvocation(*_function.modifiers().at(0)) + | ||||||
| 				"(" + | 				"(" + | ||||||
| 				joinHumanReadable(retParams + params) + | 				joinHumanReadable(retParams + params) + | ||||||
| @ -378,13 +378,13 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateModifier( | std::string IRGenerator::generateModifier( | ||||||
| 	ModifierInvocation const& _modifierInvocation, | 	ModifierInvocation const& _modifierInvocation, | ||||||
| 	FunctionDefinition const& _function, | 	FunctionDefinition const& _function, | ||||||
| 	string const& _nextFunction | 	std::string const& _nextFunction | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string functionName = IRNames::modifierInvocation(_modifierInvocation); | 	std::string functionName = IRNames::modifierInvocation(_modifierInvocation); | ||||||
| 	return m_context.functionCollector().createFunction(functionName, [&]() { | 	return m_context.functionCollector().createFunction(functionName, [&]() { | ||||||
| 		m_context.resetLocalVariables(); | 		m_context.resetLocalVariables(); | ||||||
| 		Whiskers t(R"( | 		Whiskers t(R"( | ||||||
| @ -398,15 +398,15 @@ string IRGenerator::generateModifier( | |||||||
| 		)"); | 		)"); | ||||||
| 
 | 
 | ||||||
| 		t("functionName", functionName); | 		t("functionName", functionName); | ||||||
| 		vector<string> retParamsIn; | 		std::vector<std::string> retParamsIn; | ||||||
| 		for (auto const& varDecl: _function.returnParameters()) | 		for (auto const& varDecl: _function.returnParameters()) | ||||||
| 			retParamsIn += m_context.addLocalVariable(*varDecl).stackSlots(); | 			retParamsIn += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 		vector<string> params = retParamsIn; | 		std::vector<std::string> params = retParamsIn; | ||||||
| 		for (auto const& varDecl: _function.parameters()) | 		for (auto const& varDecl: _function.parameters()) | ||||||
| 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 		t("params", joinHumanReadable(params)); | 		t("params", joinHumanReadable(params)); | ||||||
| 		vector<string> retParams; | 		std::vector<std::string> retParams; | ||||||
| 		string assignRetParams; | 		std::string assignRetParams; | ||||||
| 		for (size_t i = 0; i < retParamsIn.size(); ++i) | 		for (size_t i = 0; i < retParamsIn.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| 			retParams.emplace_back(m_context.newYulVariable()); | 			retParams.emplace_back(m_context.newYulVariable()); | ||||||
| @ -421,7 +421,7 @@ string IRGenerator::generateModifier( | |||||||
| 		solAssert(modifier, ""); | 		solAssert(modifier, ""); | ||||||
| 
 | 
 | ||||||
| 		if (m_context.debugInfoSelection().astID) | 		if (m_context.debugInfoSelection().astID) | ||||||
| 			t("astIDComment", "/// @ast-id " + to_string(modifier->id()) + "\n"); | 			t("astIDComment", "/// @ast-id " + std::to_string(modifier->id()) + "\n"); | ||||||
| 		else | 		else | ||||||
| 			t("astIDComment", ""); | 			t("astIDComment", ""); | ||||||
| 		t("sourceLocationComment", dispenseLocationComment(*modifier)); | 		t("sourceLocationComment", dispenseLocationComment(*modifier)); | ||||||
| @ -463,7 +463,7 @@ string IRGenerator::generateModifier( | |||||||
| 
 | 
 | ||||||
| 		t("evalArgs", expressionEvaluator.code()); | 		t("evalArgs", expressionEvaluator.code()); | ||||||
| 		IRGeneratorForStatements generator(m_context, m_utils, [&]() { | 		IRGeneratorForStatements generator(m_context, m_utils, [&]() { | ||||||
| 			string ret = joinHumanReadable(retParams); | 			std::string ret = joinHumanReadable(retParams); | ||||||
| 			return | 			return | ||||||
| 				(ret.empty() ? "" : ret + " := ") + | 				(ret.empty() ? "" : ret + " := ") + | ||||||
| 				_nextFunction + "(" + joinHumanReadable(params) + ")\n"; | 				_nextFunction + "(" + joinHumanReadable(params) + ")\n"; | ||||||
| @ -474,9 +474,9 @@ string IRGenerator::generateModifier( | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function) | std::string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function) | ||||||
| { | { | ||||||
| 	string functionName = IRNames::functionWithModifierInner(_function); | 	std::string functionName = IRNames::functionWithModifierInner(_function); | ||||||
| 	return m_context.functionCollector().createFunction(functionName, [&]() { | 	return m_context.functionCollector().createFunction(functionName, [&]() { | ||||||
| 		m_context.resetLocalVariables(); | 		m_context.resetLocalVariables(); | ||||||
| 		Whiskers t(R"( | 		Whiskers t(R"( | ||||||
| @ -493,17 +493,17 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& | |||||||
| 			dispenseLocationComment(m_context.mostDerivedContract()) | 			dispenseLocationComment(m_context.mostDerivedContract()) | ||||||
| 		); | 		); | ||||||
| 		t("functionName", functionName); | 		t("functionName", functionName); | ||||||
| 		vector<string> retParams; | 		std::vector<std::string> retParams; | ||||||
| 		vector<string> retParamsIn; | 		std::vector<std::string> retParamsIn; | ||||||
| 		for (auto const& varDecl: _function.returnParameters()) | 		for (auto const& varDecl: _function.returnParameters()) | ||||||
| 			retParams += m_context.addLocalVariable(*varDecl).stackSlots(); | 			retParams += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 		string assignRetParams; | 		std::string assignRetParams; | ||||||
| 		for (size_t i = 0; i < retParams.size(); ++i) | 		for (size_t i = 0; i < retParams.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| 			retParamsIn.emplace_back(m_context.newYulVariable()); | 			retParamsIn.emplace_back(m_context.newYulVariable()); | ||||||
| 			assignRetParams += retParams.at(i) + " := " + retParamsIn.at(i) + "\n"; | 			assignRetParams += retParams.at(i) + " := " + retParamsIn.at(i) + "\n"; | ||||||
| 		} | 		} | ||||||
| 		vector<string> params = retParamsIn; | 		std::vector<std::string> params = retParamsIn; | ||||||
| 		for (auto const& varDecl: _function.parameters()) | 		for (auto const& varDecl: _function.parameters()) | ||||||
| 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | 			params += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 		t("params", joinHumanReadable(params)); | 		t("params", joinHumanReadable(params)); | ||||||
| @ -514,9 +514,9 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | ||||||
| { | { | ||||||
| 	string functionName = IRNames::function(_varDecl); | 	std::string functionName = IRNames::function(_varDecl); | ||||||
| 	return m_context.functionCollector().createFunction(functionName, [&]() { | 	return m_context.functionCollector().createFunction(functionName, [&]() { | ||||||
| 		Type const* type = _varDecl.annotation().type; | 		Type const* type = _varDecl.annotation().type; | ||||||
| 
 | 
 | ||||||
| @ -538,7 +538,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			( | 			( | ||||||
| 				"astIDComment", | 				"astIDComment", | ||||||
| 				m_context.debugInfoSelection().astID ? | 				m_context.debugInfoSelection().astID ? | ||||||
| 					"/// @ast-id " + to_string(_varDecl.id()) + "\n" : | 					"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" : | ||||||
| 					"" | 					"" | ||||||
| 			) | 			) | ||||||
| 			("sourceLocationComment", dispenseLocationComment(_varDecl)) | 			("sourceLocationComment", dispenseLocationComment(_varDecl)) | ||||||
| @ -547,7 +547,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 				dispenseLocationComment(m_context.mostDerivedContract()) | 				dispenseLocationComment(m_context.mostDerivedContract()) | ||||||
| 			) | 			) | ||||||
| 			("functionName", functionName) | 			("functionName", functionName) | ||||||
| 			("id", to_string(_varDecl.id())) | 			("id", std::to_string(_varDecl.id())) | ||||||
| 			.render(); | 			.render(); | ||||||
| 		} | 		} | ||||||
| 		else if (_varDecl.isConstant()) | 		else if (_varDecl.isConstant()) | ||||||
| @ -563,7 +563,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			( | 			( | ||||||
| 				"astIDComment", | 				"astIDComment", | ||||||
| 				m_context.debugInfoSelection().astID ? | 				m_context.debugInfoSelection().astID ? | ||||||
| 					"/// @ast-id " + to_string(_varDecl.id()) + "\n" : | 					"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" : | ||||||
| 					"" | 					"" | ||||||
| 			) | 			) | ||||||
| 			("sourceLocationComment", dispenseLocationComment(_varDecl)) | 			("sourceLocationComment", dispenseLocationComment(_varDecl)) | ||||||
| @ -577,7 +577,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			.render(); | 			.render(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		string code; | 		std::string code; | ||||||
| 
 | 
 | ||||||
| 		auto const& location = m_context.storageLocationOfStateVariable(_varDecl); | 		auto const& location = m_context.storageLocationOfStateVariable(_varDecl); | ||||||
| 		code += Whiskers(R"( | 		code += Whiskers(R"( | ||||||
| @ -585,7 +585,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			let offset := <offset> | 			let offset := <offset> | ||||||
| 		)") | 		)") | ||||||
| 		("slot", location.first.str()) | 		("slot", location.first.str()) | ||||||
| 		("offset", to_string(location.second)) | 		("offset", std::to_string(location.second)) | ||||||
| 		.render(); | 		.render(); | ||||||
| 
 | 
 | ||||||
| 		if (!paramTypes.empty()) | 		if (!paramTypes.empty()) | ||||||
| @ -601,8 +601,8 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 		// The initial value of @a currentType is only used if we skip the loop completely.
 | 		// The initial value of @a currentType is only used if we skip the loop completely.
 | ||||||
| 		Type const* currentType = _varDecl.annotation().type; | 		Type const* currentType = _varDecl.annotation().type; | ||||||
| 
 | 
 | ||||||
| 		vector<string> parameters; | 		std::vector<std::string> parameters; | ||||||
| 		vector<string> returnVariables; | 		std::vector<std::string> returnVariables; | ||||||
| 
 | 
 | ||||||
| 		for (size_t i = 0; i < paramTypes.size(); ++i) | 		for (size_t i = 0; i < paramTypes.size(); ++i) | ||||||
| 		{ | 		{ | ||||||
| @ -610,7 +610,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			ArrayType const* arrayType = dynamic_cast<ArrayType const*>(currentType); | 			ArrayType const* arrayType = dynamic_cast<ArrayType const*>(currentType); | ||||||
| 			solAssert(mappingType || arrayType, ""); | 			solAssert(mappingType || arrayType, ""); | ||||||
| 
 | 
 | ||||||
| 			vector<string> keys = IRVariable("key_" + to_string(i), | 			std::vector<std::string> keys = IRVariable("key_" + std::to_string(i), | ||||||
| 				mappingType ? *mappingType->keyType() : *TypeProvider::uint256() | 				mappingType ? *mappingType->keyType() : *TypeProvider::uint256() | ||||||
| 			).stackSlots(); | 			).stackSlots(); | ||||||
| 			parameters += keys; | 			parameters += keys; | ||||||
| @ -653,8 +653,8 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 				) | 				) | ||||||
| 					continue; | 					continue; | ||||||
| 
 | 
 | ||||||
| 				pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); | 				std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]); | ||||||
| 				vector<string> retVars = IRVariable("ret_" + to_string(returnVariables.size()), *returnTypes[i]).stackSlots(); | 				std::vector<std::string> retVars = IRVariable("ret_" + std::to_string(returnVariables.size()), *returnTypes[i]).stackSlots(); | ||||||
| 				returnVariables += retVars; | 				returnVariables += retVars; | ||||||
| 				code += Whiskers(R"( | 				code += Whiskers(R"( | ||||||
| 					<ret> := <readStorage>(add(slot, <slotOffset>)) | 					<ret> := <readStorage>(add(slot, <slotOffset>)) | ||||||
| @ -671,7 +671,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 			auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front()); | 			auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front()); | ||||||
| 			if (arrayType) | 			if (arrayType) | ||||||
| 				solAssert(arrayType->isByteArrayOrString(), ""); | 				solAssert(arrayType->isByteArrayOrString(), ""); | ||||||
| 			vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots(); | 			std::vector<std::string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots(); | ||||||
| 			returnVariables += retVars; | 			returnVariables += retVars; | ||||||
| 			code += Whiskers(R"( | 			code += Whiskers(R"( | ||||||
| 				<ret> := <readStorage>(slot, offset) | 				<ret> := <readStorage>(slot, offset) | ||||||
| @ -695,7 +695,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 		( | 		( | ||||||
| 			"astIDComment", | 			"astIDComment", | ||||||
| 			m_context.debugInfoSelection().astID ? | 			m_context.debugInfoSelection().astID ? | ||||||
| 				"/// @ast-id " + to_string(_varDecl.id()) + "\n" : | 				"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" : | ||||||
| 				"" | 				"" | ||||||
| 		) | 		) | ||||||
| 		("sourceLocationComment", dispenseLocationComment(_varDecl)) | 		("sourceLocationComment", dispenseLocationComment(_varDecl)) | ||||||
| @ -707,10 +707,10 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType) | std::string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType) | ||||||
| { | { | ||||||
| 	string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration()); | 	std::string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration()); | ||||||
| 	return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string { | 	return m_context.functionCollector().createFunction(functionName, [&](std::vector<std::string>&, std::vector<std::string>&) -> std::string { | ||||||
| 		Whiskers t(R"X( | 		Whiskers t(R"X( | ||||||
| 			<callValueCheck> | 			<callValueCheck> | ||||||
| 			<?+params>let <params> := </+params> <abiDecode>(4, calldatasize()) | 			<?+params>let <params> := </+params> <abiDecode>(4, calldatasize()) | ||||||
| @ -721,8 +721,8 @@ string IRGenerator::generateExternalFunction(ContractDefinition const& _contract | |||||||
| 		)X"); | 		)X"); | ||||||
| 		t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck()); | 		t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck()); | ||||||
| 
 | 
 | ||||||
| 		unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack(); | 		unsigned paramVars = std::make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack(); | ||||||
| 		unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack(); | 		unsigned retVars = std::make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack(); | ||||||
| 
 | 
 | ||||||
| 		ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); | 		ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector()); | ||||||
| 		t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); | 		t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes())); | ||||||
| @ -745,14 +745,14 @@ string IRGenerator::generateExternalFunction(ContractDefinition const& _contract | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl) | std::string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl) | ||||||
| { | { | ||||||
| 	IRGeneratorForStatements generator(m_context, m_utils); | 	IRGeneratorForStatements generator(m_context, m_utils); | ||||||
| 	generator.initializeLocalVar(_varDecl); | 	generator.initializeLocalVar(_varDecl); | ||||||
| 	return generator.code(); | 	return generator.code(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evaluateConstructorArguments( | std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> IRGenerator::evaluateConstructorArguments( | ||||||
| 	ContractDefinition const& _contract | 	ContractDefinition const& _contract | ||||||
| ) | ) | ||||||
| { | { | ||||||
| @ -765,12 +765,12 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua | |||||||
| 			auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2); | 			auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2); | ||||||
| 			return it1 < it2; | 			return it1 < it2; | ||||||
| 		} | 		} | ||||||
| 		vector<ContractDefinition const*> const& linearizedBaseContracts; | 		std::vector<ContractDefinition const*> const& linearizedBaseContracts; | ||||||
| 	} inheritanceOrder{_contract.annotation().linearizedBaseContracts}; | 	} inheritanceOrder{_contract.annotation().linearizedBaseContracts}; | ||||||
| 
 | 
 | ||||||
| 	map<ContractDefinition const*, vector<string>> constructorParams; | 	std::map<ContractDefinition const*, std::vector<std::string>> constructorParams; | ||||||
| 
 | 
 | ||||||
| 	map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder> | 	std::map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder> | ||||||
| 		baseConstructorArguments(inheritanceOrder); | 		baseConstructorArguments(inheritanceOrder); | ||||||
| 
 | 
 | ||||||
| 	for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts()) | 	for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts()) | ||||||
| @ -802,7 +802,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua | |||||||
| 		solAssert(baseContract && arguments, ""); | 		solAssert(baseContract && arguments, ""); | ||||||
| 		if (baseContract->constructor() && !arguments->empty()) | 		if (baseContract->constructor() && !arguments->empty()) | ||||||
| 		{ | 		{ | ||||||
| 			vector<string> params; | 			std::vector<std::string> params; | ||||||
| 			for (size_t i = 0; i < arguments->size(); ++i) | 			for (size_t i = 0; i < arguments->size(); ++i) | ||||||
| 				params += generator.evaluateExpression( | 				params += generator.evaluateExpression( | ||||||
| 					*(arguments->at(i)), | 					*(arguments->at(i)), | ||||||
| @ -815,7 +815,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua | |||||||
| 	return {generator.code(), constructorParams}; | 	return {generator.code(), constructorParams}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::initStateVariables(ContractDefinition const& _contract) | std::string IRGenerator::initStateVariables(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	IRGeneratorForStatements generator{m_context, m_utils}; | 	IRGeneratorForStatements generator{m_context, m_utils}; | ||||||
| 	for (VariableDeclaration const* variable: _contract.stateVariables()) | 	for (VariableDeclaration const* variable: _contract.stateVariables()) | ||||||
| @ -829,16 +829,16 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract) | |||||||
| void IRGenerator::generateConstructors(ContractDefinition const& _contract) | void IRGenerator::generateConstructors(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	auto listAllParams = | 	auto listAllParams = | ||||||
| 		[&](map<ContractDefinition const*, vector<string>> const& baseParams) -> vector<string> | 		[&](std::map<ContractDefinition const*, std::vector<std::string>> const& baseParams) -> std::vector<std::string> | ||||||
| 		{ | 		{ | ||||||
| 			vector<string> params; | 			std::vector<std::string> params; | ||||||
| 			for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) | 			for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) | ||||||
| 				if (baseParams.count(contract)) | 				if (baseParams.count(contract)) | ||||||
| 					params += baseParams.at(contract); | 					params += baseParams.at(contract); | ||||||
| 			return params; | 			return params; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 	map<ContractDefinition const*, vector<string>> baseConstructorParams; | 	std::map<ContractDefinition const*, std::vector<std::string>> baseConstructorParams; | ||||||
| 	for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i) | 	for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i) | ||||||
| 	{ | 	{ | ||||||
| 		ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i]; | 		ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i]; | ||||||
| @ -857,13 +857,13 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) | |||||||
| 				} | 				} | ||||||
| 				<contractSourceLocationComment> | 				<contractSourceLocationComment> | ||||||
| 			)"); | 			)"); | ||||||
| 			vector<string> params; | 			std::vector<std::string> params; | ||||||
| 			if (contract->constructor()) | 			if (contract->constructor()) | ||||||
| 				for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters()) | 				for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters()) | ||||||
| 					params += m_context.addLocalVariable(*varDecl).stackSlots(); | 					params += m_context.addLocalVariable(*varDecl).stackSlots(); | ||||||
| 
 | 
 | ||||||
| 			if (m_context.debugInfoSelection().astID && contract->constructor()) | 			if (m_context.debugInfoSelection().astID && contract->constructor()) | ||||||
| 				t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n"); | 				t("astIDComment", "/// @ast-id " + std::to_string(contract->constructor()->id()) + "\n"); | ||||||
| 			else | 			else | ||||||
| 				t("astIDComment", ""); | 				t("astIDComment", ""); | ||||||
| 			t("sourceLocationComment", dispenseLocationComment( | 			t("sourceLocationComment", dispenseLocationComment( | ||||||
| @ -877,11 +877,11 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) | |||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			t("params", joinHumanReadable(params)); | 			t("params", joinHumanReadable(params)); | ||||||
| 			vector<string> baseParams = listAllParams(baseConstructorParams); | 			std::vector<std::string> baseParams = listAllParams(baseConstructorParams); | ||||||
| 			t("baseParams", joinHumanReadable(baseParams)); | 			t("baseParams", joinHumanReadable(baseParams)); | ||||||
| 			t("comma", !params.empty() && !baseParams.empty() ? ", " : ""); | 			t("comma", !params.empty() && !baseParams.empty() ? ", " : ""); | ||||||
| 			t("functionName", IRNames::constructor(*contract)); | 			t("functionName", IRNames::constructor(*contract)); | ||||||
| 			pair<string, map<ContractDefinition const*, vector<string>>> evaluatedArgs = evaluateConstructorArguments(*contract); | 			std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> evaluatedArgs = evaluateConstructorArguments(*contract); | ||||||
| 			baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end()); | 			baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end()); | ||||||
| 			t("evalBaseArguments", evaluatedArgs.first); | 			t("evalBaseArguments", evaluatedArgs.first); | ||||||
| 			if (i < _contract.annotation().linearizedBaseContracts.size() - 1) | 			if (i < _contract.annotation().linearizedBaseContracts.size() - 1) | ||||||
| @ -894,10 +894,10 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) | |||||||
| 			else | 			else | ||||||
| 				t("hasNextConstructor", false); | 				t("hasNextConstructor", false); | ||||||
| 			t("initStateVariables", initStateVariables(*contract)); | 			t("initStateVariables", initStateVariables(*contract)); | ||||||
| 			string body; | 			std::string body; | ||||||
| 			if (FunctionDefinition const* constructor = contract->constructor()) | 			if (FunctionDefinition const* constructor = contract->constructor()) | ||||||
| 			{ | 			{ | ||||||
| 				vector<ModifierInvocation*> realModifiers; | 				std::vector<ModifierInvocation*> realModifiers; | ||||||
| 				for (auto const& modifierInvocation: constructor->modifiers()) | 				for (auto const& modifierInvocation: constructor->modifiers()) | ||||||
| 					// Filter out the base constructor calls
 | 					// Filter out the base constructor calls
 | ||||||
| 					if (dynamic_cast<ModifierDefinition const*>(modifierInvocation->name().annotation().referencedDeclaration)) | 					if (dynamic_cast<ModifierDefinition const*>(modifierInvocation->name().annotation().referencedDeclaration)) | ||||||
| @ -909,7 +909,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) | |||||||
| 					for (size_t i = 0; i < realModifiers.size(); ++i) | 					for (size_t i = 0; i < realModifiers.size(); ++i) | ||||||
| 					{ | 					{ | ||||||
| 						ModifierInvocation const& modifier = *realModifiers.at(i); | 						ModifierInvocation const& modifier = *realModifiers.at(i); | ||||||
| 						string next = | 						std::string next = | ||||||
| 							i + 1 < realModifiers.size() ? | 							i + 1 < realModifiers.size() ? | ||||||
| 							IRNames::modifierInvocation(*realModifiers.at(i + 1)) : | 							IRNames::modifierInvocation(*realModifiers.at(i + 1)) : | ||||||
| 							IRNames::functionWithModifierInner(*constructor); | 							IRNames::functionWithModifierInner(*constructor); | ||||||
| @ -931,7 +931,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::deployCode(ContractDefinition const& _contract) | std::string IRGenerator::deployCode(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	Whiskers t(R"X( | 	Whiskers t(R"X( | ||||||
| 		let <codeOffset> := <allocateUnbounded>() | 		let <codeOffset> := <allocateUnbounded>() | ||||||
| @ -945,11 +945,11 @@ string IRGenerator::deployCode(ContractDefinition const& _contract) | |||||||
| 	t("codeOffset", m_context.newYulVariable()); | 	t("codeOffset", m_context.newYulVariable()); | ||||||
| 	t("object", IRNames::deployedObject(_contract)); | 	t("object", IRNames::deployedObject(_contract)); | ||||||
| 
 | 
 | ||||||
| 	vector<map<string, string>> immutables; | 	std::vector<std::map<std::string, std::string>> immutables; | ||||||
| 	if (_contract.isLibrary()) | 	if (_contract.isLibrary()) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(ContractType(_contract).immutableVariables().empty(), ""); | 		solAssert(ContractType(_contract).immutableVariables().empty(), ""); | ||||||
| 		immutables.emplace_back(map<string, string>{ | 		immutables.emplace_back(std::map<std::string, std::string>{ | ||||||
| 			{"immutableName"s, IRNames::libraryAddressImmutable()}, | 			{"immutableName"s, IRNames::libraryAddressImmutable()}, | ||||||
| 			{"value"s, "address()"} | 			{"value"s, "address()"} | ||||||
| 		}); | 		}); | ||||||
| @ -960,21 +960,21 @@ string IRGenerator::deployCode(ContractDefinition const& _contract) | |||||||
| 		{ | 		{ | ||||||
| 			solUnimplementedAssert(immutable->type()->isValueType()); | 			solUnimplementedAssert(immutable->type()->isValueType()); | ||||||
| 			solUnimplementedAssert(immutable->type()->sizeOnStack() == 1); | 			solUnimplementedAssert(immutable->type()->sizeOnStack() == 1); | ||||||
| 			immutables.emplace_back(map<string, string>{ | 			immutables.emplace_back(std::map<std::string, std::string>{ | ||||||
| 				{"immutableName"s, to_string(immutable->id())}, | 				{"immutableName"s, std::to_string(immutable->id())}, | ||||||
| 				{"value"s, "mload(" + to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} | 				{"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"} | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 	t("immutables", std::move(immutables)); | 	t("immutables", std::move(immutables)); | ||||||
| 	return t.render(); | 	return t.render(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::callValueCheck() | std::string IRGenerator::callValueCheck() | ||||||
| { | { | ||||||
| 	return "if callvalue() { " + m_utils.revertReasonIfDebugFunction("Ether sent to non-payable function") + "() }"; | 	return "if callvalue() { " + m_utils.revertReasonIfDebugFunction("Ether sent to non-payable function") + "() }"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) | std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) | ||||||
| { | { | ||||||
| 	Whiskers t(R"X( | 	Whiskers t(R"X( | ||||||
| 		<?+cases>if iszero(lt(calldatasize(), 4)) | 		<?+cases>if iszero(lt(calldatasize(), 4)) | ||||||
| @ -995,15 +995,15 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) | |||||||
| 		<fallback> | 		<fallback> | ||||||
| 	)X"); | 	)X"); | ||||||
| 	t("shr224", m_utils.shiftRightFunction(224)); | 	t("shr224", m_utils.shiftRightFunction(224)); | ||||||
| 	vector<map<string, string>> functions; | 	std::vector<std::map<std::string, std::string>> functions; | ||||||
| 	for (auto const& function: _contract.interfaceFunctions()) | 	for (auto const& function: _contract.interfaceFunctions()) | ||||||
| 	{ | 	{ | ||||||
| 		functions.emplace_back(); | 		functions.emplace_back(); | ||||||
| 		map<string, string>& templ = functions.back(); | 		std::map<std::string, std::string>& templ = functions.back(); | ||||||
| 		templ["functionSelector"] = "0x" + function.first.hex(); | 		templ["functionSelector"] = "0x" + function.first.hex(); | ||||||
| 		FunctionTypePointer const& type = function.second; | 		FunctionTypePointer const& type = function.second; | ||||||
| 		templ["functionName"] = type->externalSignature(); | 		templ["functionName"] = type->externalSignature(); | ||||||
| 		string delegatecallCheck; | 		std::string delegatecallCheck; | ||||||
| 		if (_contract.isLibrary()) | 		if (_contract.isLibrary()) | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(!type->isPayable(), ""); | 			solAssert(!type->isPayable(), ""); | ||||||
| @ -1031,7 +1031,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) | |||||||
| 	if (FunctionDefinition const* fallback = _contract.fallbackFunction()) | 	if (FunctionDefinition const* fallback = _contract.fallbackFunction()) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(!_contract.isLibrary(), ""); | 		solAssert(!_contract.isLibrary(), ""); | ||||||
| 		string fallbackCode; | 		std::string fallbackCode; | ||||||
| 		if (!fallback->isPayable()) | 		if (!fallback->isPayable()) | ||||||
| 			fallbackCode += callValueCheck() + "\n"; | 			fallbackCode += callValueCheck() + "\n"; | ||||||
| 		if (fallback->parameters().empty()) | 		if (fallback->parameters().empty()) | ||||||
| @ -1055,7 +1055,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) | |||||||
| 	return t.render(); | 	return t.render(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::memoryInit(bool _useMemoryGuard) | std::string IRGenerator::memoryInit(bool _useMemoryGuard) | ||||||
| { | { | ||||||
| 	// This function should be called at the beginning of the EVM call frame
 | 	// This function should be called at the beginning of the EVM call frame
 | ||||||
| 	// and thus can assume all memory to be zero, including the contents of
 | 	// and thus can assume all memory to be zero, including the contents of
 | ||||||
| @ -1066,10 +1066,10 @@ string IRGenerator::memoryInit(bool _useMemoryGuard) | |||||||
| 			"mstore(<memPtr>, memoryguard(<freeMemoryStart>))" : | 			"mstore(<memPtr>, memoryguard(<freeMemoryStart>))" : | ||||||
| 			"mstore(<memPtr>, <freeMemoryStart>)" | 			"mstore(<memPtr>, <freeMemoryStart>)" | ||||||
| 		} | 		} | ||||||
| 		("memPtr", to_string(CompilerUtils::freeMemoryPointer)) | 		("memPtr", std::to_string(CompilerUtils::freeMemoryPointer)) | ||||||
| 		( | 		( | ||||||
| 			"freeMemoryStart", | 			"freeMemoryStart", | ||||||
| 			to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory()) | 			std::to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory()) | ||||||
| 		).render(); | 		).render(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1099,10 +1099,10 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon | |||||||
| 
 | 
 | ||||||
| 	m_context.setMostDerivedContract(_contract); | 	m_context.setMostDerivedContract(_contract); | ||||||
| 	for (auto const& var: ContractType(_contract).stateVariables()) | 	for (auto const& var: ContractType(_contract).stateVariables()) | ||||||
| 		m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var)); | 		m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGenerator::dispenseLocationComment(ASTNode const& _node) | std::string IRGenerator::dispenseLocationComment(ASTNode const& _node) | ||||||
| { | { | ||||||
| 	return ::dispenseLocationComment(_node, m_context); | 	return ::dispenseLocationComment(_node, m_context); | ||||||
| } | } | ||||||
|  | |||||||
| @ -49,7 +49,6 @@ | |||||||
| 
 | 
 | ||||||
| #include <range/v3/view/transform.hpp> | #include <range/v3/view/transform.hpp> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| @ -95,8 +94,8 @@ struct CopyTranslate: public yul::ASTCopier | |||||||
| 			return ASTCopier::translate(_identifier); | 			return ASTCopier::translate(_identifier); | ||||||
| 
 | 
 | ||||||
| 		yul::Expression translated = translateReference(_identifier); | 		yul::Expression translated = translateReference(_identifier); | ||||||
| 		solAssert(holds_alternative<yul::Identifier>(translated)); | 		solAssert(std::holds_alternative<yul::Identifier>(translated)); | ||||||
| 		return get<yul::Identifier>(std::move(translated)); | 		return std::get<yul::Identifier>(std::move(translated)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -109,9 +108,9 @@ private: | |||||||
| 		auto const& reference = m_references.at(&_identifier); | 		auto const& reference = m_references.at(&_identifier); | ||||||
| 		auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration); | 		auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration); | ||||||
| 		solUnimplementedAssert(varDecl); | 		solUnimplementedAssert(varDecl); | ||||||
| 		string const& suffix = reference.suffix; | 		std::string const& suffix = reference.suffix; | ||||||
| 
 | 
 | ||||||
| 		string value; | 		std::string value; | ||||||
| 		if (suffix.empty() && varDecl->isLocalVariable()) | 		if (suffix.empty() && varDecl->isLocalVariable()) | ||||||
| 		{ | 		{ | ||||||
| 			auto const& var = m_context.localVariable(*varDecl); | 			auto const& var = m_context.localVariable(*varDecl); | ||||||
| @ -165,7 +164,7 @@ private: | |||||||
| 			if (suffix == "slot") | 			if (suffix == "slot") | ||||||
| 				value = m_context.storageLocationOfStateVariable(*varDecl).first.str(); | 				value = m_context.storageLocationOfStateVariable(*varDecl).first.str(); | ||||||
| 			else if (suffix == "offset") | 			else if (suffix == "offset") | ||||||
| 				value = to_string(m_context.storageLocationOfStateVariable(*varDecl).second); | 				value = std::to_string(m_context.storageLocationOfStateVariable(*varDecl).second); | ||||||
| 			else | 			else | ||||||
| 				solAssert(false); | 				solAssert(false); | ||||||
| 		} | 		} | ||||||
| @ -216,7 +215,7 @@ private: | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGeneratorForStatementsBase::code() const | std::string IRGeneratorForStatementsBase::code() const | ||||||
| { | { | ||||||
| 	return m_code.str(); | 	return m_code.str(); | ||||||
| } | } | ||||||
| @ -240,7 +239,7 @@ void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node) | |||||||
| 	m_currentLocation = _node.location(); | 	m_currentLocation = _node.location(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGeneratorForStatements::code() const | std::string IRGeneratorForStatements::code() const | ||||||
| { | { | ||||||
| 	solAssert(!m_currentLValue, "LValue not reset!"); | 	solAssert(!m_currentLValue, "LValue not reset!"); | ||||||
| 	return IRGeneratorForStatementsBase::code(); | 	return IRGeneratorForStatementsBase::code(); | ||||||
| @ -338,11 +337,11 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant) | std::string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant) | ||||||
| { | { | ||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		string functionName = IRNames::constantValueFunction(_constant); | 		std::string functionName = IRNames::constantValueFunction(_constant); | ||||||
| 		return m_context.functionCollector().createFunction(functionName, [&] { | 		return m_context.functionCollector().createFunction(functionName, [&] { | ||||||
| 			Whiskers templ(R"( | 			Whiskers templ(R"( | ||||||
| 				<sourceLocationComment> | 				<sourceLocationComment> | ||||||
| @ -410,7 +409,7 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional) | |||||||
| 
 | 
 | ||||||
| 	setLocation(_conditional); | 	setLocation(_conditional); | ||||||
| 
 | 
 | ||||||
| 	string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean()); | 	std::string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean()); | ||||||
| 	declare(_conditional); | 	declare(_conditional); | ||||||
| 
 | 
 | ||||||
| 	appendCode() << "switch " << condition << "\n" "case 0 {\n"; | 	appendCode() << "switch " << condition << "\n" "case 0 {\n"; | ||||||
| @ -501,7 +500,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) | |||||||
| 			_tuple.components().size() << | 			_tuple.components().size() << | ||||||
| 			")\n"; | 			")\n"; | ||||||
| 
 | 
 | ||||||
| 		string mpos = IRVariable(_tuple).part("mpos").name(); | 		std::string mpos = IRVariable(_tuple).part("mpos").name(); | ||||||
| 		Type const& baseType = *arrayType.baseType(); | 		Type const& baseType = *arrayType.baseType(); | ||||||
| 		for (size_t i = 0; i < _tuple.components().size(); i++) | 		for (size_t i = 0; i < _tuple.components().size(); i++) | ||||||
| 		{ | 		{ | ||||||
| @ -512,7 +511,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) | |||||||
| 			appendCode() << | 			appendCode() << | ||||||
| 				m_utils.writeToMemoryFunction(baseType) << | 				m_utils.writeToMemoryFunction(baseType) << | ||||||
| 				"(" << | 				"(" << | ||||||
| 				("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") << | 				("add(" + mpos + ", " + std::to_string(i * arrayType.memoryStride()) + ")") << | ||||||
| 				", " << | 				", " << | ||||||
| 				converted.commaSeparatedList() << | 				converted.commaSeparatedList() << | ||||||
| 				")\n"; | 				")\n"; | ||||||
| @ -535,7 +534,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			vector<optional<IRLValue>> lvalues; | 			std::vector<std::optional<IRLValue>> lvalues; | ||||||
| 			for (size_t i = 0; i < _tuple.components().size(); ++i) | 			for (size_t i = 0; i < _tuple.components().size(); ++i) | ||||||
| 				if (auto const& component = _tuple.components()[i]) | 				if (auto const& component = _tuple.components()[i]) | ||||||
| 				{ | 				{ | ||||||
| @ -586,7 +585,7 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement) | |||||||
| { | { | ||||||
| 	_ifStatement.condition().accept(*this); | 	_ifStatement.condition().accept(*this); | ||||||
| 	setLocation(_ifStatement); | 	setLocation(_ifStatement); | ||||||
| 	string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean()); | 	std::string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean()); | ||||||
| 
 | 
 | ||||||
| 	if (_ifStatement.falseStatement()) | 	if (_ifStatement.falseStatement()) | ||||||
| 	{ | 	{ | ||||||
| @ -658,7 +657,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return) | |||||||
| 	if (Expression const* value = _return.expression()) | 	if (Expression const* value = _return.expression()) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer."); | 		solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer."); | ||||||
| 		vector<ASTPointer<VariableDeclaration>> const& returnParameters = | 		std::vector<ASTPointer<VariableDeclaration>> const& returnParameters = | ||||||
| 			_return.annotation().functionReturnParameters->parameters(); | 			_return.annotation().functionReturnParameters->parameters(); | ||||||
| 		if (returnParameters.size() > 1) | 		if (returnParameters.size() > 1) | ||||||
| 			for (size_t i = 0; i < returnParameters.size(); ++i) | 			for (size_t i = 0; i < returnParameters.size(); ++i) | ||||||
| @ -685,7 +684,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) | |||||||
| 		solAssert(function->returnParameters().size() == 1); | 		solAssert(function->returnParameters().size() == 1); | ||||||
| 		solAssert(*function->returnParameters()[0]->type() == *_unaryOperation.annotation().type); | 		solAssert(*function->returnParameters()[0]->type() == *_unaryOperation.annotation().type); | ||||||
| 
 | 
 | ||||||
| 		string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type()); | 		std::string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type()); | ||||||
| 		solAssert(!argument.empty()); | 		solAssert(!argument.empty()); | ||||||
| 
 | 
 | ||||||
| 		solAssert(_unaryOperation.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal); | 		solAssert(_unaryOperation.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal); | ||||||
| @ -812,8 +811,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) | |||||||
| 		solAssert(function->returnParameters().size() == 1); | 		solAssert(function->returnParameters().size() == 1); | ||||||
| 		solAssert(*function->returnParameters()[0]->type() == *_binOp.annotation().type); | 		solAssert(*function->returnParameters()[0]->type() == *_binOp.annotation().type); | ||||||
| 
 | 
 | ||||||
| 		string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type()); | 		std::string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type()); | ||||||
| 		string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type()); | 		std::string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type()); | ||||||
| 		solAssert(!left.empty() && !right.empty()); | 		solAssert(!left.empty() && !right.empty()); | ||||||
| 
 | 
 | ||||||
| 		solAssert(_binOp.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal); | 		solAssert(_binOp.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal); | ||||||
| @ -853,13 +852,13 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) | |||||||
| 		if (auto type = dynamic_cast<IntegerType const*>(commonType)) | 		if (auto type = dynamic_cast<IntegerType const*>(commonType)) | ||||||
| 			isSigned = type->isSigned(); | 			isSigned = type->isSigned(); | ||||||
| 
 | 
 | ||||||
| 		string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType); | 		std::string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType); | ||||||
| 		args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType); | 		args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType); | ||||||
| 
 | 
 | ||||||
| 		auto functionType = dynamic_cast<FunctionType const*>(commonType); | 		auto functionType = dynamic_cast<FunctionType const*>(commonType); | ||||||
| 		solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!"); | 		solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!"); | ||||||
| 
 | 
 | ||||||
| 		string expr; | 		std::string expr; | ||||||
| 
 | 
 | ||||||
| 		if (functionType && functionType->kind() ==  FunctionType::Kind::External) | 		if (functionType && functionType->kind() ==  FunctionType::Kind::External) | ||||||
| 		{ | 		{ | ||||||
| @ -879,9 +878,9 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) | |||||||
| 		else if (op == Token::NotEqual) | 		else if (op == Token::NotEqual) | ||||||
| 			expr = "iszero(eq(" + std::move(args) + "))"; | 			expr = "iszero(eq(" + std::move(args) + "))"; | ||||||
| 		else if (op == Token::GreaterThanOrEqual) | 		else if (op == Token::GreaterThanOrEqual) | ||||||
| 			expr = "iszero(" + string(isSigned ? "slt(" : "lt(") + std::move(args) + "))"; | 			expr = "iszero(" + std::string(isSigned ? "slt(" : "lt(") + std::move(args) + "))"; | ||||||
| 		else if (op == Token::LessThanOrEqual) | 		else if (op == Token::LessThanOrEqual) | ||||||
| 			expr = "iszero(" + string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))"; | 			expr = "iszero(" + std::string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))"; | ||||||
| 		else if (op == Token::GreaterThan) | 		else if (op == Token::GreaterThan) | ||||||
| 			expr = (isSigned ? "sgt(" : "gt(") + std::move(args) + ")"; | 			expr = (isSigned ? "sgt(" : "gt(") + std::move(args) + ")"; | ||||||
| 		else if (op == Token::LessThan) | 		else if (op == Token::LessThan) | ||||||
| @ -925,8 +924,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		string left = expressionAsType(_binOp.leftExpression(), *commonType); | 		std::string left = expressionAsType(_binOp.leftExpression(), *commonType); | ||||||
| 		string right = expressionAsType(_binOp.rightExpression(), *commonType); | 		std::string right = expressionAsType(_binOp.rightExpression(), *commonType); | ||||||
| 		define(_binOp) << binaryOperation(_binOp.getOperator(), *commonType, left, right) << "\n"; | 		define(_binOp) << binaryOperation(_binOp.getOperator(), *commonType, left, right) << "\n"; | ||||||
| 	} | 	} | ||||||
| 	return false; | 	return false; | ||||||
| @ -960,7 +959,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 
 | 
 | ||||||
| 	TypePointers parameterTypes = functionType->parameterTypes(); | 	TypePointers parameterTypes = functionType->parameterTypes(); | ||||||
| 
 | 
 | ||||||
| 	vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments(); | 	std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments(); | ||||||
| 
 | 
 | ||||||
| 	if (functionCallKind == FunctionCallKind::StructConstructorCall) | 	if (functionCallKind == FunctionCallKind::StructConstructorCall) | ||||||
| 	{ | 	{ | ||||||
| @ -1001,7 +1000,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 
 | 
 | ||||||
| 		solAssert(!functionType->takesArbitraryParameters()); | 		solAssert(!functionType->takesArbitraryParameters()); | ||||||
| 
 | 
 | ||||||
| 		vector<string> args; | 		std::vector<std::string> args; | ||||||
| 		if (functionType->hasBoundFirstArgument()) | 		if (functionType->hasBoundFirstArgument()) | ||||||
| 			args += IRVariable(_functionCall.expression()).part("self").stackSlots(); | 			args += IRVariable(_functionCall.expression()).part("self").stackSlots(); | ||||||
| 
 | 
 | ||||||
| @ -1049,8 +1048,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		TypePointers paramTypes = functionType->parameterTypes(); | 		TypePointers paramTypes = functionType->parameterTypes(); | ||||||
| 		ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); | 		ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); | ||||||
| 
 | 
 | ||||||
| 		vector<IRVariable> indexedArgs; | 		std::vector<IRVariable> indexedArgs; | ||||||
| 		vector<string> nonIndexedArgs; | 		std::vector<std::string> nonIndexedArgs; | ||||||
| 		TypePointers nonIndexedArgTypes; | 		TypePointers nonIndexedArgTypes; | ||||||
| 		TypePointers nonIndexedParamTypes; | 		TypePointers nonIndexedParamTypes; | ||||||
| 		if (!event.isAnonymous()) | 		if (!event.isAnonymous()) | ||||||
| @ -1061,7 +1060,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 			Expression const& arg = *arguments[i]; | 			Expression const& arg = *arguments[i]; | ||||||
| 			if (event.parameters()[i]->isIndexed()) | 			if (event.parameters()[i]->isIndexed()) | ||||||
| 			{ | 			{ | ||||||
| 				string value; | 				std::string value; | ||||||
| 				if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i])) | 				if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i])) | ||||||
| 					define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::uint256())) << | 					define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::uint256())) << | ||||||
| 						m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) << | 						m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) << | ||||||
| @ -1106,7 +1105,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | 		templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | ||||||
| 		templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes)); | 		templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes)); | ||||||
| 		templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs)); | 		templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs)); | ||||||
| 		templ("log", "log" + to_string(indexedArgs.size())); | 		templ("log", "log" + std::to_string(indexedArgs.size())); | ||||||
| 		templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) { | 		templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) { | ||||||
| 			return _arg.commaSeparatedList(); | 			return _arg.commaSeparatedList(); | ||||||
| 		}))); | 		}))); | ||||||
| @ -1152,7 +1151,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 			arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ? | 			arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ? | ||||||
| 			arguments[1]->annotation().type : | 			arguments[1]->annotation().type : | ||||||
| 			nullptr; | 			nullptr; | ||||||
| 		string requireOrAssertFunction = m_utils.requireOrAssertFunction( | 		std::string requireOrAssertFunction = m_utils.requireOrAssertFunction( | ||||||
| 			functionType->kind() == FunctionType::Kind::Assert, | 			functionType->kind() == FunctionType::Kind::Assert, | ||||||
| 			messageArgumentType | 			messageArgumentType | ||||||
| 		); | 		); | ||||||
| @ -1179,9 +1178,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 
 | 
 | ||||||
| 		TypePointers argumentTypes; | 		TypePointers argumentTypes; | ||||||
| 		TypePointers targetTypes; | 		TypePointers targetTypes; | ||||||
| 		vector<string> argumentVars; | 		std::vector<std::string> argumentVars; | ||||||
| 		string selector; | 		std::string selector; | ||||||
| 		vector<ASTPointer<Expression const>> argumentsOfEncodeFunction; | 		std::vector<ASTPointer<Expression const>> argumentsOfEncodeFunction; | ||||||
| 
 | 
 | ||||||
| 		if (functionType->kind() == FunctionType::Kind::ABIEncodeCall) | 		if (functionType->kind() == FunctionType::Kind::ABIEncodeCall) | ||||||
| 		{ | 		{ | ||||||
| @ -1252,13 +1251,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 				// TODO This is an abuse of the `allocateUnbounded` function.
 | 				// TODO This is an abuse of the `allocateUnbounded` function.
 | ||||||
| 				// We might want to introduce a new set of memory handling functions here
 | 				// We might want to introduce a new set of memory handling functions here
 | ||||||
| 				// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
 | 				// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
 | ||||||
| 				string freeMemoryPre = m_context.newYulVariable(); | 				std::string freeMemoryPre = m_context.newYulVariable(); | ||||||
| 				appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n"; | 				appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n"; | ||||||
| 				IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory()); | 				IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory()); | ||||||
| 				IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32)); | 				IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32)); | ||||||
| 
 | 
 | ||||||
| 				string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory()); | 				std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory()); | ||||||
| 				string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory()); | 				std::string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory()); | ||||||
| 				define(hashVariable) << | 				define(hashVariable) << | ||||||
| 					"keccak256(" << | 					"keccak256(" << | ||||||
| 					(dataAreaFunction + "(" + array.commaSeparatedList() + ")") << | 					(dataAreaFunction + "(" + array.commaSeparatedList() + ")") << | ||||||
| @ -1389,8 +1388,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		{ | 		{ | ||||||
| 			auto array = convert(*arguments[0], *arrayType); | 			auto array = convert(*arguments[0], *arrayType); | ||||||
| 
 | 
 | ||||||
| 			string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType); | 			std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType); | ||||||
| 			string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType); | 			std::string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType); | ||||||
| 			define(_functionCall) << | 			define(_functionCall) << | ||||||
| 				"keccak256(" << | 				"keccak256(" << | ||||||
| 				(dataAreaFunction + "(" + array.commaSeparatedList() + ")") << | 				(dataAreaFunction + "(" + array.commaSeparatedList() + ")") << | ||||||
| @ -1453,7 +1452,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 	case FunctionType::Kind::BytesConcat: | 	case FunctionType::Kind::BytesConcat: | ||||||
| 	{ | 	{ | ||||||
| 		TypePointers argumentTypes; | 		TypePointers argumentTypes; | ||||||
| 		vector<string> argumentVars; | 		std::vector<std::string> argumentVars; | ||||||
| 		for (ASTPointer<Expression const> const& argument: arguments) | 		for (ASTPointer<Expression const> const& argument: arguments) | ||||||
| 		{ | 		{ | ||||||
| 			argumentTypes.emplace_back(&type(*argument)); | 			argumentTypes.emplace_back(&type(*argument)); | ||||||
| @ -1473,7 +1472,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 	case FunctionType::Kind::AddMod: | 	case FunctionType::Kind::AddMod: | ||||||
| 	case FunctionType::Kind::MulMod: | 	case FunctionType::Kind::MulMod: | ||||||
| 	{ | 	{ | ||||||
| 		static map<FunctionType::Kind, string> functions = { | 		static std::map<FunctionType::Kind, std::string> functions = { | ||||||
| 			{FunctionType::Kind::AddMod, "addmod"}, | 			{FunctionType::Kind::AddMod, "addmod"}, | ||||||
| 			{FunctionType::Kind::MulMod, "mulmod"}, | 			{FunctionType::Kind::MulMod, "mulmod"}, | ||||||
| 		}; | 		}; | ||||||
| @ -1487,7 +1486,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero)); | 		templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero)); | ||||||
| 		appendCode() << templ.render(); | 		appendCode() << templ.render(); | ||||||
| 
 | 
 | ||||||
| 		string args; | 		std::string args; | ||||||
| 		for (size_t i = 0; i < 2; ++i) | 		for (size_t i = 0; i < 2; ++i) | ||||||
| 			args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", "; | 			args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", "; | ||||||
| 		args += modulus.name(); | 		args += modulus.name(); | ||||||
| @ -1498,14 +1497,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 	case FunctionType::Kind::Selfdestruct: | 	case FunctionType::Kind::Selfdestruct: | ||||||
| 	case FunctionType::Kind::BlockHash: | 	case FunctionType::Kind::BlockHash: | ||||||
| 	{ | 	{ | ||||||
| 		static map<FunctionType::Kind, string> functions = { | 		static std::map<FunctionType::Kind, std::string> functions = { | ||||||
| 			{FunctionType::Kind::GasLeft, "gas"}, | 			{FunctionType::Kind::GasLeft, "gas"}, | ||||||
| 			{FunctionType::Kind::Selfdestruct, "selfdestruct"}, | 			{FunctionType::Kind::Selfdestruct, "selfdestruct"}, | ||||||
| 			{FunctionType::Kind::BlockHash, "blockhash"}, | 			{FunctionType::Kind::BlockHash, "blockhash"}, | ||||||
| 		}; | 		}; | ||||||
| 		solAssert(functions.find(functionType->kind()) != functions.end()); | 		solAssert(functions.find(functionType->kind()) != functions.end()); | ||||||
| 
 | 
 | ||||||
| 		string args; | 		std::string args; | ||||||
| 		for (size_t i = 0; i < arguments.size(); ++i) | 		for (size_t i = 0; i < arguments.size(); ++i) | ||||||
| 			args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i])); | 			args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i])); | ||||||
| 		define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n"; | 		define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n"; | ||||||
| @ -1520,7 +1519,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		TypePointers argumentTypes; | 		TypePointers argumentTypes; | ||||||
| 		vector<string> constructorParams; | 		std::vector<std::string> constructorParams; | ||||||
| 		for (ASTPointer<Expression const> const& arg: arguments) | 		for (ASTPointer<Expression const> const& arg: arguments) | ||||||
| 		{ | 		{ | ||||||
| 			argumentTypes.push_back(arg->annotation().type); | 			argumentTypes.push_back(arg->annotation().type); | ||||||
| @ -1575,8 +1574,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 	case FunctionType::Kind::Transfer: | 	case FunctionType::Kind::Transfer: | ||||||
| 	{ | 	{ | ||||||
| 		solAssert(arguments.size() == 1 && parameterTypes.size() == 1); | 		solAssert(arguments.size() == 1 && parameterTypes.size() == 1); | ||||||
| 		string address{IRVariable(_functionCall.expression()).part("address").name()}; | 		std::string address{IRVariable(_functionCall.expression()).part("address").name()}; | ||||||
| 		string value{expressionAsType(*arguments[0], *(parameterTypes[0]))}; | 		std::string value{expressionAsType(*arguments[0], *(parameterTypes[0]))}; | ||||||
| 		Whiskers templ(R"( | 		Whiskers templ(R"( | ||||||
| 			let <gas> := 0 | 			let <gas> := 0 | ||||||
| 			if iszero(<value>) { <gas> := <callStipend> } | 			if iszero(<value>) { <gas> := <callStipend> } | ||||||
| @ -1608,14 +1607,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 		solAssert(!functionType->gasSet()); | 		solAssert(!functionType->gasSet()); | ||||||
| 		solAssert(!functionType->hasBoundFirstArgument()); | 		solAssert(!functionType->hasBoundFirstArgument()); | ||||||
| 
 | 
 | ||||||
| 		static map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = { | 		static std::map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = { | ||||||
| 			{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)}, | 			{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)}, | ||||||
| 			{FunctionType::Kind::SHA256, std::make_tuple(2, 0)}, | 			{FunctionType::Kind::SHA256, std::make_tuple(2, 0)}, | ||||||
| 			{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)}, | 			{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)}, | ||||||
| 		}; | 		}; | ||||||
| 		auto [ address, offset ] = precompiles[functionType->kind()]; | 		auto [ address, offset ] = precompiles[functionType->kind()]; | ||||||
| 		TypePointers argumentTypes; | 		TypePointers argumentTypes; | ||||||
| 		vector<string> argumentStrings; | 		std::vector<std::string> argumentStrings; | ||||||
| 		for (auto const& arg: arguments) | 		for (auto const& arg: arguments) | ||||||
| 		{ | 		{ | ||||||
| 			argumentTypes.emplace_back(&type(*arg)); | 			argumentTypes.emplace_back(&type(*arg)); | ||||||
| @ -1676,11 +1675,11 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options) | |||||||
| 
 | 
 | ||||||
| 	// Copy over existing values.
 | 	// Copy over existing values.
 | ||||||
| 	for (auto const& item: previousType.stackItems()) | 	for (auto const& item: previousType.stackItems()) | ||||||
| 		define(IRVariable(_options).part(get<0>(item)), IRVariable(_options.expression()).part(get<0>(item))); | 		define(IRVariable(_options).part(std::get<0>(item)), IRVariable(_options.expression()).part(std::get<0>(item))); | ||||||
| 
 | 
 | ||||||
| 	for (size_t i = 0; i < _options.names().size(); ++i) | 	for (size_t i = 0; i < _options.names().size(); ++i) | ||||||
| 	{ | 	{ | ||||||
| 		string const& name = *_options.names()[i]; | 		std::string const& name = *_options.names()[i]; | ||||||
| 		solAssert(name == "salt" || name == "gas" || name == "value"); | 		solAssert(name == "salt" || name == "gas" || name == "value"); | ||||||
| 
 | 
 | ||||||
| 		define(IRVariable(_options).part(name), *_options.options()[i]); | 		define(IRVariable(_options).part(name), *_options.options()[i]); | ||||||
| @ -1785,7 +1784,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 				")\n"; | 				")\n"; | ||||||
| 		else if (member == "code") | 		else if (member == "code") | ||||||
| 		{ | 		{ | ||||||
| 			string externalCodeFunction = m_utils.externalCodeFunction(); | 			std::string externalCodeFunction = m_utils.externalCodeFunction(); | ||||||
| 			define(_memberAccess) << | 			define(_memberAccess) << | ||||||
| 				externalCodeFunction << | 				externalCodeFunction << | ||||||
| 				"(" << | 				"(" << | ||||||
| @ -1797,12 +1796,12 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 				"extcodehash(" << | 				"extcodehash(" << | ||||||
| 				expressionAsType(_memberAccess.expression(), *TypeProvider::address()) << | 				expressionAsType(_memberAccess.expression(), *TypeProvider::address()) << | ||||||
| 				")\n"; | 				")\n"; | ||||||
| 		else if (set<string>{"send", "transfer"}.count(member)) | 		else if (std::set<std::string>{"send", "transfer"}.count(member)) | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable); | 			solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable); | ||||||
| 			define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression()); | 			define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression()); | ||||||
| 		} | 		} | ||||||
| 		else if (set<string>{"call", "callcode", "delegatecall", "staticcall"}.count(member)) | 		else if (std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}.count(member)) | ||||||
| 			define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression()); | 			define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression()); | ||||||
| 		else | 		else | ||||||
| 			solAssert(false, "Invalid member access to address"); | 			solAssert(false, "Invalid member access to address"); | ||||||
| @ -1945,7 +1944,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 		{ | 		{ | ||||||
| 			MagicType const* arg = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type); | 			MagicType const* arg = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type); | ||||||
| 
 | 
 | ||||||
| 			string requestedValue; | 			std::string requestedValue; | ||||||
| 			if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument())) | 			if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument())) | ||||||
| 			{ | 			{ | ||||||
| 				if (member == "min") | 				if (member == "min") | ||||||
| @ -1956,16 +1955,16 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 			else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument())) | 			else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument())) | ||||||
| 			{ | 			{ | ||||||
| 				if (member == "min") | 				if (member == "min") | ||||||
| 					requestedValue = to_string(enumType->minValue()); | 					requestedValue = std::to_string(enumType->minValue()); | ||||||
| 				else | 				else | ||||||
| 					requestedValue = to_string(enumType->maxValue()); | 					requestedValue = std::to_string(enumType->maxValue()); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				solAssert(false, "min/max requested on unexpected type."); | 				solAssert(false, "min/max requested on unexpected type."); | ||||||
| 
 | 
 | ||||||
| 			define(_memberAccess) << requestedValue << "\n"; | 			define(_memberAccess) << requestedValue << "\n"; | ||||||
| 		} | 		} | ||||||
| 		else if (set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member)) | 		else if (std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member)) | ||||||
| 		{ | 		{ | ||||||
| 			// no-op
 | 			// no-op
 | ||||||
| 		} | 		} | ||||||
| @ -1981,8 +1980,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 		{ | 		{ | ||||||
| 		case DataLocation::Storage: | 		case DataLocation::Storage: | ||||||
| 		{ | 		{ | ||||||
| 			pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member); | 			std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member); | ||||||
| 			string slot = m_context.newYulVariable(); | 			std::string slot = m_context.newYulVariable(); | ||||||
| 			appendCode() << "let " << slot << " := " << | 			appendCode() << "let " << slot << " := " << | ||||||
| 				("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n"); | 				("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n"); | ||||||
| 			setLValue(_memberAccess, IRLValue{ | 			setLValue(_memberAccess, IRLValue{ | ||||||
| @ -1993,7 +1992,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 		} | 		} | ||||||
| 		case DataLocation::Memory: | 		case DataLocation::Memory: | ||||||
| 		{ | 		{ | ||||||
| 			string pos = m_context.newYulVariable(); | 			std::string pos = m_context.newYulVariable(); | ||||||
| 			appendCode() << "let " << pos << " := " << | 			appendCode() << "let " << pos << " := " << | ||||||
| 				("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n"); | 				("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n"); | ||||||
| 			setLValue(_memberAccess, IRLValue{ | 			setLValue(_memberAccess, IRLValue{ | ||||||
| @ -2004,9 +2003,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 		} | 		} | ||||||
| 		case DataLocation::CallData: | 		case DataLocation::CallData: | ||||||
| 		{ | 		{ | ||||||
| 			string baseRef = expression.part("offset").name(); | 			std::string baseRef = expression.part("offset").name(); | ||||||
| 			string offset = m_context.newYulVariable(); | 			std::string offset = m_context.newYulVariable(); | ||||||
| 			appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n"; | 			appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << std::to_string(structType.calldataOffsetOfMember(member)) << ")\n"; | ||||||
| 			if (_memberAccess.annotation().type->isDynamicallyEncoded()) | 			if (_memberAccess.annotation().type->isDynamicallyEncoded()) | ||||||
| 				define(_memberAccess) << | 				define(_memberAccess) << | ||||||
| 					m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) << | 					m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) << | ||||||
| @ -2036,7 +2035,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 	case Type::Category::Enum: | 	case Type::Category::Enum: | ||||||
| 	{ | 	{ | ||||||
| 		EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type); | 		EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type); | ||||||
| 		define(_memberAccess) << to_string(type.memberValue(_memberAccess.memberName())) << "\n"; | 		define(_memberAccess) << std::to_string(type.memberValue(_memberAccess.memberName())) << "\n"; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case Type::Category::Array: | 	case Type::Category::Array: | ||||||
| @ -2076,7 +2075,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 	{ | 	{ | ||||||
| 		auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type); | 		auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type); | ||||||
| 		if (member == "length") | 		if (member == "length") | ||||||
| 			define(_memberAccess) << to_string(type.numBytes()) << "\n"; | 			define(_memberAccess) << std::to_string(type.numBytes()) << "\n"; | ||||||
| 		else | 		else | ||||||
| 			solAssert(false, "Illegal fixed bytes member."); | 			solAssert(false, "Illegal fixed bytes member."); | ||||||
| 		break; | 		break; | ||||||
| @ -2162,7 +2161,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 				solAssert(false); | 				solAssert(false); | ||||||
| 		} | 		} | ||||||
| 		else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType)) | 		else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType)) | ||||||
| 			define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n"; | 			define(_memberAccess) << std::to_string(enumType->memberValue(_memberAccess.memberName())) << "\n"; | ||||||
| 		else if (dynamic_cast<UserDefinedValueType const*>(&actualType)) | 		else if (dynamic_cast<UserDefinedValueType const*>(&actualType)) | ||||||
| 			solAssert(member == "wrap" || member == "unwrap"); | 			solAssert(member == "wrap" || member == "unwrap"); | ||||||
| 		else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType)) | 		else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType)) | ||||||
| @ -2222,7 +2221,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) | |||||||
| 
 | 
 | ||||||
| 	yul::Statement modified = bodyCopier(_inlineAsm.operations()); | 	yul::Statement modified = bodyCopier(_inlineAsm.operations()); | ||||||
| 
 | 
 | ||||||
| 	solAssert(holds_alternative<yul::Block>(modified)); | 	solAssert(std::holds_alternative<yul::Block>(modified)); | ||||||
| 
 | 
 | ||||||
| 	// Do not provide dialect so that we get the full type information.
 | 	// Do not provide dialect so that we get the full type information.
 | ||||||
| 	appendCode() << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n"; | 	appendCode() << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n"; | ||||||
| @ -2242,7 +2241,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) | |||||||
| 		MappingType const& mappingType = dynamic_cast<MappingType const&>(baseType); | 		MappingType const& mappingType = dynamic_cast<MappingType const&>(baseType); | ||||||
| 		Type const& keyType = *_indexAccess.indexExpression()->annotation().type; | 		Type const& keyType = *_indexAccess.indexExpression()->annotation().type; | ||||||
| 
 | 
 | ||||||
| 		string slot = m_context.newYulVariable(); | 		std::string slot = m_context.newYulVariable(); | ||||||
| 		Whiskers templ("let <slot> := <indexAccess>(<base><?+key>,<key></+key>)\n"); | 		Whiskers templ("let <slot> := <indexAccess>(<base><?+key>,<key></+key>)\n"); | ||||||
| 		templ("slot", slot); | 		templ("slot", slot); | ||||||
| 		templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType)); | 		templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType)); | ||||||
| @ -2273,8 +2272,8 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) | |||||||
| 		{ | 		{ | ||||||
| 			case DataLocation::Storage: | 			case DataLocation::Storage: | ||||||
| 			{ | 			{ | ||||||
| 				string slot = m_context.newYulVariable(); | 				std::string slot = m_context.newYulVariable(); | ||||||
| 				string offset = m_context.newYulVariable(); | 				std::string offset = m_context.newYulVariable(); | ||||||
| 
 | 
 | ||||||
| 				appendCode() << Whiskers(R"( | 				appendCode() << Whiskers(R"( | ||||||
| 					let <slot>, <offset> := <indexFunc>(<array>, <index>) | 					let <slot>, <offset> := <indexFunc>(<array>, <index>) | ||||||
| @ -2295,13 +2294,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) | |||||||
| 			} | 			} | ||||||
| 			case DataLocation::Memory: | 			case DataLocation::Memory: | ||||||
| 			{ | 			{ | ||||||
| 				string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType); | 				std::string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType); | ||||||
| 				string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name(); | 				std::string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name(); | ||||||
| 				string const indexExpression = expressionAsType( | 				std::string const indexExpression = expressionAsType( | ||||||
| 					*_indexAccess.indexExpression(), | 					*_indexAccess.indexExpression(), | ||||||
| 					*TypeProvider::uint256() | 					*TypeProvider::uint256() | ||||||
| 				); | 				); | ||||||
| 				string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")"; | 				std::string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")"; | ||||||
| 
 | 
 | ||||||
| 				setLValue(_indexAccess, IRLValue{ | 				setLValue(_indexAccess, IRLValue{ | ||||||
| 					*arrayType.baseType(), | 					*arrayType.baseType(), | ||||||
| @ -2311,13 +2310,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) | |||||||
| 			} | 			} | ||||||
| 			case DataLocation::CallData: | 			case DataLocation::CallData: | ||||||
| 			{ | 			{ | ||||||
| 				string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType); | 				std::string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType); | ||||||
| 				string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList(); | 				std::string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList(); | ||||||
| 				string const indexExpression = expressionAsType( | 				std::string const indexExpression = expressionAsType( | ||||||
| 					*_indexAccess.indexExpression(), | 					*_indexAccess.indexExpression(), | ||||||
| 					*TypeProvider::uint256() | 					*TypeProvider::uint256() | ||||||
| 				); | 				); | ||||||
| 				string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")"; | 				std::string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")"; | ||||||
| 
 | 
 | ||||||
| 				if (arrayType.isByteArrayOrString()) | 				if (arrayType.isByteArrayOrString()) | ||||||
| 					define(_indexAccess) << | 					define(_indexAccess) << | ||||||
| @ -2349,7 +2348,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) | |||||||
| 			let <result> := <shl248>(byte(<index>, <array>)) | 			let <result> := <shl248>(byte(<index>, <array>)) | ||||||
| 		)") | 		)") | ||||||
| 		("index", index.name()) | 		("index", index.name()) | ||||||
| 		("length", to_string(fixedBytesType.numBytes())) | 		("length", std::to_string(fixedBytesType.numBytes())) | ||||||
| 		("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds)) | 		("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds)) | ||||||
| 		("array", IRVariable(_indexAccess.baseExpression()).name()) | 		("array", IRVariable(_indexAccess.baseExpression()).name()) | ||||||
| 		("shl248", m_utils.shiftLeftFunction(256 - 8)) | 		("shl248", m_utils.shiftLeftFunction(256 - 8)) | ||||||
| @ -2538,7 +2537,7 @@ void IRGeneratorForStatements::handleVariableReference( | |||||||
| 
 | 
 | ||||||
| void IRGeneratorForStatements::appendExternalFunctionCall( | void IRGeneratorForStatements::appendExternalFunctionCall( | ||||||
| 	FunctionCall const& _functionCall, | 	FunctionCall const& _functionCall, | ||||||
| 	vector<ASTPointer<Expression const>> const& _arguments | 	std::vector<ASTPointer<Expression const>> const& _arguments | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression())); | 	FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression())); | ||||||
| @ -2559,7 +2558,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( | |||||||
| 
 | 
 | ||||||
| 	TypePointers parameterTypes = funType.parameterTypes(); | 	TypePointers parameterTypes = funType.parameterTypes(); | ||||||
| 	TypePointers argumentTypes; | 	TypePointers argumentTypes; | ||||||
| 	vector<string> argumentStrings; | 	std::vector<std::string> argumentStrings; | ||||||
| 	if (funType.hasBoundFirstArgument()) | 	if (funType.hasBoundFirstArgument()) | ||||||
| 	{ | 	{ | ||||||
| 		parameterTypes.insert(parameterTypes.begin(), funType.selfType()); | 		parameterTypes.insert(parameterTypes.begin(), funType.selfType()); | ||||||
| @ -2581,7 +2580,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( | |||||||
| 		// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
 | 		// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
 | ||||||
| 		// would remove that, so we use MSTORE here.
 | 		// would remove that, so we use MSTORE here.
 | ||||||
| 		if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0) | 		if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0) | ||||||
| 			appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; | 			appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << std::to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically.
 | 	// NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically.
 | ||||||
| @ -2649,10 +2648,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall( | |||||||
| 	if (returnInfo.dynamicReturnSize) | 	if (returnInfo.dynamicReturnSize) | ||||||
| 		solAssert(m_context.evmVersion().supportsReturndata()); | 		solAssert(m_context.evmVersion().supportsReturndata()); | ||||||
| 	templ("returnDataSizeVar", m_context.newYulVariable()); | 	templ("returnDataSizeVar", m_context.newYulVariable()); | ||||||
| 	templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize)); | 	templ("staticReturndataSize", std::to_string(returnInfo.estimatedReturnSize)); | ||||||
| 	templ("supportsReturnData", m_context.evmVersion().supportsReturndata()); | 	templ("supportsReturnData", m_context.evmVersion().supportsReturndata()); | ||||||
| 
 | 
 | ||||||
| 	string const retVars = IRVariable(_functionCall).commaSeparatedList(); | 	std::string const retVars = IRVariable(_functionCall).commaSeparatedList(); | ||||||
| 	templ("retVars", retVars); | 	templ("retVars", retVars); | ||||||
| 	solAssert(retVars.empty() == returnInfo.returnTypes.empty()); | 	solAssert(retVars.empty() == returnInfo.returnTypes.empty()); | ||||||
| 
 | 
 | ||||||
| @ -2704,7 +2703,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( | |||||||
| 
 | 
 | ||||||
| void IRGeneratorForStatements::appendBareCall( | void IRGeneratorForStatements::appendBareCall( | ||||||
| 	FunctionCall const& _functionCall, | 	FunctionCall const& _functionCall, | ||||||
| 	vector<ASTPointer<Expression const>> const& _arguments | 	std::vector<ASTPointer<Expression const>> const& _arguments | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression())); | 	FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression())); | ||||||
| @ -2807,7 +2806,7 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly( | |||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	define(IRVariable(_expression).part("functionIdentifier")) << | 	define(IRVariable(_expression).part("functionIdentifier")) << | ||||||
| 		to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) << | 		std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) << | ||||||
| 		"\n"; | 		"\n"; | ||||||
| 	m_context.addToInternalDispatch(_referencedFunction); | 	m_context.addToInternalDispatch(_referencedFunction); | ||||||
| } | } | ||||||
| @ -2864,7 +2863,7 @@ void IRGeneratorForStatements::declare(IRVariable const& _var) | |||||||
| 
 | 
 | ||||||
| void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup) | void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup) | ||||||
| { | { | ||||||
| 	string output; | 	std::string output; | ||||||
| 	if (_lhs.type() == _rhs.type() && !_forceCleanup) | 	if (_lhs.type() == _rhs.type() && !_forceCleanup) | ||||||
| 		for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems()) | 		for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems()) | ||||||
| 			if (stackItemType) | 			if (stackItemType) | ||||||
| @ -2894,7 +2893,7 @@ IRVariable IRGeneratorForStatements::zeroValue(Type const& _type, bool _splitFun | |||||||
| 
 | 
 | ||||||
| void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr) | void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr) | ||||||
| { | { | ||||||
| 	string func; | 	std::string func; | ||||||
| 
 | 
 | ||||||
| 	if (_operation.getOperator() == Token::Not) | 	if (_operation.getOperator() == Token::Not) | ||||||
| 		func = "iszero"; | 		func = "iszero"; | ||||||
| @ -2913,18 +2912,18 @@ void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& | |||||||
| 		")\n"; | 		")\n"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGeneratorForStatements::binaryOperation( | std::string IRGeneratorForStatements::binaryOperation( | ||||||
| 	langutil::Token _operator, | 	langutil::Token _operator, | ||||||
| 	Type const& _type, | 	Type const& _type, | ||||||
| 	string const& _left, | 	std::string const& _left, | ||||||
| 	string const& _right | 	std::string const& _right | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	solAssert( | 	solAssert( | ||||||
| 		!TokenTraits::isShiftOp(_operator), | 		!TokenTraits::isShiftOp(_operator), | ||||||
| 		"Have to use specific shift operation function for shifts." | 		"Have to use specific shift operation function for shifts." | ||||||
| 	); | 	); | ||||||
| 	string fun; | 	std::string fun; | ||||||
| 	if (TokenTraits::isBitOp(_operator)) | 	if (TokenTraits::isBitOp(_operator)) | ||||||
| 	{ | 	{ | ||||||
| 		solAssert( | 		solAssert( | ||||||
| @ -3030,12 +3029,12 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable | |||||||
| 	std::visit( | 	std::visit( | ||||||
| 		util::GenericVisitor{ | 		util::GenericVisitor{ | ||||||
| 			[&](IRLValue::Storage const& _storage) { | 			[&](IRLValue::Storage const& _storage) { | ||||||
| 				string offsetArgument; | 				std::string offsetArgument; | ||||||
| 				optional<unsigned> offsetStatic; | 				std::optional<unsigned> offsetStatic; | ||||||
| 
 | 
 | ||||||
| 				std::visit(GenericVisitor{ | 				std::visit(GenericVisitor{ | ||||||
| 					[&](unsigned _offset) { offsetStatic = _offset; }, | 					[&](unsigned _offset) { offsetStatic = _offset; }, | ||||||
| 					[&](string const& _offset) { offsetArgument = ", " + _offset; } | 					[&](std::string const& _offset) { offsetArgument = ", " + _offset; } | ||||||
| 				}, _storage.offset); | 				}, _storage.offset); | ||||||
| 
 | 
 | ||||||
| 				appendCode() << | 				appendCode() << | ||||||
| @ -3068,7 +3067,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable | |||||||
| 				} | 				} | ||||||
| 				else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type())) | 				else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type())) | ||||||
| 				{ | 				{ | ||||||
| 					string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256()); | 					std::string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256()); | ||||||
| 					appendCode() << | 					appendCode() << | ||||||
| 						writeUInt << | 						writeUInt << | ||||||
| 						"(" << | 						"(" << | ||||||
| @ -3099,7 +3098,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable | |||||||
| 				IRVariable prepared(m_context.newYulVariable(), _lvalue.type); | 				IRVariable prepared(m_context.newYulVariable(), _lvalue.type); | ||||||
| 				define(prepared, _value); | 				define(prepared, _value); | ||||||
| 
 | 
 | ||||||
| 				appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n"; | 				appendCode() << "mstore(" << std::to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n"; | ||||||
| 			}, | 			}, | ||||||
| 			[&](IRLValue::Tuple const& _tuple) { | 			[&](IRLValue::Tuple const& _tuple) { | ||||||
| 				auto components = std::move(_tuple.components); | 				auto components = std::move(_tuple.components); | ||||||
| @ -3122,13 +3121,13 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) | |||||||
| 		[&](IRLValue::Storage const& _storage) { | 		[&](IRLValue::Storage const& _storage) { | ||||||
| 			if (!_lvalue.type.isValueType()) | 			if (!_lvalue.type.isValueType()) | ||||||
| 				define(result) << _storage.slot << "\n"; | 				define(result) << _storage.slot << "\n"; | ||||||
| 			else if (std::holds_alternative<string>(_storage.offset)) | 			else if (std::holds_alternative<std::string>(_storage.offset)) | ||||||
| 				define(result) << | 				define(result) << | ||||||
| 					m_utils.readFromStorageDynamic(_lvalue.type, true) << | 					m_utils.readFromStorageDynamic(_lvalue.type, true) << | ||||||
| 					"(" << | 					"(" << | ||||||
| 					_storage.slot << | 					_storage.slot << | ||||||
| 					", " << | 					", " << | ||||||
| 					std::get<string>(_storage.offset) << | 					std::get<std::string>(_storage.offset) << | ||||||
| 					")\n"; | 					")\n"; | ||||||
| 			else | 			else | ||||||
| 				define(result) << | 				define(result) << | ||||||
| @ -3156,15 +3155,15 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) | |||||||
| 			solAssert(_lvalue.type == *_immutable.variable->type()); | 			solAssert(_lvalue.type == *_immutable.variable->type()); | ||||||
| 			if (m_context.executionContext() == IRGenerationContext::ExecutionContext::Creation) | 			if (m_context.executionContext() == IRGenerationContext::ExecutionContext::Creation) | ||||||
| 			{ | 			{ | ||||||
| 				string readFunction = m_utils.readFromMemory(*_immutable.variable->type()); | 				std::string readFunction = m_utils.readFromMemory(*_immutable.variable->type()); | ||||||
| 				define(result) << | 				define(result) << | ||||||
| 					readFunction << | 					readFunction << | ||||||
| 					"(" << | 					"(" << | ||||||
| 					to_string(m_context.immutableMemoryOffset(*_immutable.variable)) << | 					std::to_string(m_context.immutableMemoryOffset(*_immutable.variable)) << | ||||||
| 					")\n"; | 					")\n"; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				define(result) << "loadimmutable(\"" << to_string(_immutable.variable->id()) << "\")\n"; | 				define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n"; | ||||||
| 		}, | 		}, | ||||||
| 		[&](IRLValue::Tuple const&) { | 		[&](IRLValue::Tuple const&) { | ||||||
| 			solAssert(false, "Attempted to read from tuple lvalue."); | 			solAssert(false, "Attempted to read from tuple lvalue."); | ||||||
| @ -3181,7 +3180,7 @@ void IRGeneratorForStatements::setLValue(Expression const& _expression, IRLValue | |||||||
| 	{ | 	{ | ||||||
| 		m_currentLValue.emplace(std::move(_lvalue)); | 		m_currentLValue.emplace(std::move(_lvalue)); | ||||||
| 		if (_lvalue.type.dataStoredIn(DataLocation::CallData)) | 		if (_lvalue.type.dataStoredIn(DataLocation::CallData)) | ||||||
| 			solAssert(holds_alternative<IRLValue::Stack>(_lvalue.kind)); | 			solAssert(std::holds_alternative<IRLValue::Stack>(_lvalue.kind)); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 		// Only define the expression, if it will not be written to.
 | 		// Only define the expression, if it will not be written to.
 | ||||||
| @ -3196,7 +3195,7 @@ void IRGeneratorForStatements::generateLoop( | |||||||
| 	bool _isDoWhile | 	bool _isDoWhile | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	string firstRun; | 	std::string firstRun; | ||||||
| 
 | 
 | ||||||
| 	if (_isDoWhile) | 	if (_isDoWhile) | ||||||
| 	{ | 	{ | ||||||
| @ -3278,7 +3277,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement) | |||||||
| void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | ||||||
| { | { | ||||||
| 	setLocation(_tryStatement); | 	setLocation(_tryStatement); | ||||||
| 	string const runFallback = m_context.newYulVariable(); | 	std::string const runFallback = m_context.newYulVariable(); | ||||||
| 	appendCode() << "let " << runFallback << " := 1\n"; | 	appendCode() << "let " << runFallback << " := 1\n"; | ||||||
| 
 | 
 | ||||||
| 	// This function returns zero on "short returndata". We have to add a success flag
 | 	// This function returns zero on "short returndata". We have to add a success flag
 | ||||||
| @ -3290,7 +3289,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | |||||||
| 	{ | 	{ | ||||||
| 		appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n"; | 		appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n"; | ||||||
| 		setLocation(*errorClause); | 		setLocation(*errorClause); | ||||||
| 		string const dataVariable = m_context.newYulVariable(); | 		std::string const dataVariable = m_context.newYulVariable(); | ||||||
| 		appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; | 		appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; | ||||||
| 		appendCode() << "if " << dataVariable << " {\n"; | 		appendCode() << "if " << dataVariable << " {\n"; | ||||||
| 		appendCode() << runFallback << " := 0\n"; | 		appendCode() << runFallback << " := 0\n"; | ||||||
| @ -3310,8 +3309,8 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | |||||||
| 	{ | 	{ | ||||||
| 		appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n"; | 		appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n"; | ||||||
| 		setLocation(*panicClause); | 		setLocation(*panicClause); | ||||||
| 		string const success = m_context.newYulVariable(); | 		std::string const success = m_context.newYulVariable(); | ||||||
| 		string const code = m_context.newYulVariable(); | 		std::string const code = m_context.newYulVariable(); | ||||||
| 		appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n"; | 		appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n"; | ||||||
| 		appendCode() << "if " << success << " {\n"; | 		appendCode() << "if " << success << " {\n"; | ||||||
| 		appendCode() << runFallback << " := 0\n"; | 		appendCode() << runFallback << " := 0\n"; | ||||||
| @ -3358,9 +3357,9 @@ void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallba | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IRGeneratorForStatements::revertWithError( | void IRGeneratorForStatements::revertWithError( | ||||||
| 	string const& _signature, | 	std::string const& _signature, | ||||||
| 	vector<Type const*> const& _parameterTypes, | 	std::vector<Type const*> const& _parameterTypes, | ||||||
| 	vector<ASTPointer<Expression const>> const& _errorArguments | 	std::vector<ASTPointer<Expression const>> const& _errorArguments | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	Whiskers templ(R"({ | 	Whiskers templ(R"({ | ||||||
| @ -3374,8 +3373,8 @@ void IRGeneratorForStatements::revertWithError( | |||||||
| 	templ("hash", util::selectorFromSignatureU256(_signature).str()); | 	templ("hash", util::selectorFromSignatureU256(_signature).str()); | ||||||
| 	templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | 	templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | ||||||
| 
 | 
 | ||||||
| 	vector<string> errorArgumentVars; | 	std::vector<std::string> errorArgumentVars; | ||||||
| 	vector<Type const*> errorArgumentTypes; | 	std::vector<Type const*> errorArgumentTypes; | ||||||
| 	for (ASTPointer<Expression const> const& arg: _errorArguments) | 	for (ASTPointer<Expression const> const& arg: _errorArguments) | ||||||
| 	{ | 	{ | ||||||
| 		errorArgumentVars += IRVariable(*arg).stackSlots(); | 		errorArgumentVars += IRVariable(*arg).stackSlots(); | ||||||
| @ -3395,7 +3394,7 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause) | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const | std::string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const | ||||||
| { | { | ||||||
| 	solAssert(_library.isLibrary()); | 	solAssert(_library.isLibrary()); | ||||||
| 	return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")"; | 	return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")"; | ||||||
|  | |||||||
| @ -20,7 +20,6 @@ | |||||||
| #include <libsolidity/ast/AST.h> | #include <libsolidity/ast/AST.h> | ||||||
| #include <libsolutil/StringUtils.h> | #include <libsolutil/StringUtils.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; |  | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::frontend; | using namespace solidity::frontend; | ||||||
| using namespace solidity::util; | using namespace solidity::util; | ||||||
| @ -41,7 +40,7 @@ IRVariable::IRVariable(Expression const& _expression): | |||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IRVariable IRVariable::part(string const& _name) const | IRVariable IRVariable::part(std::string const& _name) const | ||||||
| { | { | ||||||
| 	for (auto const& [itemName, itemType]: m_type.stackItems()) | 	for (auto const& [itemName, itemType]: m_type.stackItems()) | ||||||
| 		if (itemName == _name) | 		if (itemName == _name) | ||||||
| @ -63,9 +62,9 @@ bool IRVariable::hasPart(std::string const& _name) const | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| vector<string> IRVariable::stackSlots() const | std::vector<std::string> IRVariable::stackSlots() const | ||||||
| { | { | ||||||
| 	vector<string> result; | 	std::vector<std::string> result; | ||||||
| 	for (auto const& [itemName, itemType]: m_type.stackItems()) | 	for (auto const& [itemName, itemType]: m_type.stackItems()) | ||||||
| 		if (itemType) | 		if (itemType) | ||||||
| 		{ | 		{ | ||||||
| @ -81,17 +80,17 @@ vector<string> IRVariable::stackSlots() const | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRVariable::commaSeparatedList() const | std::string IRVariable::commaSeparatedList() const | ||||||
| { | { | ||||||
| 	return joinHumanReadable(stackSlots()); | 	return joinHumanReadable(stackSlots()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRVariable::commaSeparatedListPrefixed() const | std::string IRVariable::commaSeparatedListPrefixed() const | ||||||
| { | { | ||||||
| 	return joinHumanReadablePrefixed(stackSlots()); | 	return joinHumanReadablePrefixed(stackSlots()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRVariable::name() const | std::string IRVariable::name() const | ||||||
| { | { | ||||||
| 	solAssert(m_type.sizeOnStack() == 1, ""); | 	solAssert(m_type.sizeOnStack() == 1, ""); | ||||||
| 	auto const& [itemName, type] = m_type.stackItems().front(); | 	auto const& [itemName, type] = m_type.stackItems().front(); | ||||||
| @ -108,7 +107,7 @@ IRVariable IRVariable::tupleComponent(size_t _i) const | |||||||
| 	return part(IRNames::tupleComponent(_i)); | 	return part(IRNames::tupleComponent(_i)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string IRVariable::suffixedName(string const& _suffix) const | std::string IRVariable::suffixedName(std::string const& _suffix) const | ||||||
| { | { | ||||||
| 	if (_suffix.empty()) | 	if (_suffix.empty()) | ||||||
| 		return m_baseName; | 		return m_baseName; | ||||||
|  | |||||||
| @ -27,6 +27,8 @@ NAMESPACE_STD_FREE_FILES=( | |||||||
|     libsolc/* |     libsolc/* | ||||||
|     libsolidity/analysis/* |     libsolidity/analysis/* | ||||||
|     libsolidity/ast/* |     libsolidity/ast/* | ||||||
|  |     libsolidity/codegen/ir/* | ||||||
|  |     libsolidity/codegen/* | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| ( | ( | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user