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