Skip to content

Commit 95f517f

Browse files
committed
Test: Add abstraction for internal compiler
1 parent 654dedc commit 95f517f

File tree

4 files changed

+241
-0
lines changed

4 files changed

+241
-0
lines changed

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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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> contracts;
81+
82+
auto const& sourceUnit = m_stack.ast(sourceName);
83+
for (auto const* contract: ASTNode::filteredNodes<ContractDefinition>(sourceUnit.nodes()))
84+
{
85+
auto contractName = contract->fullyQualifiedName();
86+
auto object = m_stack.object(contractName);
87+
auto runtimeObject = m_stack.runtimeObject(contractName);
88+
auto hasUnlinkedReferences = !object.linkReferences.empty();
89+
auto assemblyItems = m_stack.assemblyItems(contractName);
90+
auto runtimeAssemblyItems = m_stack.runtimeAssemblyItems(contractName);
91+
auto metadata = m_stack.metadata(contractName);
92+
auto cborMetadata = m_stack.cborMetadata(contractName);
93+
auto contractABI = m_stack.contractABI(contractName);
94+
auto interfaceSymbols = m_stack.interfaceSymbols(contractName);
95+
auto eventSignatures = generateEventSignatures(contractName);
96+
97+
auto compiledContract = CompiledContract{
98+
contractName,
99+
object.bytecode,
100+
runtimeObject.bytecode,
101+
hasUnlinkedReferences,
102+
assemblyItems != nullptr ? *assemblyItems : evmasm::AssemblyItems{},
103+
runtimeAssemblyItems != nullptr ? *runtimeAssemblyItems : evmasm::AssemblyItems{},
104+
metadata,
105+
cborMetadata,
106+
contractABI,
107+
interfaceSymbols,
108+
eventSignatures
109+
};
110+
contracts.emplace_back(compiledContract);
111+
}
112+
mappedContracts.insert(std::make_pair(sourceName, contracts));
113+
}
114+
115+
return std::make_pair(mappedContracts, m_stack.errors());
116+
}
117+
118+
bool InternalCompiler::success() const
119+
{
120+
return m_stack.compilationSuccessful();
121+
}
122+
123+
std::vector<AnnotatedEventSignature> InternalCompiler::generateEventSignatures(
124+
std::string const& _contractName
125+
) const
126+
{
127+
std::vector<AnnotatedEventSignature> signatures;
128+
ContractDefinition const& contract = m_stack.contractDefinition(_contractName);
129+
130+
for (EventDefinition const* event: contract.events() + contract.usedInterfaceEvents())
131+
{
132+
AnnotatedEventSignature eventInfo;
133+
auto eventFunctionType = event->functionType(true);
134+
135+
eventInfo.signature = eventFunctionType->externalSignature();
136+
for (auto const& param: event->parameters())
137+
if (param->isIndexed())
138+
eventInfo.indexedTypes.emplace_back(param->type()->toString(true));
139+
else
140+
eventInfo.nonIndexedTypes.emplace_back(param->type()->toString(true));
141+
eventInfo.isAnonymous = event->isAnonymous();
142+
143+
signatures.push_back(eventInfo);
144+
}
145+
146+
return signatures;
147+
}
148+
149+
std::string InternalCompiler::formatErrorInformation() const
150+
{
151+
std::string errorInformation;
152+
153+
for (auto const& error: m_stack.errors())
154+
{
155+
auto formatted = SourceReferenceFormatter::formatErrorInformation(
156+
*error.get(),
157+
m_stack,
158+
true,
159+
false
160+
);
161+
errorInformation.append(formatted);
162+
}
163+
164+
return errorInformation;
165+
}
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+
}

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)