mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #7770 from ethereum/yul_string_format
[Yul] Format string literals back to quoted string literals
This commit is contained in:
		
						commit
						41177bc75c
					
				| @ -6,6 +6,7 @@ Language Features: | ||||
| 
 | ||||
| 
 | ||||
| Compiler Features: | ||||
|  * Yul: When compiling via Yul, string literals from the Solidity code are kept as string literals if every character is safely printable. | ||||
| 
 | ||||
| 
 | ||||
| Bugfixes: | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| #include <libdevcore/Exceptions.h> | ||||
| #include <libdevcore/Assertions.h> | ||||
| #include <libdevcore/Keccak256.h> | ||||
| #include <libdevcore/FixedHash.h> | ||||
| 
 | ||||
| #include <boost/algorithm/string.hpp> | ||||
| 
 | ||||
| @ -181,3 +182,15 @@ bool dev::isValidDecimal(string const& _string) | ||||
| 		return false; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| // Returns a quoted string if all characters are printable ASCII chars,
 | ||||
| // or its hex representation otherwise.
 | ||||
| std::string dev::formatAsStringOrNumber(std::string const& _value) | ||||
| { | ||||
| 	if (_value.length() <= 32) | ||||
| 		for (auto const& c: _value) | ||||
| 			if (c <= 0x1f || c >= 0x7f || c == '"') | ||||
| 				return "0x" + h256(_value, h256::AlignLeft).hex(); | ||||
| 
 | ||||
| 	return "\"" + _value + "\""; | ||||
| } | ||||
|  | ||||
| @ -290,7 +290,6 @@ void iterateReplacing(std::vector<T>& _vector, F const& _f) | ||||
| 		_vector = std::move(modifiedVector); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| namespace detail | ||||
| { | ||||
| template <typename T, typename F, std::size_t... I> | ||||
| @ -355,6 +354,10 @@ std::string getChecksummedAddress(std::string const& _addr); | ||||
| bool isValidHex(std::string const& _string); | ||||
| bool isValidDecimal(std::string const& _string); | ||||
| 
 | ||||
| /// @returns a quoted string if all characters are printable ASCII chars,
 | ||||
| /// or its hex representation otherwise.
 | ||||
| std::string formatAsStringOrNumber(std::string const& _value); | ||||
| 
 | ||||
| template<typename Container, typename Compare> | ||||
| bool containerEqual(Container const& _lhs, Container const& _rhs, Compare&& _compare) | ||||
| { | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| #include <libsolidity/codegen/ABIFunctions.h> | ||||
| 
 | ||||
| #include <libsolidity/codegen/CompilerUtils.h> | ||||
| #include <libdevcore/CommonData.h> | ||||
| #include <libdevcore/Whiskers.h> | ||||
| #include <libdevcore/StringUtils.h> | ||||
| 
 | ||||
| @ -975,7 +976,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | ||||
| 			for (size_t i = 0; i < words; ++i) | ||||
| 			{ | ||||
| 				wordParams[i]["offset"] = to_string(i * 32); | ||||
| 				wordParams[i]["wordValue"] = "0x" + h256(value.substr(32 * i, 32), h256::AlignLeft).hex(); | ||||
| 				wordParams[i]["wordValue"] = formatAsStringOrNumber(value.substr(32 * i, 32)); | ||||
| 			} | ||||
| 			templ("word", wordParams); | ||||
| 			return templ.render(); | ||||
| @ -990,7 +991,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral( | ||||
| 				} | ||||
| 			)"); | ||||
| 			templ("functionName", functionName); | ||||
| 			templ("wordValue", "0x" + h256(value, h256::AlignLeft).hex()); | ||||
| 			templ("wordValue", formatAsStringOrNumber(value)); | ||||
| 			return templ.render(); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| @ -23,6 +23,8 @@ | ||||
| #include <libsolidity/codegen/MultiUseYulFunctionCollector.h> | ||||
| #include <libsolidity/ast/AST.h> | ||||
| #include <libsolidity/codegen/CompilerUtils.h> | ||||
| 
 | ||||
| #include <libdevcore/CommonData.h> | ||||
| #include <libdevcore/Whiskers.h> | ||||
| #include <libdevcore/StringUtils.h> | ||||
| 
 | ||||
| @ -1756,7 +1758,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const | ||||
| 			for (size_t i = 0; i < words; ++i) | ||||
| 			{ | ||||
| 				wordParams[i]["offset"] = to_string(32 + i * 32); | ||||
| 				wordParams[i]["wordValue"] = "0x" + h256(data.substr(32 * i, 32), h256::AlignLeft).hex(); | ||||
| 				wordParams[i]["wordValue"] = formatAsStringOrNumber(data.substr(32 * i, 32)); | ||||
| 			} | ||||
| 			templ("word", wordParams); | ||||
| 			return templ.render(); | ||||
|  | ||||
							
								
								
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii/input.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii/input.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| { | ||||
| 	"language": "Solidity", | ||||
| 	"sources": | ||||
| 	{ | ||||
| 		"A": | ||||
| 		{ | ||||
| 			"content": "pragma solidity >=0.0; contract C { function f() external pure returns (string memory) { return \"abcabc\"; } }" | ||||
| 		} | ||||
| 	}, | ||||
| 	"settings": | ||||
| 	{ | ||||
| 		"outputSelection": | ||||
| 		{ | ||||
| 			"*": { "*": ["ir"] } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										161
									
								
								test/cmdlineTests/yul_string_format_ascii/output.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								test/cmdlineTests/yul_string_format_ascii/output.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,161 @@ | ||||
| {"contracts":{"A":{"C":{"ir":"/******************************************************* | ||||
|  *                       WARNING                       * | ||||
|  *  Solidity to Yul compilation is still EXPERIMENTAL  * | ||||
|  *       It can result in LOSS OF FUNDS or worse       * | ||||
|  *                !USE AT YOUR OWN RISK!               * | ||||
|  *******************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| object \"C_10\" { | ||||
|     code { | ||||
|         mstore(64, 128) | ||||
| 
 | ||||
|         // Begin state variable initialization for contract \"C\" (0 variables) | ||||
|         // End state variable initialization for contract \"C\". | ||||
| 
 | ||||
| 
 | ||||
|         codecopy(0, dataoffset(\"C_10_deployed\"), datasize(\"C_10_deployed\")) | ||||
|         return(0, datasize(\"C_10_deployed\")) | ||||
| 
 | ||||
| 
 | ||||
|         function allocateMemory(size) -> memPtr { | ||||
|             memPtr := mload(64) | ||||
|             let newFreePtr := add(memPtr, size) | ||||
|             // protect against overflow | ||||
|             if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|             mstore(64, newFreePtr) | ||||
|         } | ||||
| 
 | ||||
|         function convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr() -> converted { | ||||
|             converted := allocateMemory(64) | ||||
|             mstore(converted, 6) | ||||
| 
 | ||||
|             mstore(add(converted, 32), \"abcabc\") | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         function fun_f_9()  -> vloc__4 { | ||||
|             for { let return_flag := 1 } return_flag {} { | ||||
|                 vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr() | ||||
|                 return_flag := 0 | ||||
|                 break | ||||
| 
 | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     object \"C_10_deployed\" { | ||||
|         code { | ||||
|             mstore(64, 128) | ||||
| 
 | ||||
|             if iszero(lt(calldatasize(), 4)) | ||||
|             { | ||||
|                 let selector := shift_right_224_unsigned(calldataload(0)) | ||||
|                 switch selector | ||||
| 
 | ||||
|                 case 0x26121ff0 | ||||
|                 { | ||||
|                     // f() | ||||
|                     if callvalue() { revert(0, 0) } | ||||
|                     abi_decode_tuple_(4, calldatasize()) | ||||
|                     let ret_0 :=  fun_f_9() | ||||
|                     let memPos := allocateMemory(0) | ||||
|                     let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos ,  ret_0) | ||||
|                     return(memPos, sub(memEnd, memPos)) | ||||
|                 } | ||||
| 
 | ||||
|                 default {} | ||||
|             } | ||||
|             revert(0, 0) | ||||
| 
 | ||||
| 
 | ||||
|             function abi_decode_tuple_(headStart, dataEnd)   { | ||||
|                 if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value, pos) -> end { | ||||
|                 let length := array_length_t_string_memory_ptr(value) | ||||
|                 pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) | ||||
|                 copy_memory_to_memory(add(value, 0x20), pos, length) | ||||
|                 end := add(pos, round_up_to_mul_of_32(length)) | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(headStart , value0) -> tail { | ||||
|                 tail := add(headStart, 32) | ||||
| 
 | ||||
|                 mstore(add(headStart, 0), sub(tail, headStart)) | ||||
|                 tail := abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value0,  tail) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function allocateMemory(size) -> memPtr { | ||||
|                 memPtr := mload(64) | ||||
|                 let newFreePtr := add(memPtr, size) | ||||
|                 // protect against overflow | ||||
|                 if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|                 mstore(64, newFreePtr) | ||||
|             } | ||||
| 
 | ||||
|             function array_length_t_string_memory_ptr(value) -> length { | ||||
| 
 | ||||
| 
 | ||||
|                 length := mload(value) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) -> updated_pos { | ||||
|                 mstore(pos, length) | ||||
|                 updated_pos := add(pos, 0x20) | ||||
|             } | ||||
| 
 | ||||
|             function convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr() -> converted { | ||||
|                 converted := allocateMemory(64) | ||||
|                 mstore(converted, 6) | ||||
| 
 | ||||
|                 mstore(add(converted, 32), \"abcabc\") | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function copy_memory_to_memory(src, dst, length) { | ||||
|                 let i := 0 | ||||
|                 for { } lt(i, length) { i := add(i, 32) } | ||||
|                 { | ||||
|                     mstore(add(dst, i), mload(add(src, i))) | ||||
|                 } | ||||
|                 if gt(i, length) | ||||
|                 { | ||||
|                     // clear end | ||||
|                     mstore(add(dst, length), 0) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function fun_f_9()  -> vloc__4 { | ||||
|                 for { let return_flag := 1 } return_flag {} { | ||||
|                     vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr() | ||||
|                     return_flag := 0 | ||||
|                     break | ||||
| 
 | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function round_up_to_mul_of_32(value) -> result { | ||||
|                 result := and(add(value, 31), not(31)) | ||||
|             } | ||||
| 
 | ||||
|             function shift_right_224_unsigned(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shr(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| "}}},"sources":{"A":{"id":0}}} | ||||
							
								
								
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii_bytes32/input.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii_bytes32/input.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| { | ||||
| 	"language": "Solidity", | ||||
| 	"sources": | ||||
| 	{ | ||||
| 		"A": | ||||
| 		{ | ||||
| 			"content": "pragma solidity >=0.0; contract C { function f() external pure returns (bytes32) { return \"abcabc\"; } }" | ||||
| 		} | ||||
| 	}, | ||||
| 	"settings": | ||||
| 	{ | ||||
| 		"outputSelection": | ||||
| 		{ | ||||
| 			"*": { "*": ["ir"] } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										114
									
								
								test/cmdlineTests/yul_string_format_ascii_bytes32/output.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								test/cmdlineTests/yul_string_format_ascii_bytes32/output.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,114 @@ | ||||
| {"contracts":{"A":{"C":{"ir":"/******************************************************* | ||||
|  *                       WARNING                       * | ||||
|  *  Solidity to Yul compilation is still EXPERIMENTAL  * | ||||
|  *       It can result in LOSS OF FUNDS or worse       * | ||||
|  *                !USE AT YOUR OWN RISK!               * | ||||
|  *******************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| object \"C_10\" { | ||||
|     code { | ||||
|         mstore(64, 128) | ||||
| 
 | ||||
|         // Begin state variable initialization for contract \"C\" (0 variables) | ||||
|         // End state variable initialization for contract \"C\". | ||||
| 
 | ||||
| 
 | ||||
|         codecopy(0, dataoffset(\"C_10_deployed\"), datasize(\"C_10_deployed\")) | ||||
|         return(0, datasize(\"C_10_deployed\")) | ||||
| 
 | ||||
| 
 | ||||
|         function convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32() -> converted { | ||||
|             converted := 0x6162636162630000000000000000000000000000000000000000000000000000 | ||||
|         } | ||||
| 
 | ||||
|         function fun_f_9()  -> vloc__4 { | ||||
|             for { let return_flag := 1 } return_flag {} { | ||||
|                 vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32() | ||||
|                 return_flag := 0 | ||||
|                 break | ||||
| 
 | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     object \"C_10_deployed\" { | ||||
|         code { | ||||
|             mstore(64, 128) | ||||
| 
 | ||||
|             if iszero(lt(calldatasize(), 4)) | ||||
|             { | ||||
|                 let selector := shift_right_224_unsigned(calldataload(0)) | ||||
|                 switch selector | ||||
| 
 | ||||
|                 case 0x26121ff0 | ||||
|                 { | ||||
|                     // f() | ||||
|                     if callvalue() { revert(0, 0) } | ||||
|                     abi_decode_tuple_(4, calldatasize()) | ||||
|                     let ret_0 :=  fun_f_9() | ||||
|                     let memPos := allocateMemory(0) | ||||
|                     let memEnd := abi_encode_tuple_t_bytes32__to_t_bytes32__fromStack(memPos ,  ret_0) | ||||
|                     return(memPos, sub(memEnd, memPos)) | ||||
|                 } | ||||
| 
 | ||||
|                 default {} | ||||
|             } | ||||
|             revert(0, 0) | ||||
| 
 | ||||
| 
 | ||||
|             function abi_decode_tuple_(headStart, dataEnd)   { | ||||
|                 if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_t_bytes32_to_t_bytes32_fromStack(value, pos) { | ||||
|                 mstore(pos, cleanup_t_bytes32(value)) | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_tuple_t_bytes32__to_t_bytes32__fromStack(headStart , value0) -> tail { | ||||
|                 tail := add(headStart, 32) | ||||
| 
 | ||||
|                 abi_encode_t_bytes32_to_t_bytes32_fromStack(value0,  add(headStart, 0)) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function allocateMemory(size) -> memPtr { | ||||
|                 memPtr := mload(64) | ||||
|                 let newFreePtr := add(memPtr, size) | ||||
|                 // protect against overflow | ||||
|                 if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|                 mstore(64, newFreePtr) | ||||
|             } | ||||
| 
 | ||||
|             function cleanup_t_bytes32(value) -> cleaned { | ||||
|                 cleaned := value | ||||
|             } | ||||
| 
 | ||||
|             function convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32() -> converted { | ||||
|                 converted := 0x6162636162630000000000000000000000000000000000000000000000000000 | ||||
|             } | ||||
| 
 | ||||
|             function fun_f_9()  -> vloc__4 { | ||||
|                 for { let return_flag := 1 } return_flag {} { | ||||
|                     vloc__4 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32() | ||||
|                     return_flag := 0 | ||||
|                     break | ||||
| 
 | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function shift_right_224_unsigned(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shr(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| "}}},"sources":{"A":{"id":0}}} | ||||
| @ -0,0 +1,17 @@ | ||||
| { | ||||
| 	"language": "Solidity", | ||||
| 	"sources": | ||||
| 	{ | ||||
| 		"A": | ||||
| 		{ | ||||
| 			"content": "pragma solidity >=0.0; contract C { function f() external pure returns (bytes4) { return 0x61626364; } }" | ||||
| 		} | ||||
| 	}, | ||||
| 	"settings": | ||||
| 	{ | ||||
| 		"outputSelection": | ||||
| 		{ | ||||
| 			"*": { "*": ["ir"] } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,138 @@ | ||||
| {"contracts":{"A":{"C":{"ir":"/******************************************************* | ||||
|  *                       WARNING                       * | ||||
|  *  Solidity to Yul compilation is still EXPERIMENTAL  * | ||||
|  *       It can result in LOSS OF FUNDS or worse       * | ||||
|  *                !USE AT YOUR OWN RISK!               * | ||||
|  *******************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| object \"C_10\" { | ||||
|     code { | ||||
|         mstore(64, 128) | ||||
| 
 | ||||
|         // Begin state variable initialization for contract \"C\" (0 variables) | ||||
|         // End state variable initialization for contract \"C\". | ||||
| 
 | ||||
| 
 | ||||
|         codecopy(0, dataoffset(\"C_10_deployed\"), datasize(\"C_10_deployed\")) | ||||
|         return(0, datasize(\"C_10_deployed\")) | ||||
| 
 | ||||
| 
 | ||||
|         function cleanup_t_rational_1633837924_by_1(value) -> cleaned { | ||||
|             cleaned := value | ||||
|         } | ||||
| 
 | ||||
|         function convert_t_rational_1633837924_by_1_to_t_bytes4(value) -> converted { | ||||
|             converted := shift_left_224(cleanup_t_rational_1633837924_by_1(value)) | ||||
|         } | ||||
| 
 | ||||
|         function fun_f_9()  -> vloc__4 { | ||||
|             for { let return_flag := 1 } return_flag {} { | ||||
|                 let expr_6 := 0x61626364 | ||||
|                 vloc__4 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_6) | ||||
|                 return_flag := 0 | ||||
|                 break | ||||
| 
 | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         function shift_left_224(value) -> newValue { | ||||
|             newValue := | ||||
| 
 | ||||
|             shl(224, value) | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     object \"C_10_deployed\" { | ||||
|         code { | ||||
|             mstore(64, 128) | ||||
| 
 | ||||
|             if iszero(lt(calldatasize(), 4)) | ||||
|             { | ||||
|                 let selector := shift_right_224_unsigned(calldataload(0)) | ||||
|                 switch selector | ||||
| 
 | ||||
|                 case 0x26121ff0 | ||||
|                 { | ||||
|                     // f() | ||||
|                     if callvalue() { revert(0, 0) } | ||||
|                     abi_decode_tuple_(4, calldatasize()) | ||||
|                     let ret_0 :=  fun_f_9() | ||||
|                     let memPos := allocateMemory(0) | ||||
|                     let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos ,  ret_0) | ||||
|                     return(memPos, sub(memEnd, memPos)) | ||||
|                 } | ||||
| 
 | ||||
|                 default {} | ||||
|             } | ||||
|             revert(0, 0) | ||||
| 
 | ||||
| 
 | ||||
|             function abi_decode_tuple_(headStart, dataEnd)   { | ||||
|                 if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_t_bytes4_to_t_bytes4_fromStack(value, pos) { | ||||
|                 mstore(pos, cleanup_t_bytes4(value)) | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(headStart , value0) -> tail { | ||||
|                 tail := add(headStart, 32) | ||||
| 
 | ||||
|                 abi_encode_t_bytes4_to_t_bytes4_fromStack(value0,  add(headStart, 0)) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function allocateMemory(size) -> memPtr { | ||||
|                 memPtr := mload(64) | ||||
|                 let newFreePtr := add(memPtr, size) | ||||
|                 // protect against overflow | ||||
|                 if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|                 mstore(64, newFreePtr) | ||||
|             } | ||||
| 
 | ||||
|             function cleanup_t_bytes4(value) -> cleaned { | ||||
|                 cleaned := and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000) | ||||
|             } | ||||
| 
 | ||||
|             function cleanup_t_rational_1633837924_by_1(value) -> cleaned { | ||||
|                 cleaned := value | ||||
|             } | ||||
| 
 | ||||
|             function convert_t_rational_1633837924_by_1_to_t_bytes4(value) -> converted { | ||||
|                 converted := shift_left_224(cleanup_t_rational_1633837924_by_1(value)) | ||||
|             } | ||||
| 
 | ||||
|             function fun_f_9()  -> vloc__4 { | ||||
|                 for { let return_flag := 1 } return_flag {} { | ||||
|                     let expr_6 := 0x61626364 | ||||
|                     vloc__4 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_6) | ||||
|                     return_flag := 0 | ||||
|                     break | ||||
| 
 | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function shift_left_224(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shl(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function shift_right_224_unsigned(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shr(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| "}}},"sources":{"A":{"id":0}}} | ||||
							
								
								
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii_long/input.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/cmdlineTests/yul_string_format_ascii_long/input.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| { | ||||
| 	"language": "Solidity", | ||||
| 	"sources": | ||||
| 	{ | ||||
| 		"A": | ||||
| 		{ | ||||
| 			"content": "pragma solidity >=0.0; contract C { function f() external pure returns (string memory) { return \"abcdabcdcafecafeabcdabcdcafecafeffffzzzzoooo0123456789,.<,>.?:;'[{]}|`~!@#$%^&*()-_=+\"; } }" | ||||
| 		} | ||||
| 	}, | ||||
| 	"settings": | ||||
| 	{ | ||||
| 		"outputSelection": | ||||
| 		{ | ||||
| 			"*": { "*": ["ir"] } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										169
									
								
								test/cmdlineTests/yul_string_format_ascii_long/output.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								test/cmdlineTests/yul_string_format_ascii_long/output.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | ||||
| {"contracts":{"A":{"C":{"ir":"/******************************************************* | ||||
|  *                       WARNING                       * | ||||
|  *  Solidity to Yul compilation is still EXPERIMENTAL  * | ||||
|  *       It can result in LOSS OF FUNDS or worse       * | ||||
|  *                !USE AT YOUR OWN RISK!               * | ||||
|  *******************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| object \"C_10\" { | ||||
|     code { | ||||
|         mstore(64, 128) | ||||
| 
 | ||||
|         // Begin state variable initialization for contract \"C\" (0 variables) | ||||
|         // End state variable initialization for contract \"C\". | ||||
| 
 | ||||
| 
 | ||||
|         codecopy(0, dataoffset(\"C_10_deployed\"), datasize(\"C_10_deployed\")) | ||||
|         return(0, datasize(\"C_10_deployed\")) | ||||
| 
 | ||||
| 
 | ||||
|         function allocateMemory(size) -> memPtr { | ||||
|             memPtr := mload(64) | ||||
|             let newFreePtr := add(memPtr, size) | ||||
|             // protect against overflow | ||||
|             if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|             mstore(64, newFreePtr) | ||||
|         } | ||||
| 
 | ||||
|         function convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr() -> converted { | ||||
|             converted := allocateMemory(128) | ||||
|             mstore(converted, 85) | ||||
| 
 | ||||
|             mstore(add(converted, 32), \"abcdabcdcafecafeabcdabcdcafecafe\") | ||||
| 
 | ||||
|             mstore(add(converted, 64), \"ffffzzzzoooo0123456789,.<,>.?:;'\") | ||||
| 
 | ||||
|             mstore(add(converted, 96), \"[{]}|`~!@#$%^&*()-_=+\") | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         function fun_f_9()  -> vloc__4 { | ||||
|             for { let return_flag := 1 } return_flag {} { | ||||
|                 vloc__4 := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr() | ||||
|                 return_flag := 0 | ||||
|                 break | ||||
| 
 | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     object \"C_10_deployed\" { | ||||
|         code { | ||||
|             mstore(64, 128) | ||||
| 
 | ||||
|             if iszero(lt(calldatasize(), 4)) | ||||
|             { | ||||
|                 let selector := shift_right_224_unsigned(calldataload(0)) | ||||
|                 switch selector | ||||
| 
 | ||||
|                 case 0x26121ff0 | ||||
|                 { | ||||
|                     // f() | ||||
|                     if callvalue() { revert(0, 0) } | ||||
|                     abi_decode_tuple_(4, calldatasize()) | ||||
|                     let ret_0 :=  fun_f_9() | ||||
|                     let memPos := allocateMemory(0) | ||||
|                     let memEnd := abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(memPos ,  ret_0) | ||||
|                     return(memPos, sub(memEnd, memPos)) | ||||
|                 } | ||||
| 
 | ||||
|                 default {} | ||||
|             } | ||||
|             revert(0, 0) | ||||
| 
 | ||||
| 
 | ||||
|             function abi_decode_tuple_(headStart, dataEnd)   { | ||||
|                 if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value, pos) -> end { | ||||
|                 let length := array_length_t_string_memory_ptr(value) | ||||
|                 pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) | ||||
|                 copy_memory_to_memory(add(value, 0x20), pos, length) | ||||
|                 end := add(pos, round_up_to_mul_of_32(length)) | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_tuple_t_string_memory_ptr__to_t_string_memory_ptr__fromStack(headStart , value0) -> tail { | ||||
|                 tail := add(headStart, 32) | ||||
| 
 | ||||
|                 mstore(add(headStart, 0), sub(tail, headStart)) | ||||
|                 tail := abi_encode_t_string_memory_ptr_to_t_string_memory_ptr_fromStack(value0,  tail) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function allocateMemory(size) -> memPtr { | ||||
|                 memPtr := mload(64) | ||||
|                 let newFreePtr := add(memPtr, size) | ||||
|                 // protect against overflow | ||||
|                 if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|                 mstore(64, newFreePtr) | ||||
|             } | ||||
| 
 | ||||
|             function array_length_t_string_memory_ptr(value) -> length { | ||||
| 
 | ||||
| 
 | ||||
|                 length := mload(value) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) -> updated_pos { | ||||
|                 mstore(pos, length) | ||||
|                 updated_pos := add(pos, 0x20) | ||||
|             } | ||||
| 
 | ||||
|             function convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr() -> converted { | ||||
|                 converted := allocateMemory(128) | ||||
|                 mstore(converted, 85) | ||||
| 
 | ||||
|                 mstore(add(converted, 32), \"abcdabcdcafecafeabcdabcdcafecafe\") | ||||
| 
 | ||||
|                 mstore(add(converted, 64), \"ffffzzzzoooo0123456789,.<,>.?:;'\") | ||||
| 
 | ||||
|                 mstore(add(converted, 96), \"[{]}|`~!@#$%^&*()-_=+\") | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function copy_memory_to_memory(src, dst, length) { | ||||
|                 let i := 0 | ||||
|                 for { } lt(i, length) { i := add(i, 32) } | ||||
|                 { | ||||
|                     mstore(add(dst, i), mload(add(src, i))) | ||||
|                 } | ||||
|                 if gt(i, length) | ||||
|                 { | ||||
|                     // clear end | ||||
|                     mstore(add(dst, length), 0) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function fun_f_9()  -> vloc__4 { | ||||
|                 for { let return_flag := 1 } return_flag {} { | ||||
|                     vloc__4 := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr() | ||||
|                     return_flag := 0 | ||||
|                     break | ||||
| 
 | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function round_up_to_mul_of_32(value) -> result { | ||||
|                 result := and(add(value, 31), not(31)) | ||||
|             } | ||||
| 
 | ||||
|             function shift_right_224_unsigned(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shr(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| "}}},"sources":{"A":{"id":0}}} | ||||
							
								
								
									
										17
									
								
								test/cmdlineTests/yul_string_format_hex/input.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/cmdlineTests/yul_string_format_hex/input.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| { | ||||
| 	"language": "Solidity", | ||||
| 	"sources": | ||||
| 	{ | ||||
| 		"A": | ||||
| 		{ | ||||
| 			"content": "pragma solidity >=0.0; contract C { function f() external pure returns (bytes4) { return 0xaabbccdd; } }" | ||||
| 		} | ||||
| 	}, | ||||
| 	"settings": | ||||
| 	{ | ||||
| 		"outputSelection": | ||||
| 		{ | ||||
| 			"*": { "*": ["ir"] } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										138
									
								
								test/cmdlineTests/yul_string_format_hex/output.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								test/cmdlineTests/yul_string_format_hex/output.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,138 @@ | ||||
| {"contracts":{"A":{"C":{"ir":"/******************************************************* | ||||
|  *                       WARNING                       * | ||||
|  *  Solidity to Yul compilation is still EXPERIMENTAL  * | ||||
|  *       It can result in LOSS OF FUNDS or worse       * | ||||
|  *                !USE AT YOUR OWN RISK!               * | ||||
|  *******************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| object \"C_10\" { | ||||
|     code { | ||||
|         mstore(64, 128) | ||||
| 
 | ||||
|         // Begin state variable initialization for contract \"C\" (0 variables) | ||||
|         // End state variable initialization for contract \"C\". | ||||
| 
 | ||||
| 
 | ||||
|         codecopy(0, dataoffset(\"C_10_deployed\"), datasize(\"C_10_deployed\")) | ||||
|         return(0, datasize(\"C_10_deployed\")) | ||||
| 
 | ||||
| 
 | ||||
|         function cleanup_t_rational_2864434397_by_1(value) -> cleaned { | ||||
|             cleaned := value | ||||
|         } | ||||
| 
 | ||||
|         function convert_t_rational_2864434397_by_1_to_t_bytes4(value) -> converted { | ||||
|             converted := shift_left_224(cleanup_t_rational_2864434397_by_1(value)) | ||||
|         } | ||||
| 
 | ||||
|         function fun_f_9()  -> vloc__4 { | ||||
|             for { let return_flag := 1 } return_flag {} { | ||||
|                 let expr_6 := 0xaabbccdd | ||||
|                 vloc__4 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_6) | ||||
|                 return_flag := 0 | ||||
|                 break | ||||
| 
 | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         function shift_left_224(value) -> newValue { | ||||
|             newValue := | ||||
| 
 | ||||
|             shl(224, value) | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     object \"C_10_deployed\" { | ||||
|         code { | ||||
|             mstore(64, 128) | ||||
| 
 | ||||
|             if iszero(lt(calldatasize(), 4)) | ||||
|             { | ||||
|                 let selector := shift_right_224_unsigned(calldataload(0)) | ||||
|                 switch selector | ||||
| 
 | ||||
|                 case 0x26121ff0 | ||||
|                 { | ||||
|                     // f() | ||||
|                     if callvalue() { revert(0, 0) } | ||||
|                     abi_decode_tuple_(4, calldatasize()) | ||||
|                     let ret_0 :=  fun_f_9() | ||||
|                     let memPos := allocateMemory(0) | ||||
|                     let memEnd := abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(memPos ,  ret_0) | ||||
|                     return(memPos, sub(memEnd, memPos)) | ||||
|                 } | ||||
| 
 | ||||
|                 default {} | ||||
|             } | ||||
|             revert(0, 0) | ||||
| 
 | ||||
| 
 | ||||
|             function abi_decode_tuple_(headStart, dataEnd)   { | ||||
|                 if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_t_bytes4_to_t_bytes4_fromStack(value, pos) { | ||||
|                 mstore(pos, cleanup_t_bytes4(value)) | ||||
|             } | ||||
| 
 | ||||
|             function abi_encode_tuple_t_bytes4__to_t_bytes4__fromStack(headStart , value0) -> tail { | ||||
|                 tail := add(headStart, 32) | ||||
| 
 | ||||
|                 abi_encode_t_bytes4_to_t_bytes4_fromStack(value0,  add(headStart, 0)) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function allocateMemory(size) -> memPtr { | ||||
|                 memPtr := mload(64) | ||||
|                 let newFreePtr := add(memPtr, size) | ||||
|                 // protect against overflow | ||||
|                 if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } | ||||
|                 mstore(64, newFreePtr) | ||||
|             } | ||||
| 
 | ||||
|             function cleanup_t_bytes4(value) -> cleaned { | ||||
|                 cleaned := and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000) | ||||
|             } | ||||
| 
 | ||||
|             function cleanup_t_rational_2864434397_by_1(value) -> cleaned { | ||||
|                 cleaned := value | ||||
|             } | ||||
| 
 | ||||
|             function convert_t_rational_2864434397_by_1_to_t_bytes4(value) -> converted { | ||||
|                 converted := shift_left_224(cleanup_t_rational_2864434397_by_1(value)) | ||||
|             } | ||||
| 
 | ||||
|             function fun_f_9()  -> vloc__4 { | ||||
|                 for { let return_flag := 1 } return_flag {} { | ||||
|                     let expr_6 := 0xaabbccdd | ||||
|                     vloc__4 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_6) | ||||
|                     return_flag := 0 | ||||
|                     break | ||||
| 
 | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             function shift_left_224(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shl(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             function shift_right_224_unsigned(value) -> newValue { | ||||
|                 newValue := | ||||
| 
 | ||||
|                 shr(224, value) | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| "}}},"sources":{"A":{"id":0}}} | ||||
							
								
								
									
										13
									
								
								test/libsolidity/semanticTests/viaYul/string_format.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/libsolidity/semanticTests/viaYul/string_format.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| contract C { | ||||
| 	function f1() external pure returns (string memory) { return "abcabc"; } | ||||
| 	function f2() external pure returns (string memory) { return "abcabc`~12345677890- _=+!@#$%^&*()[{]}|;:',<.>?"; } | ||||
| 	function g() external pure returns (bytes32) { return "abcabc"; } | ||||
| 	function h() external pure returns (bytes4) { return 0xcafecafe; } | ||||
| } | ||||
| // ==== | ||||
| // compileViaYul: only | ||||
| // ---- | ||||
| // f1() -> 0x20, 6, left(0x616263616263) | ||||
| // f2() -> 32, 47, 44048183223289766195424279195050628400112610419087780792899004030957505095210, 18165586057823232067963737336409268114628061002662705707816940456850361417728 | ||||
| // g() -> left(0x616263616263) | ||||
| // h() -> left(0xcafecafe) | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user