aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/Compiler.cpp21
-rw-r--r--libsolidity/codegen/CompilerContext.h6
2 files changed, 13 insertions, 14 deletions
diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp
index 1675f659..ebf61266 100644
--- a/libsolidity/codegen/Compiler.cpp
+++ b/libsolidity/codegen/Compiler.cpp
@@ -502,8 +502,9 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly)
{
ErrorList errors;
assembly::CodeGenerator codeGen(_inlineAssembly.operations(), errors);
- int startStackHeight = m_context.stackHeight();
- m_context.appendInlineAssembly(codeGen.assemble(
+ unsigned startStackHeight = m_context.stackHeight();
+ codeGen.assemble(
+ m_context.nonConstAssembly(),
[&](assembly::Identifier const& _identifier, eth::Assembly& _assembly, assembly::CodeGenerator::IdentifierContext _context) {
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
if (ref == _inlineAssembly.annotation().externalReferences.end())
@@ -513,19 +514,14 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly)
if (_context == assembly::CodeGenerator::IdentifierContext::RValue)
{
solAssert(!!decl->type(), "Type of declaration required but not yet determined.");
- if (/*FunctionDefinition const* functionDef = */dynamic_cast<FunctionDefinition const*>(decl))
- {
- solAssert(false, "Referencing local functions in inline assembly not yet implemented.");
- // This does not work directly, because the label does not exist in _assembly
- // (it is a fresh assembly object).
- // _assembly.append(m_context.virtualFunctionEntryLabel(*functionDef).pushTag());
- }
+ if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(decl))
+ _assembly.append(m_context.virtualFunctionEntryLabel(*functionDef).pushTag());
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
{
solAssert(!variable->isConstant(), "");
if (m_context.isLocalVariable(variable))
{
- int stackDiff = _assembly.deposit() + startStackHeight - m_context.baseStackOffsetOfVariable(*variable);
+ int stackDiff = _assembly.deposit() - m_context.baseStackOffsetOfVariable(*variable);
if (stackDiff < 1 || stackDiff > 16)
BOOST_THROW_EXCEPTION(
CompilerError() <<
@@ -565,7 +561,7 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly)
"Can only assign to stack variables in inline assembly."
);
unsigned size = variable->type()->sizeOnStack();
- int stackDiff = _assembly.deposit() + startStackHeight - m_context.baseStackOffsetOfVariable(*variable) - size;
+ int stackDiff = _assembly.deposit() - m_context.baseStackOffsetOfVariable(*variable) - size;
if (stackDiff > 16 || stackDiff < 1)
BOOST_THROW_EXCEPTION(
CompilerError() <<
@@ -578,8 +574,9 @@ bool Compiler::visit(InlineAssembly const& _inlineAssembly)
}
return true;
}
- ));
+ );
solAssert(errors.empty(), "Code generation for inline assembly with errors requested.");
+ m_context.setStackOffset(startStackHeight);
return false;
}
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 5abe59fe..a56335ce 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -113,8 +113,6 @@ public:
/// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
/// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset.
eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); }
- /// Appends the given code (used by inline assembly) ignoring any stack height changes.
- void appendInlineAssembly(eth::Assembly const& _assembly) { int deposit = m_asm.deposit(); m_asm.append(_assembly); m_asm.setDeposit(deposit); }
/// Pushes the size of the final program
void appendProgramSize() { return m_asm.appendProgramSize(); }
/// Adds data to the data section, pushes a reference to the stack
@@ -140,6 +138,10 @@ public:
void optimise(unsigned _runs = 200) { m_asm.optimise(true, true, _runs); }
eth::Assembly const& assembly() const { return m_asm; }
+ /// @returns non-const reference to the underlying assembly. Should be avoided in favour of
+ /// wrappers in this class.
+ eth::Assembly& nonConstAssembly() { return m_asm; }
+
/// @arg _sourceCodes is the map of input files to source code strings
/// @arg _inJsonFormat shows whether the out should be in Json format
Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const