mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8095 from ethereum/develop
Merge develop into release for 0.6.1
This commit is contained in:
commit
e6f7d5a492
@ -10,7 +10,7 @@ include(EthPolicy)
|
||||
eth_policy()
|
||||
|
||||
# project name and version should be set after cmake_policy CMP0048
|
||||
set(PROJECT_VERSION "0.6.0")
|
||||
set(PROJECT_VERSION "0.6.1")
|
||||
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
|
||||
|
||||
include(TestBigEndian)
|
||||
|
13
Changelog.md
13
Changelog.md
@ -1,3 +1,9 @@
|
||||
### 0.6.1 (2020-01-02)
|
||||
|
||||
Bugfixes:
|
||||
* Yul Optimizer: Fix bug in redundant assignment remover in combination with break and continue statements.
|
||||
|
||||
|
||||
### 0.6.0 (2019-12-17)
|
||||
|
||||
Breaking changes:
|
||||
@ -33,6 +39,7 @@ Language Features:
|
||||
* Allow global enums and structs.
|
||||
* Allow public variables to override external functions.
|
||||
* Allow underscores as delimiters in hex strings.
|
||||
* Allow to react on failing external calls using ``try`` and ``catch``.
|
||||
* Introduce syntax for array slices and implement them for dynamic calldata arrays.
|
||||
* Introduce ``push()`` for dynamic storage arrays. It returns a reference to the newly allocated element, if applicable.
|
||||
* Introduce ``virtual`` and ``override`` keywords.
|
||||
@ -45,6 +52,12 @@ Compiler Features:
|
||||
* ABIEncoderV2: Do not warn about enabled ABIEncoderV2 anymore (the pragma is still needed, though).
|
||||
|
||||
|
||||
### 0.5.16 (2020-01-02)
|
||||
|
||||
Backported Bugfixes:
|
||||
* Yul Optimizer: Fix bug in redundant assignment remover in combination with break and continue statements.
|
||||
|
||||
|
||||
### 0.5.15 (2019-12-17)
|
||||
|
||||
Bugfixes:
|
||||
|
@ -1,4 +1,26 @@
|
||||
[
|
||||
{
|
||||
"name": "YulOptimizerRedundantAssignmentBreakContinue",
|
||||
"summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.",
|
||||
"description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.",
|
||||
"introduced": "0.6.0",
|
||||
"fixed": "0.6.1",
|
||||
"severity": "medium",
|
||||
"conditions": {
|
||||
"yulOptimizer": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
"summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.",
|
||||
"description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.",
|
||||
"introduced": "0.5.8",
|
||||
"fixed": "0.5.16",
|
||||
"severity": "low",
|
||||
"conditions": {
|
||||
"yulOptimizer": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ABIEncoderV2LoopYulOptimizer",
|
||||
"summary": "If both the experimental ABIEncoderV2 and the experimental Yul optimizer are activated, one component of the Yul optimizer may reuse data in memory that has been changed in the meantime.",
|
||||
|
@ -742,32 +742,46 @@
|
||||
},
|
||||
"0.5.10": {
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers"
|
||||
],
|
||||
"released": "2019-06-25"
|
||||
},
|
||||
"0.5.11": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
],
|
||||
"released": "2019-08-12"
|
||||
},
|
||||
"0.5.12": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
],
|
||||
"released": "2019-10-01"
|
||||
},
|
||||
"0.5.13": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
],
|
||||
"released": "2019-11-14"
|
||||
},
|
||||
"0.5.14": {
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
"ABIEncoderV2LoopYulOptimizer"
|
||||
],
|
||||
"released": "2019-12-09"
|
||||
},
|
||||
"0.5.15": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5"
|
||||
],
|
||||
"released": "2019-12-17"
|
||||
},
|
||||
"0.5.16": {
|
||||
"bugs": [],
|
||||
"released": "2020-01-02"
|
||||
},
|
||||
"0.5.2": {
|
||||
"bugs": [
|
||||
"SignedArrayStorageCopy",
|
||||
@ -840,6 +854,7 @@
|
||||
},
|
||||
"0.5.8": {
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
|
||||
"SignedArrayStorageCopy",
|
||||
"ABIEncoderV2StorageArrayWithMultiSlotElement",
|
||||
@ -849,6 +864,7 @@
|
||||
},
|
||||
"0.5.9": {
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue0.5",
|
||||
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
|
||||
"SignedArrayStorageCopy",
|
||||
"ABIEncoderV2StorageArrayWithMultiSlotElement"
|
||||
@ -856,7 +872,13 @@
|
||||
"released": "2019-05-28"
|
||||
},
|
||||
"0.6.0": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"YulOptimizerRedundantAssignmentBreakContinue"
|
||||
],
|
||||
"released": "2019-12-17"
|
||||
},
|
||||
"0.6.1": {
|
||||
"bugs": [],
|
||||
"released": "2020-01-02"
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ Solidity Integrations
|
||||
* `Solidity IDE <https://github.com/System-Glitch/Solidity-IDE>`_
|
||||
Browser-based IDE with integrated compiler, Ganache and local file system support.
|
||||
|
||||
* `Solium <https://github.com/duaraghav8/Solium/>`_
|
||||
* `Ethlint <https://github.com/duaraghav8/Ethlint>`_
|
||||
Linter to identify and fix style and security issues in Solidity.
|
||||
|
||||
* `Superblocks Lab <https://lab.superblocks.com/>`_
|
||||
@ -48,7 +48,7 @@ Solidity Integrations
|
||||
Plugin for the Atom editor that provides Solidity linting.
|
||||
|
||||
* `Atom Solium Linter <https://atom.io/packages/linter-solium>`_
|
||||
Configurable Solidty linter for Atom using Solium as a base.
|
||||
Configurable Solidity linter for Atom using Solium (now Ethlint) as a base.
|
||||
|
||||
* Eclipse:
|
||||
|
||||
|
@ -639,7 +639,7 @@ void DeclarationRegistrationHelper::endVisit(FunctionDefinition&)
|
||||
|
||||
bool DeclarationRegistrationHelper::visit(TryCatchClause& _tryCatchClause)
|
||||
{
|
||||
_tryCatchClause.setScope(m_currentScope);
|
||||
_tryCatchClause.annotation().scope = m_currentScope;
|
||||
enterNewSubScope(_tryCatchClause);
|
||||
return true;
|
||||
}
|
||||
@ -675,7 +675,7 @@ void DeclarationRegistrationHelper::endVisit(FunctionTypeName&)
|
||||
|
||||
bool DeclarationRegistrationHelper::visit(Block& _block)
|
||||
{
|
||||
_block.setScope(m_currentScope);
|
||||
_block.annotation().scope = m_currentScope;
|
||||
enterNewSubScope(_block);
|
||||
return true;
|
||||
}
|
||||
@ -687,7 +687,7 @@ void DeclarationRegistrationHelper::endVisit(Block&)
|
||||
|
||||
bool DeclarationRegistrationHelper::visit(ForStatement& _for)
|
||||
{
|
||||
_for.setScope(m_currentScope);
|
||||
_for.annotation().scope = m_currentScope;
|
||||
enterNewSubScope(_for);
|
||||
return true;
|
||||
}
|
||||
@ -761,7 +761,7 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
||||
|
||||
registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, warnAboutShadowing, inactive, m_errorReporter);
|
||||
|
||||
_declaration.setScope(m_currentScope);
|
||||
_declaration.annotation().scope = m_currentScope;
|
||||
if (_opensScope)
|
||||
enterNewSubScope(_declaration);
|
||||
}
|
||||
|
@ -43,10 +43,6 @@ public:
|
||||
m_dialect(_dialect),
|
||||
m_reportMutability(_reportMutability) {}
|
||||
|
||||
void operator()(yul::Instruction const& _instruction)
|
||||
{
|
||||
checkInstruction(_instruction.location, _instruction.instruction);
|
||||
}
|
||||
void operator()(yul::Literal const&) {}
|
||||
void operator()(yul::Identifier const&) {}
|
||||
void operator()(yul::ExpressionStatement const& _expr)
|
||||
|
@ -449,6 +449,13 @@ string Scopable::sourceUnitName() const
|
||||
return sourceUnit().annotation().path;
|
||||
}
|
||||
|
||||
DeclarationAnnotation& Declaration::annotation() const
|
||||
{
|
||||
if (!m_annotation)
|
||||
m_annotation = make_unique<DeclarationAnnotation>();
|
||||
return dynamic_cast<DeclarationAnnotation&>(*m_annotation);
|
||||
}
|
||||
|
||||
bool VariableDeclaration::isLValue() const
|
||||
{
|
||||
// Constant declared variables are Read-Only
|
||||
@ -653,6 +660,27 @@ InlineAssemblyAnnotation& InlineAssembly::annotation() const
|
||||
return dynamic_cast<InlineAssemblyAnnotation&>(*m_annotation);
|
||||
}
|
||||
|
||||
BlockAnnotation& Block::annotation() const
|
||||
{
|
||||
if (!m_annotation)
|
||||
m_annotation = make_unique<BlockAnnotation>();
|
||||
return dynamic_cast<BlockAnnotation&>(*m_annotation);
|
||||
}
|
||||
|
||||
TryCatchClauseAnnotation& TryCatchClause::annotation() const
|
||||
{
|
||||
if (!m_annotation)
|
||||
m_annotation = make_unique<TryCatchClauseAnnotation>();
|
||||
return dynamic_cast<TryCatchClauseAnnotation&>(*m_annotation);
|
||||
}
|
||||
|
||||
ForStatementAnnotation& ForStatement::annotation() const
|
||||
{
|
||||
if (!m_annotation)
|
||||
m_annotation = make_unique<ForStatementAnnotation>();
|
||||
return dynamic_cast<ForStatementAnnotation&>(*m_annotation);
|
||||
}
|
||||
|
||||
ReturnAnnotation& Return::annotation() const
|
||||
{
|
||||
if (!m_annotation)
|
||||
|
@ -159,8 +159,7 @@ public:
|
||||
virtual ~Scopable() = default;
|
||||
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
|
||||
/// Available only after name and type resolution step.
|
||||
ASTNode const* scope() const { return m_scope; }
|
||||
void setScope(ASTNode const* _scope) { m_scope = _scope; }
|
||||
ASTNode const* scope() const { return annotation().scope; }
|
||||
|
||||
/// @returns the source unit this scopable is present in.
|
||||
SourceUnit const& sourceUnit() const;
|
||||
@ -172,8 +171,7 @@ public:
|
||||
/// Can be combined with annotation().canonicalName (if present) to form a globally unique name.
|
||||
std::string sourceUnitName() const;
|
||||
|
||||
protected:
|
||||
ASTNode const* m_scope = nullptr;
|
||||
virtual ScopableAnnotation& annotation() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -231,6 +229,8 @@ public:
|
||||
/// @returns null when it is not accessible as a function.
|
||||
virtual FunctionTypePointer functionType(bool /*_internal*/) const { return {}; }
|
||||
|
||||
DeclarationAnnotation& annotation() const override;
|
||||
|
||||
protected:
|
||||
virtual Visibility defaultVisibility() const { return Visibility::Public; }
|
||||
|
||||
@ -1169,6 +1169,8 @@ public:
|
||||
|
||||
std::vector<ASTPointer<Statement>> const& statements() const { return m_statements; }
|
||||
|
||||
BlockAnnotation& annotation() const override;
|
||||
|
||||
private:
|
||||
std::vector<ASTPointer<Statement>> m_statements;
|
||||
};
|
||||
@ -1248,6 +1250,8 @@ public:
|
||||
ParameterList const* parameters() const { return m_parameters.get(); }
|
||||
Block const& block() const { return *m_block; }
|
||||
|
||||
TryCatchClauseAnnotation& annotation() const override;
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_errorName;
|
||||
ASTPointer<ParameterList> m_parameters;
|
||||
@ -1357,6 +1361,8 @@ public:
|
||||
ExpressionStatement const* loopExpression() const { return m_loopExpression.get(); }
|
||||
Statement const& body() const { return *m_body; }
|
||||
|
||||
ForStatementAnnotation& annotation() const override;
|
||||
|
||||
private:
|
||||
/// For statement's initialization expression. for (XXX; ; ). Can be empty
|
||||
ASTPointer<Statement> m_initExpression;
|
||||
|
@ -75,7 +75,18 @@ struct SourceUnitAnnotation: ASTAnnotation
|
||||
std::set<ExperimentalFeature> experimentalFeatures;
|
||||
};
|
||||
|
||||
struct ImportAnnotation: ASTAnnotation
|
||||
struct ScopableAnnotation
|
||||
{
|
||||
/// The scope this declaration resides in. Can be nullptr if it is the global scope.
|
||||
/// Available only after name and type resolution step.
|
||||
ASTNode const* scope = nullptr;
|
||||
};
|
||||
|
||||
struct DeclarationAnnotation: ASTAnnotation, ScopableAnnotation
|
||||
{
|
||||
};
|
||||
|
||||
struct ImportAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// The absolute path of the source unit to import.
|
||||
std::string absolutePath;
|
||||
@ -83,7 +94,7 @@ struct ImportAnnotation: ASTAnnotation
|
||||
SourceUnit const* sourceUnit = nullptr;
|
||||
};
|
||||
|
||||
struct TypeDeclarationAnnotation: ASTAnnotation
|
||||
struct TypeDeclarationAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// The name of this type, prefixed by proper namespaces if globally accessible.
|
||||
std::string canonicalName;
|
||||
@ -104,7 +115,7 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, DocumentedAnnota
|
||||
std::map<FunctionDefinition const*, ASTNode const*> baseConstructorArguments;
|
||||
};
|
||||
|
||||
struct CallableDeclarationAnnotation: ASTAnnotation
|
||||
struct CallableDeclarationAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// The set of functions/modifiers/events this callable overrides.
|
||||
std::set<CallableDeclaration const*> baseFunctions;
|
||||
@ -124,7 +135,7 @@ struct ModifierDefinitionAnnotation: CallableDeclarationAnnotation, DocumentedAn
|
||||
{
|
||||
};
|
||||
|
||||
struct VariableDeclarationAnnotation: ASTAnnotation
|
||||
struct VariableDeclarationAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// Type of variable (type of identifier referencing this variable).
|
||||
TypePointer type = nullptr;
|
||||
@ -152,6 +163,18 @@ struct InlineAssemblyAnnotation: StatementAnnotation
|
||||
std::shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
|
||||
};
|
||||
|
||||
struct BlockAnnotation: StatementAnnotation, ScopableAnnotation
|
||||
{
|
||||
};
|
||||
|
||||
struct TryCatchClauseAnnotation: ASTAnnotation, ScopableAnnotation
|
||||
{
|
||||
};
|
||||
|
||||
struct ForStatementAnnotation: StatementAnnotation, ScopableAnnotation
|
||||
{
|
||||
};
|
||||
|
||||
struct ReturnAnnotation: StatementAnnotation
|
||||
{
|
||||
/// Reference to the return parameters of the function.
|
||||
|
@ -51,10 +51,6 @@
|
||||
|
||||
#include <libyul/YulString.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/backends/wasm/EVMToEWasmTranslator.h>
|
||||
#include <libyul/backends/wasm/EWasmObjectCompiler.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
|
||||
#include <liblangutil/Scanner.h>
|
||||
@ -81,7 +77,7 @@ CompilerStack::CompilerStack(ReadCallback::Callback const& _readFile):
|
||||
m_readFile{_readFile},
|
||||
m_enabledSMTSolvers{smt::SMTSolverChoice::All()},
|
||||
m_generateIR{false},
|
||||
m_generateEWasm{false},
|
||||
m_generateEwasm{false},
|
||||
m_errorList{},
|
||||
m_errorReporter{m_errorList}
|
||||
{
|
||||
@ -204,7 +200,7 @@ void CompilerStack::reset(bool _keepSettings)
|
||||
m_evmVersion = langutil::EVMVersion();
|
||||
m_enabledSMTSolvers = smt::SMTSolverChoice::All();
|
||||
m_generateIR = false;
|
||||
m_generateEWasm = false;
|
||||
m_generateEwasm = false;
|
||||
m_revertStrings = RevertStrings::Default;
|
||||
m_optimiserSettings = OptimiserSettings::minimal();
|
||||
m_metadataLiteralSources = false;
|
||||
@ -467,10 +463,10 @@ bool CompilerStack::compile()
|
||||
if (isRequestedContract(*contract))
|
||||
{
|
||||
compileContract(*contract, otherCompilers);
|
||||
if (m_generateIR || m_generateEWasm)
|
||||
if (m_generateIR || m_generateEwasm)
|
||||
generateIR(*contract);
|
||||
if (m_generateEWasm)
|
||||
generateEWasm(*contract);
|
||||
if (m_generateEwasm)
|
||||
generateEwasm(*contract);
|
||||
}
|
||||
m_stackState = CompilationSuccessful;
|
||||
this->link();
|
||||
@ -596,20 +592,20 @@ string const& CompilerStack::yulIROptimized(string const& _contractName) const
|
||||
return contract(_contractName).yulIROptimized;
|
||||
}
|
||||
|
||||
string const& CompilerStack::eWasm(string const& _contractName) const
|
||||
string const& CompilerStack::ewasm(string const& _contractName) const
|
||||
{
|
||||
if (m_stackState != CompilationSuccessful)
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
return contract(_contractName).eWasm;
|
||||
return contract(_contractName).ewasm;
|
||||
}
|
||||
|
||||
eth::LinkerObject const& CompilerStack::eWasmObject(string const& _contractName) const
|
||||
eth::LinkerObject const& CompilerStack::ewasmObject(string const& _contractName) const
|
||||
{
|
||||
if (m_stackState != CompilationSuccessful)
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
return contract(_contractName).eWasmObject;
|
||||
return contract(_contractName).ewasmObject;
|
||||
}
|
||||
|
||||
eth::LinkerObject const& CompilerStack::object(string const& _contractName) const
|
||||
@ -1073,15 +1069,15 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
|
||||
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(_contract);
|
||||
}
|
||||
|
||||
void CompilerStack::generateEWasm(ContractDefinition const& _contract)
|
||||
void CompilerStack::generateEwasm(ContractDefinition const& _contract)
|
||||
{
|
||||
solAssert(m_stackState >= AnalysisPerformed, "");
|
||||
if (m_hasError)
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateEWasm with errors."));
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateEwasm with errors."));
|
||||
|
||||
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
||||
solAssert(!compiledContract.yulIROptimized.empty(), "");
|
||||
if (!compiledContract.eWasm.empty())
|
||||
if (!compiledContract.ewasm.empty())
|
||||
return;
|
||||
|
||||
// Re-parse the Yul IR in EVM dialect
|
||||
@ -1089,15 +1085,15 @@ void CompilerStack::generateEWasm(ContractDefinition const& _contract)
|
||||
stack.parseAndAnalyze("", compiledContract.yulIROptimized);
|
||||
|
||||
stack.optimize();
|
||||
stack.translate(yul::AssemblyStack::Language::EWasm);
|
||||
stack.translate(yul::AssemblyStack::Language::Ewasm);
|
||||
stack.optimize();
|
||||
|
||||
//cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl;
|
||||
|
||||
// Turn into eWasm text representation.
|
||||
auto result = stack.assemble(yul::AssemblyStack::Machine::eWasm);
|
||||
compiledContract.eWasm = std::move(result.assembly);
|
||||
compiledContract.eWasmObject = std::move(*result.bytecode);
|
||||
// Turn into Ewasm text representation.
|
||||
auto result = stack.assemble(yul::AssemblyStack::Machine::Ewasm);
|
||||
compiledContract.ewasm = std::move(result.assembly);
|
||||
compiledContract.ewasmObject = std::move(*result.bytecode);
|
||||
}
|
||||
|
||||
CompilerStack::Contract const& CompilerStack::contract(string const& _contractName) const
|
||||
|
@ -178,8 +178,8 @@ public:
|
||||
/// Enable experimental generation of Yul IR code.
|
||||
void enableIRGeneration(bool _enable = true) { m_generateIR = _enable; }
|
||||
|
||||
/// Enable experimental generation of eWasm code. If enabled, IR is also generated.
|
||||
void enableEWasmGeneration(bool _enable = true) { m_generateEWasm = _enable; }
|
||||
/// Enable experimental generation of Ewasm code. If enabled, IR is also generated.
|
||||
void enableEwasmGeneration(bool _enable = true) { m_generateEwasm = _enable; }
|
||||
|
||||
/// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata.
|
||||
/// Must be set before parsing.
|
||||
@ -251,11 +251,11 @@ public:
|
||||
/// @returns the optimized IR representation of a contract.
|
||||
std::string const& yulIROptimized(std::string const& _contractName) const;
|
||||
|
||||
/// @returns the eWasm text representation of a contract.
|
||||
std::string const& eWasm(std::string const& _contractName) const;
|
||||
/// @returns the Ewasm text representation of a contract.
|
||||
std::string const& ewasm(std::string const& _contractName) const;
|
||||
|
||||
/// @returns the eWasm representation of a contract.
|
||||
eth::LinkerObject const& eWasmObject(std::string const& _contractName) const;
|
||||
/// @returns the Ewasm representation of a contract.
|
||||
eth::LinkerObject const& ewasmObject(std::string const& _contractName) const;
|
||||
|
||||
/// @returns the assembled object for a contract.
|
||||
eth::LinkerObject const& object(std::string const& _contractName) const;
|
||||
@ -338,8 +338,8 @@ private:
|
||||
eth::LinkerObject runtimeObject; ///< Runtime object.
|
||||
std::string yulIR; ///< Experimental Yul IR code.
|
||||
std::string yulIROptimized; ///< Optimized experimental Yul IR code.
|
||||
std::string eWasm; ///< Experimental eWasm text representation
|
||||
eth::LinkerObject eWasmObject; ///< Experimental eWasm code
|
||||
std::string ewasm; ///< Experimental Ewasm text representation
|
||||
eth::LinkerObject ewasmObject; ///< Experimental Ewasm code
|
||||
mutable std::unique_ptr<std::string const> metadata; ///< The metadata json that will be hashed into the chain.
|
||||
mutable std::unique_ptr<Json::Value const> abi;
|
||||
mutable std::unique_ptr<Json::Value const> storageLayout;
|
||||
@ -374,8 +374,8 @@ private:
|
||||
/// The IR is stored but otherwise unused.
|
||||
void generateIR(ContractDefinition const& _contract);
|
||||
|
||||
/// Generate eWasm representation for a single contract.
|
||||
void generateEWasm(ContractDefinition const& _contract);
|
||||
/// Generate Ewasm representation for a single contract.
|
||||
void generateEwasm(ContractDefinition const& _contract);
|
||||
|
||||
/// Links all the known library addresses in the available objects. Any unknown
|
||||
/// library will still be kept as an unlinked placeholder in the objects.
|
||||
@ -436,7 +436,7 @@ private:
|
||||
smt::SMTSolverChoice m_enabledSMTSolvers;
|
||||
std::map<std::string, std::set<std::string>> m_requestedContractNames;
|
||||
bool m_generateIR;
|
||||
bool m_generateEWasm;
|
||||
bool m_generateEwasm;
|
||||
std::map<std::string, h160> m_libraries;
|
||||
/// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum
|
||||
/// "context:prefix=target"
|
||||
|
@ -247,9 +247,9 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @returns true if any eWasm code was requested. Note that as an exception, '*' does not
|
||||
/// @returns true if any Ewasm code was requested. Note that as an exception, '*' does not
|
||||
/// yet match "ewasm.wast" or "ewasm"
|
||||
bool isEWasmRequested(Json::Value const& _outputSelection)
|
||||
bool isEwasmRequested(Json::Value const& _outputSelection)
|
||||
{
|
||||
if (!_outputSelection.isObject())
|
||||
return false;
|
||||
@ -267,7 +267,7 @@ bool isEWasmRequested(Json::Value const& _outputSelection)
|
||||
/// yet match "ir" or "irOptimized"
|
||||
bool isIRRequested(Json::Value const& _outputSelection)
|
||||
{
|
||||
if (isEWasmRequested(_outputSelection))
|
||||
if (isEwasmRequested(_outputSelection))
|
||||
return true;
|
||||
|
||||
if (!_outputSelection.isObject())
|
||||
@ -780,7 +780,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
|
||||
compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection));
|
||||
|
||||
compilerStack.enableEWasmGeneration(isEWasmRequested(_inputsAndSettings.outputSelection));
|
||||
compilerStack.enableEwasmGeneration(isEwasmRequested(_inputsAndSettings.outputSelection));
|
||||
|
||||
Json::Value errors = std::move(_inputsAndSettings.errors);
|
||||
|
||||
@ -956,11 +956,11 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimized", wildcardMatchesExperimental))
|
||||
contractData["irOptimized"] = compilerStack.yulIROptimized(contractName);
|
||||
|
||||
// eWasm
|
||||
// Ewasm
|
||||
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wast", wildcardMatchesExperimental))
|
||||
contractData["ewasm"]["wast"] = compilerStack.eWasm(contractName);
|
||||
contractData["ewasm"]["wast"] = compilerStack.ewasm(contractName);
|
||||
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wasm", wildcardMatchesExperimental))
|
||||
contractData["ewasm"]["wasm"] = compilerStack.eWasmObject(contractName).toHex();
|
||||
contractData["ewasm"]["wasm"] = compilerStack.ewasmObject(contractName).toHex();
|
||||
|
||||
// EVM
|
||||
Json::Value evmData(Json::objectValue);
|
||||
|
@ -86,16 +86,6 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect,
|
||||
return analysisInfo;
|
||||
}
|
||||
|
||||
bool AsmAnalyzer::operator()(yul::Instruction const& _instruction)
|
||||
{
|
||||
yulAssert(false, "The use of non-functional instructions is disallowed. Please use functional notation instead.");
|
||||
auto const& info = instructionInfo(_instruction.instruction);
|
||||
m_stackHeight += info.ret - info.args;
|
||||
m_info.stackHeightInfo[&_instruction] = m_stackHeight;
|
||||
warnOnInstructions(_instruction.instruction, _instruction.location);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AsmAnalyzer::operator()(Literal const& _literal)
|
||||
{
|
||||
expectValidType(_literal.type.str(), _literal.location);
|
||||
|
@ -77,7 +77,6 @@ public:
|
||||
/// Asserts on failure.
|
||||
static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object);
|
||||
|
||||
bool operator()(Instruction const&);
|
||||
bool operator()(Literal const& _literal);
|
||||
bool operator()(Identifier const&);
|
||||
bool operator()(ExpressionStatement const&);
|
||||
|
@ -25,12 +25,8 @@
|
||||
#include <libyul/AsmDataForward.h>
|
||||
#include <libyul/YulString.h>
|
||||
|
||||
#include <libevmasm/Instruction.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace yul
|
||||
@ -41,8 +37,6 @@ using Type = YulString;
|
||||
struct TypedName { langutil::SourceLocation location; YulString name; Type type; };
|
||||
using TypedNameList = std::vector<TypedName>;
|
||||
|
||||
/// Direct EVM instruction (except PUSHi and JUMPDEST)
|
||||
struct Instruction { langutil::SourceLocation location; dev::eth::Instruction instruction; };
|
||||
/// Literal number or string (up to 32 bytes)
|
||||
enum class LiteralKind { Number, Boolean, String };
|
||||
struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; };
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/ParserBase.h>
|
||||
|
||||
#include <libevmasm/Instruction.h>
|
||||
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
@ -56,7 +58,7 @@ public:
|
||||
static std::map<std::string, dev::eth::Instruction> const& instructions();
|
||||
|
||||
protected:
|
||||
using ElementaryOperation = std::variant<Instruction, Literal, Identifier, FunctionCall>;
|
||||
using ElementaryOperation = std::variant<Literal, Identifier, FunctionCall>;
|
||||
|
||||
/// Creates an inline assembly node with the given source location.
|
||||
template <class T> T createWithLocation(langutil::SourceLocation const& _loc = {}) const
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
/**
|
||||
* Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 and
|
||||
* eWasm as output.
|
||||
* Ewasm as output.
|
||||
*/
|
||||
|
||||
|
||||
@ -33,8 +33,8 @@
|
||||
#include <libyul/backends/evm/EVMObjectCompiler.h>
|
||||
#include <libyul/backends/evm/EVMMetrics.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
#include <libyul/backends/wasm/EWasmObjectCompiler.h>
|
||||
#include <libyul/backends/wasm/EVMToEWasmTranslator.h>
|
||||
#include <libyul/backends/wasm/WasmObjectCompiler.h>
|
||||
#include <libyul/backends/wasm/EVMToEwasmTranslator.h>
|
||||
#include <libyul/optimiser/Metrics.h>
|
||||
#include <libyul/ObjectParser.h>
|
||||
#include <libyul/optimiser/Suite.h>
|
||||
@ -59,7 +59,7 @@ Dialect const& languageToDialect(AssemblyStack::Language _language, EVMVersion _
|
||||
return EVMDialect::strictAssemblyForEVMObjects(_version);
|
||||
case AssemblyStack::Language::Yul:
|
||||
return Dialect::yul();
|
||||
case AssemblyStack::Language::EWasm:
|
||||
case AssemblyStack::Language::Ewasm:
|
||||
return WasmDialect::instance();
|
||||
}
|
||||
yulAssert(false, "");
|
||||
@ -108,11 +108,11 @@ void AssemblyStack::translate(AssemblyStack::Language _targetLanguage)
|
||||
return;
|
||||
|
||||
solAssert(
|
||||
m_language == Language::StrictAssembly && _targetLanguage == Language::EWasm,
|
||||
m_language == Language::StrictAssembly && _targetLanguage == Language::Ewasm,
|
||||
"Invalid language combination"
|
||||
);
|
||||
|
||||
*m_parserResult = EVMToEWasmTranslator(
|
||||
*m_parserResult = EVMToEwasmTranslator(
|
||||
languageToDialect(m_language, m_evmVersion)
|
||||
).run(*parserResult());
|
||||
|
||||
@ -214,13 +214,13 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
|
||||
/// TODO: fill out text representation
|
||||
return object;
|
||||
}
|
||||
case Machine::eWasm:
|
||||
case Machine::Ewasm:
|
||||
{
|
||||
yulAssert(m_language == Language::EWasm, "");
|
||||
yulAssert(m_language == Language::Ewasm, "");
|
||||
Dialect const& dialect = languageToDialect(m_language, EVMVersion{});
|
||||
|
||||
MachineAssemblyObject object;
|
||||
auto result = EWasmObjectCompiler::compile(*m_parserResult, dialect);
|
||||
auto result = WasmObjectCompiler::compile(*m_parserResult, dialect);
|
||||
object.assembly = std::move(result.first);
|
||||
object.bytecode = make_shared<dev::eth::LinkerObject>();
|
||||
object.bytecode->bytecode = std::move(result.second);
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
/**
|
||||
* Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 and
|
||||
* eWasm as output.
|
||||
* Ewasm as output.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -52,13 +52,13 @@ struct MachineAssemblyObject
|
||||
|
||||
/*
|
||||
* Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 and
|
||||
* eWasm as output.
|
||||
* Ewasm as output.
|
||||
*/
|
||||
class AssemblyStack
|
||||
{
|
||||
public:
|
||||
enum class Language { Yul, Assembly, StrictAssembly, EWasm };
|
||||
enum class Machine { EVM, EVM15, eWasm };
|
||||
enum class Language { Yul, Assembly, StrictAssembly, Ewasm };
|
||||
enum class Machine { EVM, EVM15, Ewasm };
|
||||
|
||||
AssemblyStack():
|
||||
AssemblyStack(langutil::EVMVersion{}, Language::Assembly, dev::solidity::OptimiserSettings::none())
|
||||
|
@ -44,18 +44,18 @@ add_library(yul
|
||||
backends/evm/EVMMetrics.h
|
||||
backends/evm/NoOutputAssembly.h
|
||||
backends/evm/NoOutputAssembly.cpp
|
||||
backends/wasm/EVMToEWasmTranslator.cpp
|
||||
backends/wasm/EVMToEWasmTranslator.h
|
||||
backends/wasm/EWasmCodeTransform.cpp
|
||||
backends/wasm/EWasmCodeTransform.h
|
||||
backends/wasm/EWasmObjectCompiler.cpp
|
||||
backends/wasm/EWasmObjectCompiler.h
|
||||
backends/wasm/EVMToEwasmTranslator.cpp
|
||||
backends/wasm/EVMToEwasmTranslator.h
|
||||
backends/wasm/BinaryTransform.cpp
|
||||
backends/wasm/BinaryTransform.h
|
||||
backends/wasm/TextTransform.cpp
|
||||
backends/wasm/TextTransform.h
|
||||
backends/wasm/WasmCodeTransform.cpp
|
||||
backends/wasm/WasmCodeTransform.h
|
||||
backends/wasm/WasmDialect.cpp
|
||||
backends/wasm/WasmDialect.h
|
||||
backends/wasm/WasmObjectCompiler.cpp
|
||||
backends/wasm/WasmObjectCompiler.h
|
||||
backends/wasm/WordSizeTransform.cpp
|
||||
backends/wasm/WordSizeTransform.h
|
||||
optimiser/ASTCopier.cpp
|
||||
|
@ -43,7 +43,6 @@ enum class Instruction: uint8_t;
|
||||
|
||||
namespace yul
|
||||
{
|
||||
struct Instruction;
|
||||
struct Identifier;
|
||||
|
||||
///
|
||||
|
@ -350,16 +350,6 @@ void CodeTransform::operator()(Literal const& _literal)
|
||||
checkStackHeight(&_literal);
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(yul::Instruction const& _instruction)
|
||||
{
|
||||
yulAssert(!m_allowStackOpt, "");
|
||||
yulAssert(!m_evm15 || _instruction.instruction != dev::eth::Instruction::JUMP, "Bare JUMP instruction used for EVM1.5");
|
||||
yulAssert(!m_evm15 || _instruction.instruction != dev::eth::Instruction::JUMPI, "Bare JUMPI instruction used for EVM1.5");
|
||||
m_assembly.setSourceLocation(_instruction.location);
|
||||
m_assembly.appendInstruction(_instruction.instruction);
|
||||
checkStackHeight(&_instruction);
|
||||
}
|
||||
|
||||
void CodeTransform::operator()(If const& _if)
|
||||
{
|
||||
visitExpression(*_if.condition);
|
||||
|
@ -170,7 +170,6 @@ protected:
|
||||
void deleteVariable(Scope::Variable const& _var);
|
||||
|
||||
public:
|
||||
void operator()(Instruction const& _instruction);
|
||||
void operator()(Literal const& _literal);
|
||||
void operator()(Identifier const& _identifier);
|
||||
void operator()(FunctionCall const&);
|
||||
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* EWasm to binary encoder.
|
||||
* Component that transforms internal Wasm representation to binary.
|
||||
*/
|
||||
|
||||
#include <libyul/backends/wasm/BinaryTransform.h>
|
||||
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* EWasm to binary encoder.
|
||||
* Component that transforms internal Wasm representation to binary.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -15,10 +15,10 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Translates Yul code from EVM dialect to eWasm dialect.
|
||||
* Translates Yul code from EVM dialect to Ewasm dialect.
|
||||
*/
|
||||
|
||||
#include <libyul/backends/wasm/EVMToEWasmTranslator.h>
|
||||
#include <libyul/backends/wasm/EVMToEwasmTranslator.h>
|
||||
|
||||
#include <libyul/backends/wasm/WordSizeTransform.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
@ -138,6 +138,10 @@ function div(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
r4 := i64.div_u(x4, y4)
|
||||
}
|
||||
function sdiv(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
unreachable()
|
||||
}
|
||||
function mod(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
r4 := i64.rem_u(x4, y4)
|
||||
@ -318,11 +322,11 @@ function sar(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
}
|
||||
function addmod(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
function addmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
}
|
||||
function mulmod(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
function mulmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
}
|
||||
@ -397,8 +401,7 @@ function calldatacopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
|
||||
// Needed?
|
||||
function codesize() -> z1, z2, z3, z4 {
|
||||
eth.getCodeSize(0)
|
||||
z1, z2, z3, z4 := mload_internal(0)
|
||||
z4 := eth.getCodeSize()
|
||||
}
|
||||
function codecopy(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4) {
|
||||
eth.codeCopy(
|
||||
@ -698,7 +701,7 @@ function invalid() {
|
||||
|
||||
}
|
||||
|
||||
Object EVMToEWasmTranslator::run(Object const& _object)
|
||||
Object EVMToEwasmTranslator::run(Object const& _object)
|
||||
{
|
||||
if (!m_polyfill)
|
||||
parsePolyfill();
|
||||
@ -746,7 +749,7 @@ Object EVMToEWasmTranslator::run(Object const& _object)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EVMToEWasmTranslator::parsePolyfill()
|
||||
void EVMToEwasmTranslator::parsePolyfill()
|
||||
{
|
||||
ErrorList errors;
|
||||
ErrorReporter errorReporter(errors);
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Translates Yul code from EVM dialect to eWasm dialect.
|
||||
* Translates Yul code from EVM dialect to Ewasm dialect.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -28,10 +28,10 @@ namespace yul
|
||||
{
|
||||
struct Object;
|
||||
|
||||
class EVMToEWasmTranslator: public ASTModifier
|
||||
class EVMToEwasmTranslator: public ASTModifier
|
||||
{
|
||||
public:
|
||||
EVMToEWasmTranslator(Dialect const& _evmDialect): m_dialect(_evmDialect) {}
|
||||
EVMToEwasmTranslator(Dialect const& _evmDialect): m_dialect(_evmDialect) {}
|
||||
Object run(Object const& _object);
|
||||
|
||||
private:
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Component that transforms interval Wasm representation to text.
|
||||
* Component that transforms internal Wasm representation to text.
|
||||
*/
|
||||
|
||||
#include <libyul/backends/wasm/TextTransform.h>
|
||||
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Component that transforms interval Wasm representation to text.
|
||||
* Component that transforms internal Wasm representation to text.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -15,10 +15,10 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Common code generator for translating Yul / inline assembly to EWasm.
|
||||
* Common code generator for translating Yul / inline assembly to Wasm.
|
||||
*/
|
||||
|
||||
#include <libyul/backends/wasm/EWasmCodeTransform.h>
|
||||
#include <libyul/backends/wasm/WasmCodeTransform.h>
|
||||
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
|
||||
@ -36,11 +36,11 @@ using namespace std;
|
||||
using namespace dev;
|
||||
using namespace yul;
|
||||
|
||||
wasm::Module EWasmCodeTransform::run(Dialect const& _dialect, yul::Block const& _ast)
|
||||
wasm::Module WasmCodeTransform::run(Dialect const& _dialect, yul::Block const& _ast)
|
||||
{
|
||||
wasm::Module module;
|
||||
|
||||
EWasmCodeTransform transform(_dialect, _ast);
|
||||
WasmCodeTransform transform(_dialect, _ast);
|
||||
|
||||
for (auto const& statement: _ast.statements)
|
||||
{
|
||||
@ -59,7 +59,7 @@ wasm::Module EWasmCodeTransform::run(Dialect const& _dialect, yul::Block const&
|
||||
return module;
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::generateMultiAssignment(
|
||||
wasm::Expression WasmCodeTransform::generateMultiAssignment(
|
||||
vector<string> _variableNames,
|
||||
unique_ptr<wasm::Expression> _firstValue
|
||||
)
|
||||
@ -82,7 +82,7 @@ wasm::Expression EWasmCodeTransform::generateMultiAssignment(
|
||||
return { std::move(block) };
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(VariableDeclaration const& _varDecl)
|
||||
wasm::Expression WasmCodeTransform::operator()(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
vector<string> variableNames;
|
||||
for (auto const& var: _varDecl.variables)
|
||||
@ -97,7 +97,7 @@ wasm::Expression EWasmCodeTransform::operator()(VariableDeclaration const& _varD
|
||||
return wasm::BuiltinCall{"nop", {}};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Assignment const& _assignment)
|
||||
wasm::Expression WasmCodeTransform::operator()(Assignment const& _assignment)
|
||||
{
|
||||
vector<string> variableNames;
|
||||
for (auto const& var: _assignment.variableNames)
|
||||
@ -105,12 +105,12 @@ wasm::Expression EWasmCodeTransform::operator()(Assignment const& _assignment)
|
||||
return generateMultiAssignment(move(variableNames), visit(*_assignment.value));
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(ExpressionStatement const& _statement)
|
||||
wasm::Expression WasmCodeTransform::operator()(ExpressionStatement const& _statement)
|
||||
{
|
||||
return visitReturnByValue(_statement.expression);
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(FunctionCall const& _call)
|
||||
wasm::Expression WasmCodeTransform::operator()(FunctionCall const& _call)
|
||||
{
|
||||
bool typeConversionNeeded = false;
|
||||
|
||||
@ -171,19 +171,19 @@ wasm::Expression EWasmCodeTransform::operator()(FunctionCall const& _call)
|
||||
return {std::move(funCall)};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Identifier const& _identifier)
|
||||
wasm::Expression WasmCodeTransform::operator()(Identifier const& _identifier)
|
||||
{
|
||||
return wasm::LocalVariable{_identifier.name.str()};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Literal const& _literal)
|
||||
wasm::Expression WasmCodeTransform::operator()(Literal const& _literal)
|
||||
{
|
||||
u256 value = valueOfLiteral(_literal);
|
||||
yulAssert(value <= numeric_limits<uint64_t>::max(), "Literal too large: " + value.str());
|
||||
return wasm::Literal{uint64_t(value)};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(If const& _if)
|
||||
wasm::Expression WasmCodeTransform::operator()(If const& _if)
|
||||
{
|
||||
// TODO converting i64 to i32 might not always be needed.
|
||||
|
||||
@ -197,7 +197,7 @@ wasm::Expression EWasmCodeTransform::operator()(If const& _if)
|
||||
};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Switch const& _switch)
|
||||
wasm::Expression WasmCodeTransform::operator()(Switch const& _switch)
|
||||
{
|
||||
wasm::Block block;
|
||||
string condition = m_nameDispenser.newName("condition"_yulstring).str();
|
||||
@ -237,13 +237,13 @@ wasm::Expression EWasmCodeTransform::operator()(Switch const& _switch)
|
||||
return { std::move(block) };
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(FunctionDefinition const&)
|
||||
wasm::Expression WasmCodeTransform::operator()(FunctionDefinition const&)
|
||||
{
|
||||
yulAssert(false, "Should not have visited here.");
|
||||
return {};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(ForLoop const& _for)
|
||||
wasm::Expression WasmCodeTransform::operator()(ForLoop const& _for)
|
||||
{
|
||||
string breakLabel = newLabel();
|
||||
string continueLabel = newLabel();
|
||||
@ -262,37 +262,37 @@ wasm::Expression EWasmCodeTransform::operator()(ForLoop const& _for)
|
||||
return { wasm::Block{breakLabel, make_vector<wasm::Expression>(move(loop))} };
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Break const&)
|
||||
wasm::Expression WasmCodeTransform::operator()(Break const&)
|
||||
{
|
||||
return wasm::Break{wasm::Label{m_breakContinueLabelNames.top().first}};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Continue const&)
|
||||
wasm::Expression WasmCodeTransform::operator()(Continue const&)
|
||||
{
|
||||
return wasm::Break{wasm::Label{m_breakContinueLabelNames.top().second}};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Leave const&)
|
||||
wasm::Expression WasmCodeTransform::operator()(Leave const&)
|
||||
{
|
||||
return wasm::Return{};
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::operator()(Block const& _block)
|
||||
wasm::Expression WasmCodeTransform::operator()(Block const& _block)
|
||||
{
|
||||
return wasm::Block{{}, visit(_block.statements)};
|
||||
}
|
||||
|
||||
unique_ptr<wasm::Expression> EWasmCodeTransform::visit(yul::Expression const& _expression)
|
||||
unique_ptr<wasm::Expression> WasmCodeTransform::visit(yul::Expression const& _expression)
|
||||
{
|
||||
return make_unique<wasm::Expression>(std::visit(*this, _expression));
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::visitReturnByValue(yul::Expression const& _expression)
|
||||
wasm::Expression WasmCodeTransform::visitReturnByValue(yul::Expression const& _expression)
|
||||
{
|
||||
return std::visit(*this, _expression);
|
||||
}
|
||||
|
||||
vector<wasm::Expression> EWasmCodeTransform::visit(vector<yul::Expression> const& _expressions)
|
||||
vector<wasm::Expression> WasmCodeTransform::visit(vector<yul::Expression> const& _expressions)
|
||||
{
|
||||
vector<wasm::Expression> ret;
|
||||
for (auto const& e: _expressions)
|
||||
@ -300,12 +300,12 @@ vector<wasm::Expression> EWasmCodeTransform::visit(vector<yul::Expression> const
|
||||
return ret;
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::visit(yul::Statement const& _statement)
|
||||
wasm::Expression WasmCodeTransform::visit(yul::Statement const& _statement)
|
||||
{
|
||||
return std::visit(*this, _statement);
|
||||
}
|
||||
|
||||
vector<wasm::Expression> EWasmCodeTransform::visit(vector<yul::Statement> const& _statements)
|
||||
vector<wasm::Expression> WasmCodeTransform::visit(vector<yul::Statement> const& _statements)
|
||||
{
|
||||
vector<wasm::Expression> ret;
|
||||
for (auto const& s: _statements)
|
||||
@ -313,7 +313,7 @@ vector<wasm::Expression> EWasmCodeTransform::visit(vector<yul::Statement> const&
|
||||
return ret;
|
||||
}
|
||||
|
||||
wasm::FunctionDefinition EWasmCodeTransform::translateFunction(yul::FunctionDefinition const& _fun)
|
||||
wasm::FunctionDefinition WasmCodeTransform::translateFunction(yul::FunctionDefinition const& _fun)
|
||||
{
|
||||
wasm::FunctionDefinition fun;
|
||||
fun.name = _fun.name.str();
|
||||
@ -344,7 +344,7 @@ wasm::FunctionDefinition EWasmCodeTransform::translateFunction(yul::FunctionDefi
|
||||
return fun;
|
||||
}
|
||||
|
||||
wasm::Expression EWasmCodeTransform::injectTypeConversionIfNeeded(wasm::FunctionCall _call) const
|
||||
wasm::Expression WasmCodeTransform::injectTypeConversionIfNeeded(wasm::FunctionCall _call) const
|
||||
{
|
||||
wasm::FunctionImport const& import = m_functionsToImport.at(YulString{_call.functionName});
|
||||
for (size_t i = 0; i < _call.arguments.size(); ++i)
|
||||
@ -361,7 +361,7 @@ wasm::Expression EWasmCodeTransform::injectTypeConversionIfNeeded(wasm::Function
|
||||
return {std::move(_call)};
|
||||
}
|
||||
|
||||
vector<wasm::Expression> EWasmCodeTransform::injectTypeConversionIfNeeded(
|
||||
vector<wasm::Expression> WasmCodeTransform::injectTypeConversionIfNeeded(
|
||||
vector<wasm::Expression> _arguments,
|
||||
vector<Type> const& _parameterTypes
|
||||
) const
|
||||
@ -378,12 +378,12 @@ vector<wasm::Expression> EWasmCodeTransform::injectTypeConversionIfNeeded(
|
||||
return _arguments;
|
||||
}
|
||||
|
||||
string EWasmCodeTransform::newLabel()
|
||||
string WasmCodeTransform::newLabel()
|
||||
{
|
||||
return m_nameDispenser.newName("label_"_yulstring).str();
|
||||
}
|
||||
|
||||
void EWasmCodeTransform::allocateGlobals(size_t _amount)
|
||||
void WasmCodeTransform::allocateGlobals(size_t _amount)
|
||||
{
|
||||
while (m_globalVariables.size() < _amount)
|
||||
m_globalVariables.emplace_back(wasm::GlobalVariableDeclaration{
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Common code generator for translating Yul / inline assembly to EWasm.
|
||||
* Common code generator for translating Yul / inline assembly to Wasm.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -32,7 +32,7 @@ namespace yul
|
||||
{
|
||||
struct AsmAnalysisInfo;
|
||||
|
||||
class EWasmCodeTransform
|
||||
class WasmCodeTransform
|
||||
{
|
||||
public:
|
||||
static wasm::Module run(Dialect const& _dialect, yul::Block const& _ast);
|
||||
@ -54,7 +54,7 @@ public:
|
||||
wasm::Expression operator()(yul::Block const& _block);
|
||||
|
||||
private:
|
||||
EWasmCodeTransform(
|
||||
WasmCodeTransform(
|
||||
Dialect const& _dialect,
|
||||
Block const& _ast
|
||||
):
|
@ -56,10 +56,16 @@ WasmDialect::WasmDialect():
|
||||
addFunction("i64.eqz", 1, 1);
|
||||
m_functions["i64.eqz"_yulstring].returns.front() = "i32"_yulstring;
|
||||
|
||||
addFunction("i64.clz", 1, 1);
|
||||
|
||||
addFunction("i64.store", 2, 0, false);
|
||||
m_functions["i64.store"_yulstring].parameters.front() = "i32"_yulstring;
|
||||
m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
|
||||
addFunction("i64.store8", 2, 0, false);
|
||||
m_functions["i64.store8"_yulstring].parameters.front() = "i32"_yulstring;
|
||||
m_functions["i64.store8"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
|
||||
addFunction("i64.load", 1, 1, false);
|
||||
m_functions["i64.load"_yulstring].parameters.front() = "i32"_yulstring;
|
||||
m_functions["i64.load"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
@ -120,7 +126,7 @@ void WasmDialect::addEthereumExternals()
|
||||
{"getCaller", {i32ptr}, {}},
|
||||
{"getCallValue", {i32ptr}, {}},
|
||||
{"codeCopy", {i32ptr, i32, i32}, {}},
|
||||
{"getCodeSize", {i32ptr}, {}},
|
||||
{"getCodeSize", {}, {i32}},
|
||||
{"getBlockCoinbase", {i32ptr}, {}},
|
||||
{"create", {i32ptr, i32ptr, i32, i32ptr}, {i32}},
|
||||
{"getBlockDifficulty", {i32ptr}, {}},
|
||||
|
@ -18,9 +18,9 @@
|
||||
* Compiler that transforms Yul Objects to Wasm text and binary representation (Ewasm flavoured).
|
||||
*/
|
||||
|
||||
#include <libyul/backends/wasm/EWasmObjectCompiler.h>
|
||||
#include <libyul/backends/wasm/WasmObjectCompiler.h>
|
||||
|
||||
#include <libyul/backends/wasm/EWasmCodeTransform.h>
|
||||
#include <libyul/backends/wasm/WasmCodeTransform.h>
|
||||
#include <libyul/backends/wasm/BinaryTransform.h>
|
||||
#include <libyul/backends/wasm/TextTransform.h>
|
||||
|
||||
@ -32,25 +32,25 @@
|
||||
using namespace yul;
|
||||
using namespace std;
|
||||
|
||||
pair<string, dev::bytes> EWasmObjectCompiler::compile(Object& _object, Dialect const& _dialect)
|
||||
pair<string, dev::bytes> WasmObjectCompiler::compile(Object& _object, Dialect const& _dialect)
|
||||
{
|
||||
EWasmObjectCompiler compiler(_dialect);
|
||||
WasmObjectCompiler compiler(_dialect);
|
||||
wasm::Module module = compiler.run(_object);
|
||||
return {wasm::TextTransform().run(module), wasm::BinaryTransform::run(module)};
|
||||
}
|
||||
|
||||
wasm::Module EWasmObjectCompiler::run(Object& _object)
|
||||
wasm::Module WasmObjectCompiler::run(Object& _object)
|
||||
{
|
||||
yulAssert(_object.analysisInfo, "No analysis info.");
|
||||
yulAssert(_object.code, "No code.");
|
||||
|
||||
wasm::Module module = EWasmCodeTransform::run(m_dialect, *_object.code);
|
||||
wasm::Module module = WasmCodeTransform::run(m_dialect, *_object.code);
|
||||
|
||||
for (auto& subNode: _object.subObjects)
|
||||
if (Object* subObject = dynamic_cast<Object*>(subNode.get()))
|
||||
module.subModules[subObject->name.str()] = run(*subObject);
|
||||
else
|
||||
yulAssert(false, "Data is not yet supported for EWasm.");
|
||||
yulAssert(false, "Data is not yet supported for Wasm.");
|
||||
|
||||
return module;
|
||||
}
|
@ -28,6 +28,7 @@ namespace dev
|
||||
{
|
||||
using bytes = std::vector<uint8_t>;
|
||||
}
|
||||
|
||||
namespace yul
|
||||
{
|
||||
struct Object;
|
||||
@ -37,13 +38,13 @@ namespace wasm
|
||||
struct Module;
|
||||
}
|
||||
|
||||
class EWasmObjectCompiler
|
||||
class WasmObjectCompiler
|
||||
{
|
||||
public:
|
||||
/// Compiles the given object and returns the WAST and the binary representation.
|
||||
/// Compiles the given object and returns the Wasm text and binary representation.
|
||||
static std::pair<std::string, dev::bytes> compile(Object& _object, Dialect const& _dialect);
|
||||
private:
|
||||
EWasmObjectCompiler(Dialect const& _dialect):
|
||||
WasmObjectCompiler(Dialect const& _dialect):
|
||||
m_dialect(_dialect)
|
||||
{}
|
||||
|
@ -280,29 +280,28 @@ void RedundantAssignEliminator::changeUndecidedTo(YulString _variable, Redundant
|
||||
|
||||
void RedundantAssignEliminator::finalize(YulString _variable, RedundantAssignEliminator::State _finalState)
|
||||
{
|
||||
finalize(m_assignments, _variable, _finalState);
|
||||
for (auto& assignments: m_forLoopInfo.pendingBreakStmts)
|
||||
finalize(assignments, _variable, _finalState);
|
||||
for (auto& assignments: m_forLoopInfo.pendingContinueStmts)
|
||||
finalize(assignments, _variable, _finalState);
|
||||
}
|
||||
std::map<Assignment const*, State> assignments;
|
||||
joinMap(assignments, std::move(m_assignments[_variable]), State::join);
|
||||
m_assignments.erase(_variable);
|
||||
|
||||
void RedundantAssignEliminator::finalize(
|
||||
TrackedAssignments& _assignments,
|
||||
YulString _variable,
|
||||
RedundantAssignEliminator::State _finalState
|
||||
)
|
||||
{
|
||||
for (auto const& assignment: _assignments[_variable])
|
||||
for (auto& breakAssignments: m_forLoopInfo.pendingBreakStmts)
|
||||
{
|
||||
joinMap(assignments, std::move(breakAssignments[_variable]), State::join);
|
||||
breakAssignments.erase(_variable);
|
||||
}
|
||||
for (auto& continueAssignments: m_forLoopInfo.pendingContinueStmts)
|
||||
{
|
||||
joinMap(assignments, std::move(continueAssignments[_variable]), State::join);
|
||||
continueAssignments.erase(_variable);
|
||||
}
|
||||
|
||||
for (auto const& assignment: assignments)
|
||||
{
|
||||
State const state = assignment.second == State::Undecided ? _finalState : assignment.second;
|
||||
|
||||
if (state == State::Unused && SideEffectsCollector{*m_dialect, *assignment.first->value}.movable())
|
||||
// TODO the only point where we actually need this
|
||||
// to be a set is for the for loop
|
||||
m_pendingRemovals.insert(assignment.first);
|
||||
}
|
||||
_assignments.erase(_variable);
|
||||
}
|
||||
|
||||
void AssignmentRemover::operator()(Block& _block)
|
||||
|
@ -161,8 +161,6 @@ private:
|
||||
/// assignments to the final state. In this case, this also applies to pending
|
||||
/// break and continue TrackedAssignments.
|
||||
void finalize(YulString _variable, State _finalState);
|
||||
/// Helper function for the above.
|
||||
void finalize(TrackedAssignments& _assignments, YulString _variable, State _finalState);
|
||||
|
||||
Dialect const* m_dialect;
|
||||
std::set<YulString> m_declaredVariables;
|
||||
|
@ -116,7 +116,7 @@ static string const g_strErrorRecovery = "error-recovery";
|
||||
static string const g_strEVM = "evm";
|
||||
static string const g_strEVM15 = "evm15";
|
||||
static string const g_strEVMVersion = "evm-version";
|
||||
static string const g_streWasm = "ewasm";
|
||||
static string const g_strEwasm = "ewasm";
|
||||
static string const g_strGas = "gas";
|
||||
static string const g_strHelp = "help";
|
||||
static string const g_strInputFile = "input-file";
|
||||
@ -125,7 +125,6 @@ static string const g_strYul = "yul";
|
||||
static string const g_strYulDialect = "yul-dialect";
|
||||
static string const g_strIR = "ir";
|
||||
static string const g_strIPFS = "ipfs";
|
||||
static string const g_strEWasm = "ewasm";
|
||||
static string const g_strLicense = "license";
|
||||
static string const g_strLibraries = "libraries";
|
||||
static string const g_strLink = "link";
|
||||
@ -187,7 +186,7 @@ static string const g_argHelp = g_strHelp;
|
||||
static string const g_argInputFile = g_strInputFile;
|
||||
static string const g_argYul = g_strYul;
|
||||
static string const g_argIR = g_strIR;
|
||||
static string const g_argEWasm = g_strEWasm;
|
||||
static string const g_argEwasm = g_strEwasm;
|
||||
static string const g_argLibraries = g_strLibraries;
|
||||
static string const g_argLink = g_strLink;
|
||||
static string const g_argMachine = g_strMachine;
|
||||
@ -234,14 +233,14 @@ static set<string> const g_machineArgs
|
||||
{
|
||||
g_strEVM,
|
||||
g_strEVM15,
|
||||
g_streWasm
|
||||
g_strEwasm
|
||||
};
|
||||
|
||||
/// Possible arguments to for --yul-dialect
|
||||
static set<string> const g_yulDialectArgs
|
||||
{
|
||||
g_strEVM,
|
||||
g_streWasm
|
||||
g_strEwasm
|
||||
};
|
||||
|
||||
/// Possible arguments to for --metadata-hash
|
||||
@ -345,23 +344,23 @@ void CommandLineInterface::handleIR(string const& _contractName)
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineInterface::handleEWasm(string const& _contractName)
|
||||
void CommandLineInterface::handleEwasm(string const& _contractName)
|
||||
{
|
||||
if (m_args.count(g_argEWasm))
|
||||
if (m_args.count(g_argEwasm))
|
||||
{
|
||||
if (m_args.count(g_argOutputDir))
|
||||
{
|
||||
createFile(m_compiler->filesystemFriendlyName(_contractName) + ".wast", m_compiler->eWasm(_contractName));
|
||||
createFile(m_compiler->filesystemFriendlyName(_contractName) + ".wast", m_compiler->ewasm(_contractName));
|
||||
createFile(
|
||||
m_compiler->filesystemFriendlyName(_contractName) + ".wasm",
|
||||
asString(m_compiler->eWasmObject(_contractName).bytecode)
|
||||
asString(m_compiler->ewasmObject(_contractName).bytecode)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
sout() << "EWasm text:" << endl;
|
||||
sout() << m_compiler->eWasm(_contractName) << endl;
|
||||
sout() << "EWasm binary (hex): " << m_compiler->eWasmObject(_contractName).toHex() << endl;
|
||||
sout() << "Ewasm text:" << endl;
|
||||
sout() << m_compiler->ewasm(_contractName) << endl;
|
||||
sout() << "Ewasm binary (hex): " << m_compiler->ewasmObject(_contractName).toHex() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -776,7 +775,7 @@ Allowed options)",
|
||||
(g_argBinaryRuntime.c_str(), "Binary of the runtime part of the contracts in hex.")
|
||||
(g_argAbi.c_str(), "ABI specification of the contracts.")
|
||||
(g_argIR.c_str(), "Intermediate Representation (IR) of all contracts (EXPERIMENTAL).")
|
||||
(g_argEWasm.c_str(), "EWasm text representation of all contracts (EXPERIMENTAL).")
|
||||
(g_argEwasm.c_str(), "Ewasm text representation of all contracts (EXPERIMENTAL).")
|
||||
(g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.")
|
||||
(g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.")
|
||||
(g_argNatspecDev.c_str(), "Natspec developer documentation of all contracts.")
|
||||
@ -981,27 +980,27 @@ bool CommandLineInterface::processInput()
|
||||
targetMachine = Machine::EVM;
|
||||
else if (machine == g_strEVM15)
|
||||
targetMachine = Machine::EVM15;
|
||||
else if (machine == g_streWasm)
|
||||
targetMachine = Machine::eWasm;
|
||||
else if (machine == g_strEwasm)
|
||||
targetMachine = Machine::Ewasm;
|
||||
else
|
||||
{
|
||||
serr() << "Invalid option for --machine: " << machine << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (targetMachine == Machine::eWasm && inputLanguage == Input::StrictAssembly)
|
||||
inputLanguage = Input::EWasm;
|
||||
if (targetMachine == Machine::Ewasm && inputLanguage == Input::StrictAssembly)
|
||||
inputLanguage = Input::Ewasm;
|
||||
if (m_args.count(g_strYulDialect))
|
||||
{
|
||||
string dialect = m_args[g_strYulDialect].as<string>();
|
||||
if (dialect == g_strEVM)
|
||||
inputLanguage = Input::StrictAssembly;
|
||||
else if (dialect == g_streWasm)
|
||||
else if (dialect == g_strEwasm)
|
||||
{
|
||||
inputLanguage = Input::EWasm;
|
||||
if (targetMachine != Machine::eWasm)
|
||||
inputLanguage = Input::Ewasm;
|
||||
if (targetMachine != Machine::Ewasm)
|
||||
{
|
||||
serr() << "If you select eWasm as --yul-dialect, --machine has to be eWasm as well." << endl;
|
||||
serr() << "If you select Ewasm as --yul-dialect, --machine has to be Ewasm as well." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1011,7 +1010,7 @@ bool CommandLineInterface::processInput()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (optimize && (inputLanguage != Input::StrictAssembly && inputLanguage != Input::EWasm))
|
||||
if (optimize && (inputLanguage != Input::StrictAssembly && inputLanguage != Input::Ewasm))
|
||||
{
|
||||
serr() <<
|
||||
"Optimizer can only be used for strict assembly. Use --" <<
|
||||
@ -1074,7 +1073,7 @@ bool CommandLineInterface::processInput()
|
||||
// TODO: Perhaps we should not compile unless requested
|
||||
|
||||
m_compiler->enableIRGeneration(m_args.count(g_argIR));
|
||||
m_compiler->enableEWasmGeneration(m_args.count(g_argEWasm));
|
||||
m_compiler->enableEwasmGeneration(m_args.count(g_argEwasm));
|
||||
|
||||
OptimiserSettings settings = m_args.count(g_argOptimize) ? OptimiserSettings::standard() : OptimiserSettings::minimal();
|
||||
settings.expectedExecutionsPerDeployment = m_args[g_argOptimizeRuns].as<unsigned>();
|
||||
@ -1453,7 +1452,7 @@ bool CommandLineInterface::assemble(
|
||||
string machine =
|
||||
_targetMachine == yul::AssemblyStack::Machine::EVM ? "EVM" :
|
||||
_targetMachine == yul::AssemblyStack::Machine::EVM15 ? "EVM 1.5" :
|
||||
"eWasm";
|
||||
"Ewasm";
|
||||
sout() << endl << "======= " << src.first << " (" << machine << ") =======" << endl;
|
||||
|
||||
yul::AssemblyStack& stack = assemblyStacks[src.first];
|
||||
@ -1461,9 +1460,9 @@ bool CommandLineInterface::assemble(
|
||||
sout() << endl << "Pretty printed source:" << endl;
|
||||
sout() << stack.print() << endl;
|
||||
|
||||
if (_language != yul::AssemblyStack::Language::EWasm && _targetMachine == yul::AssemblyStack::Machine::eWasm)
|
||||
if (_language != yul::AssemblyStack::Language::Ewasm && _targetMachine == yul::AssemblyStack::Machine::Ewasm)
|
||||
{
|
||||
stack.translate(yul::AssemblyStack::Language::EWasm);
|
||||
stack.translate(yul::AssemblyStack::Language::Ewasm);
|
||||
stack.optimize();
|
||||
|
||||
sout() << endl << "==========================" << endl;
|
||||
@ -1554,7 +1553,7 @@ void CommandLineInterface::outputCompilationResults()
|
||||
|
||||
handleBytecode(contract);
|
||||
handleIR(contract);
|
||||
handleEWasm(contract);
|
||||
handleEwasm(contract);
|
||||
handleSignatureHashes(contract);
|
||||
handleMetadata(contract);
|
||||
handleABI(contract);
|
||||
|
@ -67,7 +67,7 @@ private:
|
||||
void handleBinary(std::string const& _contract);
|
||||
void handleOpcode(std::string const& _contract);
|
||||
void handleIR(std::string const& _contract);
|
||||
void handleEWasm(std::string const& _contract);
|
||||
void handleEwasm(std::string const& _contract);
|
||||
void handleBytecode(std::string const& _contract);
|
||||
void handleSignatureHashes(std::string const& _contract);
|
||||
void handleMetadata(std::string const& _contract);
|
||||
|
@ -131,8 +131,8 @@ set(libyul_sources
|
||||
libyul/Common.cpp
|
||||
libyul/Common.h
|
||||
libyul/CompilabilityChecker.cpp
|
||||
libyul/EWasmTranslationTest.cpp
|
||||
libyul/EWasmTranslationTest.h
|
||||
libyul/EwasmTranslationTest.cpp
|
||||
libyul/EwasmTranslationTest.h
|
||||
libyul/FunctionSideEffects.cpp
|
||||
libyul/FunctionSideEffects.h
|
||||
libyul/Inliner.cpp
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <test/libsolidity/SemanticTest.h>
|
||||
#include <test/libsolidity/SMTCheckerTest.h>
|
||||
#include <test/libsolidity/SMTCheckerJSONTest.h>
|
||||
#include <test/libyul/EWasmTranslationTest.h>
|
||||
#include <test/libyul/EwasmTranslationTest.h>
|
||||
#include <test/libyul/YulOptimizerTest.h>
|
||||
#include <test/libyul/YulInterpreterTest.h>
|
||||
#include <test/libyul/ObjectCompilerTest.h>
|
||||
@ -56,7 +56,7 @@ struct Testsuite
|
||||
Testsuite const g_interactiveTestsuites[] = {
|
||||
/*
|
||||
Title Path Subpath SMT NeedsVM Creator function */
|
||||
{"EWasm Translation", "libyul", "ewasmTranslationTests",false,false, &yul::test::EWasmTranslationTest::create},
|
||||
{"Ewasm Translation", "libyul", "ewasmTranslationTests",false,false, &yul::test::EwasmTranslationTest::create},
|
||||
{"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create},
|
||||
{"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create},
|
||||
{"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create},
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
======= evm_to_wasm/input.sol (eWasm) =======
|
||||
======= evm_to_wasm/input.sol (Ewasm) =======
|
||||
|
||||
Pretty printed source:
|
||||
object "object" {
|
||||
|
@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(string_storage)
|
||||
auto evmVersion = dev::test::Options::get().evmVersion();
|
||||
|
||||
if (evmVersion <= EVMVersion::byzantium())
|
||||
CHECK_DEPLOY_GAS(134145, 130831, evmVersion);
|
||||
CHECK_DEPLOY_GAS(134209, 130895, evmVersion);
|
||||
// This is only correct on >=Constantinople.
|
||||
else if (Options::get().useABIEncoderV2)
|
||||
{
|
||||
@ -107,22 +107,22 @@ BOOST_AUTO_TEST_CASE(string_storage)
|
||||
{
|
||||
// Costs with 0 are cases which cannot be triggered in tests.
|
||||
if (evmVersion < EVMVersion::istanbul())
|
||||
CHECK_DEPLOY_GAS(0, 123969, evmVersion);
|
||||
CHECK_DEPLOY_GAS(0, 124033, evmVersion);
|
||||
else
|
||||
CHECK_DEPLOY_GAS(0, 110969, evmVersion);
|
||||
CHECK_DEPLOY_GAS(0, 110981, evmVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (evmVersion < EVMVersion::istanbul())
|
||||
CHECK_DEPLOY_GAS(147771, 131687, evmVersion);
|
||||
CHECK_DEPLOY_GAS(147835, 131687, evmVersion);
|
||||
else
|
||||
CHECK_DEPLOY_GAS(131859, 117231, evmVersion);
|
||||
CHECK_DEPLOY_GAS(131871, 117231, evmVersion);
|
||||
}
|
||||
}
|
||||
else if (evmVersion < EVMVersion::istanbul())
|
||||
CHECK_DEPLOY_GAS(126929, 119659, evmVersion);
|
||||
CHECK_DEPLOY_GAS(126993, 119723, evmVersion);
|
||||
else
|
||||
CHECK_DEPLOY_GAS(114345, 107335, evmVersion);
|
||||
CHECK_DEPLOY_GAS(114357, 107347, evmVersion);
|
||||
|
||||
if (evmVersion >= EVMVersion::byzantium())
|
||||
{
|
||||
|
@ -14319,8 +14319,6 @@ BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "ClientReceipt", bytes());
|
||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"ClientReceipt", m_contractAddress}});
|
||||
u256 value(18);
|
||||
u256 id(0x1234);
|
||||
|
||||
callContractFunction("f()");
|
||||
BOOST_REQUIRE_EQUAL(numLogs(), 1);
|
||||
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <test/libyul/EWasmTranslationTest.h>
|
||||
#include <test/libyul/EwasmTranslationTest.h>
|
||||
|
||||
#include <test/tools/yulInterpreter/Interpreter.h>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
#include <libyul/backends/wasm/EVMToEWasmTranslator.h>
|
||||
#include <libyul/backends/wasm/EVMToEwasmTranslator.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
@ -47,7 +47,7 @@ using namespace dev::solidity::test;
|
||||
using namespace std;
|
||||
|
||||
|
||||
EWasmTranslationTest::EWasmTranslationTest(string const& _filename)
|
||||
EwasmTranslationTest::EwasmTranslationTest(string const& _filename)
|
||||
{
|
||||
boost::filesystem::path path(_filename);
|
||||
|
||||
@ -60,12 +60,12 @@ EWasmTranslationTest::EWasmTranslationTest(string const& _filename)
|
||||
m_expectation = parseSimpleExpectations(file);
|
||||
}
|
||||
|
||||
TestCase::TestResult EWasmTranslationTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
|
||||
TestCase::TestResult EwasmTranslationTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
|
||||
{
|
||||
if (!parse(_stream, _linePrefix, _formatted))
|
||||
return TestResult::FatalError;
|
||||
|
||||
*m_object = EVMToEWasmTranslator(
|
||||
*m_object = EVMToEwasmTranslator(
|
||||
EVMDialect::strictAssemblyForEVMObjects(dev::test::Options::get().evmVersion())
|
||||
).run(*m_object);
|
||||
|
||||
@ -89,17 +89,17 @@ TestCase::TestResult EWasmTranslationTest::run(ostream& _stream, string const& _
|
||||
return TestResult::Success;
|
||||
}
|
||||
|
||||
void EWasmTranslationTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const
|
||||
void EwasmTranslationTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const
|
||||
{
|
||||
printIndented(_stream, m_source, _linePrefix);
|
||||
}
|
||||
|
||||
void EWasmTranslationTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const
|
||||
void EwasmTranslationTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const
|
||||
{
|
||||
printIndented(_stream, m_obtainedResult, _linePrefix);
|
||||
}
|
||||
|
||||
void EWasmTranslationTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const
|
||||
void EwasmTranslationTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const
|
||||
{
|
||||
stringstream output(_output);
|
||||
string line;
|
||||
@ -107,7 +107,7 @@ void EWasmTranslationTest::printIndented(ostream& _stream, string const& _output
|
||||
_stream << _linePrefix << line << endl;
|
||||
}
|
||||
|
||||
bool EWasmTranslationTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
|
||||
bool EwasmTranslationTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
|
||||
{
|
||||
AssemblyStack stack(
|
||||
dev::test::Options::get().evmVersion(),
|
||||
@ -127,11 +127,11 @@ bool EWasmTranslationTest::parse(ostream& _stream, string const& _linePrefix, bo
|
||||
}
|
||||
}
|
||||
|
||||
string EWasmTranslationTest::interpret()
|
||||
string EwasmTranslationTest::interpret()
|
||||
{
|
||||
InterpreterState state;
|
||||
state.maxTraceSize = 10000;
|
||||
state.maxSteps = 10000;
|
||||
state.maxSteps = 100000;
|
||||
WasmDialect dialect;
|
||||
Interpreter interpreter(state, dialect);
|
||||
try
|
||||
@ -147,7 +147,7 @@ string EWasmTranslationTest::interpret()
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void EWasmTranslationTest::printErrors(ostream& _stream, ErrorList const& _errors)
|
||||
void EwasmTranslationTest::printErrors(ostream& _stream, ErrorList const& _errors)
|
||||
{
|
||||
SourceReferenceFormatter formatter(_stream);
|
||||
|
@ -32,15 +32,15 @@ namespace yul
|
||||
namespace test
|
||||
{
|
||||
|
||||
class EWasmTranslationTest: public dev::solidity::test::EVMVersionRestrictedTestCase
|
||||
class EwasmTranslationTest: public dev::solidity::test::EVMVersionRestrictedTestCase
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<TestCase> create(Config const& _config)
|
||||
{
|
||||
return std::make_unique<EWasmTranslationTest>(_config.filename);
|
||||
return std::make_unique<EwasmTranslationTest>(_config.filename);
|
||||
}
|
||||
|
||||
explicit EWasmTranslationTest(std::string const& _filename);
|
||||
explicit EwasmTranslationTest(std::string const& _filename);
|
||||
|
||||
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override;
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/backends/evm/EVMMetrics.h>
|
||||
#include <libyul/backends/wasm/WordSizeTransform.h>
|
||||
#include <libyul/backends/wasm/WasmDialect.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AsmParser.h>
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
@ -98,12 +99,24 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename)
|
||||
file.exceptions(ios::badbit);
|
||||
|
||||
m_source = parseSourceAndSettings(file);
|
||||
if (m_settings.count("yul"))
|
||||
if (m_settings.count("dialect"))
|
||||
{
|
||||
m_yul = true;
|
||||
m_validatedSettings["yul"] = "true";
|
||||
m_settings.erase("yul");
|
||||
auto dialectName = m_settings["dialect"];
|
||||
if (dialectName == "yul")
|
||||
m_dialect = &Dialect::yul();
|
||||
else if (dialectName == "ewasm")
|
||||
m_dialect = &WasmDialect::instance();
|
||||
else if (dialectName == "evm")
|
||||
m_dialect = &EVMDialect::strictAssemblyForEVMObjects(dev::test::Options::get().evmVersion());
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Invalid dialect " + dialectName));
|
||||
|
||||
m_validatedSettings["dialect"] = dialectName;
|
||||
m_settings.erase("dialect");
|
||||
}
|
||||
else
|
||||
m_dialect = &EVMDialect::strictAssemblyForEVMObjects(dev::test::Options::get().evmVersion());
|
||||
|
||||
if (m_settings.count("step"))
|
||||
{
|
||||
m_validatedSettings["step"] = m_settings["step"];
|
||||
@ -350,7 +363,7 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
||||
return TestResult::FatalError;
|
||||
}
|
||||
|
||||
m_obtainedResult = AsmPrinter{m_yul}(*m_ast) + "\n";
|
||||
m_obtainedResult = AsmPrinter{m_dialect->flavour == AsmFlavour::Yul}(*m_ast) + "\n";
|
||||
|
||||
if (m_optimizerStep != m_validatedSettings["step"])
|
||||
{
|
||||
@ -406,7 +419,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
|
||||
{
|
||||
AssemblyStack stack(
|
||||
dev::test::Options::get().evmVersion(),
|
||||
m_yul ? AssemblyStack::Language::Yul : AssemblyStack::Language::StrictAssembly,
|
||||
m_dialect->flavour == AsmFlavour::Yul ? AssemblyStack::Language::Yul : AssemblyStack::Language::StrictAssembly,
|
||||
dev::solidity::OptimiserSettings::none()
|
||||
);
|
||||
if (!stack.parseAndAnalyze("", m_source) || !stack.errors().empty())
|
||||
@ -415,7 +428,6 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
|
||||
printErrors(_stream, stack.errors());
|
||||
return false;
|
||||
}
|
||||
m_dialect = m_yul ? &Dialect::yul() : &EVMDialect::strictAssemblyForEVMObjects(dev::test::Options::get().evmVersion());
|
||||
m_ast = stack.parserResult()->code;
|
||||
m_analysisInfo = stack.parserResult()->analysisInfo;
|
||||
return true;
|
||||
|
@ -71,7 +71,6 @@ private:
|
||||
static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors);
|
||||
|
||||
std::string m_source;
|
||||
bool m_yul = false;
|
||||
std::string m_optimizerStep;
|
||||
std::string m_expectation;
|
||||
|
||||
|
35
test/libyul/ewasmTranslationTests/arithmetic_add.yul
Normal file
35
test/libyul/ewasmTranslationTests/arithmetic_add.yul
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
sstore(0, add(0, 1))
|
||||
sstore(1, add(1, not(0)))
|
||||
sstore(2, add(0, 0))
|
||||
sstore(3, add(1, 2))
|
||||
sstore(4, add(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1))
|
||||
sstore(5, add(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, add(not(0), 1))
|
||||
sstore(7, add(0xffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(8, add(0xffffffffffffffff, 1))
|
||||
sstore(9, add(0xffffffffffffffffffffffffffffffff0000000000000000, 1))
|
||||
sstore(10, add(0xffffffffffffffffffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(11, add(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, add(0xffffffffffffffff, 3))
|
||||
sstore(13, add(0xffffffffffffffffffffffffffffffff0000000000000000, 3))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000d
|
||||
// 20: 0000000000000000ffffffffffffffffffffffffffffffff0000000000000003
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000003
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 8000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000100000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 0000000000000000000000000000000000000000000000010000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 0000000000000000ffffffffffffffffffffffffffffffff0000000000000001
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000001000000000000000000000000000000000000000000000002
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 0000000000000000000000000000000100000000000000000000000000000002
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 0000000000000000000000000000000000000000000000010000000000000002
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000000ffffffffffffffffffffffffffffffff0000000000000003
|
20
test/libyul/ewasmTranslationTests/arithmetic_addmod.yul
Normal file
20
test/libyul/ewasmTranslationTests/arithmetic_addmod.yul
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
sstore(0, addmod(0, 1, 1))
|
||||
sstore(1, addmod(0, 1, 2))
|
||||
sstore(2, addmod(3, 1, 2))
|
||||
sstore(3, addmod(1, not(0), 5))
|
||||
sstore(4, addmod(0, 0, 0))
|
||||
sstore(5, addmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1, 1))
|
||||
sstore(6, addmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1, 0))
|
||||
sstore(7, addmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd, 1, 5))
|
||||
sstore(8, addmod(
|
||||
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
|
||||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe,
|
||||
5
|
||||
))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// Storage dump:
|
23
test/libyul/ewasmTranslationTests/arithmetic_div.yul
Normal file
23
test/libyul/ewasmTranslationTests/arithmetic_div.yul
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
sstore(0, div(0, 1))
|
||||
sstore(1, div(1, not(0)))
|
||||
sstore(2, div(0, 0))
|
||||
sstore(3, div(1, 2))
|
||||
sstore(4, div(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1))
|
||||
sstore(5, div(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, div(not(0), 1))
|
||||
sstore(7, div(0xffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(8, div(0xffffffffffffffff, 1))
|
||||
sstore(9, div(0xffffffffffffffffffffffffffffffff0000000000000000, 1))
|
||||
sstore(10, div(0xffffffffffffffffffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(11, div(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, div(0xffffffffffffffff, 3))
|
||||
sstore(13, div(0xffffffffffffffffffffffffffffffff0000000000000000, 3))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// Storage dump:
|
25
test/libyul/ewasmTranslationTests/arithmetic_exp.yul
Normal file
25
test/libyul/ewasmTranslationTests/arithmetic_exp.yul
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
sstore(0, exp(0, 1))
|
||||
sstore(1, exp(1, not(0)))
|
||||
sstore(2, exp(0, 0))
|
||||
sstore(3, exp(1, 2))
|
||||
sstore(4, exp(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1))
|
||||
sstore(5, exp(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, exp(not(0), 1))
|
||||
sstore(7, exp(0xffffffffffffffffffffffffffffffff, 2))
|
||||
sstore(8, exp(0xffffffffffffffff, 2))
|
||||
sstore(9, exp(0xffffffffffffffffffffffffffffffff0000000000000000, 2))
|
||||
sstore(10, exp(0xffffffffffffffffffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(11, exp(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, exp(0xffffffffffffffff, 3))
|
||||
sstore(13, exp(0xffffffffffffffffffffffffffffffff0000000000000000, 3))
|
||||
sstore(14, exp(2, 256))
|
||||
sstore(15, exp(2, 255))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// Storage dump:
|
25
test/libyul/ewasmTranslationTests/arithmetic_mod.yul
Normal file
25
test/libyul/ewasmTranslationTests/arithmetic_mod.yul
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
sstore(0, mod(0, 1))
|
||||
sstore(1, mod(1, not(0)))
|
||||
sstore(2, mod(0, 0))
|
||||
sstore(3, mod(1, 2))
|
||||
sstore(4, mod(not(0), 1))
|
||||
sstore(5, mod(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, mod(not(0), 1))
|
||||
sstore(7, mod(0xffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(8, mod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 0xfffffffffffffffffffffffffffffffe))
|
||||
sstore(9, mod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 5))
|
||||
sstore(10, mod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 4))
|
||||
sstore(11, mod(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, mod(0xffffffffffffffff, 3))
|
||||
sstore(13, mod(0xffffffffffffffffffffffffffffffff0000000000000000, 0xffffffffffffffff43342553000))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
36
test/libyul/ewasmTranslationTests/arithmetic_mul.yul
Normal file
36
test/libyul/ewasmTranslationTests/arithmetic_mul.yul
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
sstore(0, mul(0, 1))
|
||||
sstore(1, mul(1, not(0)))
|
||||
sstore(2, mul(0, 0))
|
||||
sstore(3, mul(1, 2))
|
||||
sstore(4, mul(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1))
|
||||
sstore(5, mul(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, mul(not(0), 1))
|
||||
sstore(7, mul(0xffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(8, mul(0xffffffffffffffff, 1))
|
||||
sstore(9, mul(0xffffffffffffffffffffffffffffffff0000000000000000, 1))
|
||||
sstore(10, mul(0xffffffffffffffffffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(11, mul(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, mul(0xffffffffffffffff, 3))
|
||||
sstore(13, mul(0xffffffffffffffffffffffffffffffff0000000000000000, 3))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000d
|
||||
// 20: 0000000000000002fffffffffffffffffffffffffffffffd0000000000000000
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000002
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000006: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 00000000000000000000000000000000ffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000000ffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 0000000000000000ffffffffffffffffffffffffffffffff0000000000000000
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000002fffffffffffffffffffffffffffffffffffffffffffffffd
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 00000000000000000000000000000002fffffffffffffffffffffffffffffffd
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 000000000000000000000000000000000000000000000002fffffffffffffffd
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000002fffffffffffffffffffffffffffffffd0000000000000000
|
22
test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul
Normal file
22
test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
sstore(0, mulmod(0, 1, 2))
|
||||
sstore(1, mulmod(1, not(0), 5))
|
||||
sstore(2, mulmod(0, 0, 5))
|
||||
sstore(3, mulmod(1, 3, 2))
|
||||
sstore(4, mulmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe,
|
||||
1,
|
||||
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
|
||||
sstore(5, mulmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1, 1))
|
||||
sstore(6, mulmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe, 1, 0))
|
||||
sstore(7, mulmod(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd, 1, 5))
|
||||
sstore(8, mulmod(
|
||||
not(0),
|
||||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe,
|
||||
25
|
||||
))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// Storage dump:
|
25
test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul
Normal file
25
test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
sstore(0, sdiv(0, 1))
|
||||
sstore(1, sdiv(0, not(0)))
|
||||
sstore(2, sdiv(0, 0))
|
||||
sstore(3, sdiv(1, 2))
|
||||
sstore(4, sdiv(not(0), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe))
|
||||
sstore(5, sdiv(0x8000000000000000000000000000000000000000000000000000000000000000, not(0)))
|
||||
sstore(6, sdiv(not(0), 0x8000000000000000000000000000000000000000000000000000000000000000))
|
||||
sstore(7, sdiv(0x7000000000000000000000000000000000000000000000000000000000000000, 1))
|
||||
sstore(8, sdiv(1, 0x7000000000000000000000000000000000000000000000000000000000000000))
|
||||
sstore(9, sdiv(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, not(0)))
|
||||
sstore(10, sdiv(not(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
|
||||
sstore(11, sdiv(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(12, sdiv(not(0), not(0)))
|
||||
sstore(13, sdiv(
|
||||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe,
|
||||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
))
|
||||
sstore(14, sdiv(0x8000000000000000000000000000000000000000000000000000000000000001, not(0)))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// Storage dump:
|
29
test/libyul/ewasmTranslationTests/arithmetic_smod.yul
Normal file
29
test/libyul/ewasmTranslationTests/arithmetic_smod.yul
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
sstore(0, smod(0, 1))
|
||||
sstore(1, smod(1, not(0)))
|
||||
sstore(2, smod(0, 0))
|
||||
sstore(3, smod(1, 2))
|
||||
sstore(4, smod(not(0), 1))
|
||||
sstore(5, smod(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, smod(not(0), 1))
|
||||
sstore(7, smod(0xffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(8, smod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 0xfffffffffffffffffffffffffffffffe))
|
||||
sstore(9, smod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 5))
|
||||
sstore(10, smod(0xffffffffffffffffffffffffffffffffffffffffffffffff, 4))
|
||||
sstore(11, smod(0xffffffffffffffffffffffffffffffff, 3))
|
||||
sstore(12, smod(0xffffffffffffffff, 3))
|
||||
sstore(13, smod(0xffffffffffffffffffffffffffffffff0000000000000000, 0xffffffffffffffff43342553000))
|
||||
sstore(14, smod(
|
||||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd,
|
||||
0xffffffffffffffff43342553000
|
||||
))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
36
test/libyul/ewasmTranslationTests/arithmetic_sub.yul
Normal file
36
test/libyul/ewasmTranslationTests/arithmetic_sub.yul
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
sstore(0, sub(0, 1))
|
||||
sstore(1, sub(1, not(0)))
|
||||
sstore(2, sub(0, 0))
|
||||
sstore(3, sub(1, 2))
|
||||
sstore(4, sub(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 1))
|
||||
sstore(5, sub(
|
||||
0x8000000000000000000000000000000000000000000000000000000000000000, 1
|
||||
))
|
||||
sstore(6, sub(not(0), 1))
|
||||
sstore(7, sub(not(0), not(0)))
|
||||
sstore(8, sub(0x1000000000000000000000000000000000000000000000000, 1))
|
||||
sstore(9, sub(0x100000000000000000000000000000000, 1))
|
||||
sstore(10, sub(0x10000000000000000, 1))
|
||||
sstore(11, sub(0x1000000000000000000000000000000000000000000000000, 3))
|
||||
sstore(12, sub(0x100000000000000000000000000000000, 3))
|
||||
sstore(13, sub(0x10000000000000000, 3))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000d
|
||||
// 20: 000000000000000000000000000000000000000000000000fffffffffffffffd
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000002
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000006: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 00000000000000000000000000000000ffffffffffffffffffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 000000000000000000000000000000000000000000000000ffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 0000000000000000fffffffffffffffffffffffffffffffffffffffffffffffd
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 00000000000000000000000000000000fffffffffffffffffffffffffffffffd
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 000000000000000000000000000000000000000000000000fffffffffffffffd
|
@ -4,11 +4,16 @@
|
||||
let z := shr(136, y)
|
||||
sstore(0, y)
|
||||
sstore(1, z)
|
||||
sstore(2, sar(136, 0x801112131415161718191a1b1c1d1e1f20000000000000000000000000000000))
|
||||
sstore(3, sar(256, 0x801112131415161718191a1b1c1d1e1f20000000000000000000000000000000))
|
||||
sstore(4, sar(136, 0x701112131415161718191a1b1c1d1e1f20000000000000000000000000000000))
|
||||
sstore(5, sar(256, 0x701112131415161718191a1b1c1d1e1f20000000000000000000000000000000))
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000101112131415161718191a1b1c1d1e
|
||||
|
11
test/libyul/ewasmTranslationTests/signextend.yul
Normal file
11
test/libyul/ewasmTranslationTests/signextend.yul
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
sstore(0, signextend(0, 0x86))
|
||||
sstore(1, signextend(0, 0x76))
|
||||
sstore(2, signextend(32, not(0)))
|
||||
sstore(3, signextend(5, 0xff8844553322))
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// Storage dump:
|
@ -7,6 +7,5 @@
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000014
|
||||
// 40: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000
|
||||
// Storage dump:
|
||||
|
@ -9,6 +9,5 @@
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000014
|
||||
// 80: 636f6465636f6465636f6465636f6465636f6465000000000000000000000000
|
||||
// Storage dump:
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256, b:u256 }
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256, b:u256, c:u256 }
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } }
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{ }
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// { }
|
||||
|
@ -9,7 +9,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256, b:u256, c:u256 }
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ { let a:u256 } { let a:u256 } }
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256 }
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ { let a:u256 let a_1:u256 } { let a:u256 } }
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: disambiguator
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: expressionInliner
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function f() -> x:u256
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: expressionInliner
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function f(a:u256) -> x:u256
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }
|
||||
// ====
|
||||
// step: functionGrouper
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -6,7 +6,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionGrouper
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
|
@ -10,7 +10,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionGrouper
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256 }
|
||||
|
@ -3,7 +3,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionGrouper
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// { let a:u256 }
|
||||
|
@ -9,7 +9,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionHoister
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// let a:u256
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionHoister
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// let a:u256
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionHoister
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// let a:u256
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: functionHoister
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// let a:u256
|
||||
|
@ -9,7 +9,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: mainFunction
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function main()
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: mainFunction
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function main()
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: mainFunction
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function main()
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
// ====
|
||||
// step: mainFunction
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function main()
|
||||
|
@ -1,7 +1,7 @@
|
||||
{}
|
||||
// ====
|
||||
// step: mainFunction
|
||||
// yul: true
|
||||
// dialect: yul
|
||||
// ----
|
||||
// {
|
||||
// function main()
|
||||
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
let i := 0
|
||||
for {} lt(i, 2) { i := add(i, 1) }
|
||||
{
|
||||
let x
|
||||
x := 1337
|
||||
if lt(i,1) {
|
||||
x := 42
|
||||
break
|
||||
}
|
||||
mstore(0, x)
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: redundantAssignEliminator
|
||||
// ----
|
||||
// {
|
||||
// let i := 0
|
||||
// for { } lt(i, 2) { i := add(i, 1) }
|
||||
// {
|
||||
// let x
|
||||
// x := 1337
|
||||
// if lt(i, 1) { break }
|
||||
// mstore(0, x)
|
||||
// }
|
||||
// }
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
let i := 0
|
||||
for {} lt(i, 2) { i := add(i, 1) }
|
||||
{
|
||||
let x
|
||||
x := 1337
|
||||
if lt(i,1) {
|
||||
x := 42
|
||||
continue
|
||||
}
|
||||
mstore(0, x)
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// step: redundantAssignEliminator
|
||||
// ----
|
||||
// {
|
||||
// let i := 0
|
||||
// for { } lt(i, 2) { i := add(i, 1) }
|
||||
// {
|
||||
// let x
|
||||
// x := 1337
|
||||
// if lt(i, 1) { continue }
|
||||
// mstore(0, x)
|
||||
// }
|
||||
// }
|
@ -32,7 +32,7 @@ add_executable(isoltest
|
||||
../libsolidity/SMTCheckerTest.cpp
|
||||
../libsolidity/SMTCheckerJSONTest.cpp
|
||||
../libyul/Common.cpp
|
||||
../libyul/EWasmTranslationTest.cpp
|
||||
../libyul/EwasmTranslationTest.cpp
|
||||
../libyul/FunctionSideEffects.cpp
|
||||
../libyul/ObjectCompilerTest.cpp
|
||||
../libyul/YulOptimizerTest.cpp
|
||||
|
@ -1,8 +1,8 @@
|
||||
set(sources
|
||||
EVMInstructionInterpreter.h
|
||||
EVMInstructionInterpreter.cpp
|
||||
EWasmBuiltinInterpreter.h
|
||||
EWasmBuiltinInterpreter.cpp
|
||||
EwasmBuiltinInterpreter.h
|
||||
EwasmBuiltinInterpreter.cpp
|
||||
Interpreter.h
|
||||
Interpreter.cpp
|
||||
)
|
||||
|
@ -15,10 +15,10 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Yul interpreter module that evaluates EWasm builtins.
|
||||
* Yul interpreter module that evaluates Ewasm builtins.
|
||||
*/
|
||||
|
||||
#include <test/tools/yulInterpreter/EWasmBuiltinInterpreter.h>
|
||||
#include <test/tools/yulInterpreter/EwasmBuiltinInterpreter.h>
|
||||
|
||||
#include <test/tools/yulInterpreter/Interpreter.h>
|
||||
|
||||
@ -49,11 +49,26 @@ void copyZeroExtended(
|
||||
_target[_targetOffset + i] = _sourceOffset + i < _source.size() ? _source[_sourceOffset + i] : 0;
|
||||
}
|
||||
|
||||
/// Count leading zeros for uint64
|
||||
uint64_t clz(uint64_t _v)
|
||||
{
|
||||
if (_v == 0)
|
||||
return 64;
|
||||
|
||||
uint64_t r = 0;
|
||||
while (!(_v & 0x8000000000000000))
|
||||
{
|
||||
r += 1;
|
||||
_v = _v << 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
|
||||
u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _arguments)
|
||||
u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _arguments)
|
||||
{
|
||||
vector<uint64_t> arg;
|
||||
for (u256 const& a: _arguments)
|
||||
@ -119,6 +134,8 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return arg[0] != arg[1] ? 1 : 0;
|
||||
else if (_fun == "i64.eqz"_yulstring)
|
||||
return arg[0] == 0 ? 1 : 0;
|
||||
else if (_fun == "i64.clz"_yulstring)
|
||||
return clz(arg[0]);
|
||||
else if (_fun == "i64.lt_u"_yulstring)
|
||||
return arg[0] < arg[1] ? 1 : 0;
|
||||
else if (_fun == "i64.gt_u"_yulstring)
|
||||
@ -133,24 +150,39 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
writeMemoryWord(arg[0], arg[1]);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "i64.store8"_yulstring)
|
||||
{
|
||||
accessMemory(arg[0], 1);
|
||||
writeMemoryByte(arg[0], static_cast<uint8_t>(arg[1] & 0xff));
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "i64.load"_yulstring)
|
||||
{
|
||||
accessMemory(arg[0], 8);
|
||||
return readMemoryWord(arg[0]);
|
||||
}
|
||||
else if (_fun == "eth.getAddress"_yulstring)
|
||||
return writeAddress(arg[0], m_state.address);
|
||||
{
|
||||
writeAddress(arg[0], m_state.address);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getExternalBalance"_yulstring)
|
||||
{
|
||||
// TODO this does not read the address, but is consistent with
|
||||
// EVM interpreter implementation.
|
||||
// If we take the address into account, this needs to use readAddress.
|
||||
return writeU128(arg[0], m_state.balance);
|
||||
writeU128(arg[1], m_state.balance);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getBlockHash"_yulstring)
|
||||
{
|
||||
if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber)
|
||||
return 1;
|
||||
else
|
||||
return writeU256(arg[1], 0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256));
|
||||
{
|
||||
writeU256(arg[1], 0xaaaaaaaa + u256(arg[0] - m_state.blockNumber - 256));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (_fun == "eth.call"_yulstring)
|
||||
{
|
||||
@ -199,12 +231,21 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.storageLoad"_yulstring)
|
||||
return writeU256(arg[1], m_state.storage[h256(readU256(arg[0]))]);
|
||||
{
|
||||
writeU256(arg[1], m_state.storage[h256(readU256(arg[0]))]);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getCaller"_yulstring)
|
||||
{
|
||||
// TODO should this only write 20 bytes?
|
||||
return writeAddress(arg[0], m_state.caller);
|
||||
writeAddress(arg[0], m_state.caller);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getCallValue"_yulstring)
|
||||
return writeU128(arg[0], m_state.callvalue);
|
||||
{
|
||||
writeU128(arg[0], m_state.callvalue);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.codeCopy"_yulstring)
|
||||
{
|
||||
if (accessMemory(arg[0], arg[2]))
|
||||
@ -215,9 +256,12 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getCodeSize"_yulstring)
|
||||
return writeU256(arg[0], m_state.code.size());
|
||||
return m_state.code.size();
|
||||
else if (_fun == "eth.getBlockCoinbase"_yulstring)
|
||||
return writeAddress(arg[0], m_state.coinbase);
|
||||
{
|
||||
writeAddress(arg[0], m_state.coinbase);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.create"_yulstring)
|
||||
{
|
||||
// TODO access memory
|
||||
@ -226,7 +270,10 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return 0xcccccc + arg[1];
|
||||
}
|
||||
else if (_fun == "eth.getBlockDifficulty"_yulstring)
|
||||
return writeU256(arg[0], m_state.difficulty);
|
||||
{
|
||||
writeU256(arg[0], m_state.difficulty);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.externalCodeCopy"_yulstring)
|
||||
{
|
||||
// TODO use readAddress to read address.
|
||||
@ -239,22 +286,32 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getExternalCodeSize"_yulstring)
|
||||
return u256(keccak256(h256(readAddress(arg[0])))) & 0xffffff;
|
||||
// Generate "random" code length. Make sure it fits the page size.
|
||||
return u256(keccak256(h256(readAddress(arg[0])))) & 0xfff;
|
||||
else if (_fun == "eth.getGasLeft"_yulstring)
|
||||
return 0x99;
|
||||
else if (_fun == "eth.getBlockGasLimit"_yulstring)
|
||||
return uint64_t(m_state.gaslimit);
|
||||
else if (_fun == "eth.getTxGasPrice"_yulstring)
|
||||
return writeU128(arg[0], m_state.gasprice);
|
||||
{
|
||||
writeU128(arg[0], m_state.gasprice);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.log"_yulstring)
|
||||
{
|
||||
logTrace(eth::Instruction::LOG0, {});
|
||||
uint64_t numberOfTopics = arg[2];
|
||||
if (numberOfTopics > 4)
|
||||
throw ExplicitlyTerminated();
|
||||
logTrace(eth::logInstruction(numberOfTopics), {});
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.getBlockNumber"_yulstring)
|
||||
return m_state.blockNumber;
|
||||
else if (_fun == "eth.getTxOrigin"_yulstring)
|
||||
return writeAddress(arg[0], m_state.origin);
|
||||
{
|
||||
writeAddress(arg[0], m_state.origin);
|
||||
return 0;
|
||||
}
|
||||
else if (_fun == "eth.finish"_yulstring)
|
||||
{
|
||||
bytes data;
|
||||
@ -298,7 +355,7 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EWasmBuiltinInterpreter::accessMemory(u256 const& _offset, u256 const& _size)
|
||||
bool EwasmBuiltinInterpreter::accessMemory(u256 const& _offset, u256 const& _size)
|
||||
{
|
||||
if (((_offset + _size) >= _offset) && ((_offset + _size + 0x1f) >= (_offset + _size)))
|
||||
{
|
||||
@ -312,7 +369,7 @@ bool EWasmBuiltinInterpreter::accessMemory(u256 const& _offset, u256 const& _siz
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes EWasmBuiltinInterpreter::readMemory(uint64_t _offset, uint64_t _size)
|
||||
bytes EwasmBuiltinInterpreter::readMemory(uint64_t _offset, uint64_t _size)
|
||||
{
|
||||
yulAssert(_size <= 0xffff, "Too large read.");
|
||||
bytes data(size_t(_size), uint8_t(0));
|
||||
@ -321,7 +378,7 @@ bytes EWasmBuiltinInterpreter::readMemory(uint64_t _offset, uint64_t _size)
|
||||
return data;
|
||||
}
|
||||
|
||||
uint64_t EWasmBuiltinInterpreter::readMemoryWord(uint64_t _offset)
|
||||
uint64_t EwasmBuiltinInterpreter::readMemoryWord(uint64_t _offset)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
@ -329,13 +386,18 @@ uint64_t EWasmBuiltinInterpreter::readMemoryWord(uint64_t _offset)
|
||||
return r;
|
||||
}
|
||||
|
||||
void EWasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
|
||||
void EwasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
|
||||
{
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
m_state.memory[_offset + i] = uint8_t((_value >> (i * 8)) & 0xff);
|
||||
}
|
||||
|
||||
u256 EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _croppedTo)
|
||||
void EwasmBuiltinInterpreter::writeMemoryByte(uint64_t _offset, uint8_t _value)
|
||||
{
|
||||
m_state.memory[_offset] = _value;
|
||||
}
|
||||
|
||||
void EwasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _croppedTo)
|
||||
{
|
||||
accessMemory(_offset, _croppedTo);
|
||||
for (size_t i = 0; i < _croppedTo; i++)
|
||||
@ -343,11 +405,9 @@ u256 EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _c
|
||||
m_state.memory[_offset + _croppedTo - 1 - i] = uint8_t(_value & 0xff);
|
||||
_value >>= 8;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
u256 EWasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
||||
u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
||||
{
|
||||
accessMemory(_offset, _croppedTo);
|
||||
u256 value;
|
||||
@ -357,12 +417,12 @@ u256 EWasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
||||
return value;
|
||||
}
|
||||
|
||||
void EWasmBuiltinInterpreter::logTrace(dev::eth::Instruction _instruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
void EwasmBuiltinInterpreter::logTrace(dev::eth::Instruction _instruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
{
|
||||
logTrace(dev::eth::instructionInfo(_instruction).name, _arguments, _data);
|
||||
}
|
||||
|
||||
void EWasmBuiltinInterpreter::logTrace(std::string const& _pseudoInstruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
void EwasmBuiltinInterpreter::logTrace(std::string const& _pseudoInstruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
{
|
||||
string message = _pseudoInstruction + "(";
|
||||
for (size_t i = 0; i < _arguments.size(); ++i)
|
@ -15,7 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* Yul interpreter module that evaluates EWasm builtins.
|
||||
* Yul interpreter module that evaluates Ewasm builtins.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -45,7 +45,7 @@ namespace test
|
||||
struct InterpreterState;
|
||||
|
||||
/**
|
||||
* Interprets EWasm builtins based on the current state and logs instructions with
|
||||
* Interprets Ewasm builtins based on the current state and logs instructions with
|
||||
* side-effects.
|
||||
*
|
||||
* Since this is mainly meant to be used for differential fuzz testing, it is focused
|
||||
@ -63,10 +63,10 @@ struct InterpreterState;
|
||||
* The main focus is that the generated execution trace is the same for equivalent executions
|
||||
* and likely to be different for non-equivalent executions.
|
||||
*/
|
||||
class EWasmBuiltinInterpreter
|
||||
class EwasmBuiltinInterpreter
|
||||
{
|
||||
public:
|
||||
explicit EWasmBuiltinInterpreter(InterpreterState& _state):
|
||||
explicit EwasmBuiltinInterpreter(InterpreterState& _state):
|
||||
m_state(_state)
|
||||
{}
|
||||
/// Evaluate builtin function
|
||||
@ -86,11 +86,14 @@ private:
|
||||
/// Writes a word to memory (little-endian)
|
||||
/// Does not adjust msize, use @a accessMemory for that
|
||||
void writeMemoryWord(uint64_t _offset, uint64_t _value);
|
||||
/// Writes a byte to memory
|
||||
/// Does not adjust msize, use @a accessMemory for that
|
||||
void writeMemoryByte(uint64_t _offset, uint8_t _value);
|
||||
|
||||
/// Helper for eth.* builtins. Writes to memory (big-endian) and always returns zero.
|
||||
dev::u256 writeU256(uint64_t _offset, dev::u256 _value, size_t _croppedTo = 32);
|
||||
dev::u256 writeU128(uint64_t _offset, dev::u256 _value) { return writeU256(_offset, std::move(_value), 16); }
|
||||
dev::u256 writeAddress(uint64_t _offset, dev::u256 _value) { return writeU256(_offset, std::move(_value), 20); }
|
||||
void writeU256(uint64_t _offset, dev::u256 _value, size_t _croppedTo = 32);
|
||||
void writeU128(uint64_t _offset, dev::u256 _value) { writeU256(_offset, std::move(_value), 16); }
|
||||
void writeAddress(uint64_t _offset, dev::u256 _value) { writeU256(_offset, std::move(_value), 20); }
|
||||
/// Helper for eth.* builtins. Reads from memory (big-endian) and returns the value;
|
||||
dev::u256 readU256(uint64_t _offset, size_t _croppedTo = 32);
|
||||
dev::u256 readU128(uint64_t _offset) { return readU256(_offset, 16); }
|
@ -21,7 +21,7 @@
|
||||
#include <test/tools/yulInterpreter/Interpreter.h>
|
||||
|
||||
#include <test/tools/yulInterpreter/EVMInstructionInterpreter.h>
|
||||
#include <test/tools/yulInterpreter/EWasmBuiltinInterpreter.h>
|
||||
#include <test/tools/yulInterpreter/EwasmBuiltinInterpreter.h>
|
||||
|
||||
#include <libyul/AsmData.h>
|
||||
#include <libyul/Dialect.h>
|
||||
@ -246,7 +246,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall)
|
||||
else if (WasmDialect const* dialect = dynamic_cast<WasmDialect const*>(&m_dialect))
|
||||
if (dialect->builtin(_funCall.functionName.name))
|
||||
{
|
||||
EWasmBuiltinInterpreter interpreter(m_state);
|
||||
EwasmBuiltinInterpreter interpreter(m_state);
|
||||
setValue(interpreter.evalBuiltin(_funCall.functionName.name, values()));
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user