Skip to content

Commit 7cbf046

Browse files
authored
Merge pull request #5358 from ethereum/yulObjects
[Yul] Yul objects parser
2 parents bc7cb30 + 69dcf1a commit 7cbf046

File tree

10 files changed

+635
-34
lines changed

10 files changed

+635
-34
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Compiler Features:
1111
* SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables.
1212
* SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions.
1313
* SMTChecker: Support internal bound function calls.
14+
* Yul: Support Yul objects in ``--assemble`` and ``--yul`` commandline options.
1415

1516

1617
Bugfixes:

libsolidity/interface/AssemblyStack.cpp

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <libyul/AsmCodeGen.h>
3131
#include <libyul/backends/evm/EVMCodeTransform.h>
3232
#include <libyul/backends/evm/EVMAssembly.h>
33+
#include <libyul/ObjectParser.h>
3334

3435
#include <libevmasm/Assembly.h>
3536

@@ -69,46 +70,39 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string
6970
m_errors.clear();
7071
m_analysisSuccessful = false;
7172
m_scanner = make_shared<Scanner>(CharStream(_source), _sourceName);
72-
m_parserResult = yul::Parser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false);
73+
m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false);
7374
if (!m_errorReporter.errors().empty())
7475
return false;
7576
solAssert(m_parserResult, "");
76-
77-
return analyzeParsed();
78-
}
79-
80-
bool AssemblyStack::analyze(yul::Block const& _block, Scanner const* _scanner)
81-
{
82-
m_errors.clear();
83-
m_analysisSuccessful = false;
84-
if (_scanner)
85-
m_scanner = make_shared<Scanner>(*_scanner);
86-
m_parserResult = make_shared<yul::Block>(_block);
77+
solAssert(m_parserResult->code, "");
8778

8879
return analyzeParsed();
8980
}
9081

9182
bool AssemblyStack::analyzeParsed()
9283
{
93-
m_analysisInfo = make_shared<yul::AsmAnalysisInfo>();
94-
yul::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language));
95-
m_analysisSuccessful = analyzer.analyze(*m_parserResult);
84+
solAssert(m_parserResult, "");
85+
solAssert(m_parserResult->code, "");
86+
m_parserResult->analysisInfo = make_shared<yul::AsmAnalysisInfo>();
87+
yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language));
88+
m_analysisSuccessful = analyzer.analyze(*m_parserResult->code);
9689
return m_analysisSuccessful;
9790
}
9891

9992
MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
10093
{
10194
solAssert(m_analysisSuccessful, "");
10295
solAssert(m_parserResult, "");
103-
solAssert(m_analysisInfo, "");
96+
solAssert(m_parserResult->code, "");
97+
solAssert(m_parserResult->analysisInfo, "");
10498

10599
switch (_machine)
106100
{
107101
case Machine::EVM:
108102
{
109103
MachineAssemblyObject object;
110104
eth::Assembly assembly;
111-
yul::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly);
105+
yul::CodeGenerator::assemble(*m_parserResult->code, *m_parserResult->analysisInfo, assembly);
112106
object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble());
113107
object.assembly = assembly.assemblyString();
114108
return object;
@@ -117,7 +111,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
117111
{
118112
MachineAssemblyObject object;
119113
yul::EVMAssembly assembly(true);
120-
yul::CodeTransform(assembly, *m_analysisInfo, m_language == Language::Yul, true)(*m_parserResult);
114+
yul::CodeTransform(assembly, *m_parserResult->analysisInfo, m_language == Language::Yul, true)(*m_parserResult->code);
121115
object.bytecode = make_shared<eth::LinkerObject>(assembly.finalize());
122116
/// TODO: fill out text representation
123117
return object;
@@ -132,5 +126,6 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
132126
string AssemblyStack::print() const
133127
{
134128
solAssert(m_parserResult, "");
135-
return yul::AsmPrinter(m_language == Language::Yul)(*m_parserResult);
129+
solAssert(m_parserResult->code, "");
130+
return m_parserResult->toString(m_language == Language::Yul) + "\n";
136131
}

libsolidity/interface/AssemblyStack.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include <liblangutil/ErrorReporter.h>
2525
#include <liblangutil/EVMVersion.h>
2626

27+
#include <libyul/Object.h>
28+
#include <libyul/ObjectParser.h>
29+
2730
#include <libevmasm/LinkerObject.h>
2831

2932
#include <string>
@@ -34,12 +37,6 @@ namespace langutil
3437
class Scanner;
3538
}
3639

37-
namespace yul
38-
{
39-
struct AsmAnalysisInfo;
40-
struct Block;
41-
}
42-
4340
namespace dev
4441
{
4542
namespace solidity
@@ -72,10 +69,6 @@ class AssemblyStack
7269
/// Multiple calls overwrite the previous state.
7370
bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source);
7471

75-
/// Runs analysis step on the supplied block, returns false if input cannot be assembled.
76-
/// Multiple calls overwrite the previous state.
77-
bool analyze(yul::Block const& _block, langutil::Scanner const* _scanner = nullptr);
78-
7972
/// Run the assembly step (should only be called after parseAndAnalyze).
8073
MachineAssemblyObject assemble(Machine _machine) const;
8174

@@ -94,8 +87,7 @@ class AssemblyStack
9487
std::shared_ptr<langutil::Scanner> m_scanner;
9588

9689
bool m_analysisSuccessful = false;
97-
std::shared_ptr<yul::Block> m_parserResult;
98-
std::shared_ptr<yul::AsmAnalysisInfo> m_analysisInfo;
90+
std::shared_ptr<yul::Object> m_parserResult;
9991
langutil::ErrorList m_errors;
10092
langutil::ErrorReporter m_errorReporter;
10193
};

libyul/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ add_library(yul
66
AsmPrinter.cpp
77
AsmScope.cpp
88
AsmScopeFiller.cpp
9+
Object.cpp
10+
ObjectParser.cpp
911
backends/evm/EVMAssembly.cpp
1012
backends/evm/EVMCodeTransform.cpp
1113
optimiser/ASTCopier.cpp

libyul/Object.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
This file is part of solidity.
3+
4+
solidity is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
solidity is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with solidity. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
/**
18+
* Yul code and data object container.
19+
*/
20+
21+
#include <libyul/Object.h>
22+
23+
#include <libyul/AsmPrinter.h>
24+
#include <libyul/Exceptions.h>
25+
26+
#include <libdevcore/Visitor.h>
27+
#include <libdevcore/CommonData.h>
28+
29+
#include <boost/algorithm/string/replace.hpp>
30+
31+
using namespace dev;
32+
using namespace yul;
33+
using namespace std;
34+
35+
namespace
36+
{
37+
38+
string indent(std::string const& _input)
39+
{
40+
if (_input.empty())
41+
return _input;
42+
return boost::replace_all_copy(" " + _input, "\n", "\n ");
43+
}
44+
45+
}
46+
47+
string Data::toString(bool) const
48+
{
49+
return "data \"" + name.str() + "\" hex\"" + dev::toHex(data) + "\"";
50+
}
51+
52+
string Object::toString(bool _yul) const
53+
{
54+
yulAssert(code, "No code");
55+
string inner = "code " + AsmPrinter{_yul}(*code);
56+
57+
for (auto const& obj: subObjects)
58+
inner += "\n" + obj->toString(_yul);
59+
60+
return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}";
61+
}

libyul/Object.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
This file is part of solidity.
3+
4+
solidity is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
solidity is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with solidity. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
/**
18+
* Yul code and data object container.
19+
*/
20+
21+
#pragma once
22+
23+
#include <libyul/AsmDataForward.h>
24+
#include <libyul/YulString.h>
25+
26+
#include <libdevcore/Common.h>
27+
28+
#include <memory>
29+
30+
namespace yul
31+
{
32+
struct AsmAnalysisInfo;
33+
34+
35+
/**
36+
* Generic base class for both Yul objects and Yul data.
37+
*/
38+
struct ObjectNode
39+
{
40+
virtual ~ObjectNode() {}
41+
virtual std::string toString(bool _yul) const = 0;
42+
43+
YulString name;
44+
};
45+
46+
/**
47+
* Named data in Yul objects.
48+
*/
49+
struct Data: ObjectNode
50+
{
51+
Data(YulString _name, dev::bytes _data): data(std::move(_data)) { name = _name; }
52+
std::string toString(bool _yul) const override;
53+
54+
dev::bytes data;
55+
};
56+
57+
/**
58+
* Yul code and data object container.
59+
*/
60+
struct Object: ObjectNode
61+
{
62+
public:
63+
/// @returns a (parseable) string representation. Includes types if @a _yul is set.
64+
std::string toString(bool _yul) const override;
65+
66+
std::shared_ptr<Block> code;
67+
std::vector<std::shared_ptr<ObjectNode>> subObjects;
68+
std::map<YulString, size_t> subIndexByName;
69+
std::shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
70+
};
71+
72+
}

0 commit comments

Comments
 (0)