Skip to content

Commit 9bcc135

Browse files
committed
[solc] Basic --import-asm-json import.
1 parent c7bd8c0 commit 9bcc135

File tree

8 files changed

+512
-116
lines changed

8 files changed

+512
-116
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
@@ -165,6 +165,7 @@ class AssemblyItem
165165
langutil::SourceLocation const& location() const { return m_location; }
166166

167167
void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; }
168+
void setJumpType(std::string const& _jumpType);
168169
JumpType getJumpType() const { return m_jumpType; }
169170
std::string getJumpTypeAsString() const;
170171

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
@@ -200,7 +200,11 @@ void CommandLineInterface::handleOpcode(string const& _contract)
200200

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

205209
if (!m_options.compiler.outputs.ir)
206210
return;
@@ -216,7 +220,11 @@ void CommandLineInterface::handleIR(string const& _contractName)
216220

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

221229
if (!m_options.compiler.outputs.irOptimized)
222230
return;
@@ -232,7 +240,11 @@ void CommandLineInterface::handleIROptimized(string const& _contractName)
232240

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

237249
if (!m_options.compiler.outputs.ewasm)
238250
return;
@@ -255,7 +267,11 @@ void CommandLineInterface::handleEwasm(string const& _contractName)
255267

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

260276
if (m_options.compiler.outputs.opcodes)
261277
handleOpcode(_contract);
@@ -265,7 +281,11 @@ void CommandLineInterface::handleBytecode(string const& _contract)
265281

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

270290
if (!m_options.compiler.outputs.signatureHashes)
271291
return;
@@ -297,7 +317,11 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
297317

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

302326
if (!m_options.compiler.outputs.metadata)
303327
return;
@@ -311,7 +335,11 @@ void CommandLineInterface::handleMetadata(string const& _contract)
311335

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

316344
if (!m_options.compiler.outputs.abi)
317345
return;
@@ -325,7 +353,11 @@ void CommandLineInterface::handleABI(string const& _contract)
325353

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

330362
if (!m_options.compiler.outputs.storageLayout)
331363
return;
@@ -339,7 +371,11 @@ void CommandLineInterface::handleStorageLayout(string const& _contract)
339371

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

344380
bool enabled = false;
345381
std::string suffix;
@@ -381,7 +417,11 @@ void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contra
381417

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

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

0 commit comments

Comments
 (0)