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) | ||||
| 
 | ||||
| Language Features: | ||||
|  * Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``. | ||||
| 
 | ||||
| Compiler Features: | ||||
|  * Code Generator: Evaluate ``keccak256`` of string literals at compile-time. | ||||
| 
 | ||||
|  | ||||
| @ -38,13 +38,18 @@ WasmDialect::WasmDialect() | ||||
| 			"add", | ||||
| 			"sub", | ||||
| 			"mul", | ||||
| 			// TODO: div_s
 | ||||
| 			"div_u", | ||||
| 			// TODO: rem_s
 | ||||
| 			"rem_u", | ||||
| 			"and", | ||||
| 			"or", | ||||
| 			"xor", | ||||
| 			"shl", | ||||
| 			// TODO: shr_s
 | ||||
| 			"shr_u", | ||||
| 			// TODO: rotl
 | ||||
| 			// TODO: rotr
 | ||||
| 		}) | ||||
| 			addFunction(t.str() + "." + name, {t, t}, {t}); | ||||
| 
 | ||||
| @ -52,9 +57,13 @@ WasmDialect::WasmDialect() | ||||
| 		for (auto const& name: { | ||||
| 			"eq", | ||||
| 			"ne", | ||||
| 			// TODO: lt_s
 | ||||
| 			"lt_u", | ||||
| 			// TODO: gt_s
 | ||||
| 			"gt_u", | ||||
| 			// TODO: le_s
 | ||||
| 			"le_u", | ||||
| 			// TODO: ge_s
 | ||||
| 			"ge_u" | ||||
| 		}) | ||||
| 			addFunction(t.str() + "." + name, {t, t}, {i32}); | ||||
| @ -62,8 +71,13 @@ WasmDialect::WasmDialect() | ||||
| 	addFunction("i32.eqz", {i32}, {i32}); | ||||
| 	addFunction("i64.eqz", {i64}, {i32}); | ||||
| 
 | ||||
| 	addFunction("i32.clz", {i32}, {i32}); | ||||
| 	addFunction("i64.clz", {i64}, {i64}); | ||||
| 	for (auto t: types) | ||||
| 		for (auto const& name: { | ||||
| 			"clz", | ||||
| 			"ctz", | ||||
| 			"popcnt", | ||||
| 		}) | ||||
| 			addFunction(t.str() + "." + name, {t}, {t}); | ||||
| 
 | ||||
| 	addFunction("i32.wrap_i64", {i64}, {i32}); | ||||
| 
 | ||||
| @ -73,6 +87,7 @@ WasmDialect::WasmDialect() | ||||
| 	m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false; | ||||
| 	addFunction("i64.store", {i32, i64}, {}, 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); | ||||
| 	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.sideEffectFree = 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.
 | ||||
| 	// Because of that, we introduce "i32.drop" and "i64.drop".
 | ||||
|  | ||||
| @ -67,6 +67,50 @@ uint64_t clz64(uint64_t _v) | ||||
| 	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>>; | ||||
| @ -139,6 +183,10 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a | ||||
| 		return clz64(arg[0] & uint32_t(-1)) - 32; | ||||
| 	else if (_fun == "i64.clz"_yulstring) | ||||
| 		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 suffix; | ||||
| @ -207,6 +255,8 @@ u256 EwasmBuiltinInterpreter::evalWasmBuiltin(string const& _fun, vector<Word> c | ||||
| 		return arg[0] != arg[1] ? 1 : 0; | ||||
| 	else if (_fun == "eqz") | ||||
| 		return arg[0] == 0 ? 1 : 0; | ||||
| 	else if (_fun == "popcnt") | ||||
| 		return popcnt(arg[0]); | ||||
| 	else if (_fun == "lt_u") | ||||
| 		return arg[0] < arg[1] ? 1 : 0; | ||||
| 	else if (_fun == "gt_u") | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user