Skip to content

Commit 1d4d683

Browse files
committed
Don't ignore errors reported at optimization and assembling steps in Yul compilation
1 parent d09b495 commit 1d4d683

File tree

4 files changed

+62
-49
lines changed

4 files changed

+62
-49
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Compiler Features:
99

1010
Bugfixes:
1111
* General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts.
12+
* Yul: Fix internal compiler error when a code generation error should be reported instead.
1213

1314

1415
### 0.8.28 (2024-10-09)

libsolidity/interface/StandardCompiler.cpp

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,9 +1616,35 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
16161616
std::string const& sourceName = _inputsAndSettings.sources.begin()->first;
16171617
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;
16181618

1619-
// Inconsistent state - stop here to receive error reports from users
1620-
if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors())
1621-
solAssert(false, "No error reported, but parsing/analysis failed.");
1619+
std::string contractName;
1620+
bool const wildcardMatchesExperimental = true;
1621+
MachineAssemblyObject object;
1622+
MachineAssemblyObject deployedObject;
1623+
1624+
bool successful = stack.parseAndAnalyze(sourceName, sourceContents);
1625+
if (!successful)
1626+
// Inconsistent state - stop here to receive error reports from users
1627+
solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed.");
1628+
else
1629+
{
1630+
contractName = stack.parserResult()->name;
1631+
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental))
1632+
output["contracts"][sourceName][contractName]["ir"] = stack.print();
1633+
1634+
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental))
1635+
{
1636+
Json sourceResult;
1637+
sourceResult["id"] = 0;
1638+
sourceResult["ast"] = stack.astJson();
1639+
output["sources"][sourceName] = sourceResult;
1640+
}
1641+
stack.optimize();
1642+
std::tie(object, deployedObject) = stack.assembleWithDeployed();
1643+
if (object.bytecode)
1644+
object.bytecode->link(_inputsAndSettings.libraries);
1645+
if (deployedObject.bytecode)
1646+
deployedObject.bytecode->link(_inputsAndSettings.libraries);
1647+
}
16221648

16231649
for (auto const& error: stack.errors())
16241650
{
@@ -1635,30 +1661,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
16351661
if (stack.hasErrors())
16361662
return output;
16371663

1638-
std::string contractName = stack.parserResult()->name;
1639-
1640-
bool const wildcardMatchesExperimental = true;
1641-
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental))
1642-
output["contracts"][sourceName][contractName]["ir"] = stack.print();
1643-
1644-
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ast", wildcardMatchesExperimental))
1645-
{
1646-
Json sourceResult;
1647-
sourceResult["id"] = 0;
1648-
sourceResult["ast"] = stack.astJson();
1649-
output["sources"][sourceName] = sourceResult;
1650-
}
1651-
stack.optimize();
1652-
1653-
MachineAssemblyObject object;
1654-
MachineAssemblyObject deployedObject;
1655-
std::tie(object, deployedObject) = stack.assembleWithDeployed();
1656-
1657-
if (object.bytecode)
1658-
object.bytecode->link(_inputsAndSettings.libraries);
1659-
if (deployedObject.bytecode)
1660-
deployedObject.bytecode->link(_inputsAndSettings.libraries);
1661-
16621664
for (auto&& [kind, isDeployed]: {make_pair("bytecode"s, false), make_pair("deployedBytecode"s, true)})
16631665
if (isArtifactRequested(
16641666
_inputsAndSettings.outputSelection,

solc/CommandLineInterface.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,9 +1232,10 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
12321232

12331233
bool successful = true;
12341234
std::map<std::string, yul::YulStack> yulStacks;
1235-
for (auto const& src: m_fileReader.sourceUnits())
1235+
std::map<std::string, yul::MachineAssemblyObject> objects;
1236+
for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits())
12361237
{
1237-
auto& stack = yulStacks[src.first] = yul::YulStack(
1238+
auto& stack = yulStacks[sourceUnitName] = yul::YulStack(
12381239
m_options.output.evmVersion,
12391240
m_options.output.eofVersion,
12401241
_language,
@@ -1244,20 +1245,28 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
12441245
DebugInfoSelection::Default()
12451246
);
12461247

1247-
if (!stack.parseAndAnalyze(src.first, src.second))
1248-
successful = false;
1248+
successful = successful && stack.parseAndAnalyze(sourceUnitName, yulSource);
1249+
if (!successful)
1250+
solAssert(stack.hasErrors(), "No error reported, but parsing/analysis failed.");
12491251
else
1250-
stack.optimize();
1251-
1252-
if (successful && m_options.compiler.outputs.asmJson)
12531252
{
1254-
std::shared_ptr<yul::Object> result = stack.parserResult();
1255-
if (result && !result->hasContiguousSourceIndices())
1253+
if (
1254+
m_options.compiler.outputs.asmJson &&
1255+
stack.parserResult() &&
1256+
!stack.parserResult()->hasContiguousSourceIndices()
1257+
)
12561258
solThrow(
12571259
CommandLineExecutionError,
12581260
"Generating the assembly JSON output was not possible. "
12591261
"Source indices provided in the @use-src annotation in the Yul input do not start at 0 or are not contiguous."
12601262
);
1263+
1264+
stack.optimize();
1265+
1266+
yul::MachineAssemblyObject object = stack.assemble(_targetMachine);
1267+
if (object.bytecode)
1268+
object.bytecode->link(m_options.linker.libraries);
1269+
objects.insert({sourceUnitName, std::move(object)});
12611270
}
12621271
}
12631272

@@ -1281,13 +1290,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
12811290
solThrow(CommandLineExecutionError, "");
12821291
}
12831292

1284-
for (auto const& src: m_fileReader.sourceUnits())
1293+
for (auto const& [sourceUnitName, yulSource]: m_fileReader.sourceUnits())
12851294
{
12861295
solAssert(_targetMachine == yul::YulStack::Machine::EVM);
12871296
std::string machine = "EVM";
1288-
sout() << std::endl << "======= " << src.first << " (" << machine << ") =======" << std::endl;
1297+
sout() << std::endl << "======= " << sourceUnitName << " (" << machine << ") =======" << std::endl;
12891298

1290-
yul::YulStack& stack = yulStacks[src.first];
1299+
yul::YulStack const& stack = yulStacks[sourceUnitName];
1300+
yul::MachineAssemblyObject const& object = objects[sourceUnitName];
12911301

12921302
if (m_options.compiler.outputs.irOptimized)
12931303
{
@@ -1297,10 +1307,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
12971307
sout() << stack.print() << std::endl;
12981308
}
12991309

1300-
yul::MachineAssemblyObject object;
1301-
object = stack.assemble(_targetMachine);
1302-
object.bytecode->link(m_options.linker.libraries);
1303-
13041310
if (m_options.compiler.outputs.binary)
13051311
{
13061312
sout() << std::endl << "Binary representation:" << std::endl;

test/libyul/ObjectCompilerTest.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,22 @@ TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string
7171
OptimiserSettings::preset(m_optimisationPreset),
7272
DebugInfoSelection::All()
7373
);
74-
if (!stack.parseAndAnalyze("source", m_source))
74+
bool successful = stack.parseAndAnalyze("source", m_source);
75+
MachineAssemblyObject obj;
76+
if (successful)
77+
{
78+
stack.optimize();
79+
obj = stack.assemble(YulStack::Machine::EVM);
80+
}
81+
if (stack.hasErrors())
7582
{
7683
AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl;
7784
SourceReferenceFormatter{_stream, stack, true, false}
7885
.printErrorInformation(stack.errors());
7986
return TestResult::FatalError;
8087
}
81-
stack.optimize();
82-
83-
MachineAssemblyObject obj = stack.assemble(YulStack::Machine::EVM);
84-
solAssert(obj.bytecode, "");
85-
solAssert(obj.sourceMappings, "");
88+
solAssert(obj.bytecode);
89+
solAssert(obj.sourceMappings);
8690

8791
m_obtainedResult = "Assembly:\n" + obj.assembly->assemblyString(stack.debugInfoSelection());
8892
if (obj.bytecode->bytecode.empty())

0 commit comments

Comments
 (0)