mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adapt EVM codegen to new namespace.
This commit is contained in:
@@ -7,10 +7,12 @@ aux_source_directory(formal SRC_LIST)
|
||||
aux_source_directory(interface SRC_LIST)
|
||||
aux_source_directory(parsing SRC_LIST)
|
||||
aux_source_directory(inlineasm SRC_LIST)
|
||||
# Until we have a clear separation, libjulia has to be included here
|
||||
aux_source_directory(../libjulia SRC_LIST)
|
||||
|
||||
set(EXECUTABLE solidity)
|
||||
|
||||
file(GLOB HEADERS "*/*.h")
|
||||
file(GLOB HEADERS "*/*.h" "../libjulia/backends/evm/*")
|
||||
|
||||
include_directories(BEFORE ..)
|
||||
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
|
||||
|
||||
@@ -166,8 +166,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
|
||||
// The only purpose of this step is to fill the inline assembly annotation with
|
||||
// external references.
|
||||
ErrorList errorsIgnored;
|
||||
assembly::ExternalIdentifierAccess::Resolver resolver =
|
||||
[&](assembly::Identifier const& _identifier, assembly::IdentifierContext) {
|
||||
julia::ExternalIdentifierAccess::Resolver resolver =
|
||||
[&](assembly::Identifier const& _identifier, julia::IdentifierContext) {
|
||||
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name);
|
||||
bool isSlot = boost::algorithm::ends_with(_identifier.name, "_slot");
|
||||
bool isOffset = boost::algorithm::ends_with(_identifier.name, "_offset");
|
||||
|
||||
@@ -631,9 +631,9 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
// External references have already been resolved in a prior stage and stored in the annotation.
|
||||
// We run the resolve step again regardless.
|
||||
assembly::ExternalIdentifierAccess::Resolver identifierAccess = [&](
|
||||
julia::ExternalIdentifierAccess::Resolver identifierAccess = [&](
|
||||
assembly::Identifier const& _identifier,
|
||||
assembly::IdentifierContext _context
|
||||
julia::IdentifierContext _context
|
||||
)
|
||||
{
|
||||
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
||||
@@ -650,7 +650,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
|
||||
return size_t(-1);
|
||||
}
|
||||
else if (_context != assembly::IdentifierContext::RValue)
|
||||
else if (_context != julia::IdentifierContext::RValue)
|
||||
{
|
||||
typeError(_identifier.location, "Storage variables cannot be assigned to.");
|
||||
return size_t(-1);
|
||||
@@ -677,13 +677,13 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
return size_t(-1);
|
||||
}
|
||||
}
|
||||
else if (_context == assembly::IdentifierContext::LValue)
|
||||
else if (_context == julia::IdentifierContext::LValue)
|
||||
{
|
||||
typeError(_identifier.location, "Only local variables can be assigned to in inline assembly.");
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
if (_context == assembly::IdentifierContext::RValue)
|
||||
if (_context == julia::IdentifierContext::RValue)
|
||||
{
|
||||
solAssert(!!declaration->type(), "Type of declaration required but not yet determined.");
|
||||
if (dynamic_cast<FunctionDefinition const*>(declaration))
|
||||
|
||||
@@ -266,10 +266,10 @@ void CompilerContext::appendInlineAssembly(
|
||||
|
||||
int startStackHeight = stackHeight();
|
||||
|
||||
assembly::ExternalIdentifierAccess identifierAccess;
|
||||
julia::ExternalIdentifierAccess identifierAccess;
|
||||
identifierAccess.resolve = [&](
|
||||
assembly::Identifier const& _identifier,
|
||||
assembly::IdentifierContext
|
||||
julia::IdentifierContext
|
||||
)
|
||||
{
|
||||
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
|
||||
@@ -277,7 +277,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
};
|
||||
identifierAccess.generateCode = [&](
|
||||
assembly::Identifier const& _identifier,
|
||||
assembly::IdentifierContext _context,
|
||||
julia::IdentifierContext _context,
|
||||
julia::AbstractAssembly& _assembly
|
||||
)
|
||||
{
|
||||
@@ -285,14 +285,14 @@ void CompilerContext::appendInlineAssembly(
|
||||
solAssert(it != _localVariables.end(), "");
|
||||
int stackDepth = _localVariables.end() - it;
|
||||
int stackDiff = _assembly.stackHeight() - startStackHeight + stackDepth;
|
||||
if (_context == assembly::IdentifierContext::LValue)
|
||||
if (_context == julia::IdentifierContext::LValue)
|
||||
stackDiff -= 1;
|
||||
if (stackDiff < 1 || stackDiff > 16)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
CompilerError() <<
|
||||
errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
|
||||
);
|
||||
if (_context == assembly::IdentifierContext::RValue)
|
||||
if (_context == julia::IdentifierContext::RValue)
|
||||
_assembly.appendInstruction(dupInstruction(stackDiff));
|
||||
else
|
||||
{
|
||||
|
||||
@@ -522,21 +522,21 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
ErrorList errors;
|
||||
assembly::CodeGenerator codeGen(errors);
|
||||
unsigned startStackHeight = m_context.stackHeight();
|
||||
assembly::ExternalIdentifierAccess identifierAccess;
|
||||
identifierAccess.resolve = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext)
|
||||
julia::ExternalIdentifierAccess identifierAccess;
|
||||
identifierAccess.resolve = [&](assembly::Identifier const& _identifier, julia::IdentifierContext)
|
||||
{
|
||||
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
||||
if (ref == _inlineAssembly.annotation().externalReferences.end())
|
||||
return size_t(-1);
|
||||
return ref->second.valueSize;
|
||||
};
|
||||
identifierAccess.generateCode = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext _context, julia::AbstractAssembly& _assembly)
|
||||
identifierAccess.generateCode = [&](assembly::Identifier const& _identifier, julia::IdentifierContext _context, julia::AbstractAssembly& _assembly)
|
||||
{
|
||||
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
||||
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
|
||||
Declaration const* decl = ref->second.declaration;
|
||||
solAssert(!!decl, "");
|
||||
if (_context == assembly::IdentifierContext::RValue)
|
||||
if (_context == julia::IdentifierContext::RValue)
|
||||
{
|
||||
int const depositBefore = _assembly.stackHeight();
|
||||
solAssert(!!decl->type(), "Type of declaration required but not yet determined.");
|
||||
|
||||
@@ -41,7 +41,7 @@ using namespace dev::solidity::assembly;
|
||||
AsmAnalyzer::AsmAnalyzer(
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
ErrorList& _errors,
|
||||
ExternalIdentifierAccess::Resolver const& _resolver
|
||||
julia::ExternalIdentifierAccess::Resolver const& _resolver
|
||||
):
|
||||
m_resolver(_resolver), m_info(_analysisInfo), m_errors(_errors)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
|
||||
{
|
||||
size_t stackSize(-1);
|
||||
if (m_resolver)
|
||||
stackSize = m_resolver(_identifier, IdentifierContext::RValue);
|
||||
stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue);
|
||||
if (stackSize == size_t(-1))
|
||||
{
|
||||
// Only add an error message if the callback did not do it.
|
||||
@@ -393,7 +393,7 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
|
||||
variableSize = 1;
|
||||
}
|
||||
else if (m_resolver)
|
||||
variableSize = m_resolver(_variable, IdentifierContext::LValue);
|
||||
variableSize = m_resolver(_variable, julia::IdentifierContext::LValue);
|
||||
if (variableSize == size_t(-1))
|
||||
{
|
||||
// Only add message if the callback did not.
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
AsmAnalyzer(
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
ErrorList& _errors,
|
||||
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver()
|
||||
julia::ExternalIdentifierAccess::Resolver const& _resolver = julia::ExternalIdentifierAccess::Resolver()
|
||||
);
|
||||
|
||||
bool analyze(assembly::Block const& _block);
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
/// we enter the block.
|
||||
int m_virtualVariablesInNextBlock = 0;
|
||||
int m_stackHeight = 0;
|
||||
ExternalIdentifierAccess::Resolver const& m_resolver;
|
||||
julia::ExternalIdentifierAccess::Resolver const& m_resolver;
|
||||
Scope* m_currentScope = nullptr;
|
||||
AsmAnalysisInfo& m_info;
|
||||
ErrorList& m_errors;
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include <libevmasm/SourceLocation.h>
|
||||
#include <libevmasm/Instruction.h>
|
||||
|
||||
#include <libjulia/backends/AbstractAssembly.h>
|
||||
#include <libjulia/backends/evm/AbstractAssembly.h>
|
||||
#include <libjulia/backends/evm/EVMCodeTransform.h>
|
||||
|
||||
#include <libdevcore/CommonIO.h>
|
||||
|
||||
@@ -48,15 +49,6 @@ using namespace dev;
|
||||
using namespace dev::solidity;
|
||||
using namespace dev::solidity::assembly;
|
||||
|
||||
struct GeneratorState
|
||||
{
|
||||
GeneratorState(ErrorList& _errors, AsmAnalysisInfo& _analysisInfo):
|
||||
errors(_errors), info(_analysisInfo) {}
|
||||
|
||||
ErrorList& errors;
|
||||
AsmAnalysisInfo info;
|
||||
};
|
||||
|
||||
class EthAssemblyAdapter: public julia::AbstractAssembly
|
||||
{
|
||||
public:
|
||||
@@ -110,13 +102,12 @@ private:
|
||||
eth::Assembly assembly::CodeGenerator::assemble(
|
||||
Block const& _parsedData,
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
ExternalIdentifierAccess const& _identifierAccess
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess
|
||||
)
|
||||
{
|
||||
eth::Assembly assembly;
|
||||
GeneratorState state(m_errors, _analysisInfo);
|
||||
EthAssemblyAdapter assemblyAdapter(assembly);
|
||||
CodeTransform(state, assemblyAdapter, _parsedData, _identifierAccess);
|
||||
julia::CodeTransform(m_errors, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
|
||||
return assembly;
|
||||
}
|
||||
|
||||
@@ -124,10 +115,9 @@ void assembly::CodeGenerator::assemble(
|
||||
Block const& _parsedData,
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
eth::Assembly& _assembly,
|
||||
ExternalIdentifierAccess const& _identifierAccess
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess
|
||||
)
|
||||
{
|
||||
GeneratorState state(m_errors, _analysisInfo);
|
||||
EthAssemblyAdapter assemblyAdapter(_assembly);
|
||||
CodeTransform(state, assemblyAdapter, _parsedData, _identifierAccess);
|
||||
julia::CodeTransform(m_errors, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ public:
|
||||
eth::Assembly assemble(
|
||||
Block const& _parsedData,
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
|
||||
);
|
||||
/// Performs code generation and appends generated to to _assembly.
|
||||
void assemble(
|
||||
Block const& _parsedData,
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
eth::Assembly& _assembly,
|
||||
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
@@ -42,7 +42,7 @@ using namespace dev::solidity::assembly;
|
||||
|
||||
bool InlineAssemblyStack::parse(
|
||||
shared_ptr<Scanner> const& _scanner,
|
||||
ExternalIdentifierAccess::Resolver const& _resolver
|
||||
julia::ExternalIdentifierAccess::Resolver const& _resolver
|
||||
)
|
||||
{
|
||||
m_parserResult = make_shared<Block>();
|
||||
@@ -73,7 +73,7 @@ eth::Assembly InlineAssemblyStack::assemble()
|
||||
bool InlineAssemblyStack::parseAndAssemble(
|
||||
string const& _input,
|
||||
eth::Assembly& _assembly,
|
||||
ExternalIdentifierAccess const& _identifierAccess
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess
|
||||
)
|
||||
{
|
||||
ErrorList errors;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <libsolidity/interface/Exceptions.h>
|
||||
|
||||
#include <libjulia/backends/AbstractAssembly.h>
|
||||
#include <libjulia/backends/evm/AbstractAssembly.h>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
@@ -43,23 +43,6 @@ namespace assembly
|
||||
struct Block;
|
||||
struct Identifier;
|
||||
|
||||
enum class IdentifierContext { LValue, RValue };
|
||||
|
||||
/// Object that is used to resolve references and generate code for access to identifiers external
|
||||
/// to inline assembly (not used in standalone assembly mode).
|
||||
struct ExternalIdentifierAccess
|
||||
{
|
||||
using Resolver = std::function<size_t(assembly::Identifier const&, IdentifierContext)>;
|
||||
/// Resolve a an external reference given by the identifier in the given context.
|
||||
/// @returns the size of the value (number of stack slots) or size_t(-1) if not found.
|
||||
Resolver resolve;
|
||||
using CodeGenerator = std::function<void(assembly::Identifier const&, IdentifierContext, julia::AbstractAssembly&)>;
|
||||
/// Generate code for retrieving the value (rvalue context) or storing the value (lvalue context)
|
||||
/// of an identifier. The code should be appended to the assembly. In rvalue context, the value is supposed
|
||||
/// to be put onto the stack, in lvalue context, the value is assumed to be at the top of the stack.
|
||||
CodeGenerator generateCode;
|
||||
};
|
||||
|
||||
class InlineAssemblyStack
|
||||
{
|
||||
public:
|
||||
@@ -67,7 +50,7 @@ public:
|
||||
/// @return false or error.
|
||||
bool parse(
|
||||
std::shared_ptr<Scanner> const& _scanner,
|
||||
ExternalIdentifierAccess::Resolver const& _externalIdentifierResolver = ExternalIdentifierAccess::Resolver()
|
||||
julia::ExternalIdentifierAccess::Resolver const& _externalIdentifierResolver = julia::ExternalIdentifierAccess::Resolver()
|
||||
);
|
||||
/// Converts the parser result back into a string form (not necessarily the same form
|
||||
/// as the source form, but it should parse into the same parsed form again).
|
||||
@@ -79,7 +62,7 @@ public:
|
||||
bool parseAndAssemble(
|
||||
std::string const& _input,
|
||||
eth::Assembly& _assembly,
|
||||
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess()
|
||||
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
|
||||
);
|
||||
|
||||
ErrorList const& errors() const { return m_errors; }
|
||||
|
||||
+8
-8
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <libsolidity/interface/MultiBackendAssemblyStack.h>
|
||||
#include <libsolidity/interface/AssemblyStack.h>
|
||||
|
||||
#include <libsolidity/parsing/Scanner.h>
|
||||
#include <libsolidity/inlineasm/AsmPrinter.h>
|
||||
@@ -35,17 +35,17 @@ using namespace dev;
|
||||
using namespace dev::solidity;
|
||||
|
||||
|
||||
Scanner const& MultiBackendAssemblyStack::scanner() const
|
||||
Scanner const& AssemblyStack::scanner() const
|
||||
{
|
||||
solAssert(m_scanner, "");
|
||||
return *m_scanner;
|
||||
}
|
||||
|
||||
bool MultiBackendAssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source)
|
||||
bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source)
|
||||
{
|
||||
m_analysisSuccessful = false;
|
||||
m_scanner = make_shared<Scanner>(CharStream(_source), _sourceName);
|
||||
m_parserResult = assembly::Parser(m_errors, m_input == Input::JULIA).parse(m_scanner);
|
||||
m_parserResult = assembly::Parser(m_errors, m_language == Language::JULIA).parse(m_scanner);
|
||||
if (!m_errors.empty())
|
||||
return false;
|
||||
solAssert(m_parserResult, "");
|
||||
@@ -56,13 +56,13 @@ bool MultiBackendAssemblyStack::parseAndAnalyze(std::string const& _sourceName,
|
||||
return m_analysisSuccessful;
|
||||
}
|
||||
|
||||
eth::LinkerObject MultiBackendAssemblyStack::assemble()
|
||||
eth::LinkerObject AssemblyStack::assemble(Machine _machine)
|
||||
{
|
||||
solAssert(m_analysisSuccessful, "");
|
||||
solAssert(m_parserResult, "");
|
||||
solAssert(m_analysisInfo, "");
|
||||
|
||||
switch (m_targetMachine)
|
||||
switch (_machine)
|
||||
{
|
||||
case Machine::EVM:
|
||||
{
|
||||
@@ -78,8 +78,8 @@ eth::LinkerObject MultiBackendAssemblyStack::assemble()
|
||||
return eth::LinkerObject();
|
||||
}
|
||||
|
||||
string MultiBackendAssemblyStack::print()
|
||||
string AssemblyStack::print()
|
||||
{
|
||||
solAssert(m_parserResult, "");
|
||||
return assembly::AsmPrinter(m_input == Input::JULIA)(*m_parserResult);
|
||||
return assembly::AsmPrinter(m_language == Language::JULIA)(*m_parserResult);
|
||||
}
|
||||
+6
-8
@@ -43,15 +43,14 @@ struct Block;
|
||||
* Full assembly stack that can support EVM-assembly and JULIA as input and EVM, EVM1.5 and
|
||||
* eWasm as output.
|
||||
*/
|
||||
class MultiBackendAssemblyStack
|
||||
class AssemblyStack
|
||||
{
|
||||
public:
|
||||
enum class Input { JULIA, Assembly };
|
||||
enum class Language { JULIA, Assembly };
|
||||
enum class Machine { EVM, EVM15, eWasm };
|
||||
|
||||
MultiBackendAssemblyStack(Input _input = Input::Assembly, Machine _targetMachine = Machine::EVM):
|
||||
m_input(_input),
|
||||
m_targetMachine(_targetMachine)
|
||||
explicit AssemblyStack(Language _language = Language::Assembly):
|
||||
m_language(_language)
|
||||
{}
|
||||
|
||||
/// @returns the scanner used during parsing
|
||||
@@ -61,7 +60,7 @@ public:
|
||||
bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source);
|
||||
|
||||
/// Run the assembly step (should only be called after parseAndAnalyze).
|
||||
eth::LinkerObject assemble();
|
||||
eth::LinkerObject assemble(Machine _machine);
|
||||
|
||||
ErrorList const& errors() const { return m_errors; }
|
||||
|
||||
@@ -70,8 +69,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
Input m_input = Input::Assembly;
|
||||
Machine m_targetMachine = Machine::EVM;
|
||||
Language m_language = Language::Assembly;
|
||||
|
||||
std::shared_ptr<Scanner> m_scanner;
|
||||
|
||||
Reference in New Issue
Block a user