mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #2319 from ethereum/virtualBlocks
Introduce virtual blocks for function arguments.
This commit is contained in:
		
						commit
						8b29cc5535
					
				| @ -46,7 +46,7 @@ set<string> const builtinTypes{"bool", "u8", "s8", "u32", "s32", "u64", "s64", " | ||||
| 
 | ||||
| bool AsmAnalyzer::analyze(Block const& _block) | ||||
| { | ||||
| 	if (!(ScopeFiller(m_info.scopes, m_errors))(_block)) | ||||
| 	if (!(ScopeFiller(m_info, m_errors))(_block)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return (*this)(_block); | ||||
| @ -206,16 +206,17 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) | ||||
| { | ||||
| 	Scope& bodyScope = scope(&_funDef.body); | ||||
| 	Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get(); | ||||
| 	solAssert(virtualBlock, ""); | ||||
| 	Scope& varScope = scope(virtualBlock); | ||||
| 	for (auto const& var: _funDef.arguments + _funDef.returns) | ||||
| 	{ | ||||
| 		expectValidType(var.type, var.location); | ||||
| 		boost::get<Scope::Variable>(bodyScope.identifiers.at(var.name)).active = true; | ||||
| 		boost::get<Scope::Variable>(varScope.identifiers.at(var.name)).active = true; | ||||
| 	} | ||||
| 
 | ||||
| 	int const stackHeight = m_stackHeight; | ||||
| 	m_stackHeight = _funDef.arguments.size() + _funDef.returns.size(); | ||||
| 	m_virtualVariablesInNextBlock = m_stackHeight; | ||||
| 
 | ||||
| 	bool success = (*this)(_funDef.body); | ||||
| 
 | ||||
| @ -337,10 +338,10 @@ bool AsmAnalyzer::operator()(Switch const& _switch) | ||||
| bool AsmAnalyzer::operator()(Block const& _block) | ||||
| { | ||||
| 	bool success = true; | ||||
| 	auto previousScope = m_currentScope; | ||||
| 	m_currentScope = &scope(&_block); | ||||
| 
 | ||||
| 	int const initialStackHeight = m_stackHeight - m_virtualVariablesInNextBlock; | ||||
| 	m_virtualVariablesInNextBlock = 0; | ||||
| 	int const initialStackHeight = m_stackHeight; | ||||
| 
 | ||||
| 	for (auto const& s: _block.statements) | ||||
| 		if (!boost::apply_visitor(*this, s)) | ||||
| @ -366,8 +367,8 @@ bool AsmAnalyzer::operator()(Block const& _block) | ||||
| 		success = false; | ||||
| 	} | ||||
| 
 | ||||
| 	m_currentScope = m_currentScope->superScope; | ||||
| 	m_info.stackHeightInfo[&_block] = m_stackHeight; | ||||
| 	m_currentScope = previousScope; | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -91,10 +91,6 @@ private: | ||||
| 	Scope& scope(assembly::Block const* _block); | ||||
| 	void expectValidType(std::string const& type, SourceLocation const& _location); | ||||
| 
 | ||||
| 	/// This is used when we enter the body of a function definition. There, the parameters
 | ||||
| 	/// and return parameters appear as variables which are already on the stack before
 | ||||
| 	/// we enter the block.
 | ||||
| 	int m_virtualVariablesInNextBlock = 0; | ||||
| 	int m_stackHeight = 0; | ||||
| 	julia::ExternalIdentifierAccess::Resolver const& m_resolver; | ||||
| 	Scope* m_currentScope = nullptr; | ||||
|  | ||||
| @ -24,6 +24,7 @@ | ||||
| 
 | ||||
| #include <map> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace dev | ||||
| { | ||||
| @ -55,6 +56,8 @@ struct AsmAnalysisInfo | ||||
| 	using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; | ||||
| 	Scopes scopes; | ||||
| 	StackHeightInfo stackHeightInfo; | ||||
| 	/// Virtual blocks which will be used for scopes for function arguments and return values.
 | ||||
| 	std::map<FunctionDefinition const*, std::shared_ptr<assembly::Block const>> virtualBlocks; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
| 
 | ||||
| #include <libsolidity/inlineasm/AsmData.h> | ||||
| #include <libsolidity/inlineasm/AsmScope.h> | ||||
| #include <libsolidity/inlineasm/AsmAnalysisInfo.h> | ||||
| 
 | ||||
| #include <libsolidity/interface/Exceptions.h> | ||||
| #include <libsolidity/interface/Utils.h> | ||||
| @ -36,8 +37,8 @@ using namespace dev; | ||||
| using namespace dev::solidity; | ||||
| using namespace dev::solidity::assembly; | ||||
| 
 | ||||
| ScopeFiller::ScopeFiller(ScopeFiller::Scopes& _scopes, ErrorList& _errors): | ||||
| 	m_scopes(_scopes), m_errors(_errors) | ||||
| ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorList& _errors): | ||||
| 	m_info(_info), m_errors(_errors) | ||||
| { | ||||
| 	m_currentScope = &scope(nullptr); | ||||
| } | ||||
| @ -84,16 +85,22 @@ bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef) | ||||
| 		)); | ||||
| 		success = false; | ||||
| 	} | ||||
| 	Scope& body = scope(&_funDef.body); | ||||
| 	body.superScope = m_currentScope; | ||||
| 	body.functionScope = true; | ||||
| 
 | ||||
| 	auto virtualBlock = m_info.virtualBlocks[&_funDef] = make_shared<Block>(); | ||||
| 	Scope& varScope = scope(virtualBlock.get()); | ||||
| 	varScope.superScope = m_currentScope; | ||||
| 	m_currentScope = &varScope; | ||||
| 	varScope.functionScope = true; | ||||
| 	for (auto const& var: _funDef.arguments + _funDef.returns) | ||||
| 		if (!registerVariable(var, _funDef.location, body)) | ||||
| 		if (!registerVariable(var, _funDef.location, varScope)) | ||||
| 			success = false; | ||||
| 
 | ||||
| 	if (!(*this)(_funDef.body)) | ||||
| 		success = false; | ||||
| 
 | ||||
| 	solAssert(m_currentScope == &varScope, ""); | ||||
| 	m_currentScope = m_currentScope->superScope; | ||||
| 
 | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -137,7 +144,7 @@ bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& | ||||
| 
 | ||||
| Scope& ScopeFiller::scope(Block const* _block) | ||||
| { | ||||
| 	auto& scope = m_scopes[_block]; | ||||
| 	auto& scope = m_info.scopes[_block]; | ||||
| 	if (!scope) | ||||
| 		scope = make_shared<Scope>(); | ||||
| 	return *scope; | ||||
|  | ||||
| @ -49,6 +49,7 @@ struct FunctionCall; | ||||
| struct Switch; | ||||
| 
 | ||||
| struct Scope; | ||||
| struct AsmAnalysisInfo; | ||||
| 
 | ||||
| /**
 | ||||
|  * Fills scopes with identifiers and checks for name clashes. | ||||
| @ -57,8 +58,7 @@ struct Scope; | ||||
| class ScopeFiller: public boost::static_visitor<bool> | ||||
| { | ||||
| public: | ||||
| 	using Scopes = std::map<assembly::Block const*, std::shared_ptr<Scope>>; | ||||
| 	ScopeFiller(Scopes& _scopes, ErrorList& _errors); | ||||
| 	ScopeFiller(AsmAnalysisInfo& _info, ErrorList& _errors); | ||||
| 
 | ||||
| 	bool operator()(assembly::Instruction const&) { return true; } | ||||
| 	bool operator()(assembly::Literal const&) { return true; } | ||||
| @ -83,7 +83,7 @@ private: | ||||
| 	Scope& scope(assembly::Block const* _block); | ||||
| 
 | ||||
| 	Scope* m_currentScope = nullptr; | ||||
| 	Scopes& m_scopes; | ||||
| 	AsmAnalysisInfo& m_info; | ||||
| 	ErrorList& m_errors; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user