From e79a32e9d5d4dbb14ff436664e1d4d0bb2b0cbae Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 31 Oct 2019 18:42:14 +0100 Subject: [PATCH 1/2] Wasm to binary assembly stack. --- libsolidity/interface/CompilerStack.cpp | 12 +++++++++++- libsolidity/interface/CompilerStack.h | 10 +++++++--- libyul/AssemblyStack.cpp | 5 ++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 5bd9f9a45..fa7c9ec95 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -578,6 +578,14 @@ string const& CompilerStack::eWasm(string const& _contractName) const return contract(_contractName).eWasm; } +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; +} + eth::LinkerObject const& CompilerStack::object(string const& _contractName) const { if (m_stackState != CompilationSuccessful) @@ -1047,7 +1055,9 @@ void CompilerStack::generateEWasm(ContractDefinition const& _contract) //cout << yul::AsmPrinter{}(*ewasmStack.parserResult()->code) << endl; // Turn into eWasm text representation. - compiledContract.eWasm = ewasmStack.assemble(yul::AssemblyStack::Machine::eWasm).assembly; + auto result = ewasmStack.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 diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index b38227b78..43d04cedb 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -232,9 +232,12 @@ 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. + /// @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 assembled object for a contract. eth::LinkerObject const& object(std::string const& _contractName) const; @@ -312,7 +315,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 code (text representation). + std::string eWasm; ///< Experimental eWasm text representation + eth::LinkerObject eWasmObject; ///< Experimental eWasm code mutable std::unique_ptr metadata; ///< The metadata json that will be hashed into the chain. mutable std::unique_ptr abi; mutable std::unique_ptr userDocumentation; @@ -346,7 +350,7 @@ private: /// The IR is stored but otherwise unused. void generateIR(ContractDefinition const& _contract); - /// Generate eWasm text representation for a single 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 diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index ca569f9d1..87df95f37 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -200,7 +200,10 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const Dialect const& dialect = languageToDialect(m_language, EVMVersion{}); MachineAssemblyObject object; - object.assembly = EWasmObjectCompiler::compile(*m_parserResult, dialect).first; + auto result = EWasmObjectCompiler::compile(*m_parserResult, dialect); + object.assembly = std::move(result.first); + object.bytecode = make_shared(); + object.bytecode->bytecode = std::move(result.second); return object; } } From 587c87b15b06571560816267e6395e2678d32196 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 31 Oct 2019 18:43:54 +0100 Subject: [PATCH 2/2] Commandline interface additions for webassembly binary. --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 2 ++ solc/CommandLineInterface.cpp | 9 ++++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 9924dbf4f..7c69ac008 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: * Code Generator: Use SELFBALANCE for ``address(this).balance`` if using Istanbul EVM * SMTChecker: Add break/continue support to the CHC engine. * SMTChecker: Support assignments to multi-dimensional arrays and mappings. + * EWasm: Experimental EWasm binary output. Bugfixes: diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 86e88ce3d..d1701320f 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -907,6 +907,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting // eWasm if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wast", wildcardMatchesExperimental)) contractData["ewasm"]["wast"] = compilerStack.eWasm(contractName); + if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ewasm.wasm", wildcardMatchesExperimental)) + contractData["ewasm"]["wasm"] = compilerStack.eWasmObject(contractName).toHex(); // EVM Json::Value evmData(Json::objectValue); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 28f4d6074..34b7c67c5 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -318,11 +318,18 @@ void CommandLineInterface::handleEWasm(string const& _contractName) 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) + ".wasm", + asString(m_compiler->eWasmObject(_contractName).bytecode) + ); + } else { - sout() << "eWasm: " << endl; + sout() << "EWasm text: " << endl; sout() << m_compiler->eWasm(_contractName) << endl; + sout() << "EWasm binary (hex): " << m_compiler->eWasmObject(_contractName).toHex() << endl; } } }