mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Disallow optimizer steps that require SMT if none is available.
This commit is contained in:
parent
9bcc2f1713
commit
bfd3ab23e2
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <libyul/Exceptions.h>
|
#include <libyul/Exceptions.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@ -49,17 +50,41 @@ struct OptimiserStep
|
|||||||
virtual ~OptimiserStep() = default;
|
virtual ~OptimiserStep() = default;
|
||||||
|
|
||||||
virtual void run(OptimiserStepContext&, Block&) const = 0;
|
virtual void run(OptimiserStepContext&, Block&) const = 0;
|
||||||
|
/// @returns non-nullopt if the step cannot be run, for example because it requires
|
||||||
|
/// an SMT solver to be loaded, but none is available. In that case, the string
|
||||||
|
/// contains a human-readable reason.
|
||||||
|
virtual std::optional<std::string> invalidInCurrentEnvironment() const = 0;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Step>
|
template <class Step>
|
||||||
struct OptimiserStepInstance: public OptimiserStep
|
struct OptimiserStepInstance: public OptimiserStep
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
template<typename T>
|
||||||
|
struct HasInvalidInCurrentEnvironmentMethod
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<typename U> static auto test(int) -> decltype(U::invalidInCurrentEnvironment(), std::true_type());
|
||||||
|
template<typename> static std::false_type test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr bool value = decltype(test<T>(0))::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
OptimiserStepInstance(): OptimiserStep{Step::name} {}
|
OptimiserStepInstance(): OptimiserStep{Step::name} {}
|
||||||
void run(OptimiserStepContext& _context, Block& _ast) const override
|
void run(OptimiserStepContext& _context, Block& _ast) const override
|
||||||
{
|
{
|
||||||
Step::run(_context, _ast);
|
Step::run(_context, _ast);
|
||||||
}
|
}
|
||||||
|
std::optional<std::string> invalidInCurrentEnvironment() const override
|
||||||
|
{
|
||||||
|
if constexpr (HasInvalidInCurrentEnvironmentMethod<Step>::value)
|
||||||
|
return Step::invalidInCurrentEnvironment();
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +46,15 @@ void ReasoningBasedSimplifier::run(OptimiserStepContext& _context, Block& _ast)
|
|||||||
ReasoningBasedSimplifier{_context.dialect, ssaVars}(_ast);
|
ReasoningBasedSimplifier{_context.dialect, ssaVars}(_ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<string> ReasoningBasedSimplifier::invalidInCurrentEnvironment()
|
||||||
|
{
|
||||||
|
// SMTLib2 interface is always available, but we would like to have synchronous answers.
|
||||||
|
if (smtutil::SMTPortfolio{}.solvers() <= 1)
|
||||||
|
return string{"No SMT solvers available."};
|
||||||
|
else
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void ReasoningBasedSimplifier::operator()(VariableDeclaration& _varDecl)
|
void ReasoningBasedSimplifier::operator()(VariableDeclaration& _varDecl)
|
||||||
{
|
{
|
||||||
if (_varDecl.variables.size() != 1 || !_varDecl.value)
|
if (_varDecl.variables.size() != 1 || !_varDecl.value)
|
||||||
|
@ -51,6 +51,7 @@ class ReasoningBasedSimplifier: public ASTModifier
|
|||||||
public:
|
public:
|
||||||
static constexpr char const* name{"ReasoningBasedSimplifier"};
|
static constexpr char const* name{"ReasoningBasedSimplifier"};
|
||||||
static void run(OptimiserStepContext& _context, Block& _ast);
|
static void run(OptimiserStepContext& _context, Block& _ast);
|
||||||
|
static std::optional<std::string> invalidInCurrentEnvironment();
|
||||||
|
|
||||||
using ASTModifier::operator();
|
using ASTModifier::operator();
|
||||||
void operator()(VariableDeclaration& _varDecl) override;
|
void operator()(VariableDeclaration& _varDecl) override;
|
||||||
|
@ -269,6 +269,7 @@ void OptimiserSuite::validateSequence(string const& _stepAbbreviations)
|
|||||||
insideLoop = false;
|
insideLoop = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
yulAssert(
|
yulAssert(
|
||||||
string(NonStepAbbreviations).find(abbreviation) == string::npos,
|
string(NonStepAbbreviations).find(abbreviation) == string::npos,
|
||||||
"Unhandled syntactic element in the abbreviation sequence"
|
"Unhandled syntactic element in the abbreviation sequence"
|
||||||
@ -278,6 +279,14 @@ void OptimiserSuite::validateSequence(string const& _stepAbbreviations)
|
|||||||
OptimizerException,
|
OptimizerException,
|
||||||
"'"s + abbreviation + "' is not a valid step abbreviation"
|
"'"s + abbreviation + "' is not a valid step abbreviation"
|
||||||
);
|
);
|
||||||
|
optional<string> invalid = allSteps().at(stepAbbreviationToNameMap().at(abbreviation))->invalidInCurrentEnvironment();
|
||||||
|
assertThrow(
|
||||||
|
!invalid.has_value(),
|
||||||
|
OptimizerException,
|
||||||
|
"'"s + abbreviation + "' is invalid in the current environment: " + *invalid
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assertThrow(!insideLoop, OptimizerException, "Unbalanced brackets");
|
assertThrow(!insideLoop, OptimizerException, "Unbalanced brackets");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user