diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 3d261fdee..4a1aff0fc 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -58,8 +58,8 @@ struct Dialect: boost::noncopyable /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. virtual BuiltinFunction const* builtin(YulString /*_name*/) const { return nullptr; } - virtual BuiltinFunction const* discardFunction() const { return nullptr; } - virtual BuiltinFunction const* equalityFunction() const { return nullptr; } + virtual BuiltinFunction const* discardFunction(YulString /* _type */) const { return nullptr; } + virtual BuiltinFunction const* equalityFunction(YulString /* _type */) const { return nullptr; } virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } /// Check whether the given type is legal for the given literal value. diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 39fc65632..27a2b85e3 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -290,6 +290,28 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA m_functions["u256_to_bool"_yulstring].returns = {"bool"_yulstring}; } +BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(YulString _type) const +{ + if (_type == "bool"_yulstring) + return builtin("popbool"_yulstring); + else + { + yulAssert(_type == defaultType, ""); + return builtin("pop"_yulstring); + } +} + +BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulString _type) const +{ + if (_type == "bool"_yulstring) + return nullptr; + else + { + yulAssert(_type == defaultType, ""); + return builtin("eq"_yulstring); + } +} + EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version) { static map> dialects; diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 40842fa57..2141ab98f 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -68,8 +68,8 @@ struct EVMDialect: public Dialect /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. BuiltinFunctionForEVM const* builtin(YulString _name) const override; - BuiltinFunctionForEVM const* discardFunction() const override { return builtin("pop"_yulstring); } - BuiltinFunctionForEVM const* equalityFunction() const override { return builtin("eq"_yulstring); } + BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); } + BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_yulstring); } BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); @@ -102,6 +102,10 @@ struct EVMDialectTyped: public EVMDialect /// Constructor, should only be used internally. Use the factory function below. EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess); + BuiltinFunctionForEVM const* discardFunction(YulString _type) const override; + BuiltinFunctionForEVM const* equalityFunction(YulString _type) const override; + BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("not"_yulstring); } + static EVMDialectTyped const& instance(langutil::EVMVersion _version); }; diff --git a/libyul/backends/wasm/WasmDialect.cpp b/libyul/backends/wasm/WasmDialect.cpp index 947326306..7f2149adc 100644 --- a/libyul/backends/wasm/WasmDialect.cpp +++ b/libyul/backends/wasm/WasmDialect.cpp @@ -91,8 +91,9 @@ WasmDialect::WasmDialect() m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = true; // Drop is actually overloaded for all types, but Yul does not support that. - // We could introduce "i32.drop". + // Because of that, we introduce "i32.drop". addFunction("drop", {i64}, {}); + addFunction("i32.drop", {i32}, {}); addFunction("nop", {}, {}); addFunction("unreachable", {}, {}, false); @@ -114,6 +115,22 @@ BuiltinFunction const* WasmDialect::builtin(YulString _name) const return nullptr; } +BuiltinFunction const* WasmDialect::discardFunction(YulString _type) const +{ + if (_type == "i32"_yulstring) + return builtin("i32.drop"_yulstring); + yulAssert(_type == "i64"_yulstring, ""); + return builtin("drop"_yulstring); +} + +BuiltinFunction const* WasmDialect::equalityFunction(YulString _type) const +{ + if (_type == "i32"_yulstring) + return builtin("i32.eq"_yulstring); + yulAssert(_type == "i64"_yulstring, ""); + return builtin("i64.eq"_yulstring); +} + WasmDialect const& WasmDialect::instance() { static std::unique_ptr dialect; diff --git a/libyul/backends/wasm/WasmDialect.h b/libyul/backends/wasm/WasmDialect.h index cf1a76d9d..1de65dfdc 100644 --- a/libyul/backends/wasm/WasmDialect.h +++ b/libyul/backends/wasm/WasmDialect.h @@ -35,19 +35,19 @@ struct Object; /** * Yul dialect for Wasm as a backend. * - * Builtin functions are a subset of the wasm instructions, always implicitly assuming - * unsigned 64 bit types. + * Builtin functions are a subset of the wasm instructions. + * + * There is a builtin function `i32.drop` that takes an i32, while `drop` takes i64. * - * !This is subject to changes! */ struct WasmDialect: public Dialect { WasmDialect(); BuiltinFunction const* builtin(YulString _name) const override; - BuiltinFunction const* discardFunction() const override { return builtin("drop"_yulstring); } - BuiltinFunction const* equalityFunction() const override { return builtin("i64.eq"_yulstring); } - BuiltinFunction const* booleanNegationFunction() const override { return builtin("i64.eqz"_yulstring); } + BuiltinFunction const* discardFunction(YulString _type) const override; + BuiltinFunction const* equalityFunction(YulString _type) const override; + BuiltinFunction const* booleanNegationFunction() const override { return builtin("i32.eqz"_yulstring); } std::set fixedFunctionNames() const override { return {"main"_yulstring}; }