[solc] Add --import-asm-json input mode.

This commit is contained in:
Alexander Arlt 2021-11-04 16:53:32 -05:00
parent 7334420423
commit 235af2b4d1
4 changed files with 190 additions and 142 deletions

View File

@ -634,6 +634,7 @@ bool CommandLineInterface::processInput()
break;
case InputMode::Compiler:
case InputMode::CompilerWithASTImport:
case InputMode::CompilerWithEvmAssemblyJsonImport:
if (!compile())
return false;
outputCompilationResults();
@ -657,11 +658,22 @@ void CommandLineInterface::printLicense()
bool CommandLineInterface::compile()
{
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, ""
);
m_compiler = make_unique<CompilerStack>(m_fileReader.reader());
SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
}
else
{
SourceReferenceFormatter
formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
try
{
@ -682,25 +694,20 @@ 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());
@ -757,13 +764,18 @@ bool CommandLineInterface::compile()
return false;
}
}
return true;
}
void CommandLineInterface::handleCombinedJSON()
{
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::CompilerWithEvmAssemblyJsonImport ||
m_options.input.mode == InputMode::CompilerWithASTImport, ""
);
if (!m_options.compiler.combinedJsonRequests.has_value())
return;
@ -1095,17 +1107,25 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul:
void CommandLineInterface::outputCompilationResults()
{
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::CompilerWithEvmAssemblyJsonImport ||
m_options.input.mode == InputMode::CompilerWithASTImport, ""
);
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;
@ -1159,5 +1179,6 @@ void CommandLineInterface::outputCompilationResults()
serr() << "Compiler run successful, no output requested." << endl;
}
}
}
}

View File

@ -46,6 +46,7 @@ static string const g_strAllowPaths = "allow-paths";
static string const g_strBasePath = "base-path";
static string const g_strIncludePath = "include-path";
static string const g_strAssemble = "assemble";
static string const g_strImportEvmAssemblerJson = "import-asm-json";
static string const g_strCombinedJson = "combined-json";
static string const g_strErrorRecovery = "error-recovery";
static string const g_strEVM = "evm";
@ -134,6 +135,7 @@ static map<InputMode, string> const g_inputModeName = {
{InputMode::Compiler, "compiler"},
{InputMode::CompilerWithASTImport, "compiler (AST import)"},
{InputMode::Assembler, "assembler"},
{InputMode::CompilerWithEvmAssemblyJsonImport, "assembler (EVM ASM JSON import)"},
{InputMode::StandardJson, "standard JSON"},
{InputMode::Linker, "linker"},
};
@ -321,7 +323,20 @@ bool CommandLineParser::parseInputPathsAndRemappings()
m_options.input.paths.insert(positionalArg);
}
if (m_options.input.mode == InputMode::StandardJson)
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
if (m_options.input.paths.size() > 1 || (m_options.input.paths.size() == 1 && m_options.input.addStdin))
{
serr() << "Too many input files for --" << g_strImportEvmAssemblerJson << "." << endl;
serr() << "Please either specify a single file name or provide its content on standard input." << endl;
return false;
}
else if (m_options.input.paths.size() == 0)
// Standard JSON mode input used to be handled separately and zero files meant "read from stdin".
// Keep it working that way for backwards-compatibility.
m_options.input.addStdin = true;
}
else if (m_options.input.mode == InputMode::StandardJson)
{
if (m_options.input.paths.size() > 1 || (m_options.input.paths.size() == 1 && m_options.input.addStdin))
{
@ -466,6 +481,7 @@ bool CommandLineParser::parseOutputSelection()
case InputMode::Version:
solAssert(false);
case InputMode::Compiler:
case InputMode::CompilerWithEvmAssemblyJsonImport:
case InputMode::CompilerWithASTImport:
return contains(compilerModeOutputs, _outputName);
case InputMode::Assembler:
@ -644,6 +660,10 @@ General Information)").c_str(),
"Supported Inputs is the output of the --" + g_strStandardJSON + " or the one produced by "
"--" + g_strCombinedJson + " " + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast)).c_str()
)
(
g_strImportEvmAssemblerJson.c_str(),
"Import evm assembler json to be compiled, assumes input holds the evm assembly in JSON format."
)
;
desc.add(alternativeInputModes);
@ -879,6 +899,7 @@ bool CommandLineParser::processArgs()
g_strStrictAssembly,
g_strYul,
g_strImportAst,
g_strImportEvmAssemblerJson,
}))
return false;
@ -892,6 +913,8 @@ bool CommandLineParser::processArgs()
m_options.input.mode = InputMode::StandardJson;
else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0 || m_args.count(g_strYul) > 0)
m_options.input.mode = InputMode::Assembler;
else if (m_args.count(g_strImportEvmAssemblerJson) > 0)
m_options.input.mode = InputMode::CompilerWithEvmAssemblyJsonImport;
else if (m_args.count(g_strLink) > 0)
m_options.input.mode = InputMode::Linker;
else if (m_args.count(g_strImportAst) > 0)
@ -946,8 +969,8 @@ bool CommandLineParser::processArgs()
if (
m_options.input.mode != InputMode::Compiler &&
m_options.input.mode != InputMode::CompilerWithASTImport &&
m_options.input.mode != InputMode::Assembler
)
m_options.input.mode != InputMode::Assembler &&
m_options.input.mode != InputMode::CompilerWithEvmAssemblyJsonImport)
{
if (!m_args[g_strOptimizeRuns].defaulted())
{
@ -1127,16 +1150,18 @@ bool CommandLineParser::processArgs()
m_options.optimizer.yulSteps = m_args[g_strYulOptimizations].as<string>();
}
if (m_options.input.mode == InputMode::Assembler)
if (m_options.input.mode == InputMode::Assembler ||
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
{
vector<string> const nonAssemblyModeOptions = {
vector<string> nonAssemblyModeOptions = {
// TODO: The list is not complete. Add more.
g_strOutputDir,
g_strGas,
g_strCombinedJson,
g_strOptimizeYul,
g_strNoOptimizeYul,
};
if (m_options.input.mode == InputMode::Assembler)
nonAssemblyModeOptions.emplace_back(g_strCombinedJson);
if (countEnabledOptions(nonAssemblyModeOptions) >= 1)
{
auto optionEnabled = [&](string const& name){ return m_args.count(name) > 0; };
@ -1206,6 +1231,7 @@ bool CommandLineParser::processArgs()
serr() << "and automatic translation is not available." << endl;
return false;
}
if (m_options.input.mode == InputMode::Assembler)
serr() <<
"Warning: Yul is still experimental. Please use the output with care." <<
endl;

View File

@ -56,6 +56,7 @@ enum class InputMode
StandardJson,
Linker,
Assembler,
CompilerWithEvmAssemblyJsonImport,
};
struct CompilerOutputs

View File

@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes)
};
string expectedMessage =
"The following options are mutually exclusive: "
"--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast. "
"--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --import-asm-json. "
"Select at most one.\n";
for (string const& mode1: inputModeOptions)