|
|
@ -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); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|