mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #9367 from ethereum/wasm-dialect
Add ctz and popcnt to WasmDialect
This commit is contained in:
		
						commit
						1d666335f8
					
				| @ -1,5 +1,8 @@ | |||||||
| ### 0.6.12 (unreleased) | ### 0.6.12 (unreleased) | ||||||
| 
 | 
 | ||||||
|  | Language Features: | ||||||
|  |  * Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``. | ||||||
|  | 
 | ||||||
| Compiler Features: | Compiler Features: | ||||||
|  * Code Generator: Evaluate ``keccak256`` of string literals at compile-time. |  * Code Generator: Evaluate ``keccak256`` of string literals at compile-time. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -38,13 +38,18 @@ WasmDialect::WasmDialect() | |||||||
| 			"add", | 			"add", | ||||||
| 			"sub", | 			"sub", | ||||||
| 			"mul", | 			"mul", | ||||||
|  | 			// TODO: div_s
 | ||||||
| 			"div_u", | 			"div_u", | ||||||
|  | 			// TODO: rem_s
 | ||||||
| 			"rem_u", | 			"rem_u", | ||||||
| 			"and", | 			"and", | ||||||
| 			"or", | 			"or", | ||||||
| 			"xor", | 			"xor", | ||||||
| 			"shl", | 			"shl", | ||||||
|  | 			// TODO: shr_s
 | ||||||
| 			"shr_u", | 			"shr_u", | ||||||
|  | 			// TODO: rotl
 | ||||||
|  | 			// TODO: rotr
 | ||||||
| 		}) | 		}) | ||||||
| 			addFunction(t.str() + "." + name, {t, t}, {t}); | 			addFunction(t.str() + "." + name, {t, t}, {t}); | ||||||
| 
 | 
 | ||||||
| @ -52,9 +57,13 @@ WasmDialect::WasmDialect() | |||||||
| 		for (auto const& name: { | 		for (auto const& name: { | ||||||
| 			"eq", | 			"eq", | ||||||
| 			"ne", | 			"ne", | ||||||
|  | 			// TODO: lt_s
 | ||||||
| 			"lt_u", | 			"lt_u", | ||||||
|  | 			// TODO: gt_s
 | ||||||
| 			"gt_u", | 			"gt_u", | ||||||
|  | 			// TODO: le_s
 | ||||||
| 			"le_u", | 			"le_u", | ||||||
|  | 			// TODO: ge_s
 | ||||||
| 			"ge_u" | 			"ge_u" | ||||||
| 		}) | 		}) | ||||||
| 			addFunction(t.str() + "." + name, {t, t}, {i32}); | 			addFunction(t.str() + "." + name, {t, t}, {i32}); | ||||||
| @ -62,8 +71,13 @@ WasmDialect::WasmDialect() | |||||||
| 	addFunction("i32.eqz", {i32}, {i32}); | 	addFunction("i32.eqz", {i32}, {i32}); | ||||||
| 	addFunction("i64.eqz", {i64}, {i32}); | 	addFunction("i64.eqz", {i64}, {i32}); | ||||||
| 
 | 
 | ||||||
| 	addFunction("i32.clz", {i32}, {i32}); | 	for (auto t: types) | ||||||
| 	addFunction("i64.clz", {i64}, {i64}); | 		for (auto const& name: { | ||||||
|  | 			"clz", | ||||||
|  | 			"ctz", | ||||||
|  | 			"popcnt", | ||||||
|  | 		}) | ||||||
|  | 			addFunction(t.str() + "." + name, {t}, {t}); | ||||||
| 
 | 
 | ||||||
| 	addFunction("i32.wrap_i64", {i64}, {i32}); | 	addFunction("i32.wrap_i64", {i64}, {i32}); | ||||||
| 
 | 
 | ||||||
| @ -73,6 +87,7 @@ WasmDialect::WasmDialect() | |||||||
| 	m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false; | 	m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false; | ||||||
| 	addFunction("i64.store", {i32, i64}, {}, false); | 	addFunction("i64.store", {i32, i64}, {}, false); | ||||||
| 	m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false; | 	m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false; | ||||||
|  | 	// TODO: add i32.store16, i64.store8, i64.store16, i64.store32
 | ||||||
| 
 | 
 | ||||||
| 	addFunction("i32.store8", {i32, i32}, {}, false); | 	addFunction("i32.store8", {i32, i32}, {}, false); | ||||||
| 	m_functions["i32.store8"_yulstring].sideEffects.invalidatesStorage = false; | 	m_functions["i32.store8"_yulstring].sideEffects.invalidatesStorage = false; | ||||||
| @ -89,6 +104,7 @@ WasmDialect::WasmDialect() | |||||||
| 	m_functions["i64.load"_yulstring].sideEffects.invalidatesMemory = false; | 	m_functions["i64.load"_yulstring].sideEffects.invalidatesMemory = false; | ||||||
| 	m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true; | 	m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true; | ||||||
| 	m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = true; | 	m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = true; | ||||||
|  | 	// TODO: add i32.load8, i32.load16, i64.load8, i64.load16, i64.load32
 | ||||||
| 
 | 
 | ||||||
| 	// Drop is actually overloaded for all types, but Yul does not support that.
 | 	// Drop is actually overloaded for all types, but Yul does not support that.
 | ||||||
| 	// Because of that, we introduce "i32.drop" and "i64.drop".
 | 	// Because of that, we introduce "i32.drop" and "i64.drop".
 | ||||||
|  | |||||||
| @ -67,6 +67,50 @@ uint64_t clz64(uint64_t _v) | |||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// Count trailing zeros for uint32. Following WebAssembly rules, it returns 32 for @a _v being zero.
 | ||||||
|  | /// NOTE: the ctz builtin of the compiler may or may not do this
 | ||||||
|  | uint32_t ctz32(uint32_t _v) | ||||||
|  | { | ||||||
|  | 	if (_v == 0) | ||||||
|  | 		return 32; | ||||||
|  | 
 | ||||||
|  | 	uint32_t r = 0; | ||||||
|  | 	while (!(_v & 1)) | ||||||
|  | 	{ | ||||||
|  | 		r++; | ||||||
|  | 		_v >>= 1; | ||||||
|  | 	} | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Count trailing zeros for uint64. Following WebAssembly rules, it returns 64 for @a _v being zero.
 | ||||||
|  | /// NOTE: the ctz builtin of the compiler may or may not do this
 | ||||||
|  | uint64_t ctz64(uint64_t _v) | ||||||
|  | { | ||||||
|  | 	if (_v == 0) | ||||||
|  | 		return 64; | ||||||
|  | 
 | ||||||
|  | 	uint64_t r = 0; | ||||||
|  | 	while (!(_v & 1)) | ||||||
|  | 	{ | ||||||
|  | 		r++; | ||||||
|  | 		_v >>= 1; | ||||||
|  | 	} | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Count number of bits set for uint64
 | ||||||
|  | uint64_t popcnt(uint64_t _v) | ||||||
|  | { | ||||||
|  | 	uint64_t r = 0; | ||||||
|  | 	while (_v) | ||||||
|  | 	{ | ||||||
|  | 		r += (_v & 1); | ||||||
|  | 		_v >>= 1; | ||||||
|  | 	} | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>; | using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>; | ||||||
| @ -139,6 +183,10 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a | |||||||
| 		return clz64(arg[0] & uint32_t(-1)) - 32; | 		return clz64(arg[0] & uint32_t(-1)) - 32; | ||||||
| 	else if (_fun == "i64.clz"_yulstring) | 	else if (_fun == "i64.clz"_yulstring) | ||||||
| 		return clz64(arg[0]); | 		return clz64(arg[0]); | ||||||
|  | 	else if (_fun == "i32.ctz"_yulstring) | ||||||
|  | 		return ctz32(uint32_t(arg[0] & uint32_t(-1))); | ||||||
|  | 	else if (_fun == "i64.ctz"_yulstring) | ||||||
|  | 		return ctz64(arg[0]); | ||||||
| 
 | 
 | ||||||
| 	string prefix = _fun.str(); | 	string prefix = _fun.str(); | ||||||
| 	string suffix; | 	string suffix; | ||||||
| @ -207,6 +255,8 @@ u256 EwasmBuiltinInterpreter::evalWasmBuiltin(string const& _fun, vector<Word> c | |||||||
| 		return arg[0] != arg[1] ? 1 : 0; | 		return arg[0] != arg[1] ? 1 : 0; | ||||||
| 	else if (_fun == "eqz") | 	else if (_fun == "eqz") | ||||||
| 		return arg[0] == 0 ? 1 : 0; | 		return arg[0] == 0 ? 1 : 0; | ||||||
|  | 	else if (_fun == "popcnt") | ||||||
|  | 		return popcnt(arg[0]); | ||||||
| 	else if (_fun == "lt_u") | 	else if (_fun == "lt_u") | ||||||
| 		return arg[0] < arg[1] ? 1 : 0; | 		return arg[0] < arg[1] ? 1 : 0; | ||||||
| 	else if (_fun == "gt_u") | 	else if (_fun == "gt_u") | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user