aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/inlineasm
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2017-02-16 17:12:54 +0800
committerchriseth <c@ethdev.com>2017-03-03 22:41:02 +0800
commitcaa3761dc9be5963d2a5f6448db117fb6272b911 (patch)
treea9deeba9f4ebb5b56982646ade75d18bd365f7f7 /libsolidity/inlineasm
parentf4f82615b129974c811288a5af8e40c95548f11b (diff)
downloaddexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar.gz
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar.bz2
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar.lz
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar.xz
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.tar.zst
dexon-solidity-caa3761dc9be5963d2a5f6448db117fb6272b911.zip
Refactor variable access.
Diffstat (limited to 'libsolidity/inlineasm')
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp70
1 files changed, 30 insertions, 40 deletions
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index c6142011..c1efc72c 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -140,28 +140,11 @@ public:
if (m_scope.lookup(_identifier.name, Scope::NonconstVisitor(
[=](Scope::Variable& _var)
{
- if (!_var.active)
- {
- m_state.addError(
- Error::Type::TypeError,
- "Variable used before it was declared",
- _identifier.location
- );
- m_state.assembly.append(u256(0));
- return;
- }
- int heightDiff = m_state.assembly.deposit() - _var.stackHeight;
- if (heightDiff <= 0 || heightDiff > 16)
- {
- m_state.addError(
- Error::Type::TypeError,
- "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")",
- _identifier.location
- );
- m_state.assembly.append(u256(0));
- }
- else
+ if (int heightDiff = variableHeightDiff(_var, _identifier.location, false))
m_state.assembly.append(solidity::dupInstruction(heightDiff));
+ else
+ // Store something to balance the stack
+ m_state.assembly.append(u256(0));
},
[=](Scope::Label& _label)
{
@@ -266,25 +249,8 @@ private:
if (m_scope.lookup(_variableName.name, Scope::Visitor(
[=](Scope::Variable const& _var)
{
- if (!_var.active)
- {
- m_state.addError(
- Error::Type::TypeError,
- "Variable used before it was declared",
- _location
- );
- m_state.assembly.append(u256(0));
- return;
- }
- int heightDiff = m_state.assembly.deposit() - _var.stackHeight - 1;
- if (heightDiff <= 0 || heightDiff > 16)
- m_state.addError(
- Error::Type::TypeError,
- "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")",
- _location
- );
- else
- m_state.assembly.append(solidity::swapInstruction(heightDiff));
+ if (int heightDiff = variableHeightDiff(_var, _location, true))
+ m_state.assembly.append(solidity::swapInstruction(heightDiff - 1));
m_state.assembly.append(solidity::Instruction::POP);
},
[=](Scope::Label const&)
@@ -304,6 +270,30 @@ private:
);
}
+ /// Determines the stack height difference to the given variables. Automatically generates
+ /// errors if it is not yet in scope or the height difference is too large. Returns 0 on
+ /// errors and the (positive) stack height difference otherwise.
+ int variableHeightDiff(Scope::Variable const& _var, SourceLocation const& _location, bool _forSwap)
+ {
+ if (!_var.active)
+ {
+ m_state.addError( Error::Type::TypeError, "Variable used before it was declared", _location);
+ return 0;
+ }
+ int heightDiff = m_state.assembly.deposit() - _var.stackHeight;
+ if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16))
+ {
+ m_state.addError(
+ Error::Type::TypeError,
+ "Variable inaccessible, too deep inside stack (" + boost::lexical_cast<string>(heightDiff) + ")",
+ _location
+ );
+ return 0;
+ }
+ else
+ return heightDiff;
+ }
+
void expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location)
{
if (m_state.assembly.deposit() != _oldHeight + 1)