Introduce typed EVM dialect.

This commit is contained in:
chriseth 2019-12-19 16:01:28 +01:00
parent e41155cf48
commit 90c98a3289
3 changed files with 75 additions and 11 deletions

View File

@ -157,7 +157,7 @@ void AssemblyStack::compileEVM(AbstractAssembly& _assembly, bool _evm15, bool _o
dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion);
break;
case Language::Yul:
dialect = &EVMDialect::yulForEVM(m_evmVersion);
dialect = &EVMDialectTyped::instance(m_evmVersion);
break;
default:
solAssert(false, "Invalid language.");

View File

@ -203,15 +203,6 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _
return *dialects[_version];
}
EVMDialect const& EVMDialect::yulForEVM(langutil::EVMVersion _version)
{
static map<langutil::EVMVersion, unique_ptr<EVMDialect const>> dialects;
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
if (!dialects[_version])
dialects[_version] = make_unique<EVMDialect>(_version, false);
return *dialects[_version];
}
SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction)
{
return SideEffects{
@ -222,3 +213,58 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio
evmasm::SemanticInformation::invalidatesMemory(_instruction)
};
}
EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess):
EVMDialect(_evmVersion, _objectAccess)
{
defaultType = "u256"_yulstring;
m_functions["lt"_yulstring].returns = {"bool"_yulstring};
m_functions["gt"_yulstring].returns = {"bool"_yulstring};
m_functions["slt"_yulstring].returns = {"bool"_yulstring};
m_functions["sgt"_yulstring].returns = {"bool"_yulstring};
m_functions["eq"_yulstring].returns = {"bool"_yulstring};
m_functions["iszero"_yulstring].returns = {"bool"_yulstring};
m_functions["bitand"_yulstring] = m_functions["and"_yulstring];
m_functions["bitor"_yulstring] = m_functions["or"_yulstring];
m_functions["bitxor"_yulstring] = m_functions["xor"_yulstring];
m_functions["and"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring};
m_functions["and"_yulstring].returns = {"bool"_yulstring};
m_functions["or"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring};
m_functions["or"_yulstring].returns = {"bool"_yulstring};
m_functions["xor"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring};
m_functions["xor"_yulstring].returns = {"bool"_yulstring};
m_functions["isfalse"_yulstring] = m_functions["iszero"_yulstring];
m_functions["isfalse"_yulstring].parameters = {"bool"_yulstring};
m_functions["popbool"_yulstring] = m_functions["pop"_yulstring];
m_functions["popbool"_yulstring].parameters = {"bool"_yulstring};
m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, false, [](
FunctionCall const&,
AbstractAssembly&,
BuiltinContext&,
std::function<void()> _visitArguments
) {
_visitArguments();
}));
m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring};
m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, false, [](
FunctionCall const&,
AbstractAssembly& _assembly,
BuiltinContext&,
std::function<void()> _visitArguments
) {
// TODO Should a value larger than 1 be invalid?
_visitArguments();
_assembly.appendInstruction(evmasm::Instruction::ISZERO);
_assembly.appendInstruction(evmasm::Instruction::ISZERO);
}));
m_functions["u256_to_bool"_yulstring].returns = {"bool"_yulstring};
}
EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version)
{
static map<langutil::EVMVersion, unique_ptr<EVMDialectTyped const>> dialects;
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
if (!dialects[_version])
dialects[_version] = make_unique<EVMDialectTyped>(_version, true);
return *dialects[_version];
}

View File

@ -74,7 +74,6 @@ struct EVMDialect: public Dialect
static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version);
static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version);
static EVMDialect const& yulForEVM(langutil::EVMVersion _version);
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
@ -88,4 +87,23 @@ protected:
std::map<YulString, BuiltinFunctionForEVM> m_functions;
};
/**
* EVM dialect with types u256 (default) and bool.
* Difference to EVMDialect:
* - All comparison functions return type bool
* - bitwise operations are called bitor, bitand, bitxor and bitnot
* - and, or, xor take bool and return bool
* - iszero returns bool
* - isfalse takes bool and returns bool
* - there are conversion functions bool_to_u256 and u256_to_bool.
* - there is popbool
*/
struct EVMDialectTyped: public EVMDialect
{
/// Constructor, should only be used internally. Use the factory function below.
EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess);
static EVMDialectTyped const& instance(langutil::EVMVersion _version);
};
}