aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Kotewicz <marek.kotewicz@gmail.com>2014-12-10 22:32:50 +0800
committerMarek Kotewicz <marek.kotewicz@gmail.com>2014-12-10 22:32:50 +0800
commitf86187a6e804761d5eb9e3e2bc0fc6c9c1976b68 (patch)
tree1854ec1b20b8600944474e2e39f7f6b3d93d1acf
parentff445324a30f1c91c1b8a6b7c828d88bc4c66e78 (diff)
parente8b7d266641175039d40c344449409a60527156e (diff)
downloaddexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar.gz
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar.bz2
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar.lz
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar.xz
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.tar.zst
dexon-solidity-f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68.zip
Merge branch 'develop' into build_enhancement
-rw-r--r--Compiler.cpp43
-rw-r--r--CompilerContext.cpp30
-rw-r--r--CompilerContext.h13
-rw-r--r--CompilerUtils.cpp71
-rw-r--r--CompilerUtils.h63
-rw-r--r--ExpressionCompiler.cpp68
-rw-r--r--ExpressionCompiler.h5
7 files changed, 239 insertions, 54 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index 17ad4fd1..a8a07403 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -26,6 +26,7 @@
#include <libsolidity/AST.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/ExpressionCompiler.h>
+#include <libsolidity/CompilerUtils.h>
using namespace std;
@@ -135,7 +136,7 @@ unsigned Compiler::appendCalldataUnpacker(FunctionDefinition const& _function, b
for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
{
unsigned const numBytes = var->getType()->getCalldataEncodedSize();
- if (numBytes == 0)
+ if (numBytes == 0 || numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(var->getLocation())
<< errinfo_comment("Type " + var->getType()->toString() + " not yet supported."));
@@ -154,18 +155,20 @@ void Compiler::appendReturnValuePacker(FunctionDefinition const& _function)
//@todo this can be also done more efficiently
unsigned dataOffset = 0;
vector<ASTPointer<VariableDeclaration>> const& parameters = _function.getReturnParameters();
+ unsigned stackDepth = CompilerUtils(m_context).getSizeOnStack(parameters);
for (unsigned i = 0; i < parameters.size(); ++i)
{
Type const& paramType = *parameters[i]->getType();
unsigned numBytes = paramType.getCalldataEncodedSize();
- if (numBytes == 0)
+ if (numBytes == 0 || numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(parameters[i]->getLocation())
<< errinfo_comment("Type " + paramType.toString() + " not yet supported."));
- m_context << eth::dupInstruction(parameters.size() - i);
+ CompilerUtils(m_context).copyToStackTop(stackDepth, paramType);
if (numBytes != 32)
m_context << (u256(1) << ((32 - numBytes) * 8)) << eth::Instruction::MUL;
m_context << u256(dataOffset) << eth::Instruction::MSTORE;
+ stackDepth -= paramType.getSizeOnStack();
dataOffset += numBytes;
}
// note that the stack is not cleaned up here
@@ -195,15 +198,12 @@ bool Compiler::visit(FunctionDefinition& _function)
// stack upon entry: [return address] [arg0] [arg1] ... [argn]
// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]
- unsigned const numArguments = _function.getParameters().size();
- unsigned const numReturnValues = _function.getReturnParameters().size();
- unsigned const numLocalVariables = _function.getLocalVariables().size();
-
- for (ASTPointer<VariableDeclaration> const& variable: _function.getParameters() + _function.getReturnParameters())
+ for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
m_context.addVariable(*variable);
+ for (ASTPointer<VariableDeclaration const> const& variable: _function.getReturnParameters())
+ m_context.addAndInitializeVariable(*variable);
for (VariableDeclaration const* localVariable: _function.getLocalVariables())
- m_context.addVariable(*localVariable);
- m_context.initializeLocalVariables(numReturnValues + numLocalVariables);
+ m_context.addAndInitializeVariable(*localVariable);
_function.getBody().accept(*this);
@@ -215,12 +215,16 @@ bool Compiler::visit(FunctionDefinition& _function)
// Note that the fact that the return arguments are of increasing index is vital for this
// algorithm to work.
+ unsigned const argumentsSize = CompilerUtils::getSizeOnStack(_function.getParameters());
+ unsigned const returnValuesSize = CompilerUtils::getSizeOnStack(_function.getReturnParameters());
+ unsigned const localVariablesSize = CompilerUtils::getSizeOnStack(_function.getLocalVariables());
+
vector<int> stackLayout;
- stackLayout.push_back(numReturnValues); // target of return address
- stackLayout += vector<int>(numArguments, -1); // discard all arguments
- for (unsigned i = 0; i < numReturnValues; ++i)
+ stackLayout.push_back(returnValuesSize); // target of return address
+ stackLayout += vector<int>(argumentsSize, -1); // discard all arguments
+ for (unsigned i = 0; i < returnValuesSize; ++i)
stackLayout.push_back(i);
- stackLayout += vector<int>(numLocalVariables, -1);
+ stackLayout += vector<int>(localVariablesSize, -1);
while (stackLayout.back() != int(stackLayout.size() - 1))
if (stackLayout.back() < 0)
@@ -298,8 +302,7 @@ bool Compiler::visit(Return& _return)
VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType());
- unsigned stackPosition = m_context.baseToCurrentStackOffset(m_context.getBaseStackOffsetOfVariable(firstVariable));
- m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
+ CompilerUtils(m_context).moveToStackVariable(firstVariable);
}
m_context.appendJumpTo(m_returnTag);
return false;
@@ -313,9 +316,7 @@ bool Compiler::visit(VariableDefinition& _variableDefinition)
ExpressionCompiler::appendTypeConversion(m_context,
*expression->getType(),
*_variableDefinition.getDeclaration().getType());
- unsigned baseStackOffset = m_context.getBaseStackOffsetOfVariable(_variableDefinition.getDeclaration());
- unsigned stackPosition = m_context.baseToCurrentStackOffset(baseStackOffset);
- m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
+ CompilerUtils(m_context).moveToStackVariable(_variableDefinition.getDeclaration());
}
return false;
}
@@ -324,9 +325,7 @@ bool Compiler::visit(ExpressionStatement& _expressionStatement)
{
Expression& expression = _expressionStatement.getExpression();
ExpressionCompiler::compileExpression(m_context, expression);
-// Type::Category category = expression.getType()->getCategory();
- for (unsigned i = 0; i < expression.getType()->getSizeOnStack(); ++i)
- m_context << eth::Instruction::POP;
+ CompilerUtils(m_context).popStackElement(*expression.getType());
return false;
}
diff --git a/CompilerContext.cpp b/CompilerContext.cpp
index b89a8e5b..cd22c4e8 100644
--- a/CompilerContext.cpp
+++ b/CompilerContext.cpp
@@ -41,20 +41,30 @@ void CompilerContext::addStateVariable(VariableDeclaration const& _declaration)
m_stateVariablesSize += _declaration.getType()->getStorageSize();
}
-void CompilerContext::initializeLocalVariables(unsigned _numVariables)
+void CompilerContext::addVariable(VariableDeclaration const& _declaration)
{
- if (_numVariables > 0)
- {
+ m_localVariables[&_declaration] = m_localVariablesSize;
+ m_localVariablesSize += _declaration.getType()->getSizeOnStack();
+}
+
+void CompilerContext::addAndInitializeVariable(VariableDeclaration const& _declaration)
+{
+ addVariable(_declaration);
+
+ unsigned const size = _declaration.getType()->getSizeOnStack();
+ for (unsigned i = 0; i < size; ++i)
*this << u256(0);
- for (unsigned i = 1; i < _numVariables; ++i)
- *this << eth::Instruction::DUP1;
- m_asm.adjustDeposit(-_numVariables);
- }
+ m_asm.adjustDeposit(-size);
+}
+
+void CompilerContext::addFunction(FunctionDefinition const& _function)
+{
+ m_functionEntryLabels.insert(std::make_pair(&_function, m_asm.newTag()));
}
bool CompilerContext::isLocalVariable(Declaration const* _declaration) const
{
- return std::find(m_localVariables.begin(), m_localVariables.end(), _declaration) != m_localVariables.end();
+ return m_localVariables.count(_declaration) > 0;
}
eth::AssemblyItem CompilerContext::getFunctionEntryLabel(FunctionDefinition const& _function) const
@@ -67,10 +77,10 @@ eth::AssemblyItem CompilerContext::getFunctionEntryLabel(FunctionDefinition cons
unsigned CompilerContext::getBaseStackOffsetOfVariable(Declaration const& _declaration) const
{
- auto res = find(begin(m_localVariables), end(m_localVariables), &_declaration);
+ auto res = m_localVariables.find(&_declaration);
if (asserts(res != m_localVariables.end()))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Variable not found on stack."));
- return unsigned(end(m_localVariables) - res - 1);
+ return m_localVariablesSize - res->second - 1;
}
unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
diff --git a/CompilerContext.h b/CompilerContext.h
index 6a48e148..652e65a6 100644
--- a/CompilerContext.h
+++ b/CompilerContext.h
@@ -25,6 +25,7 @@
#include <ostream>
#include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h>
+#include <libsolidity/ASTForward.h>
#include <libsolidity/Types.h>
namespace dev {
@@ -43,9 +44,9 @@ public:
void addMagicGlobal(MagicVariableDeclaration const& _declaration);
void addStateVariable(VariableDeclaration const& _declaration);
void startNewFunction() { m_localVariables.clear(); m_asm.setDeposit(0); }
- void initializeLocalVariables(unsigned _numVariables);
- void addVariable(VariableDeclaration const& _declaration) { m_localVariables.push_back(&_declaration); }
- void addFunction(FunctionDefinition const& _function) { m_functionEntryLabels.insert(std::make_pair(&_function, m_asm.newTag())); }
+ void addVariable(VariableDeclaration const& _declaration);
+ void addAndInitializeVariable(VariableDeclaration const& _declaration);
+ void addFunction(FunctionDefinition const& _function);
void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); }
@@ -98,8 +99,10 @@ private:
u256 m_stateVariablesSize;
/// Storage offsets of state variables
std::map<Declaration const*, u256> m_stateVariables;
- /// Offsets of local variables on the stack.
- std::vector<Declaration const*> m_localVariables;
+ /// Offsets of local variables on the stack (relative to stack base).
+ std::map<Declaration const*, unsigned> m_localVariables;
+ /// Sum of stack sizes of local variables
+ unsigned m_localVariablesSize;
/// Labels pointing to the entry points of funcitons.
std::map<Declaration const*, eth::AssemblyItem> m_functionEntryLabels;
};
diff --git a/CompilerUtils.cpp b/CompilerUtils.cpp
new file mode 100644
index 00000000..d4dfbe3c
--- /dev/null
+++ b/CompilerUtils.cpp
@@ -0,0 +1,71 @@
+/*
+ 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
+ * Routines used by both the compiler and the expression compiler.
+ */
+
+#include <libsolidity/CompilerUtils.h>
+#include <libsolidity/AST.h>
+#include <libevmcore/Instruction.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+
+void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable)
+{
+ unsigned const stackPosition = m_context.baseToCurrentStackOffset(m_context.getBaseStackOffsetOfVariable(_variable));
+ unsigned const size = _variable.getType()->getSizeOnStack();
+ // move variable starting from its top end in the stack
+ if (stackPosition - size + 1 > 16)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_variable.getLocation())
+ << errinfo_comment("Stack too deep."));
+ for (unsigned i = 0; i < size; ++i)
+ m_context << eth::swapInstruction(stackPosition - size + 1) << eth::Instruction::POP;
+}
+
+void CompilerUtils::copyToStackTop(unsigned _stackDepth, Type const& _type)
+{
+ if (_stackDepth > 16)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Stack too deep."));
+ unsigned const size = _type.getSizeOnStack();
+ for (unsigned i = 0; i < size; ++i)
+ m_context << eth::dupInstruction(_stackDepth);
+}
+
+void CompilerUtils::popStackElement(Type const& _type)
+{
+ unsigned const size = _type.getSizeOnStack();
+ for (unsigned i = 0; i < size; ++i)
+ m_context << eth::Instruction::POP;
+}
+
+unsigned CompilerUtils::getSizeOnStack(vector<shared_ptr<Type const>> const& _variableTypes)
+{
+ unsigned size = 0;
+ for (shared_ptr<Type const> const& type: _variableTypes)
+ size += type->getSizeOnStack();
+ return size;
+}
+
+}
+}
diff --git a/CompilerUtils.h b/CompilerUtils.h
new file mode 100644
index 00000000..4da53375
--- /dev/null
+++ b/CompilerUtils.h
@@ -0,0 +1,63 @@
+/*
+ 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
+ * Routines used by both the compiler and the expression compiler.
+ */
+
+#pragma once
+
+#include <libsolidity/CompilerContext.h>
+#include <libsolidity/ASTForward.h>
+
+namespace dev {
+namespace solidity {
+
+class Type; // forward
+
+class CompilerUtils
+{
+public:
+ CompilerUtils(CompilerContext& _context): m_context(_context) {}
+
+ /// Moves the value that is at the top of the stack to a stack variable.
+ void moveToStackVariable(VariableDeclaration const& _variable);
+ /// Copies a variable of type @a _type from a stack depth of @a _stackDepth to the top of the stack.
+ void copyToStackTop(unsigned _stackDepth, Type const& _type);
+ /// Removes the current value from the top of the stack.
+ void popStackElement(Type const& _type);
+
+ template <class T>
+ static unsigned getSizeOnStack(std::vector<T> const& _variables);
+ static unsigned getSizeOnStack(std::vector<std::shared_ptr<Type const>> const& _variableTypes);
+
+private:
+ CompilerContext& m_context;
+};
+
+template <class T>
+unsigned CompilerUtils::getSizeOnStack(std::vector<T> const& _variables)
+{
+ unsigned size = 0;
+ for (T const& variable: _variables)
+ size += variable->getType()->getSizeOnStack();
+ return size;
+}
+
+}
+}
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 352b0e6d..f1086c14 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -26,6 +26,7 @@
#include <libsolidity/AST.h>
#include <libsolidity/ExpressionCompiler.h>
#include <libsolidity/CompilerContext.h>
+#include <libsolidity/CompilerUtils.h>
using namespace std;
@@ -174,9 +175,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
// explicit type conversion contract -> address, nothing to do.
}
else
- {
appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
- }
}
else
{
@@ -203,13 +202,14 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
m_context.appendJump();
m_context << returnLabel;
+ unsigned returnParametersSize = CompilerUtils::getSizeOnStack(function.getReturnParameterTypes());
// callee adds return parameters, but removes arguments and return label
- m_context.adjustStackOffset(function.getReturnParameterTypes().size() - arguments.size() - 1);
+ m_context.adjustStackOffset(returnParametersSize - CompilerUtils::getSizeOnStack(arguments) - 1);
// @todo for now, the return value of a function is its first return value, so remove
// all others
for (unsigned i = 1; i < function.getReturnParameterTypes().size(); ++i)
- m_context << eth::Instruction::POP;
+ CompilerUtils(m_context).popStackElement(*function.getReturnParameterTypes()[i]);
break;
}
case Location::EXTERNAL:
@@ -356,7 +356,7 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
{
StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
m_context << type.getStorageOffsetOfMember(member) << eth::Instruction::ADD;
- m_currentLValue = LValue(m_context, LValue::STORAGE);
+ m_currentLValue = LValue(m_context, LValue::STORAGE, *_memberAccess.getType());
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
break;
}
@@ -376,7 +376,7 @@ bool ExpressionCompiler::visit(IndexAccess& _indexAccess)
m_context << u256(32) << eth::Instruction::MSTORE << u256(0) << eth::Instruction::MSTORE;
m_context << u256(64) << u256(0) << eth::Instruction::SHA3;
- m_currentLValue = LValue(m_context, LValue::STORAGE);
+ m_currentLValue = LValue(m_context, LValue::STORAGE, *_indexAccess.getType());
m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess);
return false;
@@ -565,6 +565,13 @@ void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack)
m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND;
}
+ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType,
+ unsigned _baseStackOffset):
+ m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset),
+ m_stackSize(_dataType.getSizeOnStack())
+{
+}
+
void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bool _remove) const
{
switch (m_type)
@@ -575,7 +582,8 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo
if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation())
<< errinfo_comment("Stack too deep."));
- *m_context << eth::dupInstruction(stackPos + 1);
+ for (unsigned i = 0; i < m_stackSize; ++i)
+ *m_context << eth::dupInstruction(stackPos + 1);
break;
}
case STORAGE:
@@ -583,7 +591,17 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo
break; // no distinction between value and reference for non-value types
if (!_remove)
*m_context << eth::Instruction::DUP1;
- *m_context << eth::Instruction::SLOAD;
+ if (m_stackSize == 1)
+ *m_context << eth::Instruction::SLOAD;
+ else
+ for (unsigned i = 0; i < m_stackSize; ++i)
+ {
+ *m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1;
+ if (i + 1 < m_stackSize)
+ *m_context << u256(1) << eth::Instruction::ADD;
+ else
+ *m_context << eth::Instruction::POP;
+ }
break;
case MEMORY:
if (!_expression.getType()->isValueType())
@@ -604,12 +622,13 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool
{
case STACK:
{
- unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset));
- if (stackPos > 16)
+ unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)) - m_stackSize + 1;
+ if (stackDiff > 16)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation())
<< errinfo_comment("Stack too deep."));
- else if (stackPos > 0)
- *m_context << eth::swapInstruction(stackPos) << eth::Instruction::POP;
+ else if (stackDiff > 0)
+ for (unsigned i = 0; i < m_stackSize; ++i)
+ *m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP;
if (!_move)
retrieveValue(_expression);
break;
@@ -617,9 +636,27 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool
case LValue::STORAGE:
if (!_expression.getType()->isValueType())
break; // no distinction between value and reference for non-value types
- if (!_move)
- *m_context << eth::Instruction::DUP2 << eth::Instruction::SWAP1;
- *m_context << eth::Instruction::SSTORE;
+ // stack layout: value value ... value ref
+ if (!_move) // copy values
+ {
+ if (m_stackSize + 1 > 16)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation())
+ << errinfo_comment("Stack too deep."));
+ for (unsigned i = 0; i < m_stackSize; ++i)
+ *m_context << eth::dupInstruction(m_stackSize + 1) << eth::Instruction::SWAP1;
+ }
+ if (m_stackSize > 0) // store high index value first
+ *m_context << u256(m_stackSize - 1) << eth::Instruction::ADD;
+ for (unsigned i = 0; i < m_stackSize; ++i)
+ {
+ if (i + 1 >= m_stackSize)
+ *m_context << eth::Instruction::SSTORE;
+ else
+ // v v ... v v r+x
+ *m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2
+ << eth::Instruction::SSTORE
+ << u256(1) << eth::Instruction::SWAP1 << eth::Instruction::SUB;
+ }
break;
case LValue::MEMORY:
if (!_expression.getType()->isValueType())
@@ -645,6 +682,7 @@ void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression co
void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, Declaration const& _declaration)
{
+ m_stackSize = _identifier.getType()->getSizeOnStack();
if (m_context->isLocalVariable(&_declaration))
{
m_type = STACK;
diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h
index fbecbdc8..966be30e 100644
--- a/ExpressionCompiler.h
+++ b/ExpressionCompiler.h
@@ -93,8 +93,7 @@ private:
enum LValueType { NONE, STACK, MEMORY, STORAGE };
explicit LValue(CompilerContext& _compilerContext): m_context(&_compilerContext) { reset(); }
- LValue(CompilerContext& _compilerContext, LValueType _type, unsigned _baseStackOffset = 0):
- m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset) {}
+ LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, unsigned _baseStackOffset = 0);
/// Set type according to the declaration and retrieve the reference.
/// @a _expression is the current expression
@@ -129,6 +128,8 @@ private:
/// If m_type is STACK, this is base stack offset (@see
/// CompilerContext::getBaseStackOffsetOfVariable) of a local variable.
unsigned m_baseStackOffset;
+ /// Size of the value of this lvalue on the stack.
+ unsigned m_stackSize;
};
CompilerContext& m_context;