[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;
}
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)
{
if (m_stackState != Empty)

View File

@ -222,6 +222,8 @@ public:
/// Will throw errors if the import fails
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,
/// typechecking, staticAnalysis) on previously parsed sources.
/// @returns false on error.
@ -499,6 +501,7 @@ private:
std::map<std::string const, Source> m_sources;
// if imported, store AST-JSONS for each filename
std::map<std::string, Json::Value> m_sourceJsons;
std::unique_ptr<Json::Value> m_evmAssemblyJson;
std::vector<std::string> m_unhandledSMTLib2Queries;
std::map<util::h256, std::string> m_smtlib2Responses;
std::shared_ptr<GlobalContext> m_globalContext;

View File

@ -155,7 +155,11 @@ static bool coloredOutput(CommandLineOptions const& _options)
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)
{
@ -250,7 +254,11 @@ void CommandLineInterface::handleEwasm(string const& _contractName)
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)
handleOpcode(_contract);
@ -546,6 +554,25 @@ map<string, Json::Value> CommandLineInterface::parseAstFromInput()
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)
{
namespace fs = boost::filesystem;
@ -666,14 +693,7 @@ bool CommandLineInterface::compile()
m_compiler = make_unique<CompilerStack>(m_fileReader.reader());
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
}
else
{
SourceReferenceFormatter
formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
try
{
@ -694,20 +714,25 @@ bool CommandLineInterface::compile()
m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized);
m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm);
m_compiler->enableEvmBytecodeGeneration(
m_options.compiler.estimateGas || m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson
|| m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary
|| m_options.compiler.outputs.binaryRuntime
|| (m_options.compiler.combinedJsonRequests
&& (m_options.compiler.combinedJsonRequests->binary
|| m_options.compiler.combinedJsonRequests->binaryRuntime
|| m_options.compiler.combinedJsonRequests->opcodes
|| m_options.compiler.combinedJsonRequests->asm_
|| m_options.compiler.combinedJsonRequests->generatedSources
|| m_options.compiler.combinedJsonRequests->generatedSourcesRuntime
|| m_options.compiler.combinedJsonRequests->srcMap
|| m_options.compiler.combinedJsonRequests->srcMapRuntime
|| m_options.compiler.combinedJsonRequests->funDebug
|| m_options.compiler.combinedJsonRequests->funDebugRuntime)));
m_options.compiler.estimateGas ||
m_options.compiler.outputs.asm_ ||
m_options.compiler.outputs.asmJson ||
m_options.compiler.outputs.opcodes ||
m_options.compiler.outputs.binary ||
m_options.compiler.outputs.binaryRuntime ||
(m_options.compiler.combinedJsonRequests && (
m_options.compiler.combinedJsonRequests->binary ||
m_options.compiler.combinedJsonRequests->binaryRuntime ||
m_options.compiler.combinedJsonRequests->opcodes ||
m_options.compiler.combinedJsonRequests->asm_ ||
m_options.compiler.combinedJsonRequests->generatedSources ||
m_options.compiler.combinedJsonRequests->generatedSourcesRuntime ||
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());
@ -729,6 +754,19 @@ bool CommandLineInterface::compile()
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
{
m_compiler->setSources(m_fileReader.sourceCodes());
@ -764,7 +802,6 @@ bool CommandLineInterface::compile()
return false;
}
}
return true;
}
@ -773,8 +810,8 @@ void CommandLineInterface::handleCombinedJSON()
{
solAssert(
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())
@ -867,7 +904,11 @@ void CommandLineInterface::handleCombinedJSON()
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)
return;
@ -1109,23 +1150,19 @@ void CommandLineInterface::outputCompilationResults()
{
solAssert(
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();
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
handleBytecode("");
}
else
{
// do we need AST output?
handleAst();
if (!m_compiler->compilationSuccessful()
&& m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful)
if (
!m_compiler->compilationSuccessful() &&
m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful
)
{
serr() << endl << "Compilation halted after AST generation due to errors." << endl;
return;
@ -1179,6 +1216,5 @@ void CommandLineInterface::outputCompilationResults()
serr() << "Compiler run successful, no output requested." << endl;
}
}
}
}

View File

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