Fix dependency tracking for abstract contracts for Yul codegen

This commit is contained in:
Mathias Baumann 2020-10-14 12:42:44 +02:00
parent 2a3a8b54dd
commit c99131f9ec
3 changed files with 19 additions and 12 deletions

View File

@ -516,6 +516,8 @@ bool CompilerStack::compile(State _stopAfter)
// Only compile contracts individually which have been requested.
map<ContractDefinition const*, shared_ptr<Compiler const>> otherCompilers;
map<ContractDefinition const*, string const> otherYulSources;
for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
@ -526,7 +528,7 @@ bool CompilerStack::compile(State _stopAfter)
if (m_generateEvmBytecode)
compileContract(*contract, otherCompilers);
if (m_generateIR || m_generateEwasm)
generateIR(*contract);
generateIR(*contract, otherYulSources);
if (m_generateEwasm)
generateEwasm(*contract);
}
@ -1216,17 +1218,15 @@ void CompilerStack::compileContract(
_otherCompilers[compiledContract.contract] = compiler;
}
void CompilerStack::generateIR(ContractDefinition const& _contract)
void CompilerStack::generateIR(
ContractDefinition const& _contract,
map<ContractDefinition const*, string const>& _otherYulSources
)
{
solAssert(m_stackState >= AnalysisPerformed, "");
if (m_hasError)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateIR with errors."));
if (!_contract.canBeDeployed())
return;
map<ContractDefinition const*, string const> otherYulSources;
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
if (!compiledContract.yulIR.empty())
return;
@ -1234,12 +1234,15 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
string dependenciesSource;
for (auto const* dependency: _contract.annotation().contractDependencies)
{
generateIR(*dependency);
otherYulSources.emplace(dependency, m_contracts.at(dependency->fullyQualifiedName()).yulIR);
generateIR(*dependency, _otherYulSources);
_otherYulSources.emplace(dependency, m_contracts.at(dependency->fullyQualifiedName()).yulIR);
}
if (!_contract.canBeDeployed())
return;
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings);
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(_contract, otherYulSources);
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(_contract, _otherYulSources);
}
void CompilerStack::generateEwasm(ContractDefinition const& _contract)

View File

@ -393,7 +393,10 @@ private:
/// Generate Yul IR for a single contract.
/// The IR is stored but otherwise unused.
void generateIR(ContractDefinition const& _contract);
void generateIR(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, std::string const>& _otherYulSources
);
/// Generate Ewasm representation for a single contract.
void generateEwasm(ContractDefinition const& _contract);

View File

@ -1521,7 +1521,7 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract)
"settings": {
"outputSelection": {
"BlockRewardAuRaCoins.sol": {
"BlockRewardAuRaCoins": ["evm.bytecode.sourceMap"]
"BlockRewardAuRaCoins": ["ir", "evm.bytecode.sourceMap"]
}
}
}
@ -1540,6 +1540,7 @@ BOOST_AUTO_TEST_CASE(dependency_tracking_of_abstract_contract)
BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"].size() == 1);
BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"].isObject());
BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"].isObject());
BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["ir"].isString());
BOOST_REQUIRE(result["contracts"]["BlockRewardAuRaCoins.sol"]["BlockRewardAuRaCoins"]["evm"]["bytecode"].isObject());
BOOST_REQUIRE(result["sources"].isObject());
BOOST_REQUIRE(result["sources"].size() == 2);