-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Add --import-asm-json input mode. #12704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
43fe553
d71de24
e25a1a3
00f0343
0c0853e
c097842
39d56ee
43faf23
e8f76ff
6700a65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -414,6 +414,28 @@ void CompilerStack::importASTs(map<string, Json::Value> const& _sources) | |
storeContractDefinitions(); | ||
} | ||
|
||
void CompilerStack::importEvmAssemblyJson(std::map<std::string, Json::Value> const& _sources) | ||
{ | ||
solAssert(_sources.size() == 1, ""); | ||
solAssert(m_sources.empty(), ""); | ||
solAssert(m_sourceOrder.empty(), ""); | ||
if (m_stackState != Empty) | ||
solThrow(CompilerError, "Must call importEvmAssemblyJson only before the SourcesSet state."); | ||
|
||
Json::Value jsonValue = _sources.begin()->second; | ||
if (jsonValue.isMember("sourceList")) | ||
for (auto const& item: jsonValue["sourceList"]) | ||
{ | ||
Source source; | ||
source.charStream = std::make_shared<CharStream>(item.asString(), ""); | ||
m_sources.emplace(std::make_pair(item.asString(), source)); | ||
m_sourceOrder.push_back(&m_sources[item.asString()]); | ||
} | ||
m_evmAssemblyJson[_sources.begin()->first] = jsonValue; | ||
m_importedSources = true; | ||
m_stackState = SourcesSet; | ||
} | ||
|
||
bool CompilerStack::analyze() | ||
{ | ||
if (m_stackState != ParsedAndImported || m_stackState >= AnalysisPerformed) | ||
|
@@ -600,6 +622,9 @@ bool CompilerStack::parseAndAnalyze(State _stopAfter) | |
{ | ||
m_stopAfter = _stopAfter; | ||
|
||
if (!m_evmAssemblyJson.empty()) | ||
return true; | ||
|
||
bool success = parse(); | ||
if (m_stackState >= m_stopAfter) | ||
return success; | ||
|
@@ -649,55 +674,85 @@ bool CompilerStack::compile(State _stopAfter) | |
// Only compile contracts individually which have been requested. | ||
map<ContractDefinition const*, shared_ptr<Compiler const>> otherCompilers; | ||
|
||
for (Source const* source: m_sourceOrder) | ||
for (ASTPointer<ASTNode> const& node: source->ast->nodes()) | ||
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) | ||
if (isRequestedContract(*contract)) | ||
{ | ||
try | ||
if (!m_evmAssemblyJson.empty()) | ||
{ | ||
solAssert(m_importedSources, ""); | ||
solAssert(m_evmAssemblyJson.size() == 1, ""); | ||
|
||
string const evmSourceName = m_evmAssemblyJson.begin()->first; | ||
Json::Value const evmJson = m_evmAssemblyJson.begin()->second; | ||
|
||
evmasm::Assembly::OptimiserSettings optimiserSettings; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I saw somewhere a optimiser-settings transform function. |
||
optimiserSettings.evmVersion = m_evmVersion; | ||
optimiserSettings.expectedExecutionsPerDeployment = m_optimiserSettings.expectedExecutionsPerDeployment; | ||
optimiserSettings.runCSE = m_optimiserSettings.runCSE; | ||
optimiserSettings.runConstantOptimiser = m_optimiserSettings.runConstantOptimiser; | ||
optimiserSettings.runDeduplicate = m_optimiserSettings.runDeduplicate; | ||
optimiserSettings.runInliner = m_optimiserSettings.runInliner; | ||
optimiserSettings.runJumpdestRemover = m_optimiserSettings.runJumpdestRemover; | ||
optimiserSettings.runPeephole = m_optimiserSettings.runPeephole; | ||
|
||
m_contracts[evmSourceName].evmAssembly = make_shared<evmasm::Assembly>(true, evmSourceName); | ||
m_contracts[evmSourceName].evmAssembly->loadFromAssemblyJSON(m_evmAssemblyJson[evmSourceName]); | ||
if (m_optimiserSettings.enabled) | ||
m_contracts[evmSourceName].evmAssembly->optimise(optimiserSettings); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
m_contracts[evmSourceName].object = m_contracts[evmSourceName].evmAssembly->assemble(); | ||
|
||
m_contracts[evmSourceName].evmRuntimeAssembly = make_shared<evmasm::Assembly>(false, evmSourceName); | ||
m_contracts[evmSourceName].evmRuntimeAssembly->setSources(m_contracts[evmSourceName].evmAssembly->sources()); | ||
m_contracts[evmSourceName].evmRuntimeAssembly->loadFromAssemblyJSON(m_evmAssemblyJson[evmSourceName][".data"]["0"], false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @chriseth @ekpyron Does it make sense to load the runtime assembly hardcoded from |
||
if (m_optimiserSettings.enabled) | ||
m_contracts[evmSourceName].evmRuntimeAssembly->optimise(optimiserSettings); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
m_contracts[evmSourceName].runtimeObject = m_contracts[evmSourceName].evmRuntimeAssembly->assemble(); | ||
} | ||
else | ||
{ | ||
for (Source const* source: m_sourceOrder) | ||
for (ASTPointer<ASTNode> const& node: source->ast->nodes()) | ||
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) | ||
if (isRequestedContract(*contract)) | ||
{ | ||
if (m_viaIR || m_generateIR || m_generateEwasm) | ||
generateIR(*contract); | ||
if (m_generateEvmBytecode) | ||
try | ||
{ | ||
if (m_viaIR) | ||
generateEVMFromIR(*contract); | ||
else | ||
compileContract(*contract, otherCompilers); | ||
if (m_viaIR || m_generateIR || m_generateEwasm) | ||
generateIR(*contract); | ||
if (m_generateEvmBytecode) | ||
{ | ||
if (m_viaIR) | ||
generateEVMFromIR(*contract); | ||
else | ||
compileContract(*contract, otherCompilers); | ||
} | ||
if (m_generateEwasm) | ||
generateEwasm(*contract); | ||
} | ||
if (m_generateEwasm) | ||
generateEwasm(*contract); | ||
} | ||
catch (Error const& _error) | ||
{ | ||
if (_error.type() != Error::Type::CodeGenerationError) | ||
throw; | ||
m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); | ||
return false; | ||
} | ||
catch (UnimplementedFeatureError const& _unimplementedError) | ||
{ | ||
if ( | ||
SourceLocation const* sourceLocation = | ||
boost::get_error_info<langutil::errinfo_sourceLocation>(_unimplementedError) | ||
) | ||
catch (Error const& _error) | ||
{ | ||
string const* comment = _unimplementedError.comment(); | ||
m_errorReporter.error( | ||
1834_error, | ||
Error::Type::CodeGenerationError, | ||
*sourceLocation, | ||
"Unimplemented feature error" + | ||
((comment && !comment->empty()) ? ": " + *comment : string{}) + | ||
" in " + | ||
_unimplementedError.lineInfo() | ||
); | ||
if (_error.type() != Error::Type::CodeGenerationError) | ||
throw; | ||
m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); | ||
return false; | ||
} | ||
else | ||
throw; | ||
catch (UnimplementedFeatureError const& _unimplementedError) | ||
{ | ||
if (SourceLocation const* sourceLocation | ||
= boost::get_error_info<langutil::errinfo_sourceLocation>(_unimplementedError)) | ||
{ | ||
string const* comment = _unimplementedError.comment(); | ||
m_errorReporter.error( | ||
1834_error, | ||
Error::Type::CodeGenerationError, | ||
*sourceLocation, | ||
"Unimplemented feature error" | ||
+ ((comment && !comment->empty()) ? ": " + *comment : string{}) + " in " | ||
+ _unimplementedError.lineInfo()); | ||
return false; | ||
} | ||
else | ||
throw; | ||
} | ||
} | ||
} | ||
} | ||
m_stackState = CompilationSuccessful; | ||
this->link(); | ||
return true; | ||
|
@@ -933,14 +988,21 @@ vector<string> CompilerStack::sourceNames() const | |
return names; | ||
} | ||
|
||
map<string, unsigned> CompilerStack::sourceIndices() const | ||
map<string, unsigned> CompilerStack::sourceIndices(bool _includeInternalSources /* = true */) const | ||
{ | ||
map<string, unsigned> indices; | ||
unsigned index = 0; | ||
for (auto const& s: m_sources) | ||
indices[s.first] = index++; | ||
solAssert(!indices.count(CompilerContext::yulUtilityFileName()), ""); | ||
indices[CompilerContext::yulUtilityFileName()] = index++; | ||
if (m_evmAssemblyJson.empty()) | ||
{ | ||
for (auto const& s: m_sources) | ||
indices[s.first] = index++; | ||
solAssert(!indices.count(CompilerContext::yulUtilityFileName()), ""); | ||
if (_includeInternalSources) | ||
indices[CompilerContext::yulUtilityFileName()] = index++; | ||
} | ||
else | ||
for (auto const& s: m_sourceOrder) | ||
indices[s->charStream->source()] = index++; | ||
return indices; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.