Skip to content

Commit 8bcad89

Browse files
committed
[solc] Basic --import-asm-json import.
1 parent 4f2baed commit 8bcad89

File tree

9 files changed

+518
-117
lines changed

9 files changed

+518
-117
lines changed

libevmasm/Assembly.cpp

Lines changed: 335 additions & 88 deletions
Large diffs are not rendered by default.

libevmasm/Assembly.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <sstream>
4040
#include <memory>
4141
#include <map>
42+
#include <utility>
4243

4344
namespace solidity::evmasm
4445
{
@@ -155,15 +156,28 @@ class Assembly
155156

156157
/// Create a JSON representation of the assembly.
157158
Json::Value assemblyJSON(
158-
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>()
159+
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(),
160+
bool _includeSourceList = true
159161
) const;
160162

163+
bool loadFromAssemblyJSON(Json::Value const& _json, bool _loadSources = true);
164+
161165
/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
162166
void markAsInvalid() { m_invalid = true; }
163167

164168
std::vector<size_t> decodeSubPath(size_t _subObjectId) const;
165169
size_t encodeSubPath(std::vector<size_t> const& _subPath);
166170

171+
void setSources(std::vector<std::shared_ptr<std::string const>> _sources) {
172+
m_sources = std::move(_sources);
173+
}
174+
175+
void setSources(std::vector<std::string> const& _sources) {
176+
for (auto const& item: _sources)
177+
m_sources.emplace_back(std::make_shared<std::string>(item));
178+
}
179+
std::vector<std::shared_ptr<std::string const>> sources() const& { return m_sources; }
180+
167181
protected:
168182
/// Does the same operations as @a optimise, but should only be applied to a sub and
169183
/// returns the replaced tags. Also takes an argument containing the tags of this assembly
@@ -172,10 +186,15 @@ class Assembly
172186

173187
unsigned codeSize(unsigned subTagSize) const;
174188

189+
AssemblyItem loadItemFromJSON(Json::Value const& _json);
190+
std::vector<Json::Value> assemblyItemAsJSON(AssemblyItem const& _item, int _sourceIndex) const;
191+
175192
private:
193+
bool addAssemblyItemsFromJSON(Json::Value const& _code);
176194
static Json::Value createJsonValue(
177195
std::string _name,
178-
int _source,
196+
int _sourceIndex,
197+
size_t _modifierDepth,
179198
int _begin,
180199
int _end,
181200
std::string _value = std::string(),
@@ -226,6 +245,8 @@ class Assembly
226245
std::string m_name;
227246

228247
langutil::SourceLocation m_currentSourceLocation;
248+
std::vector<std::shared_ptr<std::string const>> m_sources;
249+
229250
public:
230251
size_t m_currentModifierDepth = 0;
231252
};

libevmasm/AssemblyItem.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ string AssemblyItem::getJumpTypeAsString() const
192192
}
193193
}
194194

195+
void AssemblyItem::setJumpType(std::string const& _jumpType)
196+
{
197+
if (_jumpType == "[in]")
198+
m_jumpType = JumpType::IntoFunction;
199+
else if (_jumpType == "[out]")
200+
m_jumpType = JumpType::OutOfFunction;
201+
else if (_jumpType.empty())
202+
m_jumpType = JumpType::Ordinary;
203+
else
204+
assertThrow(false, AssemblyException, "Invalid jump type.");
205+
}
206+
195207
string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
196208
{
197209
string text;

libevmasm/AssemblyItem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class AssemblyItem
166166
langutil::SourceLocation const& location() const { return m_location; }
167167

168168
void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; }
169+
void setJumpType(std::string const& _jumpType);
169170
JumpType getJumpType() const { return m_jumpType; }
170171
std::string getJumpTypeAsString() const;
171172

libsolidity/interface/CompilerStack.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,34 @@ bool CompilerStack::compile(State _stopAfter)
676676

677677
if (!m_evmAssemblyJson.empty())
678678
{
679-
679+
solAssert(m_importedSources, "");
680+
solAssert(m_evmAssemblyJson.size() == 1, "");
681+
682+
string const evmSourceName = m_evmAssemblyJson.begin()->first;
683+
Json::Value const evmJson = m_evmAssemblyJson.begin()->second;
684+
685+
evmasm::Assembly::OptimiserSettings optimiserSettings;
686+
optimiserSettings.evmVersion = m_evmVersion;
687+
optimiserSettings.expectedExecutionsPerDeployment = m_optimiserSettings.expectedExecutionsPerDeployment;
688+
optimiserSettings.runCSE = m_optimiserSettings.runCSE;
689+
optimiserSettings.runConstantOptimiser = m_optimiserSettings.runConstantOptimiser;
690+
optimiserSettings.runDeduplicate = m_optimiserSettings.runDeduplicate;
691+
optimiserSettings.runInliner = m_optimiserSettings.runInliner;
692+
optimiserSettings.runJumpdestRemover = m_optimiserSettings.runJumpdestRemover;
693+
optimiserSettings.runPeephole = m_optimiserSettings.runPeephole;
694+
695+
m_contracts[evmSourceName].evmAssembly = make_shared<evmasm::Assembly>(evmSourceName);
696+
m_contracts[evmSourceName].evmAssembly->loadFromAssemblyJSON(m_evmAssemblyJson[evmSourceName]);
697+
if (m_optimiserSettings.enabled)
698+
m_contracts[evmSourceName].evmAssembly->optimise(optimiserSettings);
699+
m_contracts[evmSourceName].object = m_contracts[evmSourceName].evmAssembly->assemble();
700+
701+
m_contracts[evmSourceName].evmRuntimeAssembly = make_shared<evmasm::Assembly>(evmSourceName);
702+
m_contracts[evmSourceName].evmRuntimeAssembly->setSources(m_contracts[evmSourceName].evmAssembly->sources());
703+
m_contracts[evmSourceName].evmRuntimeAssembly->loadFromAssemblyJSON(m_evmAssemblyJson[evmSourceName][".data"]["0"], false);
704+
if (m_optimiserSettings.enabled)
705+
m_contracts[evmSourceName].evmRuntimeAssembly->optimise(optimiserSettings);
706+
m_contracts[evmSourceName].runtimeObject = m_contracts[evmSourceName].evmRuntimeAssembly->assemble();
680707
}
681708
else
682709
{
@@ -961,14 +988,21 @@ vector<string> CompilerStack::sourceNames() const
961988
return names;
962989
}
963990

964-
map<string, unsigned> CompilerStack::sourceIndices() const
991+
map<string, unsigned> CompilerStack::sourceIndices(bool _includeInternalSources /* = true */) const
965992
{
966993
map<string, unsigned> indices;
967994
unsigned index = 0;
968-
for (auto const& s: m_sources)
969-
indices[s.first] = index++;
970-
solAssert(!indices.count(CompilerContext::yulUtilityFileName()), "");
971-
indices[CompilerContext::yulUtilityFileName()] = index++;
995+
if (m_evmAssemblyJson.empty())
996+
{
997+
for (auto const& s: m_sources)
998+
indices[s.first] = index++;
999+
solAssert(!indices.count(CompilerContext::yulUtilityFileName()), "");
1000+
if (_includeInternalSources)
1001+
indices[CompilerContext::yulUtilityFileName()] = index++;
1002+
}
1003+
else
1004+
for (auto const& s: m_sourceOrder)
1005+
indices[s->charStream->source()] = index++;
9721006
return indices;
9731007
}
9741008

libsolidity/interface/CompilerStack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ class CompilerStack: public langutil::CharStreamProvider
244244

245245
/// @returns a mapping assigning each source name its index inside the vector returned
246246
/// by sourceNames().
247-
std::map<std::string, unsigned> sourceIndices() const;
247+
std::map<std::string, unsigned> sourceIndices(bool _includeInternalSources = true) const;
248248

249249
/// @returns the previously used character stream, useful for counting lines during error reporting.
250250
langutil::CharStream const& charStream(std::string const& _sourceName) const override;

solc/CommandLineInterface.cpp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ void CommandLineInterface::handleOpcode(string const& _contract)
201201

202202
void CommandLineInterface::handleIR(string const& _contractName)
203203
{
204-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
204+
solAssert(
205+
m_options.input.mode == InputMode::Compiler ||
206+
m_options.input.mode == InputMode::CompilerWithASTImport ||
207+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
208+
);
205209

206210
if (!m_options.compiler.outputs.ir)
207211
return;
@@ -217,7 +221,11 @@ void CommandLineInterface::handleIR(string const& _contractName)
217221

218222
void CommandLineInterface::handleIROptimized(string const& _contractName)
219223
{
220-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
224+
solAssert(
225+
m_options.input.mode == InputMode::Compiler ||
226+
m_options.input.mode == InputMode::CompilerWithASTImport ||
227+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
228+
);
221229

222230
if (!m_options.compiler.outputs.irOptimized)
223231
return;
@@ -233,7 +241,11 @@ void CommandLineInterface::handleIROptimized(string const& _contractName)
233241

234242
void CommandLineInterface::handleEwasm(string const& _contractName)
235243
{
236-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
244+
solAssert(
245+
m_options.input.mode == InputMode::Compiler ||
246+
m_options.input.mode == InputMode::CompilerWithASTImport ||
247+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
248+
);
237249

238250
if (!m_options.compiler.outputs.ewasm)
239251
return;
@@ -256,7 +268,11 @@ void CommandLineInterface::handleEwasm(string const& _contractName)
256268

257269
void CommandLineInterface::handleBytecode(string const& _contract)
258270
{
259-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
271+
solAssert(
272+
m_options.input.mode == InputMode::Compiler ||
273+
m_options.input.mode == InputMode::CompilerWithASTImport ||
274+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
275+
);
260276

261277
if (m_options.compiler.outputs.opcodes)
262278
handleOpcode(_contract);
@@ -266,7 +282,11 @@ void CommandLineInterface::handleBytecode(string const& _contract)
266282

267283
void CommandLineInterface::handleSignatureHashes(string const& _contract)
268284
{
269-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
285+
solAssert(
286+
m_options.input.mode == InputMode::Compiler ||
287+
m_options.input.mode == InputMode::CompilerWithASTImport ||
288+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
289+
);
270290

271291
if (!m_options.compiler.outputs.signatureHashes)
272292
return;
@@ -298,7 +318,11 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
298318

299319
void CommandLineInterface::handleMetadata(string const& _contract)
300320
{
301-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
321+
solAssert(
322+
m_options.input.mode == InputMode::Compiler ||
323+
m_options.input.mode == InputMode::CompilerWithASTImport ||
324+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
325+
);
302326

303327
if (!m_options.compiler.outputs.metadata)
304328
return;
@@ -312,7 +336,11 @@ void CommandLineInterface::handleMetadata(string const& _contract)
312336

313337
void CommandLineInterface::handleABI(string const& _contract)
314338
{
315-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
339+
solAssert(
340+
m_options.input.mode == InputMode::Compiler ||
341+
m_options.input.mode == InputMode::CompilerWithASTImport ||
342+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
343+
);
316344

317345
if (!m_options.compiler.outputs.abi)
318346
return;
@@ -326,7 +354,11 @@ void CommandLineInterface::handleABI(string const& _contract)
326354

327355
void CommandLineInterface::handleStorageLayout(string const& _contract)
328356
{
329-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
357+
solAssert(
358+
m_options.input.mode == InputMode::Compiler ||
359+
m_options.input.mode == InputMode::CompilerWithASTImport ||
360+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
361+
);
330362

331363
if (!m_options.compiler.outputs.storageLayout)
332364
return;
@@ -340,7 +372,11 @@ void CommandLineInterface::handleStorageLayout(string const& _contract)
340372

341373
void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contract)
342374
{
343-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
375+
solAssert(
376+
m_options.input.mode == InputMode::Compiler ||
377+
m_options.input.mode == InputMode::CompilerWithASTImport ||
378+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
379+
);
344380

345381
bool enabled = false;
346382
std::string suffix;
@@ -382,7 +418,11 @@ void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contra
382418

383419
void CommandLineInterface::handleGasEstimation(string const& _contract)
384420
{
385-
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
421+
solAssert(
422+
m_options.input.mode == InputMode::Compiler ||
423+
m_options.input.mode == InputMode::CompilerWithASTImport ||
424+
m_options.input.mode == InputMode::CompilerWithEvmAssemblyJsonImport, ""
425+
);
386426

387427
Json::Value estimates = m_compiler->gasEstimates(_contract);
388428
sout() << "Gas estimation:" << endl;

test/cmdlineTests/asm_json/output

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,5 +1582,10 @@ EVM assembly:
15821582
}
15831583
]
15841584
}
1585-
}
1585+
},
1586+
"sourceList":
1587+
[
1588+
"asm_json/input.sol",
1589+
"#utility.yul"
1590+
]
15861591
}

0 commit comments

Comments
 (0)