mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8068 from ethereum/evmTypedDialect
[Yul] EVM typed dialect
This commit is contained in:
commit
ada0cef150
@ -387,7 +387,7 @@ void CompilerContext::appendInlineAssembly(
|
|||||||
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
|
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
|
||||||
shared_ptr<yul::Block> parserResult = yul::Parser(errorReporter, dialect).parse(scanner, false);
|
shared_ptr<yul::Block> parserResult = yul::Parser(errorReporter, dialect).parse(scanner, false);
|
||||||
#ifdef SOL_OUTPUT_ASM
|
#ifdef SOL_OUTPUT_ASM
|
||||||
cout << yul::AsmPrinter()(*parserResult) << endl;
|
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto reportError = [&](string const& _context)
|
auto reportError = [&](string const& _context)
|
||||||
@ -438,7 +438,7 @@ void CompilerContext::appendInlineAssembly(
|
|||||||
|
|
||||||
#ifdef SOL_OUTPUT_ASM
|
#ifdef SOL_OUTPUT_ASM
|
||||||
cout << "After optimizer:" << endl;
|
cout << "After optimizer:" << endl;
|
||||||
cout << yul::AsmPrinter()(*parserResult) << endl;
|
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,6 +892,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
|
|||||||
|
|
||||||
solAssert(holds_alternative<yul::Block>(modified), "");
|
solAssert(holds_alternative<yul::Block>(modified), "");
|
||||||
|
|
||||||
|
// Do not provide dialect so that we get the full type information.
|
||||||
m_code << yul::AsmPrinter()(std::get<yul::Block>(std::move(modified))) << "\n";
|
m_code << yul::AsmPrinter()(std::get<yul::Block>(std::move(modified))) << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ Scope& AsmAnalyzer::scope(Block const* _block)
|
|||||||
}
|
}
|
||||||
void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _location)
|
void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _location)
|
||||||
{
|
{
|
||||||
if (!_type.empty() && !contains(m_dialect.types, _type))
|
if (!_type.empty() && !m_dialect.types.count(_type))
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
_location,
|
_location,
|
||||||
"\"" + _type.str() + "\" is not a valid type (user defined types are not yet supported)."
|
"\"" + _type.str() + "\" is not a valid type (user defined types are not yet supported)."
|
||||||
|
@ -366,7 +366,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
|
|||||||
location(),
|
location(),
|
||||||
kind,
|
kind,
|
||||||
YulString{currentLiteral()},
|
YulString{currentLiteral()},
|
||||||
{}
|
kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType
|
||||||
};
|
};
|
||||||
advance();
|
advance();
|
||||||
if (currentToken() == Token::Colon)
|
if (currentToken() == Token::Colon)
|
||||||
@ -497,6 +497,9 @@ TypedName Parser::parseTypedName()
|
|||||||
typedName.location.end = endPosition();
|
typedName.location.end = endPosition();
|
||||||
typedName.type = expectAsmIdentifier();
|
typedName.type = expectAsmIdentifier();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
typedName.type = m_dialect.defaultType;
|
||||||
|
|
||||||
return typedName;
|
return typedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <libyul/AsmPrinter.h>
|
#include <libyul/AsmPrinter.h>
|
||||||
#include <libyul/AsmData.h>
|
#include <libyul/AsmData.h>
|
||||||
#include <libyul/Exceptions.h>
|
#include <libyul/Exceptions.h>
|
||||||
|
#include <libyul/Dialect.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ string AsmPrinter::operator()(Literal const& _literal) const
|
|||||||
return _literal.value.str() + appendTypeName(_literal.type);
|
return _literal.value.str() + appendTypeName(_literal.type);
|
||||||
case LiteralKind::Boolean:
|
case LiteralKind::Boolean:
|
||||||
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "Invalid bool literal.");
|
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "Invalid bool literal.");
|
||||||
return ((_literal.value == "true"_yulstring) ? "true" : "false") + appendTypeName(_literal.type);
|
return ((_literal.value == "true"_yulstring) ? "true" : "false") + appendTypeName(_literal.type, true);
|
||||||
case LiteralKind::String:
|
case LiteralKind::String:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -236,9 +237,18 @@ string AsmPrinter::formatTypedName(TypedName _variable) const
|
|||||||
return _variable.name.str() + appendTypeName(_variable.type);
|
return _variable.name.str() + appendTypeName(_variable.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
string AsmPrinter::appendTypeName(YulString _type) const
|
string AsmPrinter::appendTypeName(YulString _type, bool _isBoolLiteral) const
|
||||||
{
|
{
|
||||||
if (!_type.empty())
|
if (m_dialect && !_type.empty())
|
||||||
|
{
|
||||||
|
if (!_isBoolLiteral && _type == m_dialect->defaultType)
|
||||||
|
_type = {};
|
||||||
|
else if (_isBoolLiteral && _type == m_dialect->boolType && !m_dialect->defaultType.empty())
|
||||||
|
// Special case: If we have a bool type but empty default type, do not remove the type.
|
||||||
|
_type = {};
|
||||||
|
}
|
||||||
|
if (_type.empty())
|
||||||
|
return {};
|
||||||
|
else
|
||||||
return ":" + _type.str();
|
return ":" + _type.str();
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,16 @@ namespace solidity::yul
|
|||||||
{
|
{
|
||||||
struct Dialect;
|
struct Dialect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a parsed Yul AST into readable string representation.
|
||||||
|
* Ignores source locations.
|
||||||
|
* If a dialect is provided, the dialect's default type is omitted.
|
||||||
|
*/
|
||||||
class AsmPrinter
|
class AsmPrinter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AsmPrinter() {}
|
AsmPrinter() {}
|
||||||
|
explicit AsmPrinter(Dialect const& _dialect): m_dialect(&_dialect) {}
|
||||||
|
|
||||||
std::string operator()(Literal const& _literal) const;
|
std::string operator()(Literal const& _literal) const;
|
||||||
std::string operator()(Identifier const& _identifier) const;
|
std::string operator()(Identifier const& _identifier) const;
|
||||||
@ -52,7 +58,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string formatTypedName(TypedName _variable) const;
|
std::string formatTypedName(TypedName _variable) const;
|
||||||
std::string appendTypeName(YulString _type) const;
|
std::string appendTypeName(YulString _type, bool _isBoolLiteral = false) const;
|
||||||
|
|
||||||
|
Dialect const* m_dialect = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -59,12 +59,12 @@ Dialect const& languageToDialect(AssemblyStack::Language _language, EVMVersion _
|
|||||||
case AssemblyStack::Language::StrictAssembly:
|
case AssemblyStack::Language::StrictAssembly:
|
||||||
return EVMDialect::strictAssemblyForEVMObjects(_version);
|
return EVMDialect::strictAssemblyForEVMObjects(_version);
|
||||||
case AssemblyStack::Language::Yul:
|
case AssemblyStack::Language::Yul:
|
||||||
return Dialect::yul();
|
return EVMDialectTyped::instance(_version);
|
||||||
case AssemblyStack::Language::Ewasm:
|
case AssemblyStack::Language::Ewasm:
|
||||||
return WasmDialect::instance();
|
return WasmDialect::instance();
|
||||||
}
|
}
|
||||||
yulAssert(false, "");
|
yulAssert(false, "");
|
||||||
return Dialect::yul();
|
return Dialect::yulDeprecated();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ void AssemblyStack::compileEVM(AbstractAssembly& _assembly, bool _evm15, bool _o
|
|||||||
dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion);
|
dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion);
|
||||||
break;
|
break;
|
||||||
case Language::Yul:
|
case Language::Yul:
|
||||||
dialect = &EVMDialect::yulForEVM(m_evmVersion);
|
dialect = &EVMDialectTyped::instance(m_evmVersion);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
solAssert(false, "Invalid language.");
|
solAssert(false, "Invalid language.");
|
||||||
@ -236,7 +236,7 @@ string AssemblyStack::print() const
|
|||||||
{
|
{
|
||||||
yulAssert(m_parserResult, "");
|
yulAssert(m_parserResult, "");
|
||||||
yulAssert(m_parserResult->code, "");
|
yulAssert(m_parserResult->code, "");
|
||||||
return m_parserResult->toString(m_language == Language::Yul) + "\n";
|
return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion)) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Object> AssemblyStack::parserResult() const
|
shared_ptr<Object> AssemblyStack::parserResult() const
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
using namespace solidity::yul;
|
using namespace solidity::yul;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Dialect const& Dialect::yul()
|
Dialect const& Dialect::yulDeprecated()
|
||||||
{
|
{
|
||||||
static unique_ptr<Dialect> dialect;
|
static unique_ptr<Dialect> dialect;
|
||||||
static YulStringRepository::ResetCallback callback{[&] { dialect.reset(); }};
|
static YulStringRepository::ResetCallback callback{[&] { dialect.reset(); }};
|
||||||
|
@ -48,10 +48,11 @@ struct BuiltinFunction
|
|||||||
|
|
||||||
struct Dialect: boost::noncopyable
|
struct Dialect: boost::noncopyable
|
||||||
{
|
{
|
||||||
|
/// Default type, can be omitted.
|
||||||
YulString defaultType;
|
YulString defaultType;
|
||||||
/// Type used for the literals "true" and "false".
|
/// Type used for the literals "true" and "false".
|
||||||
YulString boolType;
|
YulString boolType;
|
||||||
std::vector<YulString> types;
|
std::set<YulString> types;
|
||||||
|
|
||||||
/// @returns the builtin function of the given name or a nullptr if it is not a builtin function.
|
/// @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* builtin(YulString /*_name*/) const { return nullptr; }
|
||||||
@ -65,7 +66,8 @@ struct Dialect: boost::noncopyable
|
|||||||
Dialect() = default;
|
Dialect() = default;
|
||||||
virtual ~Dialect() = default;
|
virtual ~Dialect() = default;
|
||||||
|
|
||||||
static Dialect const& yul();
|
/// Old "yul" dialect. This is only used for testing.
|
||||||
|
static Dialect const& yulDeprecated();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,18 +45,18 @@ string indent(std::string const& _input)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string Data::toString(bool) const
|
string Data::toString(Dialect const*) const
|
||||||
{
|
{
|
||||||
return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\"";
|
return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
string Object::toString(bool _yul) const
|
string Object::toString(Dialect const* _dialect) const
|
||||||
{
|
{
|
||||||
yulAssert(code, "No code");
|
yulAssert(code, "No code");
|
||||||
string inner = "code " + AsmPrinter{}(*code);
|
string inner = "code " + (_dialect ? AsmPrinter{*_dialect} : AsmPrinter{})(*code);
|
||||||
|
|
||||||
for (auto const& obj: subObjects)
|
for (auto const& obj: subObjects)
|
||||||
inner += "\n" + obj->toString(_yul);
|
inner += "\n" + obj->toString(_dialect);
|
||||||
|
|
||||||
return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}";
|
return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}";
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
namespace solidity::yul
|
namespace solidity::yul
|
||||||
{
|
{
|
||||||
|
struct Dialect;
|
||||||
struct AsmAnalysisInfo;
|
struct AsmAnalysisInfo;
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +40,8 @@ struct AsmAnalysisInfo;
|
|||||||
struct ObjectNode
|
struct ObjectNode
|
||||||
{
|
{
|
||||||
virtual ~ObjectNode() = default;
|
virtual ~ObjectNode() = default;
|
||||||
virtual std::string toString(bool _yul) const = 0;
|
virtual std::string toString(Dialect const* _dialect) const = 0;
|
||||||
|
std::string toString() { return toString(nullptr); }
|
||||||
|
|
||||||
YulString name;
|
YulString name;
|
||||||
};
|
};
|
||||||
@ -50,7 +52,7 @@ struct ObjectNode
|
|||||||
struct Data: ObjectNode
|
struct Data: ObjectNode
|
||||||
{
|
{
|
||||||
Data(YulString _name, bytes _data): data(std::move(_data)) { name = _name; }
|
Data(YulString _name, bytes _data): data(std::move(_data)) { name = _name; }
|
||||||
std::string toString(bool _yul) const override;
|
std::string toString(Dialect const* _dialect) const override;
|
||||||
|
|
||||||
bytes data;
|
bytes data;
|
||||||
};
|
};
|
||||||
@ -62,7 +64,7 @@ struct Object: ObjectNode
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// @returns a (parseable) string representation. Includes types if @a _yul is set.
|
/// @returns a (parseable) string representation. Includes types if @a _yul is set.
|
||||||
std::string toString(bool _yul) const override;
|
std::string toString(Dialect const* _dialect) const override;
|
||||||
|
|
||||||
/// @returns the set of names of data objects accessible from within the code of
|
/// @returns the set of names of data objects accessible from within the code of
|
||||||
/// this object.
|
/// this object.
|
||||||
|
@ -203,15 +203,6 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _
|
|||||||
return *dialects[_version];
|
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)
|
SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instruction)
|
||||||
{
|
{
|
||||||
return SideEffects{
|
return SideEffects{
|
||||||
@ -222,3 +213,77 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio
|
|||||||
evmasm::SemanticInformation::invalidatesMemory(_instruction)
|
evmasm::SemanticInformation::invalidatesMemory(_instruction)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess):
|
||||||
|
EVMDialect(_evmVersion, _objectAccess)
|
||||||
|
{
|
||||||
|
defaultType = "u256"_yulstring;
|
||||||
|
boolType = "bool"_yulstring;
|
||||||
|
types = {defaultType, boolType};
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
|
// "not" and "bitnot" replace "iszero" and "not"
|
||||||
|
m_functions["bitnot"_yulstring] = m_functions["not"_yulstring];
|
||||||
|
m_functions["bitnot"_yulstring].name = "bitnot"_yulstring;
|
||||||
|
m_functions["not"_yulstring] = m_functions["iszero"_yulstring];
|
||||||
|
m_functions["not"_yulstring].name = "not"_yulstring;
|
||||||
|
m_functions["not"_yulstring].returns = {"bool"_yulstring};
|
||||||
|
m_functions["not"_yulstring].parameters = {"bool"_yulstring};
|
||||||
|
m_functions.erase("iszero"_yulstring);
|
||||||
|
|
||||||
|
m_functions["bitand"_yulstring] = m_functions["and"_yulstring];
|
||||||
|
m_functions["bitand"_yulstring].name = "bitand"_yulstring;
|
||||||
|
m_functions["bitor"_yulstring] = m_functions["or"_yulstring];
|
||||||
|
m_functions["bitor"_yulstring].name = "bitor"_yulstring;
|
||||||
|
m_functions["bitxor"_yulstring] = m_functions["xor"_yulstring];
|
||||||
|
m_functions["bitxor"_yulstring].name = "bitxor"_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["popbool"_yulstring] = m_functions["pop"_yulstring];
|
||||||
|
m_functions["popbool"_yulstring].name = "popbool"_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
|
||||||
|
) {
|
||||||
|
// A value larger than 1 causes an invalid instruction.
|
||||||
|
_visitArguments();
|
||||||
|
_assembly.appendConstant(2);
|
||||||
|
_assembly.appendInstruction(evmasm::Instruction::DUP2);
|
||||||
|
_assembly.appendInstruction(evmasm::Instruction::LT);
|
||||||
|
AbstractAssembly::LabelID inRange = _assembly.newLabelId();
|
||||||
|
_assembly.appendJumpToIf(inRange);
|
||||||
|
_assembly.appendInstruction(evmasm::Instruction::INVALID);
|
||||||
|
_assembly.appendLabel(inRange);
|
||||||
|
}));
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
@ -74,7 +74,6 @@ struct EVMDialect: public Dialect
|
|||||||
|
|
||||||
static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version);
|
static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version);
|
||||||
static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version);
|
static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version);
|
||||||
static EVMDialect const& yulForEVM(langutil::EVMVersion _version);
|
|
||||||
|
|
||||||
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
|
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
|
||||||
|
|
||||||
@ -88,4 +87,22 @@ protected:
|
|||||||
std::map<YulString, BuiltinFunctionForEVM> m_functions;
|
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 is replaced by not, which 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);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,9 @@ printTask "Testing assemble, yul, strict-assembly and optimize..."
|
|||||||
# Test yul and strict assembly output
|
# Test yul and strict assembly output
|
||||||
# Non-empty code results in non-empty binary representation with optimizations turned off,
|
# Non-empty code results in non-empty binary representation with optimizations turned off,
|
||||||
# while it results in empty binary representation with optimizations turned on.
|
# while it results in empty binary representation with optimizations turned on.
|
||||||
test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ let x:u256 := 0:u256 }" "--yul"
|
test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ let x := 0 }" "--yul"
|
||||||
|
test_solc_assembly_output "{ let x:u256 := bitnot(7:u256) }" "{ let x := bitnot(7) }" "--yul"
|
||||||
|
test_solc_assembly_output "{ let t:bool := not(true) }" "{ let t:bool := not(true) }" "--yul"
|
||||||
test_solc_assembly_output "{ let x := 0 }" "{ let x := 0 }" "--strict-assembly"
|
test_solc_assembly_output "{ let x := 0 }" "{ let x := 0 }" "--strict-assembly"
|
||||||
test_solc_assembly_output "{ let x := 0 }" "{ { } }" "--strict-assembly --optimize"
|
test_solc_assembly_output "{ let x := 0 }" "{ { } }" "--strict-assembly --optimize"
|
||||||
)
|
)
|
||||||
|
@ -15,9 +15,9 @@ object "object" {
|
|||||||
function main()
|
function main()
|
||||||
{
|
{
|
||||||
let _1 := 0
|
let _1 := 0
|
||||||
mstore_internal(_1, _1, _1, _1, _1)
|
mstore_internal(0, _1, _1, _1, _1)
|
||||||
mstore_internal(32, _1, _1, _1, 1)
|
mstore_internal(32, _1, _1, _1, 1)
|
||||||
eth.storageStore(_1, 32)
|
eth.storageStore(0, 32)
|
||||||
}
|
}
|
||||||
function endian_swap_16(x) -> y
|
function endian_swap_16(x) -> y
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ object "object" {
|
|||||||
|
|
||||||
|
|
||||||
Binary representation:
|
Binary representation:
|
||||||
0061736d0100000001160460000060017e017e60057e7e7e7e7e0060027f7f0002190108657468657265756d0c73746f7261676553746f7265000303060500010101020503010001060100071102066d656d6f72790200046d61696e00010ab501052801017e420021002000200020002000200010054220200020002000420110052000a74220a710000b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e20001002421086210220022000421088100284210120010b1b01027e20001003422086210220022000422088100384210120010b3501007e2000a720011004370300200042087ca720021004370300200042107ca720031004370300200042187ca7200410043703000b
|
0061736d0100000001160460000060017e017e60057e7e7e7e7e0060027f7f0002190108657468657265756d0c73746f7261676553746f7265000303060500010101020503010001060100071102066d656d6f72790200046d61696e00010ab501052801017e420021004200200020002000200010054220200020002000420110054200a74220a710000b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e20001002421086210220022000421088100284210120010b1b01027e20001003422086210220022000422088100384210120010b3501007e2000a720011004370300200042087ca720021004370300200042107ca720031004370300200042187ca7200410043703000b
|
||||||
|
|
||||||
Text representation:
|
Text representation:
|
||||||
(module
|
(module
|
||||||
@ -56,9 +56,9 @@ Text representation:
|
|||||||
(func $main
|
(func $main
|
||||||
(local $_1 i64)
|
(local $_1 i64)
|
||||||
(local.set $_1 (i64.const 0))
|
(local.set $_1 (i64.const 0))
|
||||||
(call $mstore_internal (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))
|
(call $mstore_internal (i64.const 0) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))
|
||||||
(call $mstore_internal (i64.const 32) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 1))
|
(call $mstore_internal (i64.const 32) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 1))
|
||||||
(call $eth.storageStore (i32.wrap_i64 (local.get $_1)) (i32.wrap_i64 (i64.const 32)))
|
(call $eth.storageStore (i32.wrap_i64 (i64.const 0)) (i32.wrap_i64 (i64.const 32)))
|
||||||
)
|
)
|
||||||
|
|
||||||
(func $endian_swap_16
|
(func $endian_swap_16
|
||||||
|
@ -10,21 +10,23 @@
|
|||||||
(local $p i64)
|
(local $p i64)
|
||||||
(local $r i64)
|
(local $r i64)
|
||||||
(local $hi i64)
|
(local $hi i64)
|
||||||
(local $y i64)
|
|
||||||
(local $hi_1 i64)
|
(local $hi_1 i64)
|
||||||
|
(local $y i64)
|
||||||
|
(local $hi_2 i64)
|
||||||
(local $_2 i64)
|
(local $_2 i64)
|
||||||
(local.set $_1 (i64.const 0))
|
(local.set $_1 (i64.const 0))
|
||||||
(local.set $p (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 64)))
|
(local.set $p (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 64)))
|
||||||
(local.set $r (i64.add (local.get $p) (i64.const 64)))
|
(local.set $r (i64.add (local.get $p) (i64.const 64)))
|
||||||
(if (i64.ne (i64.extend_i32_u (i64.lt_u (local.get $r) (local.get $p))) (i64.const 0)) (then
|
(if (i64.ne (i64.extend_i32_u (i64.lt_u (local.get $r) (local.get $p))) (i64.const 0)) (then
|
||||||
(unreachable)))
|
(unreachable)))
|
||||||
(local.set $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (local.get $_1) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (local.get $_1) (i64.const 16)))) (i64.const 32)))
|
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $_1)) (i64.const 16)))
|
||||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $_1) (i64.const 32)))))
|
(local.set $hi_1 (i64.shl (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $_1) (i64.const 16)))) (i64.const 32)))
|
||||||
|
(local.set $y (i64.or (local.get $hi_1) (call $endian_swap_32 (i64.shr_u (local.get $_1) (i64.const 32)))))
|
||||||
(i64.store (i32.wrap_i64 (local.get $r)) (local.get $y))
|
(i64.store (i32.wrap_i64 (local.get $r)) (local.get $y))
|
||||||
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 8))) (local.get $y))
|
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 8))) (local.get $y))
|
||||||
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 16))) (local.get $y))
|
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 16))) (local.get $y))
|
||||||
(local.set $hi_1 (i64.shl (call $endian_swap_32 (i64.const 128)) (i64.const 32)))
|
(local.set $hi_2 (i64.shl (call $endian_swap_32 (i64.const 128)) (i64.const 32)))
|
||||||
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 24))) (i64.or (local.get $hi_1) (call $endian_swap_32 (i64.shr_u (i64.const 128) (i64.const 32)))))
|
(i64.store (i32.wrap_i64 (i64.add (local.get $r) (i64.const 24))) (i64.or (local.get $hi_2) (call $endian_swap_32 (i64.shr_u (i64.const 128) (i64.const 32)))))
|
||||||
(local.set $_2 (datasize \"C_2_deployed\"))
|
(local.set $_2 (datasize \"C_2_deployed\"))
|
||||||
(call $eth.codeCopy (i32.wrap_i64 (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\"))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_2))))
|
(call $eth.codeCopy (i32.wrap_i64 (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\"))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_2))))
|
||||||
(call $eth.finish (i32.wrap_i64 (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_2))))
|
(call $eth.finish (i32.wrap_i64 (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_2))))
|
||||||
@ -37,9 +39,9 @@
|
|||||||
(param $x4 i64)
|
(param $x4 i64)
|
||||||
(result i64)
|
(result i64)
|
||||||
(local $v i64)
|
(local $v i64)
|
||||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then
|
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then
|
||||||
(unreachable)))
|
(unreachable)))
|
||||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then
|
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then
|
||||||
(unreachable)))
|
(unreachable)))
|
||||||
(local.set $v (local.get $x4))
|
(local.set $v (local.get $x4))
|
||||||
(local.get $v)
|
(local.get $v)
|
||||||
|
@ -48,7 +48,7 @@ namespace
|
|||||||
{
|
{
|
||||||
Dialect const& defaultDialect(bool _yul)
|
Dialect const& defaultDialect(bool _yul)
|
||||||
{
|
{
|
||||||
return _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion());
|
return _yul ? yul::Dialect::yulDeprecated() : yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <test/libyul/Common.h>
|
#include <test/libyul/Common.h>
|
||||||
|
|
||||||
#include <libyul/AsmParser.h>
|
#include <libyul/AsmParser.h>
|
||||||
|
#include <libyul/AsmPrinter.h>
|
||||||
#include <libyul/AsmAnalysis.h>
|
#include <libyul/AsmAnalysis.h>
|
||||||
#include <libyul/AsmAnalysisInfo.h>
|
#include <libyul/AsmAnalysisInfo.h>
|
||||||
#include <libyul/Dialect.h>
|
#include <libyul/Dialect.h>
|
||||||
@ -49,7 +50,7 @@ namespace solidity::yul::test
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
bool parse(string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter)
|
shared_ptr<Block> parse(string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -58,18 +59,19 @@ bool parse(string const& _source, Dialect const& _dialect, ErrorReporter& errorR
|
|||||||
if (parserResult)
|
if (parserResult)
|
||||||
{
|
{
|
||||||
yul::AsmAnalysisInfo analysisInfo;
|
yul::AsmAnalysisInfo analysisInfo;
|
||||||
return (yul::AsmAnalyzer(
|
if (yul::AsmAnalyzer(
|
||||||
analysisInfo,
|
analysisInfo,
|
||||||
errorReporter,
|
errorReporter,
|
||||||
_dialect
|
_dialect
|
||||||
)).analyze(*parserResult);
|
).analyze(*parserResult))
|
||||||
|
return parserResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FatalError const&)
|
catch (FatalError const&)
|
||||||
{
|
{
|
||||||
BOOST_FAIL("Fatal error leaked.");
|
BOOST_FAIL("Fatal error leaked.");
|
||||||
}
|
}
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect const& _dialect, bool _allowWarnings = true)
|
std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect const& _dialect, bool _allowWarnings = true)
|
||||||
@ -97,12 +99,12 @@ std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect con
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yul(), bool _allowWarnings = true)
|
bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarnings = true)
|
||||||
{
|
{
|
||||||
return !parseAndReturnFirstError(_source, _dialect, _allowWarnings);
|
return !parseAndReturnFirstError(_source, _dialect, _allowWarnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yul(), bool _allowWarnings = false)
|
Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarnings = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto error = parseAndReturnFirstError(_source, _dialect, _allowWarnings);
|
auto error = parseAndReturnFirstError(_source, _dialect, _allowWarnings);
|
||||||
@ -120,7 +122,7 @@ do \
|
|||||||
BOOST_CHECK(solidity::frontend::test::searchErrorMessage(err, (substring))); \
|
BOOST_CHECK(solidity::frontend::test::searchErrorMessage(err, (substring))); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define CHECK_ERROR(text, typ, substring) CHECK_ERROR_DIALECT(text, typ, substring, Dialect::yul())
|
#define CHECK_ERROR(text, typ, substring) CHECK_ERROR_DIALECT(text, typ, substring, Dialect::yulDeprecated())
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(YulParser)
|
BOOST_AUTO_TEST_SUITE(YulParser)
|
||||||
|
|
||||||
@ -564,6 +566,50 @@ BOOST_AUTO_TEST_CASE(builtins_analysis)
|
|||||||
CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch: 2 variables and 3 values.", dialect);
|
CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch: 2 variables and 3 values.", dialect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(default_types_set)
|
||||||
|
{
|
||||||
|
ErrorList errorList;
|
||||||
|
ErrorReporter reporter(errorList);
|
||||||
|
shared_ptr<Block> result = parse(
|
||||||
|
"{"
|
||||||
|
"let x:bool := true:bool "
|
||||||
|
"let z:bool := true "
|
||||||
|
"let y := add(1, 2) "
|
||||||
|
"switch y case 0 {} default {} "
|
||||||
|
"}",
|
||||||
|
EVMDialectTyped::instance(EVMVersion{}),
|
||||||
|
reporter
|
||||||
|
);
|
||||||
|
BOOST_REQUIRE(!!result);
|
||||||
|
|
||||||
|
// Use no dialect so that all types are printed.
|
||||||
|
// This tests that the default types are properly assigned.
|
||||||
|
BOOST_CHECK_EQUAL(AsmPrinter{}(*result),
|
||||||
|
"{\n"
|
||||||
|
" let x:bool := true:bool\n"
|
||||||
|
" let z:bool := true:bool\n"
|
||||||
|
" let y:u256 := add(1:u256, 2:u256)\n"
|
||||||
|
" switch y\n"
|
||||||
|
" case 0:u256 { }\n"
|
||||||
|
" default { }\n"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now test again with type dialect. Now the default types
|
||||||
|
// should be omitted.
|
||||||
|
BOOST_CHECK_EQUAL(AsmPrinter{EVMDialectTyped::instance(EVMVersion{})}(*result),
|
||||||
|
"{\n"
|
||||||
|
" let x:bool := true\n"
|
||||||
|
" let z:bool := true\n"
|
||||||
|
" let y := add(1, 2)\n"
|
||||||
|
" switch y\n"
|
||||||
|
" case 0 { }\n"
|
||||||
|
" default { }\n"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename)
|
|||||||
{
|
{
|
||||||
auto dialectName = m_settings["dialect"];
|
auto dialectName = m_settings["dialect"];
|
||||||
if (dialectName == "yul")
|
if (dialectName == "yul")
|
||||||
m_dialect = &Dialect::yul();
|
m_dialect = &Dialect::yulDeprecated();
|
||||||
else if (dialectName == "ewasm")
|
else if (dialectName == "ewasm")
|
||||||
m_dialect = &WasmDialect::instance();
|
m_dialect = &WasmDialect::instance();
|
||||||
else if (dialectName == "evm")
|
else if (dialectName == "evm")
|
||||||
@ -365,7 +365,7 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
|||||||
return TestResult::FatalError;
|
return TestResult::FatalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_obtainedResult = AsmPrinter{}(*m_ast) + "\n";
|
m_obtainedResult = AsmPrinter{*m_dialect}(*m_ast) + "\n";
|
||||||
|
|
||||||
if (m_optimizerStep != m_validatedSettings["step"])
|
if (m_optimizerStep != m_validatedSettings["step"])
|
||||||
{
|
{
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256, b:u256 }
|
// { let a, b }
|
||||||
// {
|
// {
|
||||||
// for { let a_1:u256 } a_1 { a_1 := a_1 }
|
// for { let a_1 } a_1 { a_1 := a_1 }
|
||||||
// { let b_2:u256 := a_1 }
|
// { let b_2 := a_1 }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -7,17 +7,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
|
// { let a, b, c, d, f }
|
||||||
// {
|
// {
|
||||||
// let a:u256, b:u256, c:u256, d:u256, f:u256
|
// function f_1(a_2) -> c_3, d_4
|
||||||
// }
|
// { let b_5, c_1 := f_1(a_2) }
|
||||||
// {
|
|
||||||
// function f_1(a_2:u256) -> c_3:u256, d_4:u256
|
|
||||||
// {
|
|
||||||
// let b_5:u256, c_1:u256 := f_1(a_2)
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256, b:u256, c:u256 }
|
// { let a, b, c }
|
||||||
// {
|
// {
|
||||||
// let a_1:bool
|
// let a_1:bool
|
||||||
// if a_1 { let b_2:bool := a_1 }
|
// if a_1 { let b_2:bool := a_1 }
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } }
|
{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } }
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256
|
// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh
|
||||||
// }
|
// }
|
||||||
// {
|
// {
|
||||||
// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh_1:u256
|
// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh_1
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -8,15 +8,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256, b:u256, c:u256 }
|
// { let a, b, c }
|
||||||
// {
|
// {
|
||||||
// let a_1:u256
|
// let a_1
|
||||||
// switch a_1
|
// switch a_1
|
||||||
// case 0:u256 { let b_2:u256 := a_1 }
|
// case 0 { let b_2 := a_1 }
|
||||||
// default { let c_3:u256 := a_1 }
|
// default { let c_3 := a_1 }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{ { let a:u256 } { let a:u256 } }
|
{ { let a:u256 } { let a:u256 } }
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256 }
|
// { let a }
|
||||||
// { let a_1:u256 }
|
// { let a_1 }
|
||||||
// }
|
// }
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{ { let a:u256 let a_1:u256 } { let a:u256 } }
|
{ { let a:u256 let a_1:u256 } { let a:u256 } }
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// let a_1:u256
|
// let a_1
|
||||||
// }
|
// }
|
||||||
// { let a_2:u256 }
|
// { let a_2 }
|
||||||
// }
|
// }
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: disambiguator
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: disambiguator
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let c:u256
|
// let c
|
||||||
// let b:u256
|
// let b
|
||||||
// }
|
// }
|
||||||
// function f(a:u256, c_1:u256) -> b_2:u256
|
// function f(a, c_1) -> b_2
|
||||||
// { let x:u256 }
|
// { let x }
|
||||||
// {
|
// {
|
||||||
// let a_3:u256
|
// let a_3
|
||||||
// let x_4:u256
|
// let x_4
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
let y:u256 := f()
|
let y:u256 := f()
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: expressionInliner
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: expressionInliner
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function f() -> x:u256
|
// function f() -> x
|
||||||
// { x := 2:u256 }
|
// { x := 2 }
|
||||||
// let y:u256 := 2:u256
|
// let y := 2
|
||||||
// }
|
// }
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
let y:u256 := f(7:u256)
|
let y:u256 := f(7:u256)
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: expressionInliner
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: expressionInliner
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function f(a:u256) -> x:u256
|
// function f(a) -> x
|
||||||
// { x := a }
|
// { x := a }
|
||||||
// let y:u256 := 7:u256
|
// let y := 7
|
||||||
// }
|
// }
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }
|
{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }
|
||||||
// ====
|
// ====
|
||||||
// step: functionGrouper
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionGrouper
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
// function f() -> x:bool
|
// function f() -> x:bool
|
||||||
// {
|
// {
|
||||||
// let b:u256 := 4:u256
|
// let b := 4
|
||||||
// { }
|
// { }
|
||||||
// for { } f() { }
|
// for { } f() { }
|
||||||
// { }
|
// { }
|
||||||
|
@ -5,17 +5,17 @@
|
|||||||
let e:u256
|
let e:u256
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionGrouper
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionGrouper
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// let c:u256
|
// let c
|
||||||
// let e:u256
|
// let e
|
||||||
// }
|
// }
|
||||||
// function f()
|
// function f()
|
||||||
// { let b:u256 }
|
// { let b }
|
||||||
// function g()
|
// function g()
|
||||||
// { let d:u256 }
|
// { let d }
|
||||||
// }
|
// }
|
||||||
|
@ -9,16 +9,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionGrouper
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionGrouper
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256 }
|
// { let a }
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
// let b:u256
|
// let b
|
||||||
// function g()
|
// function g()
|
||||||
// { let c:u256 }
|
// { let c }
|
||||||
// let d:u256
|
// let d
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
let a:u256 function f() {}
|
let a:u256 function f() {}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionGrouper
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionGrouper
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// { let a:u256 }
|
// { let a }
|
||||||
// function f()
|
// function f()
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
|
@ -8,14 +8,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionHoister
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionHoister
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// function f() -> x:bool
|
// function f() -> x:bool
|
||||||
// {
|
// {
|
||||||
// let b:u256 := 4:u256
|
// let b := 4
|
||||||
// for { } f() { }
|
// for { } f() { }
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
|
@ -6,15 +6,15 @@
|
|||||||
let e:u256
|
let e:u256
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionHoister
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionHoister
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// let c:u256
|
// let c
|
||||||
// let e:u256
|
// let e
|
||||||
// function f()
|
// function f()
|
||||||
// { let b:u256 }
|
// { let b }
|
||||||
// function g()
|
// function g()
|
||||||
// { let d:u256 }
|
// { let d }
|
||||||
// }
|
// }
|
||||||
|
@ -7,16 +7,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionHoister
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionHoister
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// function g()
|
// function g()
|
||||||
// { let c:u256 }
|
// { let c }
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
// let b:u256
|
// let b
|
||||||
// let d:u256
|
// let d
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
function f() {}
|
function f() {}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: functionHoister
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: functionHoister
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// function f()
|
// function f()
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
|
@ -8,18 +8,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: mainFunction
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: mainFunction
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function main()
|
// function main()
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
// function f() -> x:bool
|
// function f() -> x:bool
|
||||||
// {
|
// {
|
||||||
// let b:u256 := 4:u256
|
// let b := 4
|
||||||
// { }
|
// { }
|
||||||
// for { } f() { }
|
// for { } f() { }
|
||||||
// { }
|
// { }
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
let e:u256
|
let e:u256
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: mainFunction
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: mainFunction
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function main()
|
// function main()
|
||||||
// {
|
// {
|
||||||
// let a:u256
|
// let a
|
||||||
// let c:u256
|
// let c
|
||||||
// let e:u256
|
// let e
|
||||||
// }
|
// }
|
||||||
// function f()
|
// function f()
|
||||||
// { let b:u256 }
|
// { let b }
|
||||||
// function g()
|
// function g()
|
||||||
// { let d:u256 }
|
// { let d }
|
||||||
// }
|
// }
|
||||||
|
@ -7,17 +7,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: mainFunction
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: mainFunction
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function main()
|
// function main()
|
||||||
// { let a:u256 }
|
// { let a }
|
||||||
// function f()
|
// function f()
|
||||||
// {
|
// {
|
||||||
// let b:u256
|
// let b
|
||||||
// function g()
|
// function g()
|
||||||
// { let c:u256 }
|
// { let c }
|
||||||
// let d:u256
|
// let d
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
function f() {}
|
function f() {}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: mainFunction
|
|
||||||
// dialect: yul
|
// dialect: yul
|
||||||
|
// step: mainFunction
|
||||||
// ----
|
// ----
|
||||||
// {
|
// {
|
||||||
// function main()
|
// function main()
|
||||||
// { let a:u256 }
|
// { let a }
|
||||||
// function f()
|
// function f()
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
@ -248,7 +248,7 @@ public:
|
|||||||
default:
|
default:
|
||||||
cout << "Unknown option." << endl;
|
cout << "Unknown option." << endl;
|
||||||
}
|
}
|
||||||
source = AsmPrinter{}(*m_ast);
|
source = AsmPrinter{m_dialect}(*m_ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user