aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-05-18 05:59:13 +0800
committerchriseth <c@ethdev.com>2016-05-18 05:59:13 +0800
commit775b757d0e2681901036fa34a67a3b5ceec24816 (patch)
tree47f4927e0a991492ea709a4e2523289082d950a4 /libsolidity
parent5bf059dc2a1f82a0bf2e8fb9ab06439d01bf29f7 (diff)
parente28604f0b021105b8e0863e485895f1009a77d37 (diff)
downloaddexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar.gz
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar.bz2
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar.lz
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar.xz
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.tar.zst
dexon-solidity-775b757d0e2681901036fa34a67a3b5ceec24816.zip
Merge pull request #545 from chriseth/accessFunLabels
Allow access to functions in inline assembly.
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/codegen/Compiler.cpp21
-rw-r--r--libsolidity/codegen/CompilerContext.h6
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp20
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.h2
4 files changed, 30 insertions, 19 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
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index d571ce0d..53d19b0a 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -36,7 +36,8 @@ using namespace dev::solidity::assembly;
struct GeneratorState
{
- explicit GeneratorState(ErrorList& _errors): errors(_errors) {}
+ GeneratorState(ErrorList& _errors, eth::Assembly& _assembly):
+ errors(_errors), assembly(_assembly) {}
void addError(Error::Type _type, std::string const& _description, SourceLocation const& _location = SourceLocation())
{
@@ -66,10 +67,10 @@ struct GeneratorState
return label != labels.end() ? &label->second : nullptr;
}
- eth::Assembly assembly;
map<string, eth::AssemblyItem> labels;
vector<pair<string, int>> variables; ///< name plus stack height
ErrorList& errors;
+ eth::Assembly& assembly;
};
/**
@@ -267,7 +268,8 @@ private:
bool assembly::CodeGenerator::typeCheck(assembly::CodeGenerator::IdentifierAccess const& _identifierAccess)
{
size_t initialErrorLen = m_errors.size();
- GeneratorState state(m_errors);
+ eth::Assembly assembly;
+ GeneratorState state(m_errors, assembly);
(LabelOrganizer(state))(m_parsedData);
(CodeTransform(state, _identifierAccess))(m_parsedData);
return m_errors.size() == initialErrorLen;
@@ -275,9 +277,17 @@ bool assembly::CodeGenerator::typeCheck(assembly::CodeGenerator::IdentifierAcces
eth::Assembly assembly::CodeGenerator::assemble(assembly::CodeGenerator::IdentifierAccess const& _identifierAccess)
{
- GeneratorState state(m_errors);
+ eth::Assembly assembly;
+ GeneratorState state(m_errors, assembly);
+ (LabelOrganizer(state))(m_parsedData);
+ (CodeTransform(state, _identifierAccess))(m_parsedData);
+ return assembly;
+}
+
+void assembly::CodeGenerator::assemble(eth::Assembly& _assembly, assembly::CodeGenerator::IdentifierAccess const& _identifierAccess)
+{
+ GeneratorState state(m_errors, _assembly);
(LabelOrganizer(state))(m_parsedData);
(CodeTransform(state, _identifierAccess))(m_parsedData);
- return state.assembly;
}
diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h
index aaabda45..b1fafe15 100644
--- a/libsolidity/inlineasm/AsmCodeGen.h
+++ b/libsolidity/inlineasm/AsmCodeGen.h
@@ -55,6 +55,8 @@ public:
bool typeCheck(IdentifierAccess const& _identifierAccess = IdentifierAccess());
/// Performs code generation and @returns the result.
eth::Assembly assemble(IdentifierAccess const& _identifierAccess = IdentifierAccess());
+ /// Performs code generation and appends generated to to _assembly.
+ void assemble(eth::Assembly& _assembly, IdentifierAccess const& _identifierAccess = IdentifierAccess());
private:
Block const& m_parsedData;