Skip to content

Commit 1f091f6

Browse files
committed
[solc] Add --import-asm-json input mode.
1 parent 19159b9 commit 1f091f6

File tree

4 files changed

+188
-140
lines changed

4 files changed

+188
-140
lines changed

solc/CommandLineInterface.cpp

Lines changed: 149 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ bool CommandLineInterface::processInput()
634634
break;
635635
case InputMode::Compiler:
636636
case InputMode::CompilerWithASTImport:
637+
case InputMode::CompilerWithEvmAssemblyJsonImport:
637638
if (!compile())
638639
return false;
639640
outputCompilationResults();
@@ -657,113 +658,124 @@ void CommandLineInterface::printLicense()
657658

658659
bool CommandLineInterface::compile()
659660
{
660-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
661+
solAssert(
662+
m_options.input.mode == InputMode::Compiler ||
663+
m_options.input.mode == InputMode::CompilerWithASTImport ||
664+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
665+
);
661666

662667
m_compiler = make_unique<CompilerStack>(m_fileReader.reader());
663668

664-
SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
665-
666-
try
669+
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
667670
{
668-
if (m_options.metadata.literalSources)
669-
m_compiler->useMetadataLiteralSources(true);
670-
m_compiler->setMetadataHash(m_options.metadata.hash);
671-
if (m_options.modelChecker.initialize)
672-
m_compiler->setModelCheckerSettings(m_options.modelChecker.settings);
673-
m_compiler->setRemappings(m_options.input.remappings);
674-
m_compiler->setLibraries(m_options.linker.libraries);
675-
m_compiler->setViaIR(m_options.output.experimentalViaIR);
676-
m_compiler->setEVMVersion(m_options.output.evmVersion);
677-
m_compiler->setRevertStringBehaviour(m_options.output.revertStrings);
678-
if (m_options.output.debugInfoSelection.has_value())
679-
m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value());
680-
// TODO: Perhaps we should not compile unless requested
681-
682-
m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized);
683-
m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm);
684-
m_compiler->enableEvmBytecodeGeneration(
685-
m_options.compiler.estimateGas ||
686-
m_options.compiler.outputs.asm_ ||
687-
m_options.compiler.outputs.asmJson ||
688-
m_options.compiler.outputs.opcodes ||
689-
m_options.compiler.outputs.binary ||
690-
m_options.compiler.outputs.binaryRuntime ||
691-
(m_options.compiler.combinedJsonRequests && (
692-
m_options.compiler.combinedJsonRequests->binary ||
693-
m_options.compiler.combinedJsonRequests->binaryRuntime ||
694-
m_options.compiler.combinedJsonRequests->opcodes ||
695-
m_options.compiler.combinedJsonRequests->asm_ ||
696-
m_options.compiler.combinedJsonRequests->generatedSources ||
697-
m_options.compiler.combinedJsonRequests->generatedSourcesRuntime ||
698-
m_options.compiler.combinedJsonRequests->srcMap ||
699-
m_options.compiler.combinedJsonRequests->srcMapRuntime ||
700-
m_options.compiler.combinedJsonRequests->funDebug ||
701-
m_options.compiler.combinedJsonRequests->funDebugRuntime
702-
))
703-
);
704671

705-
m_compiler->setOptimiserSettings(m_options.optimiserSettings());
672+
}
673+
else
674+
{
675+
SourceReferenceFormatter
676+
formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
706677

707-
if (m_options.input.mode == InputMode::CompilerWithASTImport)
678+
try
708679
{
709-
try
680+
if (m_options.metadata.literalSources)
681+
m_compiler->useMetadataLiteralSources(true);
682+
m_compiler->setMetadataHash(m_options.metadata.hash);
683+
if (m_options.modelChecker.initialize)
684+
m_compiler->setModelCheckerSettings(m_options.modelChecker.settings);
685+
m_compiler->setRemappings(m_options.input.remappings);
686+
m_compiler->setLibraries(m_options.linker.libraries);
687+
m_compiler->setViaIR(m_options.output.experimentalViaIR);
688+
m_compiler->setEVMVersion(m_options.output.evmVersion);
689+
m_compiler->setRevertStringBehaviour(m_options.output.revertStrings);
690+
if (m_options.output.debugInfoSelection.has_value())
691+
m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value());
692+
// TODO: Perhaps we should not compile unless requested
693+
694+
m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized);
695+
m_compiler->enableEwasmGeneration(m_options.compiler.outputs.ewasm);
696+
m_compiler->enableEvmBytecodeGeneration(
697+
m_options.compiler.estimateGas || m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson
698+
|| m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary
699+
|| m_options.compiler.outputs.binaryRuntime
700+
|| (m_options.compiler.combinedJsonRequests
701+
&& (m_options.compiler.combinedJsonRequests->binary
702+
|| m_options.compiler.combinedJsonRequests->binaryRuntime
703+
|| m_options.compiler.combinedJsonRequests->opcodes
704+
|| m_options.compiler.combinedJsonRequests->asm_
705+
|| m_options.compiler.combinedJsonRequests->generatedSources
706+
|| m_options.compiler.combinedJsonRequests->generatedSourcesRuntime
707+
|| m_options.compiler.combinedJsonRequests->srcMap
708+
|| m_options.compiler.combinedJsonRequests->srcMapRuntime
709+
|| m_options.compiler.combinedJsonRequests->funDebug
710+
|| m_options.compiler.combinedJsonRequests->funDebugRuntime)));
711+
712+
m_compiler->setOptimiserSettings(m_options.optimiserSettings());
713+
714+
if (m_options.input.mode == InputMode::CompilerWithASTImport)
710715
{
711-
m_compiler->importASTs(parseAstFromInput());
716+
try
717+
{
718+
m_compiler->importASTs(parseAstFromInput());
712719

713-
if (!m_compiler->analyze())
720+
if (!m_compiler->analyze())
721+
{
722+
formatter.printErrorInformation(m_compiler->errors());
723+
astAssert(false, "Analysis of the AST failed");
724+
}
725+
}
726+
catch (Exception const& _exc)
714727
{
715-
formatter.printErrorInformation(m_compiler->errors());
716-
astAssert(false, "Analysis of the AST failed");
728+
serr() << string("Failed to import AST: ") << _exc.what() << endl;
729+
return false;
717730
}
718731
}
719-
catch (Exception const& _exc)
732+
else
720733
{
721-
serr() << string("Failed to import AST: ") << _exc.what() << endl;
722-
return false;
734+
m_compiler->setSources(m_fileReader.sourceCodes());
735+
m_compiler->setParserErrorRecovery(m_options.input.errorRecovery);
723736
}
724-
}
725-
else
726-
{
727-
m_compiler->setSources(m_fileReader.sourceCodes());
728-
m_compiler->setParserErrorRecovery(m_options.input.errorRecovery);
729-
}
730737

731-
bool successful = m_compiler->compile(m_options.output.stopAfter);
738+
bool successful = m_compiler->compile(m_options.output.stopAfter);
732739

733-
for (auto const& error: m_compiler->errors())
734-
{
735-
m_hasOutput = true;
736-
formatter.printErrorInformation(*error);
737-
}
740+
for (auto const& error: m_compiler->errors())
741+
{
742+
m_hasOutput = true;
743+
formatter.printErrorInformation(*error);
744+
}
738745

739-
if (!successful)
740-
return m_options.input.errorRecovery;
741-
}
742-
catch (CompilerError const& _exception)
743-
{
744-
m_hasOutput = true;
745-
formatter.printExceptionInformation(_exception, "Compiler error");
746-
return false;
747-
}
748-
catch (Error const& _error)
749-
{
750-
if (_error.type() == Error::Type::DocstringParsingError)
751-
serr() << "Documentation parsing error: " << *boost::get_error_info<errinfo_comment>(_error) << endl;
752-
else
746+
if (!successful)
747+
return m_options.input.errorRecovery;
748+
}
749+
catch (CompilerError const& _exception)
753750
{
754751
m_hasOutput = true;
755-
formatter.printExceptionInformation(_error, _error.typeName());
752+
formatter.printExceptionInformation(_exception, "Compiler error");
753+
return false;
756754
}
755+
catch (Error const& _error)
756+
{
757+
if (_error.type() == Error::Type::DocstringParsingError)
758+
serr() << "Documentation parsing error: " << *boost::get_error_info<errinfo_comment>(_error) << endl;
759+
else
760+
{
761+
m_hasOutput = true;
762+
formatter.printExceptionInformation(_error, _error.typeName());
763+
}
757764

758-
return false;
765+
return false;
766+
}
759767
}
760768

761769
return true;
762770
}
763771

764772
void CommandLineInterface::handleCombinedJSON()
765773
{
766-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
774+
solAssert(
775+
m_options.input.mode == InputMode::Compiler ||
776+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport ||
777+
m_options.input.mode == InputMode::CompilerWithASTImport, ""
778+
);
767779

768780
if (!m_options.compiler.combinedJsonRequests.has_value())
769781
return;
@@ -1095,68 +1107,77 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul:
10951107

10961108
void CommandLineInterface::outputCompilationResults()
10971109
{
1098-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
1110+
solAssert(
1111+
m_options.input.mode == InputMode::Compiler ||
1112+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport ||
1113+
m_options.input.mode == InputMode::CompilerWithASTImport, ""
1114+
);
10991115

11001116
handleCombinedJSON();
11011117

1102-
// do we need AST output?
1103-
handleAst();
1104-
1105-
if (
1106-
!m_compiler->compilationSuccessful() &&
1107-
m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful
1108-
)
1118+
if (m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport)
11091119
{
1110-
serr() << endl << "Compilation halted after AST generation due to errors." << endl;
1111-
return;
1120+
handleBytecode("");
11121121
}
1113-
1114-
vector<string> contracts = m_compiler->contractNames();
1115-
for (string const& contract: contracts)
1122+
else
11161123
{
1117-
if (needsHumanTargetedStdout(m_options))
1118-
sout() << endl << "======= " << contract << " =======" << endl;
1124+
// do we need AST output?
1125+
handleAst();
11191126

1120-
// do we need EVM assembly?
1121-
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
1127+
if (!m_compiler->compilationSuccessful()
1128+
&& m_options.output.stopAfter == CompilerStack::State::CompilationSuccessful)
11221129
{
1123-
string ret;
1124-
if (m_options.compiler.outputs.asmJson)
1125-
ret = jsonPrettyPrint(removeNullMembers(m_compiler->assemblyJSON(contract)));
1126-
else
1127-
ret = m_compiler->assemblyString(contract, m_fileReader.sourceCodes());
1130+
serr() << endl << "Compilation halted after AST generation due to errors." << endl;
1131+
return;
1132+
}
11281133

1129-
if (!m_options.output.dir.empty())
1134+
vector<string> contracts = m_compiler->contractNames();
1135+
for (string const& contract: contracts)
1136+
{
1137+
if (needsHumanTargetedStdout(m_options))
1138+
sout() << endl << "======= " << contract << " =======" << endl;
1139+
1140+
// do we need EVM assembly?
1141+
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
11301142
{
1131-
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
1143+
string ret;
1144+
if (m_options.compiler.outputs.asmJson)
1145+
ret = jsonPrettyPrint(removeNullMembers(m_compiler->assemblyJSON(contract)));
1146+
else
1147+
ret = m_compiler->assemblyString(contract, m_fileReader.sourceCodes());
1148+
1149+
if (!m_options.output.dir.empty())
1150+
{
1151+
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
1152+
}
1153+
else
1154+
{
1155+
sout() << "EVM assembly:" << endl << ret << endl;
1156+
}
11321157
}
1158+
1159+
if (m_options.compiler.estimateGas)
1160+
handleGasEstimation(contract);
1161+
1162+
handleBytecode(contract);
1163+
handleIR(contract);
1164+
handleIROptimized(contract);
1165+
handleEwasm(contract);
1166+
handleSignatureHashes(contract);
1167+
handleMetadata(contract);
1168+
handleABI(contract);
1169+
handleStorageLayout(contract);
1170+
handleNatspec(true, contract);
1171+
handleNatspec(false, contract);
1172+
} // end of contracts iteration
1173+
1174+
if (!m_hasOutput)
1175+
{
1176+
if (!m_options.output.dir.empty())
1177+
sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl;
11331178
else
1134-
{
1135-
sout() << "EVM assembly:" << endl << ret << endl;
1136-
}
1179+
serr() << "Compiler run successful, no output requested." << endl;
11371180
}
1138-
1139-
if (m_options.compiler.estimateGas)
1140-
handleGasEstimation(contract);
1141-
1142-
handleBytecode(contract);
1143-
handleIR(contract);
1144-
handleIROptimized(contract);
1145-
handleEwasm(contract);
1146-
handleSignatureHashes(contract);
1147-
handleMetadata(contract);
1148-
handleABI(contract);
1149-
handleStorageLayout(contract);
1150-
handleNatspec(true, contract);
1151-
handleNatspec(false, contract);
1152-
} // end of contracts iteration
1153-
1154-
if (!m_hasOutput)
1155-
{
1156-
if (!m_options.output.dir.empty())
1157-
sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl;
1158-
else
1159-
serr() << "Compiler run successful, no output requested." << endl;
11601181
}
11611182
}
11621183

0 commit comments

Comments
 (0)