aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen/CompilerContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen/CompilerContext.cpp')
-rw-r--r--libsolidity/codegen/CompilerContext.cpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
new file mode 100644
index 00000000..00b9d87c
--- /dev/null
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -0,0 +1,223 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ cpp-ethereum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Utilities for the solidity compiler.
+ */
+
+#include <libsolidity/codegen/CompilerContext.h>
+#include <utility>
+#include <numeric>
+#include <libsolidity/ast/AST.h>
+#include <libsolidity/codegen/Compiler.h>
+#include <libsolidity/interface/Version.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+
+void CompilerContext::addMagicGlobal(MagicVariableDeclaration const& _declaration)
+{
+ m_magicGlobals.insert(&_declaration);
+}
+
+void CompilerContext::addStateVariable(
+ VariableDeclaration const& _declaration,
+ u256 const& _storageOffset,
+ unsigned _byteOffset
+)
+{
+ m_stateVariables[&_declaration] = make_pair(_storageOffset, _byteOffset);
+}
+
+void CompilerContext::startFunction(Declaration const& _function)
+{
+ m_functionsWithCode.insert(&_function);
+ *this << functionEntryLabel(_function);
+}
+
+void CompilerContext::addVariable(VariableDeclaration const& _declaration,
+ unsigned _offsetToCurrent)
+{
+ solAssert(m_asm.deposit() >= 0 && unsigned(m_asm.deposit()) >= _offsetToCurrent, "");
+ m_localVariables[&_declaration] = unsigned(m_asm.deposit()) - _offsetToCurrent;
+}
+
+void CompilerContext::removeVariable(VariableDeclaration const& _declaration)
+{
+ solAssert(!!m_localVariables.count(&_declaration), "");
+ m_localVariables.erase(&_declaration);
+}
+
+eth::Assembly const& CompilerContext::compiledContract(const ContractDefinition& _contract) const
+{
+ auto ret = m_compiledContracts.find(&_contract);
+ solAssert(ret != m_compiledContracts.end(), "Compiled contract not found.");
+ return *ret->second;
+}
+
+bool CompilerContext::isLocalVariable(Declaration const* _declaration) const
+{
+ return !!m_localVariables.count(_declaration);
+}
+
+eth::AssemblyItem CompilerContext::functionEntryLabel(Declaration const& _declaration)
+{
+ auto res = m_functionEntryLabels.find(&_declaration);
+ if (res == m_functionEntryLabels.end())
+ {
+ eth::AssemblyItem tag(m_asm.newTag());
+ m_functionEntryLabels.insert(make_pair(&_declaration, tag));
+ return tag.tag();
+ }
+ else
+ return res->second.tag();
+}
+
+eth::AssemblyItem CompilerContext::functionEntryLabelIfExists(Declaration const& _declaration) const
+{
+ auto res = m_functionEntryLabels.find(&_declaration);
+ return res == m_functionEntryLabels.end() ? eth::AssemblyItem(eth::UndefinedItem) : res->second.tag();
+}
+
+eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(FunctionDefinition const& _function)
+{
+ solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
+ return virtualFunctionEntryLabel(_function, m_inheritanceHierarchy.begin());
+}
+
+eth::AssemblyItem CompilerContext::superFunctionEntryLabel(FunctionDefinition const& _function, ContractDefinition const& _base)
+{
+ solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
+ return virtualFunctionEntryLabel(_function, superContract(_base));
+}
+
+FunctionDefinition const* CompilerContext::nextConstructor(ContractDefinition const& _contract) const
+{
+ vector<ContractDefinition const*>::const_iterator it = superContract(_contract);
+ for (; it != m_inheritanceHierarchy.end(); ++it)
+ if ((*it)->constructor())
+ return (*it)->constructor();
+
+ return nullptr;
+}
+
+set<Declaration const*> CompilerContext::functionsWithoutCode()
+{
+ set<Declaration const*> functions;
+ for (auto const& it: m_functionEntryLabels)
+ if (m_functionsWithCode.count(it.first) == 0)
+ functions.insert(it.first);
+ return functions;
+}
+
+ModifierDefinition const& CompilerContext::functionModifier(string const& _name) const
+{
+ solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
+ for (ContractDefinition const* contract: m_inheritanceHierarchy)
+ for (ASTPointer<ModifierDefinition> const& modifier: contract->functionModifiers())
+ if (modifier->name() == _name)
+ return *modifier.get();
+ BOOST_THROW_EXCEPTION(InternalCompilerError()
+ << errinfo_comment("Function modifier " + _name + " not found."));
+}
+
+unsigned CompilerContext::baseStackOffsetOfVariable(Declaration const& _declaration) const
+{
+ auto res = m_localVariables.find(&_declaration);
+ solAssert(res != m_localVariables.end(), "Variable not found on stack.");
+ return res->second;
+}
+
+unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
+{
+ return m_asm.deposit() - _baseOffset - 1;
+}
+
+unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
+{
+ return m_asm.deposit() - _offset - 1;
+}
+
+pair<u256, unsigned> CompilerContext::storageLocationOfVariable(const Declaration& _declaration) const
+{
+ auto it = m_stateVariables.find(&_declaration);
+ solAssert(it != m_stateVariables.end(), "Variable not found in storage.");
+ return it->second;
+}
+
+CompilerContext& CompilerContext::appendJump(eth::AssemblyItem::JumpType _jumpType)
+{
+ eth::AssemblyItem item(eth::Instruction::JUMP);
+ item.setJumpType(_jumpType);
+ return *this << item;
+}
+
+void CompilerContext::resetVisitedNodes(ASTNode const* _node)
+{
+ stack<ASTNode const*> newStack;
+ newStack.push(_node);
+ std::swap(m_visitedNodes, newStack);
+ updateSourceLocation();
+}
+
+void CompilerContext::injectVersionStampIntoSub(size_t _subIndex)
+{
+ eth::Assembly& sub = m_asm.sub(_subIndex);
+ sub.injectStart(eth::Instruction::POP);
+ sub.injectStart(fromBigEndian<u256>(binaryVersion()));
+}
+
+eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(
+ FunctionDefinition const& _function,
+ vector<ContractDefinition const*>::const_iterator _searchStart
+)
+{
+ string name = _function.name();
+ FunctionType functionType(_function);
+ auto it = _searchStart;
+ for (; it != m_inheritanceHierarchy.end(); ++it)
+ for (ASTPointer<FunctionDefinition> const& function: (*it)->definedFunctions())
+ if (
+ function->name() == name &&
+ !function->isConstructor() &&
+ FunctionType(*function).hasEqualArgumentTypes(functionType)
+ )
+ return functionEntryLabel(*function);
+ solAssert(false, "Super function " + name + " not found.");
+ return m_asm.newTag(); // not reached
+}
+
+vector<ContractDefinition const*>::const_iterator CompilerContext::superContract(ContractDefinition const& _contract) const
+{
+ solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
+ auto it = find(m_inheritanceHierarchy.begin(), m_inheritanceHierarchy.end(), &_contract);
+ solAssert(it != m_inheritanceHierarchy.end(), "Base not found in inheritance hierarchy.");
+ return ++it;
+}
+
+void CompilerContext::updateSourceLocation()
+{
+ m_asm.setSourceLocation(m_visitedNodes.empty() ? SourceLocation() : m_visitedNodes.top()->location());
+}
+
+}
+}