mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adding origin location notation to yul ir.
This commit is contained in:
parent
921e21c7cb
commit
838f59fa5b
@ -16,8 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
#include <libsolidity/codegen/ir/Common.h>
|
|
||||||
#include <libsolidity/ast/TypeProvider.h>
|
#include <libsolidity/ast/TypeProvider.h>
|
||||||
|
#include <libsolidity/codegen/ir/Common.h>
|
||||||
|
#include <libsolidity/codegen/ir/IRGenerationContext.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ using namespace std;
|
|||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
|
|
||||||
|
namespace solidity::frontend
|
||||||
|
{
|
||||||
|
|
||||||
YulArity YulArity::fromType(FunctionType const& _functionType)
|
YulArity YulArity::fromType(FunctionType const& _functionType)
|
||||||
{
|
{
|
||||||
return YulArity{
|
return YulArity{
|
||||||
@ -122,3 +126,20 @@ string IRNames::zeroValue(Type const& _type, string const& _variableName)
|
|||||||
{
|
{
|
||||||
return "zero_" + _type.identifier() + _variableName;
|
return "zero_" + _type.identifier() + _variableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string sourceLocationComment(langutil::SourceLocation const& _location, IRGenerationContext const& _context)
|
||||||
|
{
|
||||||
|
return "/// @src "
|
||||||
|
+ to_string(_context.sourceIndices().at(_location.source->name()))
|
||||||
|
+ ":"
|
||||||
|
+ to_string(_location.start)
|
||||||
|
+ ","
|
||||||
|
+ to_string(_location.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
string sourceLocationComment(ASTNode const& _node, IRGenerationContext const& _context)
|
||||||
|
{
|
||||||
|
return sourceLocationComment(_node.location(), _context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
namespace solidity::frontend
|
namespace solidity::frontend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class IRGenerationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure that describes arity and co-arity of a Yul function, i.e. the number of its inputs and outputs.
|
* Structure that describes arity and co-arity of a Yul function, i.e. the number of its inputs and outputs.
|
||||||
*/
|
*/
|
||||||
@ -66,6 +68,14 @@ struct IRNames
|
|||||||
static std::string zeroValue(Type const& _type, std::string const& _variableName);
|
static std::string zeroValue(Type const& _type, std::string const& _variableName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a source location comment in the form of
|
||||||
|
* `/// @src <sourceIndex>:<locationStart>:<locationEnd>`.
|
||||||
|
*/
|
||||||
|
std::string sourceLocationComment(langutil::SourceLocation const& _location, IRGenerationContext const& _context);
|
||||||
|
std::string sourceLocationComment(ASTNode const& _node, IRGenerationContext const& _context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloading std::less() makes it possible to use YulArity as a map key. We could define operator<
|
// Overloading std::less() makes it possible to use YulArity as a map key. We could define operator<
|
||||||
|
@ -68,11 +68,13 @@ public:
|
|||||||
IRGenerationContext(
|
IRGenerationContext(
|
||||||
langutil::EVMVersion _evmVersion,
|
langutil::EVMVersion _evmVersion,
|
||||||
RevertStrings _revertStrings,
|
RevertStrings _revertStrings,
|
||||||
OptimiserSettings _optimiserSettings
|
OptimiserSettings _optimiserSettings,
|
||||||
|
std::map<std::string, unsigned> _sourceIndices
|
||||||
):
|
):
|
||||||
m_evmVersion(_evmVersion),
|
m_evmVersion(_evmVersion),
|
||||||
m_revertStrings(_revertStrings),
|
m_revertStrings(_revertStrings),
|
||||||
m_optimiserSettings(std::move(_optimiserSettings))
|
m_optimiserSettings(std::move(_optimiserSettings)),
|
||||||
|
m_sourceIndices(std::move(_sourceIndices))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MultiUseYulFunctionCollector& functionCollector() { return m_functions; }
|
MultiUseYulFunctionCollector& functionCollector() { return m_functions; }
|
||||||
@ -150,10 +152,13 @@ public:
|
|||||||
bool inlineAssemblySeen() const { return m_inlineAssemblySeen; }
|
bool inlineAssemblySeen() const { return m_inlineAssemblySeen; }
|
||||||
void setInlineAssemblySeen() { m_inlineAssemblySeen = true; }
|
void setInlineAssemblySeen() { m_inlineAssemblySeen = true; }
|
||||||
|
|
||||||
|
std::map<std::string, unsigned> const& sourceIndices() const { return m_sourceIndices; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
RevertStrings m_revertStrings;
|
RevertStrings m_revertStrings;
|
||||||
OptimiserSettings m_optimiserSettings;
|
OptimiserSettings m_optimiserSettings;
|
||||||
|
std::map<std::string, unsigned> m_sourceIndices;
|
||||||
ContractDefinition const* m_mostDerivedContract = nullptr;
|
ContractDefinition const* m_mostDerivedContract = nullptr;
|
||||||
std::map<VariableDeclaration const*, IRVariable> m_localVariables;
|
std::map<VariableDeclaration const*, IRVariable> m_localVariables;
|
||||||
/// Memory offsets reserved for the values of immutable variables during contract creation.
|
/// Memory offsets reserved for the values of immutable variables during contract creation.
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
* Component that translates Solidity code into Yul.
|
* Component that translates Solidity code into Yul.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libsolidity/codegen/ir/Common.h>
|
||||||
#include <libsolidity/codegen/ir/IRGenerator.h>
|
#include <libsolidity/codegen/ir/IRGenerator.h>
|
||||||
|
|
||||||
#include <libsolidity/codegen/ir/IRGeneratorForStatements.h>
|
#include <libsolidity/codegen/ir/IRGeneratorForStatements.h>
|
||||||
|
|
||||||
#include <libsolidity/ast/AST.h>
|
#include <libsolidity/ast/AST.h>
|
||||||
@ -107,12 +107,12 @@ pair<string, string> IRGenerator::run(
|
|||||||
asmStack.optimize();
|
asmStack.optimize();
|
||||||
|
|
||||||
string warning =
|
string warning =
|
||||||
"/*******************************************************\n"
|
"/*=====================================================*\n"
|
||||||
" * WARNING *\n"
|
" * WARNING *\n"
|
||||||
" * Solidity to Yul compilation is still EXPERIMENTAL *\n"
|
" * Solidity to Yul compilation is still EXPERIMENTAL *\n"
|
||||||
" * It can result in LOSS OF FUNDS or worse *\n"
|
" * It can result in LOSS OF FUNDS or worse *\n"
|
||||||
" * !USE AT YOUR OWN RISK! *\n"
|
" * !USE AT YOUR OWN RISK! *\n"
|
||||||
" *******************************************************/\n\n";
|
" *=====================================================*/\n\n";
|
||||||
|
|
||||||
return {warning + ir, warning + asmStack.print()};
|
return {warning + ir, warning + asmStack.print()};
|
||||||
}
|
}
|
||||||
@ -134,6 +134,7 @@ string IRGenerator::generate(
|
|||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
object "<CreationObject>" {
|
object "<CreationObject>" {
|
||||||
code {
|
code {
|
||||||
|
<sourceLocationComment>
|
||||||
<memoryInitCreation>
|
<memoryInitCreation>
|
||||||
<callValueCheck>
|
<callValueCheck>
|
||||||
<?library>
|
<?library>
|
||||||
@ -146,6 +147,7 @@ string IRGenerator::generate(
|
|||||||
}
|
}
|
||||||
object "<DeployedObject>" {
|
object "<DeployedObject>" {
|
||||||
code {
|
code {
|
||||||
|
<sourceLocationComment>
|
||||||
<memoryInitDeployed>
|
<memoryInitDeployed>
|
||||||
<?library>
|
<?library>
|
||||||
let called_via_delegatecall := iszero(eq(loadimmutable("<library_address>"), address()))
|
let called_via_delegatecall := iszero(eq(loadimmutable("<library_address>"), address()))
|
||||||
@ -164,6 +166,8 @@ string IRGenerator::generate(
|
|||||||
for (VariableDeclaration const* var: ContractType(_contract).immutableVariables())
|
for (VariableDeclaration const* var: ContractType(_contract).immutableVariables())
|
||||||
m_context.registerImmutableVariable(*var);
|
m_context.registerImmutableVariable(*var);
|
||||||
|
|
||||||
|
t("sourceLocationComment", sourceLocationComment(_contract, m_context));
|
||||||
|
|
||||||
t("CreationObject", IRNames::creationObject(_contract));
|
t("CreationObject", IRNames::creationObject(_contract));
|
||||||
t("library", _contract.isLibrary());
|
t("library", _contract.isLibrary());
|
||||||
|
|
||||||
@ -186,7 +190,7 @@ string IRGenerator::generate(
|
|||||||
t("deploy", deployCode(_contract));
|
t("deploy", deployCode(_contract));
|
||||||
generateConstructors(_contract);
|
generateConstructors(_contract);
|
||||||
set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
||||||
InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions();
|
InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract);
|
||||||
|
|
||||||
t("functions", m_context.functionCollector().requestedFunctions());
|
t("functions", m_context.functionCollector().requestedFunctions());
|
||||||
t("subObjects", subObjectSources(m_context.subObjectsCreated()));
|
t("subObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||||
@ -207,7 +211,7 @@ string IRGenerator::generate(
|
|||||||
t("library_address", IRNames::libraryAddressImmutable());
|
t("library_address", IRNames::libraryAddressImmutable());
|
||||||
t("dispatch", dispatchRoutine(_contract));
|
t("dispatch", dispatchRoutine(_contract));
|
||||||
set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
||||||
generateInternalDispatchFunctions();
|
generateInternalDispatchFunctions(_contract);
|
||||||
t("deployedFunctions", m_context.functionCollector().requestedFunctions());
|
t("deployedFunctions", m_context.functionCollector().requestedFunctions());
|
||||||
t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated()));
|
t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||||
t("metadataName", yul::Object::metadataName());
|
t("metadataName", yul::Object::metadataName());
|
||||||
@ -249,7 +253,7 @@ set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions()
|
|||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalDispatchMap IRGenerator::generateInternalDispatchFunctions()
|
InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
solAssert(
|
solAssert(
|
||||||
m_context.functionGenerationQueueEmpty(),
|
m_context.functionGenerationQueueEmpty(),
|
||||||
@ -264,6 +268,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions()
|
|||||||
m_context.functionCollector().createFunction(funName, [&]() {
|
m_context.functionCollector().createFunction(funName, [&]() {
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(fun<?+in>, <in></+in>) <?+out>-> <out></+out> {
|
function <functionName>(fun<?+in>, <in></+in>) <?+out>-> <out></+out> {
|
||||||
|
<sourceLocationComment>
|
||||||
switch fun
|
switch fun
|
||||||
<#cases>
|
<#cases>
|
||||||
case <funID>
|
case <funID>
|
||||||
@ -274,6 +279,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions()
|
|||||||
default { <panic>() }
|
default { <panic>() }
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
templ("sourceLocationComment", sourceLocationComment(_contract, m_context));
|
||||||
templ("functionName", funName);
|
templ("functionName", funName);
|
||||||
templ("panic", m_utils.panicFunction(PanicCode::InvalidInternalFunction));
|
templ("panic", m_utils.panicFunction(PanicCode::InvalidInternalFunction));
|
||||||
templ("in", suffixedVariableNameList("in_", 0, arity.in));
|
templ("in", suffixedVariableNameList("in_", 0, arity.in));
|
||||||
@ -319,10 +325,14 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
|||||||
m_context.resetLocalVariables();
|
m_context.resetLocalVariables();
|
||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||||
|
<sourceLocationComment>
|
||||||
<retInit>
|
<retInit>
|
||||||
<body>
|
<body>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
t("sourceLocationComment", sourceLocationComment(_function, m_context));
|
||||||
|
|
||||||
t("functionName", functionName);
|
t("functionName", functionName);
|
||||||
vector<string> params;
|
vector<string> params;
|
||||||
for (auto const& varDecl: _function.parameters())
|
for (auto const& varDecl: _function.parameters())
|
||||||
@ -377,6 +387,7 @@ string IRGenerator::generateModifier(
|
|||||||
m_context.resetLocalVariables();
|
m_context.resetLocalVariables();
|
||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||||
|
<sourceLocationComment>
|
||||||
<assignRetParams>
|
<assignRetParams>
|
||||||
<evalArgs>
|
<evalArgs>
|
||||||
<body>
|
<body>
|
||||||
@ -404,6 +415,7 @@ string IRGenerator::generateModifier(
|
|||||||
_modifierInvocation.name().annotation().referencedDeclaration
|
_modifierInvocation.name().annotation().referencedDeclaration
|
||||||
);
|
);
|
||||||
solAssert(modifier, "");
|
solAssert(modifier, "");
|
||||||
|
t("sourceLocationComment", sourceLocationComment(*modifier, m_context));
|
||||||
switch (*_modifierInvocation.name().annotation().requiredLookup)
|
switch (*_modifierInvocation.name().annotation().requiredLookup)
|
||||||
{
|
{
|
||||||
case VirtualLookup::Virtual:
|
case VirtualLookup::Virtual:
|
||||||
@ -455,10 +467,12 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const&
|
|||||||
m_context.resetLocalVariables();
|
m_context.resetLocalVariables();
|
||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||||
|
<sourceLocationComment>
|
||||||
<assignRetParams>
|
<assignRetParams>
|
||||||
<body>
|
<body>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
t("sourceLocationComment", sourceLocationComment(_function, m_context));
|
||||||
t("functionName", functionName);
|
t("functionName", functionName);
|
||||||
vector<string> retParams;
|
vector<string> retParams;
|
||||||
vector<string> retParamsIn;
|
vector<string> retParamsIn;
|
||||||
@ -497,9 +511,11 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
solUnimplementedAssert(type->sizeOnStack() == 1, "");
|
solUnimplementedAssert(type->sizeOnStack() == 1, "");
|
||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
function <functionName>() -> rval {
|
function <functionName>() -> rval {
|
||||||
|
<sourceLocationComment>
|
||||||
rval := loadimmutable("<id>")
|
rval := loadimmutable("<id>")
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
|
("sourceLocationComment", sourceLocationComment(_varDecl, m_context))
|
||||||
("functionName", functionName)
|
("functionName", functionName)
|
||||||
("id", to_string(_varDecl.id()))
|
("id", to_string(_varDecl.id()))
|
||||||
.render();
|
.render();
|
||||||
@ -509,9 +525,11 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
solAssert(paramTypes.empty(), "");
|
solAssert(paramTypes.empty(), "");
|
||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
function <functionName>() -> <ret> {
|
function <functionName>() -> <ret> {
|
||||||
|
<sourceLocationComment>
|
||||||
<ret> := <constantValueFunction>()
|
<ret> := <constantValueFunction>()
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
|
("sourceLocationComment", sourceLocationComment(_varDecl, m_context))
|
||||||
("functionName", functionName)
|
("functionName", functionName)
|
||||||
("constantValueFunction", IRGeneratorForStatements(m_context, m_utils).constantValueFunction(_varDecl))
|
("constantValueFunction", IRGeneratorForStatements(m_context, m_utils).constantValueFunction(_varDecl))
|
||||||
("ret", suffixedVariableNameList("ret_", 0, _varDecl.type()->sizeOnStack()))
|
("ret", suffixedVariableNameList("ret_", 0, _varDecl.type()->sizeOnStack()))
|
||||||
@ -624,6 +642,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
|
|
||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
function <functionName>(<params>) -> <retVariables> {
|
function <functionName>(<params>) -> <retVariables> {
|
||||||
|
<sourceLocationComment>
|
||||||
<code>
|
<code>
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
@ -631,6 +650,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
("params", joinHumanReadable(parameters))
|
("params", joinHumanReadable(parameters))
|
||||||
("retVariables", joinHumanReadable(returnVariables))
|
("retVariables", joinHumanReadable(returnVariables))
|
||||||
("code", std::move(code))
|
("code", std::move(code))
|
||||||
|
("sourceLocationComment", sourceLocationComment(_varDecl, m_context))
|
||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -739,6 +759,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
|||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
function <functionName>(<params><comma><baseParams>) {
|
function <functionName>(<params><comma><baseParams>) {
|
||||||
<evalBaseArguments>
|
<evalBaseArguments>
|
||||||
|
<sourceLocationComment>
|
||||||
<?hasNextConstructor> <nextConstructor>(<nextParams>) </hasNextConstructor>
|
<?hasNextConstructor> <nextConstructor>(<nextParams>) </hasNextConstructor>
|
||||||
<initStateVariables>
|
<initStateVariables>
|
||||||
<userDefinedConstructorBody>
|
<userDefinedConstructorBody>
|
||||||
@ -748,6 +769,14 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
|||||||
if (contract->constructor())
|
if (contract->constructor())
|
||||||
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
||||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||||
|
|
||||||
|
t("sourceLocationComment", sourceLocationComment(
|
||||||
|
contract->constructor() ?
|
||||||
|
contract->constructor()->location() :
|
||||||
|
contract->location(),
|
||||||
|
m_context
|
||||||
|
));
|
||||||
|
|
||||||
t("params", joinHumanReadable(params));
|
t("params", joinHumanReadable(params));
|
||||||
vector<string> baseParams = listAllParams(baseConstructorParams);
|
vector<string> baseParams = listAllParams(baseConstructorParams);
|
||||||
t("baseParams", joinHumanReadable(baseParams));
|
t("baseParams", joinHumanReadable(baseParams));
|
||||||
@ -984,7 +1013,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract)
|
|||||||
m_context.internalDispatchClean(),
|
m_context.internalDispatchClean(),
|
||||||
"Reset internal dispatch map without consuming it."
|
"Reset internal dispatch map without consuming it."
|
||||||
);
|
);
|
||||||
m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings);
|
m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices());
|
||||||
|
|
||||||
m_context.setMostDerivedContract(_contract);
|
m_context.setMostDerivedContract(_contract);
|
||||||
for (auto const& var: ContractType(_contract).stateVariables())
|
for (auto const& var: ContractType(_contract).stateVariables())
|
||||||
|
@ -42,11 +42,12 @@ public:
|
|||||||
IRGenerator(
|
IRGenerator(
|
||||||
langutil::EVMVersion _evmVersion,
|
langutil::EVMVersion _evmVersion,
|
||||||
RevertStrings _revertStrings,
|
RevertStrings _revertStrings,
|
||||||
OptimiserSettings _optimiserSettings
|
OptimiserSettings _optimiserSettings,
|
||||||
|
std::map<std::string, unsigned> _sourceIndices
|
||||||
):
|
):
|
||||||
m_evmVersion(_evmVersion),
|
m_evmVersion(_evmVersion),
|
||||||
m_optimiserSettings(_optimiserSettings),
|
m_optimiserSettings(_optimiserSettings),
|
||||||
m_context(_evmVersion, _revertStrings, std::move(_optimiserSettings)),
|
m_context(_evmVersion, _revertStrings, std::move(_optimiserSettings), std::move(_sourceIndices)),
|
||||||
m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector())
|
m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ private:
|
|||||||
/// possibly be called via a pointer.
|
/// possibly be called via a pointer.
|
||||||
/// @return The content of the dispatch for reuse in runtime code. Reuse is necessary because
|
/// @return The content of the dispatch for reuse in runtime code. Reuse is necessary because
|
||||||
/// pointers to functions can be passed from the creation code in storage variables.
|
/// pointers to functions can be passed from the creation code in storage variables.
|
||||||
InternalDispatchMap generateInternalDispatchFunctions();
|
InternalDispatchMap generateInternalDispatchFunctions(ContractDefinition const& _contract);
|
||||||
/// Generates code for and returns the name of the function.
|
/// Generates code for and returns the name of the function.
|
||||||
std::string generateFunction(FunctionDefinition const& _function);
|
std::string generateFunction(FunctionDefinition const& _function);
|
||||||
std::string generateModifier(
|
std::string generateModifier(
|
||||||
|
@ -205,10 +205,34 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string IRGeneratorForStatementsBase::code() const
|
||||||
|
{
|
||||||
|
return m_code.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream& IRGeneratorForStatementsBase::appendCode(bool _addLocationComment)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
_addLocationComment &&
|
||||||
|
m_currentLocation.isValid() &&
|
||||||
|
m_lastLocation != m_currentLocation
|
||||||
|
)
|
||||||
|
m_code << sourceLocationComment(m_currentLocation, m_context) << "\n";
|
||||||
|
|
||||||
|
m_lastLocation = m_currentLocation;
|
||||||
|
|
||||||
|
return m_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node)
|
||||||
|
{
|
||||||
|
m_currentLocation = _node.location();
|
||||||
|
}
|
||||||
|
|
||||||
string IRGeneratorForStatements::code() const
|
string IRGeneratorForStatements::code() const
|
||||||
{
|
{
|
||||||
solAssert(!m_currentLValue, "LValue not reset!");
|
solAssert(!m_currentLValue, "LValue not reset!");
|
||||||
return m_code.str();
|
return IRGeneratorForStatementsBase::code();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::generate(Block const& _block)
|
void IRGeneratorForStatements::generate(Block const& _block)
|
||||||
@ -289,6 +313,8 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre
|
|||||||
setLocation(_expression);
|
setLocation(_expression);
|
||||||
|
|
||||||
_expression.accept(*this);
|
_expression.accept(*this);
|
||||||
|
|
||||||
|
setLocation(_expression);
|
||||||
IRVariable variable{m_context.newYulVariable(), _targetType};
|
IRVariable variable{m_context.newYulVariable(), _targetType};
|
||||||
define(variable, _expression);
|
define(variable, _expression);
|
||||||
return variable;
|
return variable;
|
||||||
@ -305,16 +331,16 @@ string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
setLocation(_constant);
|
|
||||||
|
|
||||||
string functionName = IRNames::constantValueFunction(_constant);
|
string functionName = IRNames::constantValueFunction(_constant);
|
||||||
return m_context.functionCollector().createFunction(functionName, [&] {
|
return m_context.functionCollector().createFunction(functionName, [&] {
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
|
<sourceLocationComment>
|
||||||
function <functionName>() -> <ret> {
|
function <functionName>() -> <ret> {
|
||||||
<code>
|
<code>
|
||||||
<ret> := <value>
|
<ret> := <value>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
templ("sourceLocationComment", sourceLocationComment(_constant, m_context));
|
||||||
templ("functionName", functionName);
|
templ("functionName", functionName);
|
||||||
IRGeneratorForStatements generator(m_context, m_utils);
|
IRGeneratorForStatements generator(m_context, m_utils);
|
||||||
solAssert(_constant.value(), "");
|
solAssert(_constant.value(), "");
|
||||||
@ -376,19 +402,19 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional)
|
|||||||
string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
||||||
declare(_conditional);
|
declare(_conditional);
|
||||||
|
|
||||||
m_code << "switch " << condition << "\n" "case 0 {\n";
|
appendCode() << "switch " << condition << "\n" "case 0 {\n";
|
||||||
|
|
||||||
_conditional.falseExpression().accept(*this);
|
_conditional.falseExpression().accept(*this);
|
||||||
setLocation(_conditional);
|
setLocation(_conditional);
|
||||||
|
|
||||||
assign(_conditional, _conditional.falseExpression());
|
assign(_conditional, _conditional.falseExpression());
|
||||||
m_code << "}\n" "default {\n";
|
appendCode() << "}\n" "default {\n";
|
||||||
|
|
||||||
_conditional.trueExpression().accept(*this);
|
_conditional.trueExpression().accept(*this);
|
||||||
setLocation(_conditional);
|
setLocation(_conditional);
|
||||||
|
|
||||||
assign(_conditional, _conditional.trueExpression());
|
assign(_conditional, _conditional.trueExpression());
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -472,7 +498,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
|||||||
component.accept(*this);
|
component.accept(*this);
|
||||||
setLocation(_tuple);
|
setLocation(_tuple);
|
||||||
IRVariable converted = convert(component, baseType);
|
IRVariable converted = convert(component, baseType);
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.writeToMemoryFunction(baseType) <<
|
m_utils.writeToMemoryFunction(baseType) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
|
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
|
||||||
@ -553,24 +579,25 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement)
|
|||||||
|
|
||||||
if (_ifStatement.falseStatement())
|
if (_ifStatement.falseStatement())
|
||||||
{
|
{
|
||||||
m_code << "switch " << condition << "\n" "case 0 {\n";
|
appendCode() << "switch " << condition << "\n" "case 0 {\n";
|
||||||
_ifStatement.falseStatement()->accept(*this);
|
_ifStatement.falseStatement()->accept(*this);
|
||||||
setLocation(_ifStatement);
|
setLocation(_ifStatement);
|
||||||
m_code << "}\n" "default {\n";
|
appendCode() << "}\n" "default {\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_code << "if " << condition << " {\n";
|
appendCode() << "if " << condition << " {\n";
|
||||||
_ifStatement.trueStatement().accept(*this);
|
_ifStatement.trueStatement().accept(*this);
|
||||||
setLocation(_ifStatement);
|
setLocation(_ifStatement);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::endVisit(PlaceholderStatement const&)
|
void IRGeneratorForStatements::endVisit(PlaceholderStatement const& _placeholder)
|
||||||
{
|
{
|
||||||
solAssert(m_placeholderCallback, "");
|
solAssert(m_placeholderCallback, "");
|
||||||
m_code << m_placeholderCallback();
|
setLocation(_placeholder);
|
||||||
|
appendCode() << m_placeholderCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRGeneratorForStatements::visit(ForStatement const& _forStatement)
|
bool IRGeneratorForStatements::visit(ForStatement const& _forStatement)
|
||||||
@ -603,14 +630,14 @@ bool IRGeneratorForStatements::visit(WhileStatement const& _whileStatement)
|
|||||||
bool IRGeneratorForStatements::visit(Continue const& _continue)
|
bool IRGeneratorForStatements::visit(Continue const& _continue)
|
||||||
{
|
{
|
||||||
setLocation(_continue);
|
setLocation(_continue);
|
||||||
m_code << "continue\n";
|
appendCode() << "continue\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRGeneratorForStatements::visit(Break const& _break)
|
bool IRGeneratorForStatements::visit(Break const& _break)
|
||||||
{
|
{
|
||||||
setLocation(_break);
|
setLocation(_break);
|
||||||
m_code << "break\n";
|
appendCode() << "break\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,7 +655,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return)
|
|||||||
else if (returnParameters.size() == 1)
|
else if (returnParameters.size() == 1)
|
||||||
assign(m_context.localVariable(*returnParameters.front()), *value);
|
assign(m_context.localVariable(*returnParameters.front()), *value);
|
||||||
}
|
}
|
||||||
m_code << "leave\n";
|
appendCode() << "leave\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
||||||
@ -643,7 +670,7 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
|||||||
std::visit(
|
std::visit(
|
||||||
util::GenericVisitor{
|
util::GenericVisitor{
|
||||||
[&](IRLValue::Storage const& _storage) {
|
[&](IRLValue::Storage const& _storage) {
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.storageSetToZeroFunction(m_currentLValue->type) <<
|
m_utils.storageSetToZeroFunction(m_currentLValue->type) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_storage.slot <<
|
_storage.slot <<
|
||||||
@ -870,7 +897,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
for (size_t i = 0; i < arguments.size(); i++)
|
for (size_t i = 0; i < arguments.size(); i++)
|
||||||
{
|
{
|
||||||
IRVariable converted = convert(*arguments[i], *parameterTypes[i]);
|
IRVariable converted = convert(*arguments[i], *parameterTypes[i]);
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.writeToMemoryFunction(*functionType->parameterTypes()[i]) <<
|
m_utils.writeToMemoryFunction(*functionType->parameterTypes()[i]) <<
|
||||||
"(add(" <<
|
"(add(" <<
|
||||||
IRVariable(_functionCall).part("mpos").name() <<
|
IRVariable(_functionCall).part("mpos").name() <<
|
||||||
@ -1001,7 +1028,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) {
|
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) {
|
||||||
return _arg.commaSeparatedList();
|
return _arg.commaSeparatedList();
|
||||||
})));
|
})));
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::Error:
|
case FunctionType::Kind::Error:
|
||||||
@ -1030,10 +1057,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
messageArgumentType
|
messageArgumentType
|
||||||
);
|
);
|
||||||
|
|
||||||
m_code << move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name();
|
appendCode() << move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name();
|
||||||
if (messageArgumentType && messageArgumentType->sizeOnStack() > 0)
|
if (messageArgumentType && messageArgumentType->sizeOnStack() > 0)
|
||||||
m_code << ", " << IRVariable(*arguments[1]).commaSeparatedList();
|
appendCode() << ", " << IRVariable(*arguments[1]).commaSeparatedList();
|
||||||
m_code << ")\n";
|
appendCode() << ")\n";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1075,7 +1102,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
// We might want to introduce a new set of memory handling functions here
|
// We might want to introduce a new set of memory handling functions here
|
||||||
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
|
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
|
||||||
string freeMemoryPre = m_context.newYulVariable();
|
string freeMemoryPre = m_context.newYulVariable();
|
||||||
m_code << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
|
appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
|
||||||
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
|
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
|
||||||
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
|
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
|
||||||
|
|
||||||
@ -1092,7 +1119,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
IRVariable selectorVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(4));
|
IRVariable selectorVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(4));
|
||||||
define(selectorVariable, hashVariable);
|
define(selectorVariable, hashVariable);
|
||||||
selector = selectorVariable.name();
|
selector = selectorVariable.name();
|
||||||
m_code << m_utils.finalizeAllocationFunction() << "(" << freeMemoryPre << ", 0)\n";
|
appendCode() << m_utils.finalizeAllocationFunction() << "(" << freeMemoryPre << ", 0)\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector)
|
else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector)
|
||||||
@ -1122,7 +1149,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("arguments", joinHumanReadablePrefixed(argumentVars));
|
templ("arguments", joinHumanReadablePrefixed(argumentVars));
|
||||||
templ("finalizeAllocation", m_utils.finalizeAllocationFunction());
|
templ("finalizeAllocation", m_utils.finalizeAllocationFunction());
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::ABIDecode:
|
case FunctionType::Kind::ABIDecode:
|
||||||
@ -1161,7 +1188,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
}
|
}
|
||||||
templ("retVars", IRVariable(_functionCall).commaSeparatedList());
|
templ("retVars", IRVariable(_functionCall).commaSeparatedList());
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::Revert:
|
case FunctionType::Kind::Revert:
|
||||||
@ -1173,7 +1200,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
arguments.front()->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()),
|
arguments.front()->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()),
|
||||||
"");
|
"");
|
||||||
if (m_context.revertStrings() == RevertStrings::Strip || arguments.empty())
|
if (m_context.revertStrings() == RevertStrings::Strip || arguments.empty())
|
||||||
m_code << "revert(0, 0)\n";
|
appendCode() << "revert(0, 0)\n";
|
||||||
else
|
else
|
||||||
revertWithError(
|
revertWithError(
|
||||||
"Error(string)",
|
"Error(string)",
|
||||||
@ -1248,7 +1275,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
{
|
{
|
||||||
auto slotName = m_context.newYulVariable();
|
auto slotName = m_context.newYulVariable();
|
||||||
auto offsetName = m_context.newYulVariable();
|
auto offsetName = m_context.newYulVariable();
|
||||||
m_code << "let " << slotName << ", " << offsetName << " := " <<
|
appendCode() << "let " << slotName << ", " << offsetName << " := " <<
|
||||||
m_utils.storageArrayPushZeroFunction(*arrayType) <<
|
m_utils.storageArrayPushZeroFunction(*arrayType) <<
|
||||||
"(" << IRVariable(_functionCall.expression()).commaSeparatedList() << ")\n";
|
"(" << IRVariable(_functionCall.expression()).commaSeparatedList() << ")\n";
|
||||||
setLValue(_functionCall, IRLValue{
|
setLValue(_functionCall, IRLValue{
|
||||||
@ -1266,7 +1293,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
convert(*arguments.front(), *arrayType->baseType()) :
|
convert(*arguments.front(), *arrayType->baseType()) :
|
||||||
*arguments.front();
|
*arguments.front();
|
||||||
|
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.storageArrayPushFunction(*arrayType, &argument.type()) <<
|
m_utils.storageArrayPushFunction(*arrayType, &argument.type()) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
IRVariable(_functionCall.expression()).commaSeparatedList() <<
|
IRVariable(_functionCall.expression()).commaSeparatedList() <<
|
||||||
@ -1311,7 +1338,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
Whiskers templ("if iszero(<modulus>) { <panic>() }\n");
|
Whiskers templ("if iszero(<modulus>) { <panic>() }\n");
|
||||||
templ("modulus", modulus.name());
|
templ("modulus", modulus.name());
|
||||||
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
|
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
|
|
||||||
string args;
|
string args;
|
||||||
for (size_t i = 0; i < 2; ++i)
|
for (size_t i = 0; i < 2; ++i)
|
||||||
@ -1357,8 +1384,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
&dynamic_cast<ContractType const&>(*functionType->returnParameterTypes().front()).contractDefinition();
|
&dynamic_cast<ContractType const&>(*functionType->returnParameterTypes().front()).contractDefinition();
|
||||||
m_context.subObjectsCreated().insert(contract);
|
m_context.subObjectsCreated().insert(contract);
|
||||||
|
|
||||||
Whiskers t(R"(
|
Whiskers t(R"(let <memPos> := <allocateUnbounded>()
|
||||||
let <memPos> := <allocateUnbounded>()
|
|
||||||
let <memEnd> := add(<memPos>, datasize("<object>"))
|
let <memEnd> := add(<memPos>, datasize("<object>"))
|
||||||
if or(gt(<memEnd>, 0xffffffffffffffff), lt(<memEnd>, <memPos>)) { <panic>() }
|
if or(gt(<memEnd>, 0xffffffffffffffff), lt(<memEnd>, <memPos>)) { <panic>() }
|
||||||
datacopy(<memPos>, dataoffset("<object>"), datasize("<object>"))
|
datacopy(<memPos>, dataoffset("<object>"), datasize("<object>"))
|
||||||
@ -1394,7 +1420,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
t("success", IRNames::trySuccessConditionVariable(_functionCall));
|
t("success", IRNames::trySuccessConditionVariable(_functionCall));
|
||||||
else
|
else
|
||||||
t("forwardingRevert", m_utils.forwardingRevertFunction());
|
t("forwardingRevert", m_utils.forwardingRevertFunction());
|
||||||
m_code << t.render();
|
appendCode() << t.render();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1422,7 +1448,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("success", IRVariable(_functionCall).commaSeparatedList());
|
templ("success", IRVariable(_functionCall).commaSeparatedList());
|
||||||
templ("isTransfer", functionType->kind() == FunctionType::Kind::Transfer);
|
templ("isTransfer", functionType->kind() == FunctionType::Kind::Transfer);
|
||||||
templ("forwardingRevert", m_utils.forwardingRevertFunction());
|
templ("forwardingRevert", m_utils.forwardingRevertFunction());
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1485,7 +1511,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")");
|
templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1722,7 +1748,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
solAssert(!contractType.isSuper(), "");
|
solAssert(!contractType.isSuper(), "");
|
||||||
ContractDefinition const& contract = contractType.contractDefinition();
|
ContractDefinition const& contract = contractType.contractDefinition();
|
||||||
m_context.subObjectsCreated().insert(&contract);
|
m_context.subObjectsCreated().insert(&contract);
|
||||||
m_code << Whiskers(R"(
|
appendCode() << Whiskers(R"(
|
||||||
let <size> := datasize("<objectName>")
|
let <size> := datasize("<objectName>")
|
||||||
let <result> := <allocationFunction>(add(<size>, 32))
|
let <result> := <allocationFunction>(add(<size>, 32))
|
||||||
mstore(<result>, <size>)
|
mstore(<result>, <size>)
|
||||||
@ -1775,7 +1801,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
{
|
{
|
||||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||||
string slot = m_context.newYulVariable();
|
string slot = m_context.newYulVariable();
|
||||||
m_code << "let " << slot << " := " <<
|
appendCode() << "let " << slot << " := " <<
|
||||||
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
|
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
|
||||||
setLValue(_memberAccess, IRLValue{
|
setLValue(_memberAccess, IRLValue{
|
||||||
type(_memberAccess),
|
type(_memberAccess),
|
||||||
@ -1786,7 +1812,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
case DataLocation::Memory:
|
case DataLocation::Memory:
|
||||||
{
|
{
|
||||||
string pos = m_context.newYulVariable();
|
string pos = m_context.newYulVariable();
|
||||||
m_code << "let " << pos << " := " <<
|
appendCode() << "let " << pos << " := " <<
|
||||||
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
|
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
|
||||||
setLValue(_memberAccess, IRLValue{
|
setLValue(_memberAccess, IRLValue{
|
||||||
type(_memberAccess),
|
type(_memberAccess),
|
||||||
@ -1798,7 +1824,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
{
|
{
|
||||||
string baseRef = expression.part("offset").name();
|
string baseRef = expression.part("offset").name();
|
||||||
string offset = m_context.newYulVariable();
|
string offset = m_context.newYulVariable();
|
||||||
m_code << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||||
if (_memberAccess.annotation().type->isDynamicallyEncoded())
|
if (_memberAccess.annotation().type->isDynamicallyEncoded())
|
||||||
define(_memberAccess) <<
|
define(_memberAccess) <<
|
||||||
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
|
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
|
||||||
@ -2023,7 +2049,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.
|
// Do not provide dialect so that we get the full type information.
|
||||||
m_code << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n";
|
appendCode() << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2046,7 +2072,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
|||||||
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
||||||
templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList());
|
templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList());
|
||||||
templ("key", IRVariable(*_indexAccess.indexExpression()).commaSeparatedList());
|
templ("key", IRVariable(*_indexAccess.indexExpression()).commaSeparatedList());
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
setLValue(_indexAccess, IRLValue{
|
setLValue(_indexAccess, IRLValue{
|
||||||
*_indexAccess.annotation().type,
|
*_indexAccess.annotation().type,
|
||||||
IRLValue::Storage{
|
IRLValue::Storage{
|
||||||
@ -2074,7 +2100,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
|||||||
string slot = m_context.newYulVariable();
|
string slot = m_context.newYulVariable();
|
||||||
string offset = m_context.newYulVariable();
|
string offset = m_context.newYulVariable();
|
||||||
|
|
||||||
m_code << Whiskers(R"(
|
appendCode() << Whiskers(R"(
|
||||||
let <slot>, <offset> := <indexFunc>(<array>, <index>)
|
let <slot>, <offset> := <indexFunc>(<array>, <index>)
|
||||||
)")
|
)")
|
||||||
("slot", slot)
|
("slot", slot)
|
||||||
@ -2141,7 +2167,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
|||||||
|
|
||||||
IRVariable index{m_context.newYulVariable(), *TypeProvider::uint256()};
|
IRVariable index{m_context.newYulVariable(), *TypeProvider::uint256()};
|
||||||
define(index, *_indexAccess.indexExpression());
|
define(index, *_indexAccess.indexExpression());
|
||||||
m_code << Whiskers(R"(
|
appendCode() << Whiskers(R"(
|
||||||
if iszero(lt(<index>, <length>)) { <panic>() }
|
if iszero(lt(<index>, <length>)) { <panic>() }
|
||||||
let <result> := <shl248>(byte(<index>, <array>))
|
let <result> := <shl248>(byte(<index>, <array>))
|
||||||
)")
|
)")
|
||||||
@ -2307,7 +2333,6 @@ void IRGeneratorForStatements::handleVariableReference(
|
|||||||
Expression const& _referencingExpression
|
Expression const& _referencingExpression
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
setLocation(_referencingExpression);
|
|
||||||
if ((_variable.isStateVariable() || _variable.isFileLevelVariable()) && _variable.isConstant())
|
if ((_variable.isStateVariable() || _variable.isFileLevelVariable()) && _variable.isConstant())
|
||||||
define(_referencingExpression) << constantValueFunction(_variable) << "()\n";
|
define(_referencingExpression) << constantValueFunction(_variable) << "()\n";
|
||||||
else if (_variable.isStateVariable() && _variable.immutable())
|
else if (_variable.isStateVariable() && _variable.immutable())
|
||||||
@ -2377,11 +2402,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
|||||||
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
|
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
|
||||||
// would remove that, so we use MSTORE here.
|
// would remove that, so we use MSTORE here.
|
||||||
if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0)
|
if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0)
|
||||||
m_code << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(if iszero(extcodesize(<address>)) { <revertNoCode>() }
|
||||||
if iszero(extcodesize(<address>)) { <revertNoCode>() }
|
|
||||||
|
|
||||||
// storage for arguments and returned data
|
// storage for arguments and returned data
|
||||||
let <pos> := <allocateUnbounded>()
|
let <pos> := <allocateUnbounded>()
|
||||||
@ -2474,7 +2498,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
|||||||
|
|
||||||
templ("forwardingRevert", m_utils.forwardingRevertFunction());
|
templ("forwardingRevert", m_utils.forwardingRevertFunction());
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::appendBareCall(
|
void IRGeneratorForStatements::appendBareCall(
|
||||||
@ -2565,7 +2589,7 @@ void IRGeneratorForStatements::appendBareCall(
|
|||||||
templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")");
|
templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
|
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
|
||||||
@ -2597,14 +2621,14 @@ std::string IRGeneratorForStatements::expressionAsType(Expression const& _expres
|
|||||||
std::ostream& IRGeneratorForStatements::define(IRVariable const& _var)
|
std::ostream& IRGeneratorForStatements::define(IRVariable const& _var)
|
||||||
{
|
{
|
||||||
if (_var.type().sizeOnStack() > 0)
|
if (_var.type().sizeOnStack() > 0)
|
||||||
m_code << "let " << _var.commaSeparatedList() << " := ";
|
appendCode() << "let " << _var.commaSeparatedList() << " := ";
|
||||||
return m_code;
|
return appendCode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::declare(IRVariable const& _var)
|
void IRGeneratorForStatements::declare(IRVariable const& _var)
|
||||||
{
|
{
|
||||||
if (_var.type().sizeOnStack() > 0)
|
if (_var.type().sizeOnStack() > 0)
|
||||||
m_code << "let " << _var.commaSeparatedList() << "\n";
|
appendCode() << "let " << _var.commaSeparatedList() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare)
|
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare)
|
||||||
@ -2615,15 +2639,15 @@ void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable
|
|||||||
if (stackItemType)
|
if (stackItemType)
|
||||||
declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare);
|
declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare);
|
||||||
else
|
else
|
||||||
m_code << (_declare ? "let ": "") << _lhs.part(stackItemName).name() << " := " << _rhs.part(stackItemName).name() << "\n";
|
appendCode() << (_declare ? "let ": "") << _lhs.part(stackItemName).name() << " := " << _rhs.part(stackItemName).name() << "\n";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_lhs.type().sizeOnStack() > 0)
|
if (_lhs.type().sizeOnStack() > 0)
|
||||||
m_code <<
|
appendCode() <<
|
||||||
(_declare ? "let ": "") <<
|
(_declare ? "let ": "") <<
|
||||||
_lhs.commaSeparatedList() <<
|
_lhs.commaSeparatedList() <<
|
||||||
" := ";
|
" := ";
|
||||||
m_code << m_context.utils().conversionFunction(_rhs.type(), _lhs.type()) <<
|
appendCode() << m_context.utils().conversionFunction(_rhs.type(), _lhs.type()) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_rhs.commaSeparatedList() <<
|
_rhs.commaSeparatedList() <<
|
||||||
")\n";
|
")\n";
|
||||||
@ -2761,13 +2785,13 @@ void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _b
|
|||||||
IRVariable value(_binOp);
|
IRVariable value(_binOp);
|
||||||
define(value, _binOp.leftExpression());
|
define(value, _binOp.leftExpression());
|
||||||
if (op == Token::Or)
|
if (op == Token::Or)
|
||||||
m_code << "if iszero(" << value.name() << ") {\n";
|
appendCode() << "if iszero(" << value.name() << ") {\n";
|
||||||
else
|
else
|
||||||
m_code << "if " << value.name() << " {\n";
|
appendCode() << "if " << value.name() << " {\n";
|
||||||
_binOp.rightExpression().accept(*this);
|
_binOp.rightExpression().accept(*this);
|
||||||
setLocation(_binOp);
|
setLocation(_binOp);
|
||||||
assign(value, _binOp.rightExpression());
|
assign(value, _binOp.rightExpression());
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable const& _value)
|
void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable const& _value)
|
||||||
@ -2783,7 +2807,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
[&](string const& _offset) { offsetArgument = ", " + _offset; }
|
[&](string const& _offset) { offsetArgument = ", " + _offset; }
|
||||||
}, _storage.offset);
|
}, _storage.offset);
|
||||||
|
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offsetStatic) <<
|
m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offsetStatic) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_storage.slot <<
|
_storage.slot <<
|
||||||
@ -2801,10 +2825,10 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
if (_memory.byteArrayElement)
|
if (_memory.byteArrayElement)
|
||||||
{
|
{
|
||||||
solAssert(_lvalue.type == *TypeProvider::byte(), "");
|
solAssert(_lvalue.type == *TypeProvider::byte(), "");
|
||||||
m_code << "mstore8(" + _memory.address + ", byte(0, " + prepared.commaSeparatedList() + "))\n";
|
appendCode() << "mstore8(" + _memory.address + ", byte(0, " + prepared.commaSeparatedList() + "))\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_code << m_utils.writeToMemoryFunction(_lvalue.type) <<
|
appendCode() << m_utils.writeToMemoryFunction(_lvalue.type) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_memory.address <<
|
_memory.address <<
|
||||||
", " <<
|
", " <<
|
||||||
@ -2812,7 +2836,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
")\n";
|
")\n";
|
||||||
}
|
}
|
||||||
else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type()))
|
else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type()))
|
||||||
m_code <<
|
appendCode() <<
|
||||||
m_utils.writeToMemoryFunction(*TypeProvider::uint256()) <<
|
m_utils.writeToMemoryFunction(*TypeProvider::uint256()) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_memory.address <<
|
_memory.address <<
|
||||||
@ -2824,7 +2848,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
solAssert(_lvalue.type.sizeOnStack() == 1, "");
|
solAssert(_lvalue.type.sizeOnStack() == 1, "");
|
||||||
auto const* valueReferenceType = dynamic_cast<ReferenceType const*>(&_value.type());
|
auto const* valueReferenceType = dynamic_cast<ReferenceType const*>(&_value.type());
|
||||||
solAssert(valueReferenceType && valueReferenceType->dataStoredIn(DataLocation::Memory), "");
|
solAssert(valueReferenceType && valueReferenceType->dataStoredIn(DataLocation::Memory), "");
|
||||||
m_code << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n";
|
appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); },
|
[&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); },
|
||||||
@ -2838,7 +2862,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
IRVariable prepared(m_context.newYulVariable(), _lvalue.type);
|
IRVariable prepared(m_context.newYulVariable(), _lvalue.type);
|
||||||
define(prepared, _value);
|
define(prepared, _value);
|
||||||
|
|
||||||
m_code << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
||||||
},
|
},
|
||||||
[&](IRLValue::Tuple const& _tuple) {
|
[&](IRLValue::Tuple const& _tuple) {
|
||||||
auto components = std::move(_tuple.components);
|
auto components = std::move(_tuple.components);
|
||||||
@ -2931,36 +2955,36 @@ void IRGeneratorForStatements::generateLoop(
|
|||||||
{
|
{
|
||||||
solAssert(_conditionExpression, "Expected condition for doWhile");
|
solAssert(_conditionExpression, "Expected condition for doWhile");
|
||||||
firstRun = m_context.newYulVariable();
|
firstRun = m_context.newYulVariable();
|
||||||
m_code << "let " << firstRun << " := 1\n";
|
appendCode() << "let " << firstRun << " := 1\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_code << "for {\n";
|
appendCode() << "for {\n";
|
||||||
if (_initExpression)
|
if (_initExpression)
|
||||||
_initExpression->accept(*this);
|
_initExpression->accept(*this);
|
||||||
m_code << "} 1 {\n";
|
appendCode() << "} 1 {\n";
|
||||||
if (_loopExpression)
|
if (_loopExpression)
|
||||||
_loopExpression->accept(*this);
|
_loopExpression->accept(*this);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
m_code << "{\n";
|
appendCode() << "{\n";
|
||||||
|
|
||||||
if (_conditionExpression)
|
if (_conditionExpression)
|
||||||
{
|
{
|
||||||
if (_isDoWhile)
|
if (_isDoWhile)
|
||||||
m_code << "if iszero(" << firstRun << ") {\n";
|
appendCode() << "if iszero(" << firstRun << ") {\n";
|
||||||
|
|
||||||
_conditionExpression->accept(*this);
|
_conditionExpression->accept(*this);
|
||||||
m_code <<
|
appendCode() <<
|
||||||
"if iszero(" <<
|
"if iszero(" <<
|
||||||
expressionAsType(*_conditionExpression, *TypeProvider::boolean()) <<
|
expressionAsType(*_conditionExpression, *TypeProvider::boolean()) <<
|
||||||
") { break }\n";
|
") { break }\n";
|
||||||
|
|
||||||
if (_isDoWhile)
|
if (_isDoWhile)
|
||||||
m_code << "}\n" << firstRun << " := 0\n";
|
appendCode() << "}\n" << firstRun << " := 0\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
_body.accept(*this);
|
_body.accept(*this);
|
||||||
|
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Type const& IRGeneratorForStatements::type(Expression const& _expression)
|
Type const& IRGeneratorForStatements::type(Expression const& _expression)
|
||||||
@ -2975,9 +2999,9 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement)
|
|||||||
externalCall.accept(*this);
|
externalCall.accept(*this);
|
||||||
setLocation(_tryStatement);
|
setLocation(_tryStatement);
|
||||||
|
|
||||||
m_code << "switch iszero(" << IRNames::trySuccessConditionVariable(externalCall) << ")\n";
|
appendCode() << "switch iszero(" << IRNames::trySuccessConditionVariable(externalCall) << ")\n";
|
||||||
|
|
||||||
m_code << "case 0 { // success case\n";
|
appendCode() << "case 0 { // success case\n";
|
||||||
TryCatchClause const& successClause = *_tryStatement.clauses().front();
|
TryCatchClause const& successClause = *_tryStatement.clauses().front();
|
||||||
if (successClause.parameters())
|
if (successClause.parameters())
|
||||||
{
|
{
|
||||||
@ -2995,32 +3019,34 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement)
|
|||||||
|
|
||||||
successClause.block().accept(*this);
|
successClause.block().accept(*this);
|
||||||
setLocation(_tryStatement);
|
setLocation(_tryStatement);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
|
||||||
m_code << "default { // failure case\n";
|
appendCode() << "default { // failure case\n";
|
||||||
handleCatch(_tryStatement);
|
handleCatch(_tryStatement);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||||
{
|
{
|
||||||
|
setLocation(_tryStatement);
|
||||||
string const runFallback = m_context.newYulVariable();
|
string const runFallback = m_context.newYulVariable();
|
||||||
m_code << "let " << runFallback << " := 1\n";
|
appendCode() << "let " << runFallback << " := 1\n";
|
||||||
|
|
||||||
// This function returns zero on "short returndata". We have to add a success flag
|
// This function returns zero on "short returndata". We have to add a success flag
|
||||||
// once we implement custom error codes.
|
// once we implement custom error codes.
|
||||||
if (_tryStatement.errorClause() || _tryStatement.panicClause())
|
if (_tryStatement.errorClause() || _tryStatement.panicClause())
|
||||||
m_code << "switch " << m_utils.returnDataSelectorFunction() << "()\n";
|
appendCode() << "switch " << m_utils.returnDataSelectorFunction() << "()\n";
|
||||||
|
|
||||||
if (TryCatchClause const* errorClause = _tryStatement.errorClause())
|
if (TryCatchClause const* errorClause = _tryStatement.errorClause())
|
||||||
{
|
{
|
||||||
m_code << "case " << selectorFromSignature32("Error(string)") << " {\n";
|
appendCode() << "case " << selectorFromSignature32("Error(string)") << " {\n";
|
||||||
|
setLocation(*errorClause);
|
||||||
string const dataVariable = m_context.newYulVariable();
|
string const dataVariable = m_context.newYulVariable();
|
||||||
m_code << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
||||||
m_code << "if " << dataVariable << " {\n";
|
appendCode() << "if " << dataVariable << " {\n";
|
||||||
m_code << runFallback << " := 0\n";
|
appendCode() << runFallback << " := 0\n";
|
||||||
if (errorClause->parameters())
|
if (errorClause->parameters())
|
||||||
{
|
{
|
||||||
solAssert(errorClause->parameters()->parameters().size() == 1, "");
|
solAssert(errorClause->parameters()->parameters().size() == 1, "");
|
||||||
@ -3028,17 +3054,20 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
|||||||
define(var) << dataVariable << "\n";
|
define(var) << dataVariable << "\n";
|
||||||
}
|
}
|
||||||
errorClause->accept(*this);
|
errorClause->accept(*this);
|
||||||
m_code << "}\n";
|
setLocation(*errorClause);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
setLocation(_tryStatement);
|
||||||
|
appendCode() << "}\n";
|
||||||
}
|
}
|
||||||
if (TryCatchClause const* panicClause = _tryStatement.panicClause())
|
if (TryCatchClause const* panicClause = _tryStatement.panicClause())
|
||||||
{
|
{
|
||||||
m_code << "case " << selectorFromSignature32("Panic(uint256)") << " {\n";
|
appendCode() << "case " << selectorFromSignature32("Panic(uint256)") << " {\n";
|
||||||
|
setLocation(*panicClause);
|
||||||
string const success = m_context.newYulVariable();
|
string const success = m_context.newYulVariable();
|
||||||
string const code = m_context.newYulVariable();
|
string const code = m_context.newYulVariable();
|
||||||
m_code << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n";
|
appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n";
|
||||||
m_code << "if " << success << " {\n";
|
appendCode() << "if " << success << " {\n";
|
||||||
m_code << runFallback << " := 0\n";
|
appendCode() << runFallback << " := 0\n";
|
||||||
if (panicClause->parameters())
|
if (panicClause->parameters())
|
||||||
{
|
{
|
||||||
solAssert(panicClause->parameters()->parameters().size() == 1, "");
|
solAssert(panicClause->parameters()->parameters().size() == 1, "");
|
||||||
@ -3046,20 +3075,25 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
|||||||
define(var) << code << "\n";
|
define(var) << code << "\n";
|
||||||
}
|
}
|
||||||
panicClause->accept(*this);
|
panicClause->accept(*this);
|
||||||
m_code << "}\n";
|
setLocation(*panicClause);
|
||||||
m_code << "}\n";
|
appendCode() << "}\n";
|
||||||
|
setLocation(_tryStatement);
|
||||||
|
appendCode() << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_code << "if " << runFallback << " {\n";
|
setLocation(_tryStatement);
|
||||||
|
appendCode() << "if " << runFallback << " {\n";
|
||||||
if (_tryStatement.fallbackClause())
|
if (_tryStatement.fallbackClause())
|
||||||
handleCatchFallback(*_tryStatement.fallbackClause());
|
handleCatchFallback(*_tryStatement.fallbackClause());
|
||||||
else
|
else
|
||||||
m_code << m_utils.forwardingRevertFunction() << "()\n";
|
appendCode() << m_utils.forwardingRevertFunction() << "()\n";
|
||||||
m_code << "}\n";
|
setLocation(_tryStatement);
|
||||||
|
appendCode() << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallback)
|
void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallback)
|
||||||
{
|
{
|
||||||
|
setLocation(_fallback);
|
||||||
if (_fallback.parameters())
|
if (_fallback.parameters())
|
||||||
{
|
{
|
||||||
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
||||||
@ -3104,7 +3138,7 @@ void IRGeneratorForStatements::revertWithError(
|
|||||||
templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars));
|
templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars));
|
||||||
templ("encode", m_context.abiFunctions().tupleEncoder(errorArgumentTypes, _parameterTypes));
|
templ("encode", m_context.abiFunctions().tupleEncoder(errorArgumentTypes, _parameterTypes));
|
||||||
|
|
||||||
m_code << templ.render();
|
appendCode() << templ.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3114,11 +3148,6 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::setLocation(ASTNode const& _node)
|
|
||||||
{
|
|
||||||
m_currentLocation = _node.location();
|
|
||||||
}
|
|
||||||
|
|
||||||
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||||
{
|
{
|
||||||
solAssert(_library.isLibrary(), "");
|
solAssert(_library.isLibrary(), "");
|
||||||
|
@ -33,11 +33,33 @@ namespace solidity::frontend
|
|||||||
class IRGenerationContext;
|
class IRGenerationContext;
|
||||||
class YulUtilFunctions;
|
class YulUtilFunctions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for the statement generator.
|
||||||
|
* Encapsulates access to the yul code stream and handles source code locations.
|
||||||
|
*/
|
||||||
|
class IRGeneratorForStatementsBase: public ASTConstVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRGeneratorForStatementsBase(IRGenerationContext& _context):
|
||||||
|
m_context(_context)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::string code() const;
|
||||||
|
std::ostringstream& appendCode(bool _addLocationComment = true);
|
||||||
|
protected:
|
||||||
|
void setLocation(ASTNode const& _node);
|
||||||
|
langutil::SourceLocation m_currentLocation = {};
|
||||||
|
langutil::SourceLocation m_lastLocation = {};
|
||||||
|
IRGenerationContext& m_context;
|
||||||
|
private:
|
||||||
|
std::ostringstream m_code;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that translates Solidity's AST into Yul at statement level and below.
|
* Component that translates Solidity's AST into Yul at statement level and below.
|
||||||
* It is an AST visitor that appends to an internal string buffer.
|
* It is an AST visitor that appends to an internal string buffer.
|
||||||
*/
|
*/
|
||||||
class IRGeneratorForStatements: public ASTConstVisitor
|
class IRGeneratorForStatements: public IRGeneratorForStatementsBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IRGeneratorForStatements(
|
IRGeneratorForStatements(
|
||||||
@ -45,12 +67,12 @@ public:
|
|||||||
YulUtilFunctions& _utils,
|
YulUtilFunctions& _utils,
|
||||||
std::function<std::string()> _placeholderCallback = {}
|
std::function<std::string()> _placeholderCallback = {}
|
||||||
):
|
):
|
||||||
m_context(_context),
|
IRGeneratorForStatementsBase(_context),
|
||||||
m_placeholderCallback(std::move(_placeholderCallback)),
|
m_placeholderCallback(std::move(_placeholderCallback)),
|
||||||
m_utils(_utils)
|
m_utils(_utils)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string code() const;
|
std::string code() const override;
|
||||||
|
|
||||||
/// Generate the code for the statements in the block;
|
/// Generate the code for the statements in the block;
|
||||||
void generate(Block const& _block);
|
void generate(Block const& _block);
|
||||||
@ -190,16 +212,11 @@ private:
|
|||||||
|
|
||||||
static Type const& type(Expression const& _expression);
|
static Type const& type(Expression const& _expression);
|
||||||
|
|
||||||
void setLocation(ASTNode const& _node);
|
|
||||||
|
|
||||||
std::string linkerSymbol(ContractDefinition const& _library) const;
|
std::string linkerSymbol(ContractDefinition const& _library) const;
|
||||||
|
|
||||||
std::ostringstream m_code;
|
|
||||||
IRGenerationContext& m_context;
|
|
||||||
std::function<std::string()> m_placeholderCallback;
|
std::function<std::string()> m_placeholderCallback;
|
||||||
YulUtilFunctions& m_utils;
|
YulUtilFunctions& m_utils;
|
||||||
std::optional<IRLValue> m_currentLValue;
|
std::optional<IRLValue> m_currentLValue;
|
||||||
langutil::SourceLocation m_currentLocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1350,7 +1350,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
|
|||||||
for (auto const& pair: m_contracts)
|
for (auto const& pair: m_contracts)
|
||||||
otherYulSources.emplace(pair.second.contract, pair.second.yulIR);
|
otherYulSources.emplace(pair.second.contract, pair.second.yulIR);
|
||||||
|
|
||||||
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings);
|
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices());
|
||||||
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(
|
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(
|
||||||
_contract,
|
_contract,
|
||||||
createCBORMetadata(compiledContract),
|
createCBORMetadata(compiledContract),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_12" {
|
object "C_12" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
IR:
|
IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object "C_81" {
|
object "C_81" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:82,370
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ object "C_81" {
|
|||||||
|
|
||||||
function constructor_C_81() {
|
function constructor_C_81() {
|
||||||
|
|
||||||
|
/// @src 0:82,370
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -34,6 +37,7 @@ object "C_81" {
|
|||||||
}
|
}
|
||||||
object "C_81_deployed" {
|
object "C_81_deployed" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:82,370
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -208,78 +212,126 @@ object "C_81" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_80(var_a_4, var_b_6, var_c_8, var_d_10) -> var__13, var__15, var__17, var__19 {
|
function fun_f_80(var_a_4, var_b_6, var_c_8, var_d_10) -> var__13, var__15, var__17, var__19 {
|
||||||
|
/// @src 0:96,368
|
||||||
|
/// @src 0:160,164
|
||||||
let zero_t_uint256_1 := zero_value_for_split_t_uint256()
|
let zero_t_uint256_1 := zero_value_for_split_t_uint256()
|
||||||
var__13 := zero_t_uint256_1
|
var__13 := zero_t_uint256_1
|
||||||
|
/// @src 0:166,169
|
||||||
let zero_t_int256_2 := zero_value_for_split_t_int256()
|
let zero_t_int256_2 := zero_value_for_split_t_int256()
|
||||||
var__15 := zero_t_int256_2
|
var__15 := zero_t_int256_2
|
||||||
|
/// @src 0:171,175
|
||||||
let zero_t_uint256_3 := zero_value_for_split_t_uint256()
|
let zero_t_uint256_3 := zero_value_for_split_t_uint256()
|
||||||
var__17 := zero_t_uint256_3
|
var__17 := zero_t_uint256_3
|
||||||
|
/// @src 0:177,181
|
||||||
let zero_t_uint256_4 := zero_value_for_split_t_uint256()
|
let zero_t_uint256_4 := zero_value_for_split_t_uint256()
|
||||||
var__19 := zero_t_uint256_4
|
var__19 := zero_t_uint256_4
|
||||||
|
|
||||||
|
/// @src 0:196,197
|
||||||
let expr_23 := 0x02
|
let expr_23 := 0x02
|
||||||
|
/// @src 0:199,200
|
||||||
let _5 := var_a_4
|
let _5 := var_a_4
|
||||||
let expr_24 := _5
|
let expr_24 := _5
|
||||||
|
/// @src 0:196,200
|
||||||
let _6 := convert_t_rational_2_by_1_to_t_uint256(expr_23)
|
let _6 := convert_t_rational_2_by_1_to_t_uint256(expr_23)
|
||||||
let expr_25 := checked_exp_t_rational_2_by_1_t_uint256(expr_24)
|
let expr_25 := checked_exp_t_rational_2_by_1_t_uint256(expr_24)
|
||||||
|
/// @src 0:187,200
|
||||||
let var_w_22 := expr_25
|
let var_w_22 := expr_25
|
||||||
|
/// @src 0:214,215
|
||||||
let expr_29 := 0x02
|
let expr_29 := 0x02
|
||||||
|
/// @src 0:213,215
|
||||||
let expr_30 := 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
let expr_30 := 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||||
|
/// @src 0:212,216
|
||||||
let expr_31 := expr_30
|
let expr_31 := expr_30
|
||||||
|
/// @src 0:218,219
|
||||||
let _7 := var_b_6
|
let _7 := var_b_6
|
||||||
let expr_32 := _7
|
let expr_32 := _7
|
||||||
|
/// @src 0:212,219
|
||||||
let _8 := convert_t_rational_minus_2_by_1_to_t_int256(expr_31)
|
let _8 := convert_t_rational_minus_2_by_1_to_t_int256(expr_31)
|
||||||
let expr_33 := checked_exp_t_rational_minus_2_by_1_t_uint256(expr_32)
|
let expr_33 := checked_exp_t_rational_minus_2_by_1_t_uint256(expr_32)
|
||||||
|
/// @src 0:204,219
|
||||||
let var_x_28 := expr_33
|
let var_x_28 := expr_33
|
||||||
|
/// @src 0:232,234
|
||||||
let expr_37 := 0x0a
|
let expr_37 := 0x0a
|
||||||
|
/// @src 0:236,237
|
||||||
let _9 := var_c_8
|
let _9 := var_c_8
|
||||||
let expr_38 := _9
|
let expr_38 := _9
|
||||||
|
/// @src 0:232,237
|
||||||
let _10 := convert_t_rational_10_by_1_to_t_uint256(expr_37)
|
let _10 := convert_t_rational_10_by_1_to_t_uint256(expr_37)
|
||||||
let expr_39 := checked_exp_t_rational_10_by_1_t_uint256(expr_38)
|
let expr_39 := checked_exp_t_rational_10_by_1_t_uint256(expr_38)
|
||||||
|
/// @src 0:223,237
|
||||||
let var_y_36 := expr_39
|
let var_y_36 := expr_39
|
||||||
|
/// @src 0:251,260
|
||||||
let expr_47 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
let expr_47 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
/// @src 0:250,262
|
||||||
let expr_48 := expr_47
|
let expr_48 := expr_47
|
||||||
|
/// @src 0:264,265
|
||||||
let _11 := var_d_10
|
let _11 := var_d_10
|
||||||
let expr_49 := _11
|
let expr_49 := _11
|
||||||
|
/// @src 0:250,265
|
||||||
let _12 := convert_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_to_t_uint256(expr_48)
|
let _12 := convert_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_to_t_uint256(expr_48)
|
||||||
let expr_50 := checked_exp_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_t_uint256(expr_49)
|
let expr_50 := checked_exp_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_t_uint256(expr_49)
|
||||||
|
/// @src 0:241,265
|
||||||
let var_z_42 := expr_50
|
let var_z_42 := expr_50
|
||||||
|
/// @src 0:308,309
|
||||||
let expr_53 := 0x00
|
let expr_53 := 0x00
|
||||||
|
/// @src 0:307,310
|
||||||
let expr_54 := expr_53
|
let expr_54 := expr_53
|
||||||
|
/// @src 0:312,313
|
||||||
let _13 := var_a_4
|
let _13 := var_a_4
|
||||||
let expr_55 := _13
|
let expr_55 := _13
|
||||||
|
/// @src 0:307,313
|
||||||
let _14 := convert_t_rational_0_by_1_to_t_uint256(expr_54)
|
let _14 := convert_t_rational_0_by_1_to_t_uint256(expr_54)
|
||||||
let expr_56 := checked_exp_t_rational_0_by_1_t_uint256(expr_55)
|
let expr_56 := checked_exp_t_rational_0_by_1_t_uint256(expr_55)
|
||||||
|
/// @src 0:303,313
|
||||||
var_w_22 := expr_56
|
var_w_22 := expr_56
|
||||||
let expr_57 := expr_56
|
let expr_57 := expr_56
|
||||||
|
/// @src 0:323,324
|
||||||
let expr_60 := 0x01
|
let expr_60 := 0x01
|
||||||
|
/// @src 0:322,324
|
||||||
let expr_61 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
let expr_61 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
/// @src 0:321,325
|
||||||
let expr_62 := expr_61
|
let expr_62 := expr_61
|
||||||
|
/// @src 0:327,328
|
||||||
let _15 := var_b_6
|
let _15 := var_b_6
|
||||||
let expr_63 := _15
|
let expr_63 := _15
|
||||||
|
/// @src 0:321,328
|
||||||
let _16 := convert_t_rational_minus_1_by_1_to_t_int256(expr_62)
|
let _16 := convert_t_rational_minus_1_by_1_to_t_int256(expr_62)
|
||||||
let expr_64 := checked_exp_t_rational_minus_1_by_1_t_uint256(expr_63)
|
let expr_64 := checked_exp_t_rational_minus_1_by_1_t_uint256(expr_63)
|
||||||
|
/// @src 0:317,328
|
||||||
var_x_28 := expr_64
|
var_x_28 := expr_64
|
||||||
let expr_65 := expr_64
|
let expr_65 := expr_64
|
||||||
|
/// @src 0:336,337
|
||||||
let expr_68 := 0x01
|
let expr_68 := 0x01
|
||||||
|
/// @src 0:339,340
|
||||||
let _17 := var_c_8
|
let _17 := var_c_8
|
||||||
let expr_69 := _17
|
let expr_69 := _17
|
||||||
|
/// @src 0:336,340
|
||||||
let _18 := convert_t_rational_1_by_1_to_t_uint256(expr_68)
|
let _18 := convert_t_rational_1_by_1_to_t_uint256(expr_68)
|
||||||
let expr_70 := checked_exp_t_rational_1_by_1_t_uint256(expr_69)
|
let expr_70 := checked_exp_t_rational_1_by_1_t_uint256(expr_69)
|
||||||
|
/// @src 0:332,340
|
||||||
var_y_36 := expr_70
|
var_y_36 := expr_70
|
||||||
let expr_71 := expr_70
|
let expr_71 := expr_70
|
||||||
|
/// @src 0:353,354
|
||||||
let _19 := var_w_22
|
let _19 := var_w_22
|
||||||
let expr_73 := _19
|
let expr_73 := _19
|
||||||
|
/// @src 0:352,364
|
||||||
let expr_77_component_1 := expr_73
|
let expr_77_component_1 := expr_73
|
||||||
|
/// @src 0:356,357
|
||||||
let _20 := var_x_28
|
let _20 := var_x_28
|
||||||
let expr_74 := _20
|
let expr_74 := _20
|
||||||
|
/// @src 0:352,364
|
||||||
let expr_77_component_2 := expr_74
|
let expr_77_component_2 := expr_74
|
||||||
|
/// @src 0:359,360
|
||||||
let _21 := var_y_36
|
let _21 := var_y_36
|
||||||
let expr_75 := _21
|
let expr_75 := _21
|
||||||
|
/// @src 0:352,364
|
||||||
let expr_77_component_3 := expr_75
|
let expr_77_component_3 := expr_75
|
||||||
|
/// @src 0:362,363
|
||||||
let _22 := var_z_42
|
let _22 := var_z_42
|
||||||
let expr_76 := _22
|
let expr_76 := _22
|
||||||
|
/// @src 0:352,364
|
||||||
let expr_77_component_4 := expr_76
|
let expr_77_component_4 := expr_76
|
||||||
|
/// @src 0:345,364
|
||||||
var__13 := expr_77_component_1
|
var__13 := expr_77_component_1
|
||||||
var__15 := expr_77_component_2
|
var__15 := expr_77_component_2
|
||||||
var__17 := expr_77_component_3
|
var__17 := expr_77_component_3
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_7" {
|
object "C_7" {
|
||||||
code {
|
code {
|
||||||
@ -28,12 +28,12 @@ object "C_7" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "D_10" {
|
object "D_10" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_3" {
|
object "C_3" {
|
||||||
code {
|
code {
|
||||||
@ -28,12 +28,12 @@ object "C_3" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "D_16" {
|
object "D_16" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "D_12" {
|
object "D_12" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "D_8" {
|
object "D_8" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_12" {
|
object "C_12" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_7" {
|
object "C_7" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_59" {
|
object "C_59" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "Arraysum_34" {
|
object "Arraysum_34" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
IR:
|
IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object "C_15" {
|
object "C_15" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:59,147
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ object "C_15" {
|
|||||||
|
|
||||||
function constructor_C_15() {
|
function constructor_C_15() {
|
||||||
|
|
||||||
|
/// @src 0:59,147
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -49,6 +52,7 @@ object "C_15" {
|
|||||||
}
|
}
|
||||||
object "C_15_deployed" {
|
object "C_15_deployed" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:59,147
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -213,6 +217,7 @@ object "C_15" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_14(var__7_mpos, var_e_10) {
|
function fun_f_14(var__7_mpos, var_e_10) {
|
||||||
|
/// @src 0:93,145
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{"contracts":{"A":{"C":{"irOptimized":"/*******************************************************
|
{"contracts":{"A":{"C":{"irOptimized":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object \"C_7\" {
|
object \"C_7\" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_7\" {
|
object \"C_7\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,121
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_7\" {
|
|||||||
|
|
||||||
function constructor_C_7() {
|
function constructor_C_7() {
|
||||||
|
|
||||||
|
/// @src 0:79,121
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_7\" {
|
|||||||
}
|
}
|
||||||
object \"C_7_deployed\" {
|
object \"C_7_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,121
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -72,6 +76,7 @@ object \"C_7\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_6() {
|
function fun_f_6() {
|
||||||
|
/// @src 0:92,119
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"object":"<BYTECODE REMOVED>"},"deployedBytecode":{"object":"<BYTECODE REMOVED>"}},"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"object":"<BYTECODE REMOVED>"},"deployedBytecode":{"object":"<BYTECODE REMOVED>"}},"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_3\" {
|
object \"C_3\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,92
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_3\" {
|
|||||||
|
|
||||||
function constructor_C_3() {
|
function constructor_C_3() {
|
||||||
|
|
||||||
|
/// @src 0:79,92
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_3\" {
|
|||||||
}
|
}
|
||||||
object \"C_3_deployed\" {
|
object \"C_3_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,92
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -67,16 +71,17 @@ object \"C_3\" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"},"D":{"evm":{"bytecode":{"generatedSources":[],"object":"<BYTECODE REMOVED>"},"deployedBytecode":{"object":"<BYTECODE REMOVED>"}},"ir":"/*******************************************************
|
"},"D":{"evm":{"bytecode":{"generatedSources":[],"object":"<BYTECODE REMOVED>"},"deployedBytecode":{"object":"<BYTECODE REMOVED>"}},"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"D_16\" {
|
object \"D_16\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:93,146
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -93,6 +98,8 @@ object \"D_16\" {
|
|||||||
|
|
||||||
function constructor_D_16() {
|
function constructor_D_16() {
|
||||||
|
|
||||||
|
/// @src 0:93,146
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -102,6 +109,7 @@ object \"D_16\" {
|
|||||||
}
|
}
|
||||||
object \"D_16_deployed\" {
|
object \"D_16_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:93,146
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -141,7 +149,9 @@ object \"D_16\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_15() {
|
function fun_f_15() {
|
||||||
|
/// @src 0:106,144
|
||||||
|
|
||||||
|
/// @src 0:134,141
|
||||||
let _1 := allocate_unbounded()
|
let _1 := allocate_unbounded()
|
||||||
let _2 := add(_1, datasize(\"C_3\"))
|
let _2 := add(_1, datasize(\"C_3\"))
|
||||||
if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() }
|
if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() }
|
||||||
@ -152,6 +162,7 @@ object \"D_16\" {
|
|||||||
|
|
||||||
if iszero(expr_12_address) { revert_forward_1() }
|
if iszero(expr_12_address) { revert_forward_1() }
|
||||||
|
|
||||||
|
/// @src 0:128,141
|
||||||
let var_c_8_address := expr_12_address
|
let var_c_8_address := expr_12_address
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -188,15 +199,16 @@ object \"D_16\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object \"C_3\" {
|
object \"C_3\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,92
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -213,6 +225,8 @@ object \"D_16\" {
|
|||||||
|
|
||||||
function constructor_C_3() {
|
function constructor_C_3() {
|
||||||
|
|
||||||
|
/// @src 0:79,92
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -222,6 +236,7 @@ object \"D_16\" {
|
|||||||
}
|
}
|
||||||
object \"C_3_deployed\" {
|
object \"C_3_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,92
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
IR:
|
IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object "test_11" {
|
object "test_11" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,169
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ object "test_11" {
|
|||||||
|
|
||||||
function constructor_test_11() {
|
function constructor_test_11() {
|
||||||
|
|
||||||
|
/// @src 0:79,169
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -34,6 +37,7 @@ object "test_11" {
|
|||||||
}
|
}
|
||||||
object "test_11_deployed" {
|
object "test_11_deployed" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:79,169
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -83,10 +87,14 @@ object "test_11" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5 {
|
function fun_f_10() -> var__5 {
|
||||||
|
/// @src 0:99,167
|
||||||
|
/// @src 0:133,137
|
||||||
let zero_t_bool_1 := zero_value_for_split_t_bool()
|
let zero_t_bool_1 := zero_value_for_split_t_bool()
|
||||||
var__5 := zero_t_bool_1
|
var__5 := zero_t_bool_1
|
||||||
|
|
||||||
|
/// @src 0:156,160
|
||||||
let expr_7 := 0x01
|
let expr_7 := 0x01
|
||||||
|
/// @src 0:149,160
|
||||||
var__5 := expr_7
|
var__5 := expr_7
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
@ -5,12 +5,12 @@ Binary:
|
|||||||
Binary of the runtime part:
|
Binary of the runtime part:
|
||||||
<BYTECODE REMOVED>
|
<BYTECODE REMOVED>
|
||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_3" {
|
object "C_3" {
|
||||||
code {
|
code {
|
||||||
@ -40,12 +40,12 @@ Binary:
|
|||||||
Binary of the runtime part:
|
Binary of the runtime part:
|
||||||
<BYTECODE REMOVED>
|
<BYTECODE REMOVED>
|
||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "D_16" {
|
object "D_16" {
|
||||||
code {
|
code {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Optimized IR:
|
Optimized IR:
|
||||||
/*******************************************************
|
/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
object "C_7" {
|
object "C_7" {
|
||||||
code {
|
code {
|
||||||
|
21
test/cmdlineTests/yul_source_locations/input.json
Normal file
21
test/cmdlineTests/yul_source_locations/input.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"C":
|
||||||
|
{
|
||||||
|
"content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n"
|
||||||
|
},
|
||||||
|
"D":
|
||||||
|
{
|
||||||
|
"content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"outputSelection":
|
||||||
|
{
|
||||||
|
"*": { "*": ["ir"] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1120
test/cmdlineTests/yul_source_locations/output.json
Normal file
1120
test/cmdlineTests/yul_source_locations/output.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_11\" {
|
object \"C_11\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,164
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_11\" {
|
|||||||
|
|
||||||
function constructor_C_11() {
|
function constructor_C_11() {
|
||||||
|
|
||||||
|
/// @src 0:78,164
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
object \"C_11_deployed\" {
|
object \"C_11_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,164
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -146,9 +150,12 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5_mpos {
|
function fun_f_10() -> var__5_mpos {
|
||||||
|
/// @src 0:91,162
|
||||||
|
/// @src 0:127,140
|
||||||
let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
|
let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
|
||||||
var__5_mpos := zero_t_string_memory_ptr_1_mpos
|
var__5_mpos := zero_t_string_memory_ptr_1_mpos
|
||||||
|
|
||||||
|
/// @src 0:144,159
|
||||||
var__5_mpos := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr()
|
var__5_mpos := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr()
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_11\" {
|
object \"C_11\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,158
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_11\" {
|
|||||||
|
|
||||||
function constructor_C_11() {
|
function constructor_C_11() {
|
||||||
|
|
||||||
|
/// @src 0:78,158
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
object \"C_11_deployed\" {
|
object \"C_11_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,158
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -86,9 +90,12 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5 {
|
function fun_f_10() -> var__5 {
|
||||||
|
/// @src 0:91,156
|
||||||
|
/// @src 0:127,134
|
||||||
let zero_t_bytes32_1 := zero_value_for_split_t_bytes32()
|
let zero_t_bytes32_1 := zero_value_for_split_t_bytes32()
|
||||||
var__5 := zero_t_bytes32_1
|
var__5 := zero_t_bytes32_1
|
||||||
|
|
||||||
|
/// @src 0:138,153
|
||||||
var__5 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32()
|
var__5 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32()
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_11\" {
|
object \"C_11\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,159
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_11\" {
|
|||||||
|
|
||||||
function constructor_C_11() {
|
function constructor_C_11() {
|
||||||
|
|
||||||
|
/// @src 0:78,159
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
object \"C_11_deployed\" {
|
object \"C_11_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,159
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -90,10 +94,14 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5 {
|
function fun_f_10() -> var__5 {
|
||||||
|
/// @src 0:91,157
|
||||||
|
/// @src 0:127,133
|
||||||
let zero_t_bytes4_1 := zero_value_for_split_t_bytes4()
|
let zero_t_bytes4_1 := zero_value_for_split_t_bytes4()
|
||||||
var__5 := zero_t_bytes4_1
|
var__5 := zero_t_bytes4_1
|
||||||
|
|
||||||
|
/// @src 0:144,154
|
||||||
let expr_7 := 0x61626364
|
let expr_7 := 0x61626364
|
||||||
|
/// @src 0:137,154
|
||||||
var__5 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_7)
|
var__5 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_7)
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_11\" {
|
object \"C_11\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,243
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_11\" {
|
|||||||
|
|
||||||
function constructor_C_11() {
|
function constructor_C_11() {
|
||||||
|
|
||||||
|
/// @src 0:78,243
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
object \"C_11_deployed\" {
|
object \"C_11_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,243
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -146,9 +150,12 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5_mpos {
|
function fun_f_10() -> var__5_mpos {
|
||||||
|
/// @src 0:91,241
|
||||||
|
/// @src 0:127,140
|
||||||
let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
|
let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr()
|
||||||
var__5_mpos := zero_t_string_memory_ptr_1_mpos
|
var__5_mpos := zero_t_string_memory_ptr_1_mpos
|
||||||
|
|
||||||
|
/// @src 0:144,238
|
||||||
var__5_mpos := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr()
|
var__5_mpos := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr()
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{"contracts":{"A":{"C":{"ir":"/*******************************************************
|
{"contracts":{"A":{"C":{"ir":"/*=====================================================*
|
||||||
* WARNING *
|
* WARNING *
|
||||||
* Solidity to Yul compilation is still EXPERIMENTAL *
|
* Solidity to Yul compilation is still EXPERIMENTAL *
|
||||||
* It can result in LOSS OF FUNDS or worse *
|
* It can result in LOSS OF FUNDS or worse *
|
||||||
* !USE AT YOUR OWN RISK! *
|
* !USE AT YOUR OWN RISK! *
|
||||||
*******************************************************/
|
*=====================================================*/
|
||||||
|
|
||||||
|
|
||||||
object \"C_11\" {
|
object \"C_11\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,159
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() }
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ object \"C_11\" {
|
|||||||
|
|
||||||
function constructor_C_11() {
|
function constructor_C_11() {
|
||||||
|
|
||||||
|
/// @src 0:78,159
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() {
|
||||||
@ -33,6 +36,7 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
object \"C_11_deployed\" {
|
object \"C_11_deployed\" {
|
||||||
code {
|
code {
|
||||||
|
/// @src 0:78,159
|
||||||
mstore(64, 128)
|
mstore(64, 128)
|
||||||
|
|
||||||
if iszero(lt(calldatasize(), 4))
|
if iszero(lt(calldatasize(), 4))
|
||||||
@ -90,10 +94,14 @@ object \"C_11\" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fun_f_10() -> var__5 {
|
function fun_f_10() -> var__5 {
|
||||||
|
/// @src 0:91,157
|
||||||
|
/// @src 0:127,133
|
||||||
let zero_t_bytes4_1 := zero_value_for_split_t_bytes4()
|
let zero_t_bytes4_1 := zero_value_for_split_t_bytes4()
|
||||||
var__5 := zero_t_bytes4_1
|
var__5 := zero_t_bytes4_1
|
||||||
|
|
||||||
|
/// @src 0:144,154
|
||||||
let expr_7 := 0xaabbccdd
|
let expr_7 := 0xaabbccdd
|
||||||
|
/// @src 0:137,154
|
||||||
var__5 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_7)
|
var__5 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_7)
|
||||||
leave
|
leave
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user