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