diff options
author | Marek Kotewicz <marek.kotewicz@gmail.com> | 2014-12-10 22:32:50 +0800 |
---|---|---|
committer | Marek Kotewicz <marek.kotewicz@gmail.com> | 2014-12-10 22:32:50 +0800 |
commit | f86187a6e804761d5eb9e3e2bc0fc6c9c1976b68 (patch) | |
tree | 1854ec1b20b8600944474e2e39f7f6b3d93d1acf | |
parent | ff445324a30f1c91c1b8a6b7c828d88bc4c66e78 (diff) | |
parent | e8b7d266641175039d40c344449409a60527156e (diff) | |
download | dexon-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.cpp | 43 | ||||
-rw-r--r-- | CompilerContext.cpp | 30 | ||||
-rw-r--r-- | CompilerContext.h | 13 | ||||
-rw-r--r-- | CompilerUtils.cpp | 71 | ||||
-rw-r--r-- | CompilerUtils.h | 63 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 68 | ||||
-rw-r--r-- | ExpressionCompiler.h | 5 |
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; |