[libsolidity] Prepare evm assembly json import.

This commit is contained in:
Alexander Arlt 2021-11-08 14:30:11 -05:00
parent 235af2b4d1
commit 9a3e248d51
4 changed files with 196 additions and 144 deletions

View File

@ -388,6 +388,17 @@ bool CompilerStack::parse()
return !m_hasError; return !m_hasError;
} }
void CompilerStack::importEvmAssemblyJson(map<string, Json::Value> const& _sources)
{
solAssert(_sources.size() == 1, "");
if (m_stackState != Empty)
solThrow(CompilerError, "Must call importEvmAssemblyJson only before the SourcesSet state.");
m_evmAssemblyJson = std::make_unique<Json::Value>(_sources.begin()->second);
m_importedSources = true;
m_stackState = SourcesSet;
}
void CompilerStack::importASTs(map<string, Json::Value> const& _sources) void CompilerStack::importASTs(map<string, Json::Value> const& _sources)
{ {
if (m_stackState != Empty) if (m_stackState != Empty)

View File

@ -222,6 +222,8 @@ public:
/// Will throw errors if the import fails /// Will throw errors if the import fails
void importASTs(std::map<std::string, Json::Value> const& _sources); void importASTs(std::map<std::string, Json::Value> const& _sources);
void importEvmAssemblyJson(std::map<std::string, Json::Value> const& _sources);
/// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving, /// Performs the analysis steps (imports, scopesetting, syntaxCheck, referenceResolving,
/// typechecking, staticAnalysis) on previously parsed sources. /// typechecking, staticAnalysis) on previously parsed sources.
/// @returns false on error. /// @returns false on error.
@ -499,6 +501,7 @@ private:
std::map<std::string const, Source> m_sources; std::map<std::string const, Source> m_sources;
// if imported, store AST-JSONS for each filename // if imported, store AST-JSONS for each filename
std::map<std::string, Json::Value> m_sourceJsons; std::map<std::string, Json::Value> m_sourceJsons;
std::unique_ptr<Json::Value> m_evmAssemblyJson;
std::vector<std::string> m_unhandledSMTLib2Queries; std::vector<std::string> m_unhandledSMTLib2Queries;
std::map<util::h256, std::string> m_smtlib2Responses; std::map<util::h256, std::string> m_smtlib2Responses;
std::shared_ptr<GlobalContext> m_globalContext; std::shared_ptr<GlobalContext> m_globalContext;

View File

@ -155,7 +155,11 @@ static bool coloredOutput(CommandLineOptions const& _options)
void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleBinary(string const& _contract)
{ {
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); solAssert(
m_options.input.mode == InputMode::Compiler ||
m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport , ""
);
if (m_options.compiler.outputs.binary) if (m_options.compiler.outputs.binary)
{ {
@ -250,7 +254,11 @@ void CommandLineInterface::handleEwasm(string const& _contractName)
void CommandLineInterface::handleBytecode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract)
{ {
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); solAssert(
m_options.input.mode == InputMode::Compiler ||
m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport , ""
);
if (m_options.compiler.outputs.opcodes) if (m_options.compiler.outputs.opcodes)
handleOpcode(_contract); handleOpcode(_contract);
@ -546,6 +554,25 @@ map<string, Json::Value> CommandLineInterface::parseAstFromInput()
return sourceJsons; return sourceJsons;
} }
map<string, Json::Value> CommandLineInterface::parseEvmAssemblyJsonFromInput()
{
solAssert(m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, "");
solAssert(m_fileReader.sourceCodes().size() == 1, "");
map<string, Json::Value> sourceJsons;
for (auto const& iter: m_fileReader.sourceCodes())
{
Json::Value evmAsmJson;
astAssert(jsonParseStrict(iter.second, evmAsmJson), "Input file could not be parsed to JSON");
astAssert(evmAsmJson.isMember(".code"), "Invalid Format for assembly-JSON: Must have '.code'-object");
astAssert(evmAsmJson.isMember(".data"), "Invalid Format for assembly-JSON: Must have '.data'-object");
sourceJsons[iter.first] = evmAsmJson;
}
return sourceJsons;
}
void CommandLineInterface::createFile(string const& _fileName, string const& _data) void CommandLineInterface::createFile(string const& _fileName, string const& _data)
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -666,14 +693,7 @@ bool CommandLineInterface::compile()
m_compiler = make_unique<CompilerStack>(m_fileReader.reader()); m_compiler = make_unique<CompilerStack>(m_fileReader.reader());
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport) SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
{
}
else
{
SourceReferenceFormatter
formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
try try
{ {
@ -694,20 +714,25 @@ bool CommandLineInterface::compile()
m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized); m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized);
m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm); m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm);
m_compiler->enableEvmBytecodeGeneration( m_compiler->enableEvmBytecodeGeneration(
m_options.compiler.estimateGas || m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson m_options.compiler.estimateGas ||
|| m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary m_options.compiler.outputs.asm_ ||
|| m_options.compiler.outputs.binaryRuntime m_options.compiler.outputs.asmJson ||
|| (m_options.compiler.combinedJsonRequests m_options.compiler.outputs.opcodes ||
&& (m_options.compiler.combinedJsonRequests->binary m_options.compiler.outputs.binary ||
|| m_options.compiler.combinedJsonRequests->binaryRuntime m_options.compiler.outputs.binaryRuntime ||
|| m_options.compiler.combinedJsonRequests->opcodes (m_options.compiler.combinedJsonRequests && (
|| m_options.compiler.combinedJsonRequests->asm_ m_options.compiler.combinedJsonRequests->binary ||
|| m_options.compiler.combinedJsonRequests->generatedSources m_options.compiler.combinedJsonRequests->binaryRuntime ||
|| m_options.compiler.combinedJsonRequests->generatedSourcesRuntime m_options.compiler.combinedJsonRequests->opcodes ||
|| m_options.compiler.combinedJsonRequests->srcMap m_options.compiler.combinedJsonRequests->asm_ ||
|| m_options.compiler.combinedJsonRequests->srcMapRuntime m_options.compiler.combinedJsonRequests->generatedSources ||
|| m_options.compiler.combinedJsonRequests->funDebug m_options.compiler.combinedJsonRequests->generatedSourcesRuntime ||
|| m_options.compiler.combinedJsonRequests->funDebugRuntime))); m_options.compiler.combinedJsonRequests->srcMap ||
m_options.compiler.combinedJsonRequests->srcMapRuntime ||
m_options.compiler.combinedJsonRequests->funDebug ||
m_options.compiler.combinedJsonRequests->funDebugRuntime
))
);
m_compiler->setOptimiserSettings(m_options.optimiserSettings()); m_compiler->setOptimiserSettings(m_options.optimiserSettings());
@ -729,6 +754,19 @@ bool CommandLineInterface::compile()
return false; return false;
} }
} }
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
solAssert(m_fileReader.sourceCodes().size() == 1, "");
try
{
m_compiler->importEvmAssemblyJson(parseEvmAssemblyJsonFromInput());
}
catch (Exception const& _exc)
{
serr() << string("Failed to import Assembly JSON: ") << _exc.what() << endl;
return false;
}
}
else else
{ {
m_compiler->setSources(m_fileReader.sourceCodes()); m_compiler->setSources(m_fileReader.sourceCodes());
@ -764,7 +802,6 @@ bool CommandLineInterface::compile()
return false; return false;
} }
}
return true; return true;
} }
@ -773,8 +810,8 @@ void CommandLineInterface::handleCombinedJSON()
{ {
solAssert( solAssert(
m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::Compiler ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport || m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::CompilerWithASTImport, "" m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
); );
if (!m_options.compiler.combinedJsonRequests.has_value()) if (!m_options.compiler.combinedJsonRequests.has_value())
@ -867,7 +904,11 @@ void CommandLineInterface::handleCombinedJSON()
void CommandLineInterface::handleAst() void CommandLineInterface::handleAst()
{ {
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); solAssert(
m_options.input.mode == InputMode::Compiler ||
m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
);
if (!m_options.compiler.outputs.astCompactJson) if (!m_options.compiler.outputs.astCompactJson)
return; return;
@ -1109,23 +1150,19 @@ void CommandLineInterface::outputCompilationResults()
{ {
solAssert( solAssert(
m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::Compiler ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport || m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::CompilerWithASTImport, "" m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
); );
handleCombinedJSON(); handleCombinedJSON();
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
handleBytecode("");
}
else
{
// do we need AST output? // do we need AST output?
handleAst(); handleAst();
if (!m_compiler->compilationSuccessful() if (
&& m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful) !m_compiler->compilationSuccessful() &&
m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful
)
{ {
serr() << endl << "Compilation halted after AST generation due to errors." << endl; serr() << endl << "Compilation halted after AST generation due to errors." << endl;
return; return;
@ -1179,6 +1216,5 @@ void CommandLineInterface::outputCompilationResults()
serr() << "Compiler run successful, no output requested." << endl; serr() << "Compiler run successful, no output requested." << endl;
} }
} }
}
} }

View File

@ -98,6 +98,8 @@ private:
/// or standard-json output /// or standard-json output
std::map<std::string, Json::Value> parseAstFromInput(); std::map<std::string, Json::Value> parseAstFromInput();
std::map<std::string, Json::Value> parseEvmAssemblyJsonFromInput();
/// Create a file in the given directory /// Create a file in the given directory
/// @arg _fileName the name of the file /// @arg _fileName the name of the file
/// @arg _data to be written /// @arg _data to be written