aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-05-31 18:15:43 +0800
committerchriseth <chris@ethereum.org>2017-06-08 21:52:45 +0800
commitfefd3b866d982d95d05e5956d1af48b357162cc8 (patch)
treee5d9cd9a778fe5c3f0723a3b07cd4b400c4ffc46
parent64ddb176bb71498f3a129e0cc549797f4138ec1f (diff)
downloaddexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar.gz
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar.bz2
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar.lz
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar.xz
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.tar.zst
dexon-solidity-fefd3b866d982d95d05e5956d1af48b357162cc8.zip
Introduce machine-dependent stack adjustment.
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.cpp27
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.h10
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp6
3 files changed, 28 insertions, 15 deletions
diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp
index 853c4b78..c9624f82 100644
--- a/libjulia/backends/evm/EVMCodeTransform.cpp
+++ b/libjulia/backends/evm/EVMCodeTransform.cpp
@@ -105,6 +105,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
{
returnLabel = m_assembly.newLabelId();
m_assembly.appendLabelReference(returnLabel);
+ m_stackAdjustment++;
}
Scope::Function* function = nullptr;
@@ -125,6 +126,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
{
m_assembly.appendJumpTo(*function->id, function->returns.size() - function->arguments.size() - 1);
m_assembly.appendLabel(returnLabel);
+ m_stackAdjustment--;
}
checkStackHeight(&_call);
}
@@ -280,7 +282,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
Scope::Function& function = boost::get<Scope::Function>(m_scope->identifiers.at(_function.name));
assignLabelIdIfUnset(function.id);
- int height = m_evm15 ? 0 : 1;
+ int const localStackAdjustment = m_evm15 ? 0 : 1;
+ int height = localStackAdjustment;
solAssert(m_info.scopes.at(&_function.body), "");
Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get();
solAssert(varScope, "");
@@ -294,12 +297,18 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.setSourceLocation(_function.location);
int stackHeightBefore = m_assembly.stackHeight();
AbstractAssembly::LabelID afterFunction = m_assembly.newLabelId();
- m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
if (m_evm15)
+ {
+ m_assembly.appendJumpTo(afterFunction, -stackHeightBefore);
m_assembly.appendBeginsub(*function.id, _function.arguments.size());
+ }
else
+ {
+ m_assembly.appendJumpTo(afterFunction, -stackHeightBefore + height);
m_assembly.appendLabel(*function.id);
+ }
+ m_stackAdjustment += localStackAdjustment;
for (auto const& v: _function.returns)
{
@@ -309,10 +318,11 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.appendConstant(u256(0));
}
- CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, 0).run(_function.body);
+ CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, localStackAdjustment)
+ .run(_function.body);
- if (_function.arguments.size() > 0)
{
+ // Stack of target positions of stack elements
vector<int> stackLayout;
if (!m_evm15)
stackLayout.push_back(_function.returns.size()); // Move return label to the top
@@ -321,7 +331,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
stackLayout.push_back(i);
solAssert(stackLayout.size() <= 17, "Stack too deep");
- while (stackLayout.back() != int(stackLayout.size() - 1))
+ while (!stackLayout.empty() && stackLayout.back() != int(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{
m_assembly.appendInstruction(solidity::Instruction::POP);
@@ -340,13 +350,14 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_assembly.appendReturnsub(_function.returns.size());
else
m_assembly.appendJump(stackHeightBefore - _function.returns.size());
+ m_stackAdjustment -= localStackAdjustment;
m_assembly.appendLabel(afterFunction);
checkStackHeight(&_function);
}
void CodeTransform::operator()(Block const& _block)
{
- CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_initialStackHeight).run(_block);
+ CodeTransform(m_errorReporter, m_assembly, m_info, m_evm15, m_identifierAccess, m_stackAdjustment).run(_block);
}
AbstractAssembly::LabelID CodeTransform::labelFromIdentifier(Identifier const& _identifier)
@@ -420,11 +431,11 @@ void CodeTransform::checkStackHeight(void const* _astElement)
{
solAssert(m_info.stackHeightInfo.count(_astElement), "Stack height for AST element not found.");
solAssert(
- m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_initialStackHeight,
+ m_info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_stackAdjustment,
"Stack height mismatch between analysis and code generation phase: Analysis: " +
to_string(m_info.stackHeightInfo.at(_astElement)) +
" code gen: " +
- to_string(m_assembly.stackHeight() - m_initialStackHeight)
+ to_string(m_assembly.stackHeight() - m_stackAdjustment)
);
}
diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h
index d82462a7..a817efea 100644
--- a/libjulia/backends/evm/EVMCodeTransform.h
+++ b/libjulia/backends/evm/EVMCodeTransform.h
@@ -80,14 +80,14 @@ protected:
solidity::assembly::AsmAnalysisInfo& _analysisInfo,
bool _evm15,
ExternalIdentifierAccess const& _identifierAccess,
- int _initialStackHeight
+ int _stackAdjustment
):
m_errorReporter(_errorReporter),
m_assembly(_assembly),
m_info(_analysisInfo),
m_evm15(_evm15),
m_identifierAccess(_identifierAccess),
- m_initialStackHeight(_initialStackHeight)
+ m_stackAdjustment(_stackAdjustment)
{}
public:
@@ -128,7 +128,11 @@ public:
solidity::assembly::Scope* m_scope = nullptr;
bool m_evm15 = false;
ExternalIdentifierAccess m_identifierAccess;
- int const m_initialStackHeight;
+ /// Adjustment between the stack height as determined during the analysis phase
+ /// and the stack height in the assembly. This is caused by an initial stack being present
+ /// for inline assembly and different stack heights depending on the EVM backend used
+ /// (EVM 1.0 or 1.5).
+ int m_stackAdjustment = 0;
};
}
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index b59a8527..bfc6b2af 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -203,8 +203,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
}
int const stackHeight = m_stackHeight;
- // 1 for return label, depends on VM version
- m_stackHeight = 1 + _funDef.arguments.size() + _funDef.returns.size();
+ m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
bool success = (*this)(_funDef.body);
@@ -258,11 +257,10 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
success = false;
}
}
- m_stackHeight += 1; // Return label, but depends on backend
for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
if (!expectExpression(arg))
success = false;
- m_stackHeight += int(returns) - int(arguments) - 1; // Return label, but depends on backend
+ m_stackHeight += int(returns) - int(arguments);
m_info.stackHeightInfo[&_funCall] = m_stackHeight;
return success;
}