mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Remove asm flavour.
This commit is contained in:
+6
-21
@@ -43,13 +43,6 @@ using namespace solidity::yul;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
set<string> const builtinTypes{"bool", "u8", "s8", "u32", "s32", "u64", "s64", "u128", "s128", "u256", "s256"};
|
||||
|
||||
}
|
||||
|
||||
bool AsmAnalyzer::analyze(Block const& _block)
|
||||
{
|
||||
bool success = false;
|
||||
@@ -88,7 +81,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect,
|
||||
|
||||
bool AsmAnalyzer::operator()(Literal const& _literal)
|
||||
{
|
||||
expectValidType(_literal.type.str(), _literal.location);
|
||||
expectValidType(_literal.type, _literal.location);
|
||||
++m_stackHeight;
|
||||
if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32)
|
||||
{
|
||||
@@ -107,10 +100,7 @@ bool AsmAnalyzer::operator()(Literal const& _literal)
|
||||
return false;
|
||||
}
|
||||
else if (_literal.kind == LiteralKind::Boolean)
|
||||
{
|
||||
yulAssert(m_dialect.flavour == AsmFlavour::Yul, "");
|
||||
yulAssert(_literal.value == "true"_yulstring || _literal.value == "false"_yulstring, "");
|
||||
}
|
||||
m_info.stackHeightInfo[&_literal] = m_stackHeight;
|
||||
return true;
|
||||
}
|
||||
@@ -250,7 +240,7 @@ bool AsmAnalyzer::operator()(VariableDeclaration const& _varDecl)
|
||||
|
||||
for (auto const& variable: _varDecl.variables)
|
||||
{
|
||||
expectValidType(variable.type.str(), variable.location);
|
||||
expectValidType(variable.type, variable.location);
|
||||
m_activeVariables.insert(&std::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)));
|
||||
}
|
||||
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
|
||||
@@ -265,7 +255,7 @@ bool AsmAnalyzer::operator()(FunctionDefinition const& _funDef)
|
||||
Scope& varScope = scope(virtualBlock);
|
||||
for (auto const& var: _funDef.parameters + _funDef.returnVariables)
|
||||
{
|
||||
expectValidType(var.type.str(), var.location);
|
||||
expectValidType(var.type, var.location);
|
||||
m_activeVariables.insert(&std::get<Scope::Variable>(varScope.identifiers.at(var.name)));
|
||||
}
|
||||
|
||||
@@ -388,7 +378,6 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
|
||||
if (!expectExpression(*_switch.expression))
|
||||
success = false;
|
||||
|
||||
if (m_dialect.flavour == AsmFlavour::Yul)
|
||||
{
|
||||
YulString caseType;
|
||||
bool mismatchingTypes = false;
|
||||
@@ -630,15 +619,12 @@ Scope& AsmAnalyzer::scope(Block const* _block)
|
||||
yulAssert(scopePtr, "Scope requested but not present.");
|
||||
return *scopePtr;
|
||||
}
|
||||
void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _location)
|
||||
void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _location)
|
||||
{
|
||||
if (m_dialect.flavour != AsmFlavour::Yul)
|
||||
return;
|
||||
|
||||
if (!builtinTypes.count(type))
|
||||
if (!_type.empty() && !contains(m_dialect.types, _type))
|
||||
m_errorReporter.typeError(
|
||||
_location,
|
||||
"\"" + type + "\" 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)."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -658,7 +644,6 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation
|
||||
yulAssert(m_evmVersion.supportsReturndata() == m_evmVersion.hasStaticCall(), "");
|
||||
// Similarly we assume bitwise shifting and create2 go together.
|
||||
yulAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
|
||||
yulAssert(m_dialect.flavour != AsmFlavour::Yul, "");
|
||||
|
||||
auto errorForVM = [=](string const& vmKindMessage) {
|
||||
m_errorReporter.typeError(
|
||||
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
bool checkAssignment(Identifier const& _assignment, size_t _valueSize = size_t(-1));
|
||||
|
||||
Scope& scope(Block const* _block);
|
||||
void expectValidType(std::string const& type, langutil::SourceLocation const& _location);
|
||||
void expectValidType(YulString _type, langutil::SourceLocation const& _location);
|
||||
bool warnOnInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location);
|
||||
bool warnOnInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
|
||||
|
||||
|
||||
+5
-14
@@ -369,23 +369,18 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
|
||||
{}
|
||||
};
|
||||
advance();
|
||||
if (m_dialect.flavour == AsmFlavour::Yul)
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
literal.location.end = endPosition();
|
||||
literal.type = expectAsmIdentifier();
|
||||
}
|
||||
else if (kind == LiteralKind::Boolean)
|
||||
fatalParserError("True and false are not valid literals.");
|
||||
|
||||
ret = std::move(literal);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fatalParserError(
|
||||
m_dialect.flavour == AsmFlavour::Yul ?
|
||||
"Literal or identifier expected." :
|
||||
"Literal, identifier or instruction expected."
|
||||
);
|
||||
fatalParserError("Literal or identifier expected.");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -474,11 +469,7 @@ Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp)
|
||||
else if (holds_alternative<FunctionCall>(_initialOp))
|
||||
ret = std::move(std::get<FunctionCall>(_initialOp));
|
||||
else
|
||||
fatalParserError(
|
||||
m_dialect.flavour == AsmFlavour::Yul ?
|
||||
"Function name expected." :
|
||||
"Assembly instruction or function name required in front of \"(\")"
|
||||
);
|
||||
fatalParserError("Function name expected.");
|
||||
|
||||
expectToken(Token::LParen);
|
||||
if (currentToken() != Token::RParen)
|
||||
@@ -500,7 +491,7 @@ TypedName Parser::parseTypedName()
|
||||
RecursionGuard recursionGuard(*this);
|
||||
TypedName typedName = createWithLocation<TypedName>();
|
||||
typedName.name = expectAsmIdentifier();
|
||||
if (m_dialect.flavour == AsmFlavour::Yul)
|
||||
if (currentToken() == Token::Colon)
|
||||
{
|
||||
expectToken(Token::Colon);
|
||||
typedName.location.end = endPosition();
|
||||
|
||||
@@ -238,7 +238,7 @@ string AsmPrinter::formatTypedName(TypedName _variable) const
|
||||
|
||||
string AsmPrinter::appendTypeName(YulString _type) const
|
||||
{
|
||||
if (m_yul && !_type.empty())
|
||||
if (!_type.empty())
|
||||
return ":" + _type.str();
|
||||
return "";
|
||||
}
|
||||
|
||||
+2
-3
@@ -28,11 +28,12 @@
|
||||
|
||||
namespace solidity::yul
|
||||
{
|
||||
struct Dialect;
|
||||
|
||||
class AsmPrinter
|
||||
{
|
||||
public:
|
||||
explicit AsmPrinter(bool _yul = false): m_yul(_yul) {}
|
||||
explicit AsmPrinter() {}
|
||||
|
||||
std::string operator()(Literal const& _literal) const;
|
||||
std::string operator()(Identifier const& _identifier) const;
|
||||
@@ -52,8 +53,6 @@ public:
|
||||
private:
|
||||
std::string formatTypedName(TypedName _variable) const;
|
||||
std::string appendTypeName(YulString _type) const;
|
||||
|
||||
bool m_yul = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ add_library(yul
|
||||
AssemblyStack.cpp
|
||||
CompilabilityChecker.cpp
|
||||
CompilabilityChecker.h
|
||||
Dialect.cpp
|
||||
Dialect.h
|
||||
Exceptions.h
|
||||
Object.cpp
|
||||
|
||||
@@ -39,11 +39,6 @@ map<YulString, int> CompilabilityChecker::run(
|
||||
bool _optimizeStackAllocation
|
||||
)
|
||||
{
|
||||
if (_dialect.flavour == AsmFlavour::Yul)
|
||||
return {};
|
||||
|
||||
yulAssert(_dialect.flavour == AsmFlavour::Strict, "");
|
||||
|
||||
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect))
|
||||
{
|
||||
NoOutputEVMDialect noOutputDialect(*evmDialect);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Yul dialect.
|
||||
*/
|
||||
|
||||
#include <libyul/Dialect.h>
|
||||
|
||||
using namespace solidity::yul;
|
||||
using namespace std;
|
||||
|
||||
Dialect const& Dialect::yul()
|
||||
{
|
||||
static unique_ptr<Dialect> dialect;
|
||||
static YulStringRepository::ResetCallback callback{[&] { dialect.reset(); }};
|
||||
|
||||
if (!dialect)
|
||||
{
|
||||
// TODO will probably change, especially the list of types.
|
||||
dialect = make_unique<Dialect>();
|
||||
dialect->defaultType = "u256"_yulstring;
|
||||
dialect->boolType = "bool"_yulstring;
|
||||
dialect->types = {
|
||||
"bool"_yulstring,
|
||||
"u8"_yulstring,
|
||||
"s8"_yulstring,
|
||||
"u32"_yulstring,
|
||||
"s32"_yulstring,
|
||||
"u64"_yulstring,
|
||||
"s64"_yulstring,
|
||||
"u128"_yulstring,
|
||||
"s128"_yulstring,
|
||||
"u256"_yulstring,
|
||||
"s256"_yulstring
|
||||
};
|
||||
};
|
||||
|
||||
return *dialect;
|
||||
}
|
||||
+7
-13
@@ -34,12 +34,6 @@ namespace solidity::yul
|
||||
class YulString;
|
||||
using Type = YulString;
|
||||
|
||||
enum class AsmFlavour
|
||||
{
|
||||
Strict, // no types, EVM instructions as functions, but no jumps and no direct stack manipulations
|
||||
Yul // same as Strict mode with types
|
||||
};
|
||||
|
||||
struct BuiltinFunction
|
||||
{
|
||||
YulString name;
|
||||
@@ -54,7 +48,11 @@ struct BuiltinFunction
|
||||
|
||||
struct Dialect: boost::noncopyable
|
||||
{
|
||||
AsmFlavour const flavour = AsmFlavour::Strict;
|
||||
YulString defaultType;
|
||||
/// Type used for the literals "true" and "false".
|
||||
YulString boolType;
|
||||
std::vector<YulString> types;
|
||||
|
||||
/// @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; }
|
||||
|
||||
@@ -64,14 +62,10 @@ struct Dialect: boost::noncopyable
|
||||
|
||||
virtual std::set<YulString> fixedFunctionNames() const { return {}; }
|
||||
|
||||
Dialect(AsmFlavour _flavour): flavour(_flavour) {}
|
||||
Dialect() = default;
|
||||
virtual ~Dialect() = default;
|
||||
|
||||
static Dialect const& yul()
|
||||
{
|
||||
static Dialect yulDialect(AsmFlavour::Yul);
|
||||
return yulDialect;
|
||||
}
|
||||
static Dialect const& yul();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ string Data::toString(bool) const
|
||||
string Object::toString(bool _yul) const
|
||||
{
|
||||
yulAssert(code, "No code");
|
||||
string inner = "code " + AsmPrinter{_yul}(*code);
|
||||
string inner = "code " + AsmPrinter{}(*code);
|
||||
|
||||
for (auto const& obj: subObjects)
|
||||
inner += "\n" + obj->toString(_yul);
|
||||
|
||||
@@ -169,8 +169,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
|
||||
}
|
||||
|
||||
EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVersion _evmVersion):
|
||||
Dialect{_flavour},
|
||||
EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess):
|
||||
m_objectAccess(_objectAccess),
|
||||
m_evmVersion(_evmVersion),
|
||||
m_functions(createBuiltins(_evmVersion, _objectAccess))
|
||||
@@ -191,7 +190,7 @@ EVMDialect const& EVMDialect::strictAssemblyForEVM(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>(AsmFlavour::Strict, false, _version);
|
||||
dialects[_version] = make_unique<EVMDialect>(_version, false);
|
||||
return *dialects[_version];
|
||||
}
|
||||
|
||||
@@ -200,7 +199,7 @@ EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _
|
||||
static map<langutil::EVMVersion, unique_ptr<EVMDialect const>> dialects;
|
||||
static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }};
|
||||
if (!dialects[_version])
|
||||
dialects[_version] = make_unique<EVMDialect>(AsmFlavour::Strict, true, _version);
|
||||
dialects[_version] = make_unique<EVMDialect>(_version, true);
|
||||
return *dialects[_version];
|
||||
}
|
||||
|
||||
@@ -209,7 +208,7 @@ 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>(AsmFlavour::Yul, false, _version);
|
||||
dialects[_version] = make_unique<EVMDialect>(_version, false);
|
||||
return *dialects[_version];
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct BuiltinFunctionForEVM: BuiltinFunction
|
||||
struct EVMDialect: public Dialect
|
||||
{
|
||||
/// Constructor, should only be used internally. Use the factory functions below.
|
||||
EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVersion _evmVersion);
|
||||
EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess);
|
||||
|
||||
/// @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;
|
||||
|
||||
@@ -143,7 +143,7 @@ AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&)
|
||||
}
|
||||
|
||||
NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
|
||||
EVMDialect(_copyFrom.flavour, _copyFrom.providesObjectAccess(), _copyFrom.evmVersion())
|
||||
EVMDialect(_copyFrom.evmVersion(), _copyFrom.providesObjectAccess())
|
||||
{
|
||||
for (auto& fun: m_functions)
|
||||
{
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
using namespace std;
|
||||
using namespace solidity::yul;
|
||||
|
||||
WasmDialect::WasmDialect():
|
||||
Dialect{AsmFlavour::Strict}
|
||||
WasmDialect::WasmDialect()
|
||||
{
|
||||
defaultType = "i64"_yulstring;
|
||||
boolType = "i64"_yulstring;
|
||||
types = {"i64"_yulstring, "i32"_yulstring};
|
||||
|
||||
for (auto const& name: {
|
||||
"i64.add",
|
||||
"i64.sub",
|
||||
|
||||
@@ -97,12 +97,12 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
for (int i = 0; i < 3; i++)
|
||||
ret.push_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], "u64"_yulstring}},
|
||||
make_unique<Expression>(Literal{locationOf(*varDecl.value), LiteralKind::Number, "0"_yulstring, "u64"_yulstring})
|
||||
{TypedName{varDecl.location, newLhs[i], m_defaultType}},
|
||||
make_unique<Expression>(Literal{locationOf(*varDecl.value), LiteralKind::Number, "0"_yulstring, m_defaultType})
|
||||
});
|
||||
ret.push_back(VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[3], "u64"_yulstring}},
|
||||
{TypedName{varDecl.location, newLhs[3], m_defaultType}},
|
||||
std::move(varDecl.value)
|
||||
});
|
||||
return {std::move(ret)};
|
||||
@@ -130,7 +130,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
ret.push_back(
|
||||
VariableDeclaration{
|
||||
varDecl.location,
|
||||
{TypedName{varDecl.location, newLhs[i], "u64"_yulstring}},
|
||||
{TypedName{varDecl.location, newLhs[i], m_defaultType}},
|
||||
std::move(newRhs[i])
|
||||
}
|
||||
);
|
||||
@@ -157,7 +157,7 @@ void WordSizeTransform::operator()(Block& _block)
|
||||
ret.push_back(Assignment{
|
||||
assignment.location,
|
||||
{Identifier{assignment.location, newLhs[i]}},
|
||||
make_unique<Expression>(Literal{locationOf(*assignment.value), LiteralKind::Number, "0"_yulstring, "u64"_yulstring})
|
||||
make_unique<Expression>(Literal{locationOf(*assignment.value), LiteralKind::Number, "0"_yulstring, m_defaultType})
|
||||
});
|
||||
ret.push_back(Assignment{
|
||||
assignment.location,
|
||||
@@ -208,7 +208,8 @@ void WordSizeTransform::run(Dialect const& _inputDialect, Block& _ast, NameDispe
|
||||
{
|
||||
// Free the name `or_bool`.
|
||||
NameDisplacer{_nameDispenser, {"or_bool"_yulstring}}(_ast);
|
||||
WordSizeTransform{_inputDialect, _nameDispenser}(_ast);
|
||||
YulString defaultType; // should be i64 at some point.
|
||||
WordSizeTransform{_inputDialect, _nameDispenser, defaultType}(_ast);
|
||||
}
|
||||
|
||||
void WordSizeTransform::rewriteVarDeclList(TypedNameList& _nameList)
|
||||
@@ -219,7 +220,7 @@ void WordSizeTransform::rewriteVarDeclList(TypedNameList& _nameList)
|
||||
{
|
||||
TypedNameList ret;
|
||||
for (auto newName: generateU64IdentifierNames(_n.name))
|
||||
ret.emplace_back(TypedName{_n.location, newName, "u64"_yulstring});
|
||||
ret.emplace_back(TypedName{_n.location, newName, m_defaultType});
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
@@ -283,7 +284,7 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
|
||||
for (auto& c: cases)
|
||||
{
|
||||
Literal label{_location, LiteralKind::Number, YulString(c.first.str()), "u64"_yulstring};
|
||||
Literal label{_location, LiteralKind::Number, YulString(c.first.str()), m_defaultType};
|
||||
ret.cases.emplace_back(Case{
|
||||
c.second.front().location,
|
||||
make_unique<Literal>(std::move(label)),
|
||||
@@ -304,7 +305,7 @@ vector<Statement> WordSizeTransform::handleSwitchInternal(
|
||||
Assignment{
|
||||
_location,
|
||||
{{_location, _runDefaultFlag}},
|
||||
make_unique<Expression>(Literal{_location, LiteralKind::Number, "1"_yulstring, "u64"_yulstring})
|
||||
make_unique<Expression>(Literal{_location, LiteralKind::Number, "1"_yulstring, m_defaultType})
|
||||
}
|
||||
)}
|
||||
});
|
||||
@@ -329,7 +330,7 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
|
||||
_switch.cases.pop_back();
|
||||
ret.emplace_back(VariableDeclaration{
|
||||
_switch.location,
|
||||
{TypedName{_switch.location, runDefaultFlag, "u64"_yulstring}},
|
||||
{TypedName{_switch.location, runDefaultFlag, m_defaultType}},
|
||||
{}
|
||||
});
|
||||
}
|
||||
@@ -384,7 +385,7 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
|
||||
lit.location,
|
||||
LiteralKind::Number,
|
||||
YulString(currentVal.str()),
|
||||
"u64"_yulstring
|
||||
m_defaultType
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,9 +70,14 @@ public:
|
||||
static void run(Dialect const& _inputDialect, Block& _ast, NameDispenser& _nameDispenser);
|
||||
|
||||
private:
|
||||
explicit WordSizeTransform(Dialect const& _inputDialect, NameDispenser& _nameDispenser):
|
||||
explicit WordSizeTransform(
|
||||
Dialect const& _inputDialect,
|
||||
NameDispenser& _nameDispenser,
|
||||
YulString _defaultType
|
||||
):
|
||||
m_inputDialect(_inputDialect),
|
||||
m_nameDispenser(_nameDispenser)
|
||||
m_nameDispenser(_nameDispenser),
|
||||
m_defaultType(_defaultType)
|
||||
{ }
|
||||
|
||||
void rewriteVarDeclList(std::vector<TypedName>&);
|
||||
@@ -94,6 +99,7 @@ private:
|
||||
|
||||
Dialect const& m_inputDialect;
|
||||
NameDispenser& m_nameDispenser;
|
||||
YulString m_defaultType;
|
||||
/// maps original u256 variable's name to corresponding u64 variables' names
|
||||
std::map<YulString, std::array<YulString, 4>> m_variableMapping;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user