Skip to content

Commit c1b4cd5

Browse files
committed
Test: Add abstraction for internal compiler
1 parent cb41cb1 commit c1b4cd5

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed

Diff for: test/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ detect_stray_source_files("${libsolidity_sources}" "libsolidity/")
119119
set(libsolidity_util_sources
120120
libsolidity/util/compiler/Compiler.h
121121
libsolidity/util/compiler/Compiler.cpp
122+
libsolidity/util/compiler/InternalCompiler.h
123+
libsolidity/util/compiler/InternalCompiler.cpp
122124
libsolidity/util/BytesUtils.cpp
123125
libsolidity/util/BytesUtilsTests.cpp
124126
libsolidity/util/BytesUtils.h

Diff for: test/libsolidity/util/compiler/InternalCompiler.cpp

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#include <test/libsolidity/util/compiler/InternalCompiler.h>
2+
3+
using namespace solidity;
4+
using namespace solidity::frontend::test;
5+
6+
CompilerOutput InternalCompiler::compile(CompilerInput const& _input)
7+
{
8+
configure(_input);
9+
10+
auto [contracts, errors] = compile();
11+
auto output = CompilerOutput{
12+
contracts,
13+
success(),
14+
errors,
15+
formatErrorInformation()
16+
};
17+
18+
return output;
19+
}
20+
21+
void InternalCompiler::configure(CompilerInput const& _input)
22+
{
23+
m_stack.reset();
24+
25+
m_stack.setSources(_input.sourceCode);
26+
m_stack.setLibraries(_input.libraryAddresses);
27+
28+
if (_input.evmVersion.has_value())
29+
m_stack.setEVMVersion(_input.evmVersion.value());
30+
if (_input.optimise.has_value())
31+
m_stack.setOptimiserSettings(_input.optimise.value());
32+
if (_input.optimiserSettings.has_value())
33+
m_stack.setOptimiserSettings(_input.optimiserSettings.value());
34+
if (_input.revertStrings.has_value())
35+
m_stack.setRevertStringBehaviour(_input.revertStrings.value());
36+
if (_input.metadataFormat.has_value())
37+
{
38+
auto metadata = CompilerStack::MetadataFormat::NoMetadata;
39+
switch (_input.metadataFormat.value())
40+
{
41+
case MetadataFormat::WithReleaseVersionTag:
42+
metadata = CompilerStack::MetadataFormat::WithReleaseVersionTag;
43+
break;
44+
case MetadataFormat::WithPrereleaseVersionTag:
45+
metadata = CompilerStack::MetadataFormat::WithPrereleaseVersionTag;
46+
break;
47+
default:
48+
break;
49+
}
50+
m_stack.setMetadataFormat(metadata);
51+
}
52+
if (_input.metadataHash.has_value())
53+
{
54+
auto hash = CompilerStack::MetadataHash::None;
55+
switch (_input.metadataHash.value())
56+
{
57+
case MetadataHash::IPFS:
58+
hash = CompilerStack::MetadataHash::IPFS;
59+
break;
60+
case MetadataHash::Bzzr1:
61+
hash = CompilerStack::MetadataHash::Bzzr1;
62+
break;
63+
default:
64+
break;
65+
}
66+
m_stack.setMetadataHash(hash);
67+
}
68+
if (_input.viaIR.has_value())
69+
m_stack.setViaIR(_input.viaIR.value());
70+
m_stack.setEOFVersion(_input.eofVersion);
71+
}
72+
73+
std::pair<MappedContracts, Errors> InternalCompiler::compile()
74+
{
75+
m_stack.compile();
76+
77+
auto mappedContracts = MappedContracts{};
78+
for (auto sourceName: m_stack.sourceNames())
79+
{
80+
std::vector<CompiledContract> compiled;
81+
for (auto contract: m_stack.contractDefinitions(sourceName))
82+
{
83+
auto contractName = contract->fullyQualifiedName();
84+
auto object = m_stack.object(contractName);
85+
auto runtimeObject = m_stack.runtimeObject(contractName);
86+
auto hasUnlinkedReferences = !object.linkReferences.empty();
87+
auto assemblyItems = m_stack.assemblyItems(contractName);
88+
auto runtimeAssemblyItems = m_stack.runtimeAssemblyItems(contractName);
89+
auto cborMetadata = m_stack.cborMetadata(contractName);
90+
91+
if (!m_stack.isExperimentalSolidity())
92+
compiled.emplace_back(CompiledContract{
93+
contractName,
94+
object.bytecode,
95+
runtimeObject.bytecode,
96+
hasUnlinkedReferences,
97+
cborMetadata,
98+
assemblyItems != nullptr ? *assemblyItems : evmasm::AssemblyItems{},
99+
runtimeAssemblyItems != nullptr ? *runtimeAssemblyItems : evmasm::AssemblyItems{},
100+
m_stack.metadata(contractName),
101+
m_stack.contractABI(contractName),
102+
m_stack.interfaceSymbols(contractName),
103+
generateEventSignatures(contractName)
104+
});
105+
else
106+
compiled.emplace_back(CompiledContract{
107+
contractName,
108+
object.bytecode,
109+
runtimeObject.bytecode,
110+
hasUnlinkedReferences,
111+
cborMetadata,
112+
assemblyItems != nullptr ? *assemblyItems : evmasm::AssemblyItems{},
113+
runtimeAssemblyItems != nullptr ? *runtimeAssemblyItems : evmasm::AssemblyItems{},
114+
std::nullopt,
115+
std::nullopt,
116+
std::nullopt,
117+
std::vector<AnnotatedEventSignature>{}
118+
});
119+
}
120+
mappedContracts.insert(std::make_pair(sourceName, compiled));
121+
}
122+
123+
return std::make_pair(mappedContracts, m_stack.errors());
124+
}
125+
126+
bool InternalCompiler::success() const
127+
{
128+
return m_stack.compilationSuccessful();
129+
}
130+
131+
std::vector<AnnotatedEventSignature> InternalCompiler::generateEventSignatures(
132+
std::string const& _contractName
133+
) const
134+
{
135+
std::vector<AnnotatedEventSignature> signatures;
136+
ContractDefinition const& contract = m_stack.contractDefinition(_contractName);
137+
138+
for (EventDefinition const* event: contract.events() + contract.usedInterfaceEvents())
139+
{
140+
AnnotatedEventSignature eventInfo;
141+
auto eventFunctionType = event->functionType(true);
142+
143+
eventInfo.signature = eventFunctionType->externalSignature();
144+
for (auto const& param: event->parameters())
145+
if (param->isIndexed())
146+
eventInfo.indexedTypes.emplace_back(param->type()->toString(true));
147+
else
148+
eventInfo.nonIndexedTypes.emplace_back(param->type()->toString(true));
149+
eventInfo.isAnonymous = event->isAnonymous();
150+
151+
signatures.push_back(eventInfo);
152+
}
153+
154+
return signatures;
155+
}
156+
157+
std::string InternalCompiler::formatErrorInformation() const
158+
{
159+
std::string errorInformation;
160+
161+
for (auto const& error: m_stack.errors())
162+
{
163+
auto formatted = SourceReferenceFormatter::formatErrorInformation(
164+
*error.get(),
165+
m_stack,
166+
true,
167+
false
168+
);
169+
errorInformation.append(formatted);
170+
}
171+
172+
return errorInformation;
173+
}

Diff for: test/libsolidity/util/compiler/InternalCompiler.h

+72
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+
// SPDX-License-Identifier: GPL-3.0
18+
19+
#pragma once
20+
21+
#include <liblangutil/SourceReferenceFormatter.h>
22+
#include <libsolutil/Common.h>
23+
24+
#include <test/libsolidity/util/compiler/Compiler.h>
25+
26+
using namespace solidity::langutil;
27+
28+
namespace solidity::frontend::test
29+
{
30+
31+
using MappedContracts = std::map<std::string, std::vector<CompiledContract>>;
32+
using Errors = ErrorList;
33+
34+
/**
35+
* Abstraction of the internal compiler aka. `CompilerStack`.
36+
*/
37+
class InternalCompiler
38+
{
39+
public:
40+
/// Configures and compiles using the internal compiler stack.
41+
/// @param _input the compiler input with sources, options etc. optionally
42+
/// set.
43+
/// @returns the aggregated compiler output.
44+
CompilerOutput compile(CompilerInput const& _input);
45+
46+
private:
47+
/// Configures the compiler stack. Needs to be called before compilation.
48+
/// @param _input is mapped to the compiler stacks' setters.
49+
void configure(CompilerInput const& _input);
50+
51+
/// Compile with cucrrent configuration.
52+
/// @returns compiled contracts per source unit and possible errors.
53+
std::pair<MappedContracts, Errors> compile();
54+
55+
/// @returns `true` if compilation was successful and `false` otherwise.
56+
bool success() const;
57+
58+
/// @returns annotated event signatures per contract.
59+
/// @param _contractName defines the contract to be used.
60+
std::vector<AnnotatedEventSignature> generateEventSignatures(
61+
std::string const& _contractName
62+
) const;
63+
64+
/// @returns a formatted output of all errors that occurred during
65+
/// compilation.
66+
std::string formatErrorInformation() const;
67+
68+
/// The compiler stack
69+
CompilerStack m_stack;
70+
};
71+
72+
}

Diff for: test/tools/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ add_executable(isoltest
2525
../libsolidity/util/TestFunctionCall.cpp
2626
../libsolidity/util/compiler/Compiler.h
2727
../libsolidity/util/compiler/Compiler.cpp
28+
../libsolidity/util/compiler/InternalCompiler.h
29+
../libsolidity/util/compiler/InternalCompiler.cpp
2830
../libsolidity/GasTest.cpp
2931
../libsolidity/MemoryGuardTest.cpp
3032
../libsolidity/NatspecJSONTest.cpp

0 commit comments

Comments
 (0)