From 9640cfd77eec32f7b173a5dafbeac510d4b57253 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 27 Nov 2020 22:26:06 +0000 Subject: [PATCH] [ewasm] Add i32.select/i64.select --- Changelog.md | 1 + libyul/backends/wasm/BinaryTransform.cpp | 2 ++ libyul/backends/wasm/WasmDialect.cpp | 4 ++++ .../yulInterpreter/EwasmBuiltinInterpreter.cpp | 14 ++++++++++++++ 4 files changed, 21 insertions(+) diff --git a/Changelog.md b/Changelog.md index 0851a79d2..7838a1487 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: * Code generator: Support copying dynamically encoded structs from calldata to memory. * Code generator: Support copying of nested arrays from calldata to memory. * The fallback function can now also have a single ``calldata`` argument (equaling ``msg.data``) and return ``bytes memory`` (which will not be ABI-encoded but returned as-is). + * Wasm backend: Add ``i32.select`` and ``i64.select`` instructions. Compiler Features: * Code Generator: Avoid memory allocation for default value if it is not used. diff --git a/libyul/backends/wasm/BinaryTransform.cpp b/libyul/backends/wasm/BinaryTransform.cpp index a36742750..df700527e 100644 --- a/libyul/backends/wasm/BinaryTransform.cpp +++ b/libyul/backends/wasm/BinaryTransform.cpp @@ -156,6 +156,8 @@ Opcode constOpcodeFor(ValueType _type) } static map const builtins = { + {"i32.select", 0x1b}, + {"i64.select", 0x1b}, {"i32.load", 0x28}, {"i64.load", 0x29}, {"i32.load8_s", 0x2c}, diff --git a/libyul/backends/wasm/WasmDialect.cpp b/libyul/backends/wasm/WasmDialect.cpp index 1c7755d6a..1e77e1d47 100644 --- a/libyul/backends/wasm/WasmDialect.cpp +++ b/libyul/backends/wasm/WasmDialect.cpp @@ -120,6 +120,10 @@ WasmDialect::WasmDialect() addFunction("i32.drop", {i32}, {}); addFunction("i64.drop", {i64}, {}); + // Select is also overloaded. + addFunction("i32.select", {i32, i32, i32}, {i32}); + addFunction("i64.select", {i64, i64, i32}, {i64}); + addFunction("nop", {}, {}); addFunction("unreachable", {}, {}, false); m_functions["unreachable"_yulstring].sideEffects.storage = SideEffects::None; diff --git a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp index 10c8af230..7d50e1527 100644 --- a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp +++ b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp @@ -154,6 +154,20 @@ u256 EwasmBuiltinInterpreter::evalBuiltin( } else if (fun == "i32.drop" || fun == "i64.drop" || fun == "nop") return {}; + else if (fun == "i32.select") + { + if ((arg.at(2) & 0xffffffff) == 0) + return arg.at(1); + else + return arg.at(0); + } + else if (fun == "i64.select") + { + if ((arg.at(2) & 0xffffffffffffffff) == 0) + return arg.at(1); + else + return arg.at(0); + } else if (fun == "i32.wrap_i64") return arg.at(0) & uint32_t(-1); else if (fun == "i64.extend_i32_u")