aboutsummaryrefslogtreecommitdiffstats
path: root/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Compiler.cpp')
-rw-r--r--Compiler.cpp80
1 files changed, 64 insertions, 16 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index 5a434a71..fa8eb775 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -77,6 +77,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
for (ContractDefinition const* contract: bases)
{
+ //TODO include modifiers
if (FunctionDefinition const* constructor = contract->getConstructor())
nodesUsedInConstructors.insert(constructor);
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
@@ -150,11 +151,7 @@ void Compiler::appendBaseConstructorCall(FunctionDefinition const& _constructor,
FunctionType constructorType(_constructor);
eth::AssemblyItem returnLabel = m_context.pushNewTag();
for (unsigned i = 0; i < _arguments.size(); ++i)
- {
- compileExpression(*_arguments[i]);
- ExpressionCompiler::appendTypeConversion(m_context, *_arguments[i]->getType(),
- *constructorType.getParameterTypes()[i]);
- }
+ compileExpression(*_arguments[i], constructorType.getParameterTypes()[i]);
m_context.appendJumpTo(m_context.getFunctionEntryLabel(_constructor));
m_context << returnLabel;
}
@@ -280,20 +277,28 @@ bool Compiler::visit(FunctionDefinition const& _function)
m_returnTag = m_context.newTag();
m_breakTags.clear();
m_continueTags.clear();
+ m_stackCleanupForReturn = 0;
+ m_currentFunction = &_function;
+ m_modifierDepth = 0;
m_context << m_context.getFunctionEntryLabel(_function);
// stack upon entry: [return address] [arg0] [arg1] ... [argn]
// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]
+ unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters());
+ m_context.adjustStackOffset(parametersSize);
for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
- m_context.addVariable(*variable);
+ {
+ m_context.addVariable(*variable, parametersSize);
+ parametersSize -= variable->getType()->getSizeOnStack();
+ }
for (ASTPointer<VariableDeclaration const> const& variable: _function.getReturnParameters())
m_context.addAndInitializeVariable(*variable);
for (VariableDeclaration const* localVariable: _function.getLocalVariables())
m_context.addAndInitializeVariable(*localVariable);
- _function.getBody().accept(*this);
+ appendModifierOrFunctionCode();
m_context << m_returnTag;
@@ -420,13 +425,15 @@ bool Compiler::visit(Return const& _return)
//@todo modifications are needed to make this work with functions returning multiple values
if (Expression const* expression = _return.getExpression())
{
- compileExpression(*expression);
- VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
- ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType());
-
+ solAssert(_return.getFunctionReturnParameters(), "Invalid return parameters pointer.");
+ VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters()->getParameters().front();
+ compileExpression(*expression, firstVariable.getType());
CompilerUtils(m_context).moveToStackVariable(firstVariable);
}
+ for (unsigned i = 0; i < m_stackCleanupForReturn; ++i)
+ m_context << eth::Instruction::POP;
m_context.appendJumpTo(m_returnTag);
+ m_context.adjustStackOffset(m_stackCleanupForReturn);
return false;
}
@@ -434,10 +441,7 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition)
{
if (Expression const* expression = _variableDefinition.getExpression())
{
- compileExpression(*expression);
- ExpressionCompiler::appendTypeConversion(m_context,
- *expression->getType(),
- *_variableDefinition.getDeclaration().getType());
+ compileExpression(*expression, _variableDefinition.getDeclaration().getType());
CompilerUtils(m_context).moveToStackVariable(_variableDefinition.getDeclaration());
}
return false;
@@ -451,9 +455,53 @@ bool Compiler::visit(ExpressionStatement const& _expressionStatement)
return false;
}
-void Compiler::compileExpression(Expression const& _expression)
+bool Compiler::visit(PlaceholderStatement const&)
+{
+ ++m_modifierDepth;
+ appendModifierOrFunctionCode();
+ --m_modifierDepth;
+}
+
+void Compiler::appendModifierOrFunctionCode()
+{
+ solAssert(m_currentFunction, "");
+ if (m_modifierDepth >= m_currentFunction->getModifiers().size())
+ m_currentFunction->getBody().accept(*this);
+ else
+ {
+ ASTPointer<ModifierInvocation> const& modifierInvocation = m_currentFunction->getModifiers()[m_modifierDepth];
+
+ // TODO get the most derived override of the modifier
+ ModifierDefinition const* modifier = dynamic_cast<ModifierDefinition const*>(
+ modifierInvocation->getName()->getReferencedDeclaration());
+ solAssert(!!modifier, "Modifier not found.");
+ solAssert(modifier->getParameters().size() == modifierInvocation->getArguments().size(), "");
+ for (unsigned i = 0; i < modifier->getParameters().size(); ++i)
+ {
+ m_context.addVariable(*modifier->getParameters()[i]);
+ compileExpression(*modifierInvocation->getArguments()[i],
+ modifier->getParameters()[i]->getType());
+ }
+ for (VariableDeclaration const* localVariable: modifier->getLocalVariables())
+ m_context.addAndInitializeVariable(*localVariable);
+
+ unsigned const c_stackSurplus = CompilerUtils::getSizeOnStack(modifier->getParameters()) +
+ CompilerUtils::getSizeOnStack(modifier->getLocalVariables());
+ m_stackCleanupForReturn += c_stackSurplus;
+
+ modifier->getBody().accept(*this);
+
+ for (unsigned i = 0; i < c_stackSurplus; ++i)
+ m_context << eth::Instruction::POP;
+ m_stackCleanupForReturn -= c_stackSurplus;
+ }
+}
+
+void Compiler::compileExpression(Expression const& _expression, TypePointer const& _targetType)
{
ExpressionCompiler::compileExpression(m_context, _expression, m_optimize);
+ if (_targetType)
+ ExpressionCompiler::appendTypeConversion(m_context, *_expression.getType(), *_targetType);
}
}