mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move AST annotation of internal function dispatch IDs to ContractDefinition
Co-authored-by: Daniel <daniel@ekpyron.org> Co-authored-by: Nikola Matić <nikola.matic@ethereum.org>
This commit is contained in:
parent
41742c5410
commit
a29f77369a
@ -25,7 +25,7 @@ Bugfixes:
|
|||||||
|
|
||||||
|
|
||||||
AST Changes:
|
AST Changes:
|
||||||
* AST: Add the ``internalFunctionID`` field to the AST nodes of functions that may be called via the internal dispatch. These IDs are always generated, but they are only used in via-IR code generation.
|
* AST: Add the ``internalFunctionIDs`` field to the AST nodes of contracts containing IDs of functions that may be called via the internal dispatch. The field is a map from function AST IDs to internal dispatch function IDs. These IDs are always generated, but they are only used in via-IR code generation.
|
||||||
* AST: Add the ``usedEvents`` field to ``ContractDefinition`` which contains the AST IDs of all events emitted by the contract as well as all events defined and inherited by the contract.
|
* AST: Add the ``usedEvents`` field to ``ContractDefinition`` which contains the AST IDs of all events emitted by the contract as well as all events defined and inherited by the contract.
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,6 +168,9 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocu
|
|||||||
/// List of contracts whose bytecode is referenced by this contract, e.g. through "new".
|
/// List of contracts whose bytecode is referenced by this contract, e.g. through "new".
|
||||||
/// The Value represents the ast node that referenced the contract.
|
/// The Value represents the ast node that referenced the contract.
|
||||||
std::map<ContractDefinition const*, ASTNode const*, ASTCompareByID<ContractDefinition>> contractDependencies;
|
std::map<ContractDefinition const*, ASTNode const*, ASTCompareByID<ContractDefinition>> contractDependencies;
|
||||||
|
|
||||||
|
// Per-contract map from function AST IDs to internal dispatch function IDs.
|
||||||
|
std::map<FunctionDefinition const*, uint64_t> internalFunctionIDs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallableDeclarationAnnotation: DeclarationAnnotation
|
struct CallableDeclarationAnnotation: DeclarationAnnotation
|
||||||
@ -178,7 +181,6 @@ struct CallableDeclarationAnnotation: DeclarationAnnotation
|
|||||||
|
|
||||||
struct FunctionDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
struct FunctionDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
util::SetOnce<uint64_t> internalFunctionID;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
struct EventDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
|
@ -299,6 +299,14 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node)
|
|||||||
if (!_node.annotation().linearizedBaseContracts.empty())
|
if (!_node.annotation().linearizedBaseContracts.empty())
|
||||||
attributes.emplace_back("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts));
|
attributes.emplace_back("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts));
|
||||||
|
|
||||||
|
if (!_node.annotation().internalFunctionIDs.empty())
|
||||||
|
{
|
||||||
|
Json::Value internalFunctionIDs(Json::objectValue);
|
||||||
|
for (auto const& [functionDefinition, internalFunctionID]: _node.annotation().internalFunctionIDs)
|
||||||
|
internalFunctionIDs[to_string(functionDefinition->id())] = internalFunctionID;
|
||||||
|
attributes.emplace_back("internalFunctionIDs", std::move(internalFunctionIDs));
|
||||||
|
}
|
||||||
|
|
||||||
setJsonNode(_node, "ContractDefinition", std::move(attributes));
|
setJsonNode(_node, "ContractDefinition", std::move(attributes));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -473,9 +481,6 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
|
|||||||
if (!_node.annotation().baseFunctions.empty())
|
if (!_node.annotation().baseFunctions.empty())
|
||||||
attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
|
attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
|
||||||
|
|
||||||
if (_node.annotation().internalFunctionID.set())
|
|
||||||
attributes.emplace_back("internalFunctionID", *_node.annotation().internalFunctionID);
|
|
||||||
|
|
||||||
setJsonNode(_node, "FunctionDefinition", std::move(attributes));
|
setJsonNode(_node, "FunctionDefinition", std::move(attributes));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
|||||||
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
|
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
|
||||||
|
|
||||||
cases.emplace_back(map<string, string>{
|
cases.emplace_back(map<string, string>{
|
||||||
{"funID", to_string(*function->annotation().internalFunctionID)},
|
{"funID", to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
|
||||||
{"name", IRNames::function(*function)}
|
{"name", IRNames::function(*function)}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2807,7 +2807,7 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
define(IRVariable(_expression).part("functionIdentifier")) <<
|
define(IRVariable(_expression).part("functionIdentifier")) <<
|
||||||
to_string(*_referencedFunction.annotation().internalFunctionID) <<
|
to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) <<
|
||||||
"\n";
|
"\n";
|
||||||
m_context.addToInternalDispatch(_referencedFunction);
|
m_context.addToInternalDispatch(_referencedFunction);
|
||||||
}
|
}
|
||||||
|
@ -1246,7 +1246,6 @@ void CompilerStack::storeContractDefinitions()
|
|||||||
|
|
||||||
void CompilerStack::annotateInternalFunctionIDs()
|
void CompilerStack::annotateInternalFunctionIDs()
|
||||||
{
|
{
|
||||||
uint64_t internalFunctionID = 1;
|
|
||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
{
|
{
|
||||||
if (!source->ast)
|
if (!source->ast)
|
||||||
@ -1254,20 +1253,23 @@ void CompilerStack::annotateInternalFunctionIDs()
|
|||||||
|
|
||||||
for (ContractDefinition const* contract: ASTNode::filteredNodes<ContractDefinition>(source->ast->nodes()))
|
for (ContractDefinition const* contract: ASTNode::filteredNodes<ContractDefinition>(source->ast->nodes()))
|
||||||
{
|
{
|
||||||
|
uint64_t internalFunctionID = 1;
|
||||||
ContractDefinitionAnnotation& annotation = contract->annotation();
|
ContractDefinitionAnnotation& annotation = contract->annotation();
|
||||||
|
|
||||||
if (auto const* deployTimeInternalDispatch = util::valueOrNullptr((*annotation.deployedCallGraph)->edges, CallGraph::SpecialNode::InternalDispatch))
|
if (auto const* deployTimeInternalDispatch = util::valueOrNullptr((*annotation.deployedCallGraph)->edges, CallGraph::SpecialNode::InternalDispatch))
|
||||||
for (auto const& node: *deployTimeInternalDispatch)
|
for (auto const& node: *deployTimeInternalDispatch)
|
||||||
if (auto const* callable = get_if<CallableDeclaration const*>(&node))
|
if (auto const* callable = get_if<CallableDeclaration const*>(&node))
|
||||||
if (auto const* function = dynamic_cast<FunctionDefinition const*>(*callable))
|
if (auto const* function = dynamic_cast<FunctionDefinition const*>(*callable))
|
||||||
if (!function->annotation().internalFunctionID.set())
|
{
|
||||||
function->annotation().internalFunctionID = internalFunctionID++;
|
solAssert(contract->annotation().internalFunctionIDs.count(function) == 0);
|
||||||
|
contract->annotation().internalFunctionIDs[function] = internalFunctionID++;
|
||||||
|
}
|
||||||
if (auto const* creationTimeInternalDispatch = util::valueOrNullptr((*annotation.creationCallGraph)->edges, CallGraph::SpecialNode::InternalDispatch))
|
if (auto const* creationTimeInternalDispatch = util::valueOrNullptr((*annotation.creationCallGraph)->edges, CallGraph::SpecialNode::InternalDispatch))
|
||||||
for (auto const& node: *creationTimeInternalDispatch)
|
for (auto const& node: *creationTimeInternalDispatch)
|
||||||
if (auto const* callable = get_if<CallableDeclaration const*>(&node))
|
if (auto const* callable = get_if<CallableDeclaration const*>(&node))
|
||||||
if (auto const* function = dynamic_cast<FunctionDefinition const*>(*callable))
|
if (auto const* function = dynamic_cast<FunctionDefinition const*>(*callable))
|
||||||
// Make sure the function already got an ID since it also occurs in the deploy-time internal dispatch.
|
// Make sure the function already got an ID since it also occurs in the deploy-time internal dispatch.
|
||||||
solAssert(function->annotation().internalFunctionID.set());
|
solAssert(contract->annotation().internalFunctionIDs.count(function) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
|||||||
|
==== Source: L ====
|
||||||
|
|
||||||
|
function free1() {}
|
||||||
|
function free2() {}
|
||||||
|
library L {
|
||||||
|
function g() internal {}
|
||||||
|
function h() internal {}
|
||||||
|
}
|
||||||
|
|
||||||
|
==== Source: A ====
|
||||||
|
|
||||||
|
import "L";
|
||||||
|
contract A {
|
||||||
|
function f() public {
|
||||||
|
(L.g)();
|
||||||
|
(free2)();
|
||||||
|
(L.h)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract B {
|
||||||
|
function f() public {
|
||||||
|
(L.h)();
|
||||||
|
(free2)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
==== Source: C ====
|
||||||
|
|
||||||
|
import "L";
|
||||||
|
contract C {
|
||||||
|
function f() public {
|
||||||
|
(L.g)();
|
||||||
|
(free2)();
|
||||||
|
(L.h)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
@ -41,7 +41,6 @@
|
|||||||
},
|
},
|
||||||
"id": 4,
|
"id": 4,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 1,
|
|
||||||
"kind": "freeFunction",
|
"kind": "freeFunction",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "free1",
|
"name": "free1",
|
||||||
@ -77,7 +76,6 @@
|
|||||||
},
|
},
|
||||||
"id": 8,
|
"id": 8,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 2,
|
|
||||||
"kind": "freeFunction",
|
"kind": "freeFunction",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "free2",
|
"name": "free2",
|
||||||
@ -146,6 +144,13 @@
|
|||||||
"contractKind": "library",
|
"contractKind": "library",
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 53,
|
"id": 53,
|
||||||
|
"internalFunctionIDs":
|
||||||
|
{
|
||||||
|
"20": 3,
|
||||||
|
"24": 4,
|
||||||
|
"4": 1,
|
||||||
|
"8": 2
|
||||||
|
},
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
53
|
53
|
||||||
@ -201,7 +206,6 @@
|
|||||||
},
|
},
|
||||||
"id": 20,
|
"id": 20,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 3,
|
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "inr1",
|
"name": "inr1",
|
||||||
@ -237,7 +241,6 @@
|
|||||||
},
|
},
|
||||||
"id": 24,
|
"id": 24,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 4,
|
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "inr2",
|
"name": "inr2",
|
||||||
@ -579,6 +582,15 @@
|
|||||||
"contractKind": "contract",
|
"contractKind": "contract",
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 128,
|
"id": 128,
|
||||||
|
"internalFunctionIDs":
|
||||||
|
{
|
||||||
|
"20": 3,
|
||||||
|
"24": 4,
|
||||||
|
"4": 1,
|
||||||
|
"69": 5,
|
||||||
|
"73": 6,
|
||||||
|
"8": 2
|
||||||
|
},
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
128
|
128
|
||||||
@ -706,7 +718,6 @@
|
|||||||
},
|
},
|
||||||
"id": 69,
|
"id": 69,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 5,
|
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "inr1",
|
"name": "inr1",
|
||||||
@ -742,7 +753,6 @@
|
|||||||
},
|
},
|
||||||
"id": 73,
|
"id": 73,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"internalFunctionID": 6,
|
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
"name": "inr2",
|
"name": "inr2",
|
||||||
@ -1405,6 +1415,15 @@
|
|||||||
"contractKind": "contract",
|
"contractKind": "contract",
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 141,
|
"id": 141,
|
||||||
|
"internalFunctionIDs":
|
||||||
|
{
|
||||||
|
"20": 3,
|
||||||
|
"24": 4,
|
||||||
|
"4": 1,
|
||||||
|
"69": 5,
|
||||||
|
"73": 6,
|
||||||
|
"8": 2
|
||||||
|
},
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
141,
|
141,
|
||||||
|
Loading…
Reference in New Issue
Block a user