diff options
author | chriseth <chris@ethereum.org> | 2017-05-27 03:46:02 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2017-05-29 22:18:16 +0800 |
commit | 4af55c78ebcacb5cfda1b573253cac6e6824d67a (patch) | |
tree | e03445356136f0186cd37eb1fb1b9b5b4e6b66c4 | |
parent | 002df12d13fb423be641878a20b73bd10f90a6df (diff) | |
download | dexon-solidity-4af55c78ebcacb5cfda1b573253cac6e6824d67a.tar.gz dexon-solidity-4af55c78ebcacb5cfda1b573253cac6e6824d67a.tar.zst dexon-solidity-4af55c78ebcacb5cfda1b573253cac6e6824d67a.zip |
Introduce virtual blocks for function arguments.
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 15 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.h | 4 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysisInfo.h | 3 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.cpp | 21 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.h | 6 |
5 files changed, 28 insertions, 21 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index eeb7d0a6..9f512f87 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -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; } diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 87d41e11..14b18c4a 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -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; diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.h b/libsolidity/inlineasm/AsmAnalysisInfo.h index 18382db0..78c1fbe0 100644 --- a/libsolidity/inlineasm/AsmAnalysisInfo.h +++ b/libsolidity/inlineasm/AsmAnalysisInfo.h @@ -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; }; } diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index 7eb6a9ed..3fade842 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -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; diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h index c7179b3b..42e80141 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.h +++ b/libsolidity/inlineasm/AsmScopeFiller.h @@ -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; }; |