Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth 2020-12-02 12:22:55 +01:00
commit 9a5902f9d7
185 changed files with 541 additions and 272 deletions

View File

@ -91,7 +91,9 @@ defaults:
paths:
- test/tools/ossfuzz/abiv2_proto_ossfuzz
- test/tools/ossfuzz/const_opt_ossfuzz
- test/tools/ossfuzz/solc_noopt_mutator_ossfuzz
- test/tools/ossfuzz/solc_noopt_ossfuzz
- test/tools/ossfuzz/solc_opt_mutator_ossfuzz
- test/tools/ossfuzz/solc_opt_ossfuzz
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
- test/tools/ossfuzz/strictasm_diff_ossfuzz

View File

@ -44,6 +44,7 @@ Compiler Features:
* SMTChecker: Support struct constructor.
Bugfixes:
* Code generator: Do not pad empty string literals with a single 32-byte zero field in the ABI coder v1.
* SMTChecker: Fix internal compiler error when doing bitwise compound assignment with string literals.
### 0.7.5 (2020-11-18)

View File

@ -17,7 +17,7 @@
// SPDX-License-Identifier: GPL-3.0
#include <libsolidity/analysis/ControlFlowBuilder.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
using namespace solidity;

View File

@ -27,7 +27,7 @@
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/ErrorReporter.h>

View File

@ -23,7 +23,7 @@
#include <libsolidity/interface/Version.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/SemVerHandler.h>

View File

@ -28,7 +28,7 @@
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <liblangutil/ErrorReporter.h>
@ -2318,11 +2318,19 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
functionType = dynamic_cast<FunctionType const*>(expressionType);
funcCallAnno.kind = FunctionCallKind::FunctionCall;
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
{
if (dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration))
_functionCall.expression().annotation().calledDirectly = true;
}
else if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
if (dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
_functionCall.expression().annotation().calledDirectly = true;
// Purity for function calls also depends upon the callee and its FunctionType
funcCallAnno.isPure =
argumentsArePure &&
*_functionCall.expression().annotation().isPure &&
functionType &&
functionType->isPure();
if (

View File

@ -18,7 +18,7 @@
#include <libsolidity/analysis/ViewPureChecker.h>
#include <libsolidity/ast/ExperimentalFeatures.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/ErrorReporter.h>
#include <libevmasm/SemanticInformation.h>

View File

@ -45,7 +45,7 @@
namespace solidity::yul
{
// Forward-declaration to <yul/AsmData.h>
// Forward-declaration to <yul/AST.h>
struct Block;
struct Dialect;
}

View File

@ -262,6 +262,15 @@ struct ExpressionAnnotation: ASTAnnotation
/// Types and - if given - names of arguments if the expr. is a function
/// that is called, used for overload resolution
std::optional<FuncCallArguments> arguments;
/// True if the expression consists solely of the name of the function and the function is called immediately
/// instead of being stored or processed. The name may be qualified with the name of a contract, library
/// module, etc., that clarifies the scope. For example: `m.L.f()`, where `m` is a module, `L` is a library
/// and `f` is a function is a direct call. This means that the function to be called is known at compilation
/// time and it's not necessary to rely on any runtime dispatch mechanism to resolve it.
/// Note that even the simplest expressions, like `(f)()`, result in an indirect call even if they consist of
/// values known at compilation time.
bool calledDirectly = false;
};
struct IdentifierAnnotation: ExpressionAnnotation

View File

@ -26,8 +26,8 @@
#include <libsolidity/ast/TypeProvider.h>
#include <libyul/AsmJsonConverter.h>
#include <libyul/AsmData.h>
#include <libyul/AsmPrinter.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libsolutil/JSON.h>

View File

@ -25,6 +25,7 @@
#include <libyul/AsmJsonImporter.h>
#include <libyul/AsmParser.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
#include <libyul/backends/evm/EVMDialect.h>

View File

@ -32,6 +32,7 @@
#include <libyul/AsmPrinter.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/AsmCodeGen.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/backends/evm/EVMMetrics.h>

View File

@ -531,10 +531,15 @@ void CompilerUtils::encodeToMemory(
if (_givenTypes[i]->category() == Type::Category::StringLiteral)
{
auto const& strType = dynamic_cast<StringLiteralType const&>(*_givenTypes[i]);
m_context << u256(strType.value().size());
auto const size = strType.value().size();
m_context << u256(size);
storeInMemoryDynamic(*TypeProvider::uint256(), true);
// stack: ... <end_of_mem'>
storeInMemoryDynamic(strType, _padToWordBoundaries);
// Do not output empty padding for zero-length strings.
// TODO: handle this in storeInMemoryDynamic
if (size != 0)
storeInMemoryDynamic(strType, _padToWordBoundaries);
}
else
{

View File

@ -104,12 +104,13 @@ public:
/// Stores a 256 bit integer from stack in memory.
/// @param _offset offset in memory
void storeInMemory(unsigned _offset);
/// Dynamic version of @see storeInMemory, expects the memory offset below the value on the stack
/// and also updates that. For reference types, only copies the data pointer. Fails for
/// non-memory-references.
/// non-memory-references. For string literals no value is available on the stack.
/// @param _padToWords if true, adds zeros to pad to multiple of 32 bytes. Array elements
/// are always padded (except for byte arrays), regardless of this parameter.
/// @param _cleanup if true, adds code to cleanup the value before storing it.
/// are always padded (except for byte arrays), regardless of this parameter.
/// Stack pre: memory_offset value...
/// Stack post: (memory_offset+length)
void storeInMemoryDynamic(Type const& _type, bool _padToWords = true, bool _cleanup = true);

View File

@ -31,7 +31,7 @@
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/AsmCodeGen.h>
#include <libyul/backends/evm/EVMMetrics.h>
#include <libyul/backends/evm/EVMDialect.h>

View File

@ -128,7 +128,7 @@ void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _intern
{
solAssert(internalDispatchClean(), "");
for (set<FunctionDefinition const*> const& functions: _internalDispatch | boost::adaptors::map_values)
for (DispatchSet const& functions: _internalDispatch | boost::adaptors::map_values)
for (auto function: functions)
enqueueFunctionForCodeGeneration(*function);
@ -137,38 +137,26 @@ void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _intern
InternalDispatchMap IRGenerationContext::consumeInternalDispatchMap()
{
m_directInternalFunctionCalls.clear();
InternalDispatchMap internalDispatch = move(m_internalDispatchMap);
m_internalDispatchMap.clear();
return internalDispatch;
}
void IRGenerationContext::internalFunctionCalledDirectly(Expression const& _expression)
void IRGenerationContext::addToInternalDispatch(FunctionDefinition const& _function)
{
solAssert(m_directInternalFunctionCalls.count(&_expression) == 0, "");
FunctionType const* functionType = TypeProvider::function(_function, FunctionType::Kind::Internal);
solAssert(functionType, "");
m_directInternalFunctionCalls.insert(&_expression);
YulArity arity = YulArity::fromType(*functionType);
if (m_internalDispatchMap.count(arity) != 0 && m_internalDispatchMap[arity].count(&_function) != 0)
// Note that m_internalDispatchMap[arity] is a set with a custom comparator, which looks at function IDs not definitions
solAssert(*m_internalDispatchMap[arity].find(&_function) == &_function, "Different definitions with the same function ID");
m_internalDispatchMap[arity].insert(&_function);
enqueueFunctionForCodeGeneration(_function);
}
void IRGenerationContext::internalFunctionAccessed(Expression const& _expression, FunctionDefinition const& _function)
{
solAssert(
IRHelpers::referencedFunctionDeclaration(_expression) &&
_function.resolveVirtual(mostDerivedContract()) ==
IRHelpers::referencedFunctionDeclaration(_expression)->resolveVirtual(mostDerivedContract()),
"Function definition does not match the expression"
);
if (m_directInternalFunctionCalls.count(&_expression) == 0)
{
FunctionType const* functionType = TypeProvider::function(_function, FunctionType::Kind::Internal);
solAssert(functionType, "");
m_internalDispatchMap[YulArity::fromType(*functionType)].insert(&_function);
enqueueFunctionForCodeGeneration(_function);
}
}
void IRGenerationContext::internalFunctionCalledThroughDispatch(YulArity const& _arity)
{

View File

@ -44,7 +44,20 @@ namespace solidity::frontend
class YulUtilFunctions;
class ABIFunctions;
using InternalDispatchMap = std::map<YulArity, std::set<FunctionDefinition const*>>;
struct AscendingFunctionIDCompare
{
bool operator()(FunctionDefinition const* _f1, FunctionDefinition const* _f2) const
{
// NULLs always first.
if (_f1 != nullptr && _f2 != nullptr)
return _f1->id() < _f2->id();
else
return _f1 == nullptr;
}
};
using DispatchSet = std::set<FunctionDefinition const*, AscendingFunctionIDCompare>;
using InternalDispatchMap = std::map<YulArity, DispatchSet>;
/**
* Class that contains contextual information during IR generation.
@ -108,7 +121,7 @@ public:
void initializeInternalDispatch(InternalDispatchMap _internalDispatchMap);
InternalDispatchMap consumeInternalDispatchMap();
bool internalDispatchClean() const { return m_internalDispatchMap.empty() && m_directInternalFunctionCalls.empty(); }
bool internalDispatchClean() const { return m_internalDispatchMap.empty(); }
/// Notifies the context that a function call that needs to go through internal dispatch was
/// encountered while visiting the AST. This ensures that the corresponding dispatch function
@ -116,16 +129,8 @@ public:
/// the code contains a call to an uninitialized function variable).
void internalFunctionCalledThroughDispatch(YulArity const& _arity);
/// Notifies the context that a direct function call (i.e. not through internal dispatch) was
/// encountered while visiting the AST. This lets the context know that the function should
/// not be added to the dispatch (unless there are also indirect calls to it elsewhere else).
void internalFunctionCalledDirectly(Expression const& _expression);
/// Notifies the context that a name representing an internal function has been found while
/// visiting the AST. If the name has not been reported as a direct call using
/// @a internalFunctionCalledDirectly(), it's assumed to represent function variable access
/// and the function gets added to internal dispatch.
void internalFunctionAccessed(Expression const& _expression, FunctionDefinition const& _function);
/// Adds a function to the internal dispatch.
void addToInternalDispatch(FunctionDefinition const& _function);
/// @returns a new copy of the utility function generator (but using the same function set).
YulUtilFunctions utils();
@ -177,14 +182,13 @@ private:
/// The order and duplicates are irrelevant here (hence std::set rather than std::queue) as
/// long as the order of Yul functions in the generated code is deterministic and the same on
/// all platforms - which is a property guaranteed by MultiUseYulFunctionCollector.
std::set<FunctionDefinition const*> m_functionGenerationQueue;
DispatchSet m_functionGenerationQueue;
/// Collection of functions that need to be callable via internal dispatch.
/// Note that having a key with an empty set of functions is a valid situation. It means that
/// the code contains a call via a pointer even though a specific function is never assigned to it.
/// It will fail at runtime but the code must still compile.
InternalDispatchMap m_internalDispatchMap;
std::set<Expression const*> m_directInternalFunctionCalls;
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
};

View File

@ -35,7 +35,7 @@
#include <libevmasm/GasMeter.h>
#include <libyul/AsmPrinter.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
#include <libyul/optimiser/ASTCopier.h>
@ -829,20 +829,6 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
return false;
}
bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
{
setLocation(_functionCall);
FunctionTypePointer functionType = dynamic_cast<FunctionType const*>(&type(_functionCall.expression()));
if (
functionType &&
functionType->kind() == FunctionType::Kind::Internal &&
IRHelpers::referencedFunctionDeclaration(_functionCall.expression())
)
m_context.internalFunctionCalledDirectly(_functionCall.expression());
return true;
}
void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
{
setLocation(_functionCall);
@ -1558,6 +1544,7 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
setLocation(_memberAccess);
ASTString const& member = _memberAccess.memberName();
auto memberFunctionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
Type::Category objectCategory = _memberAccess.expression().annotation().type->category();
@ -1583,7 +1570,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
if (memberFunctionType->kind() == FunctionType::Kind::Internal)
{
define(IRVariable(_memberAccess).part("functionIdentifier")) << to_string(functionDefinition.id()) << "\n";
m_context.internalFunctionAccessed(_memberAccess, functionDefinition);
if (!_memberAccess.annotation().calledDirectly)
m_context.addToInternalDispatch(functionDefinition);
}
else
{
@ -1875,7 +1863,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
define(_memberAccess) << to_string(resolvedFunctionDef.id()) << "\n";
solAssert(resolvedFunctionDef.functionType(true), "");
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
m_context.internalFunctionAccessed(_memberAccess, resolvedFunctionDef);
if (!_memberAccess.annotation().calledDirectly)
m_context.addToInternalDispatch(resolvedFunctionDef);
}
else if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
handleVariableReference(*variable, _memberAccess);
@ -1889,7 +1878,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
{
define(_memberAccess) << to_string(function->id()) << "\n";
m_context.internalFunctionAccessed(_memberAccess, *function);
if (!_memberAccess.annotation().calledDirectly)
m_context.addToInternalDispatch(*function);
}
else
solAssert(false, "Function not found in member access");
@ -1964,7 +1954,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
define(_memberAccess) << to_string(function->id()) << "\n";
m_context.internalFunctionAccessed(_memberAccess, *function);
if (!_memberAccess.annotation().calledDirectly)
m_context.addToInternalDispatch(*function);
}
break;
}
@ -2208,7 +2200,8 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
solAssert(resolvedFunctionDef.functionType(true), "");
solAssert(resolvedFunctionDef.functionType(true)->kind() == FunctionType::Kind::Internal, "");
m_context.internalFunctionAccessed(_identifier, resolvedFunctionDef);
if (!_identifier.annotation().calledDirectly)
m_context.addToInternalDispatch(resolvedFunctionDef);
}
else if (VariableDeclaration const* varDecl = dynamic_cast<VariableDeclaration const*>(declaration))
handleVariableReference(*varDecl, _identifier);

View File

@ -76,7 +76,6 @@ public:
void endVisit(Return const& _return) override;
void endVisit(UnaryOperation const& _unaryOperation) override;
bool visit(BinaryOperation const& _binOp) override;
bool visit(FunctionCall const& _funCall) override;
void endVisit(FunctionCall const& _funCall) override;
void endVisit(FunctionCallOptions const& _funCallOptions) override;
void endVisit(MemberAccess const& _memberAccess) override;

View File

@ -60,6 +60,7 @@
#include <libyul/AsmJsonConverter.h>
#include <libyul/AssemblyStack.h>
#include <libyul/AsmParser.h>
#include <libyul/AST.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/SemVerHandler.h>

View File

@ -25,6 +25,7 @@
#include <libsolidity/interface/Version.h>
#include <libyul/AsmParser.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/Scanner.h>

View File

@ -23,7 +23,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>
#include <liblangutil/SourceLocation.h>

View File

@ -28,6 +28,7 @@
namespace solidity::yul
{
enum class LiteralKind;
struct Literal;
struct Label;
struct Identifier;

View File

@ -21,7 +21,7 @@
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/AsmScopeFiller.h>
#include <libyul/AsmScope.h>
#include <libyul/AsmAnalysisInfo.h>
@ -668,3 +668,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
return true;
}
bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall)
{
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
}

View File

@ -26,7 +26,7 @@
#include <libyul/Dialect.h>
#include <libyul/AsmScope.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/backends/evm/EVMDialect.h>
@ -114,10 +114,7 @@ private:
bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location);
bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
bool validateInstructions(FunctionCall const& _functionCall)
{
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
}
bool validateInstructions(FunctionCall const& _functionCall);
yul::ExternalIdentifierAccess::Resolver m_resolver;
Scope* m_currentScope = nullptr;

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <map>
#include <memory>

View File

@ -21,7 +21,7 @@
*/
#include <libyul/AsmJsonConverter.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libsolutil/CommonData.h>

View File

@ -23,7 +23,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <liblangutil/SourceLocation.h>
#include <json/json.h>
#include <boost/variant.hpp>

View File

@ -23,8 +23,7 @@
*/
#include <libyul/AsmJsonImporter.h>
#include <libyul/AsmData.h>
#include <libyul/AsmDataForward.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <liblangutil/Scanner.h>

View File

@ -25,7 +25,7 @@
#include <json/json.h>
#include <liblangutil/SourceLocation.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <utility>

View File

@ -22,6 +22,7 @@
*/
#include <libyul/AsmParser.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h>

View File

@ -23,7 +23,7 @@
#pragma once
#include <libyul/AsmData.h>
#include <libyul/ASTForward.h>
#include <libyul/Dialect.h>
#include <liblangutil/SourceLocation.h>

View File

@ -22,7 +22,7 @@
*/
#include <libyul/AsmPrinter.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libyul/Dialect.h>

View File

@ -23,7 +23,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>

View File

@ -21,7 +21,7 @@
#include <libyul/AsmScopeFiller.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/AsmScope.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/Exceptions.h>

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <functional>
#include <memory>

View File

@ -2,8 +2,8 @@ add_library(yul
AsmAnalysis.cpp
AsmAnalysis.h
AsmAnalysisInfo.h
AsmData.h
AsmDataForward.h
AST.h
ASTForward.h
AsmJsonConverter.h
AsmJsonConverter.cpp
AsmJsonImporter.h

View File

@ -22,7 +22,7 @@
#pragma once
#include <libyul/Dialect.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/Object.h>
#include <map>

View File

@ -20,7 +20,7 @@
*/
#include <libyul/Dialect.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
using namespace solidity::yul;
using namespace std;

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>
#include <libsolutil/Common.h>

View File

@ -22,6 +22,7 @@
#include <libyul/ObjectParser.h>
#include <libyul/AsmParser.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <liblangutil/Token.h>

View File

@ -21,7 +21,7 @@
#include <libyul/Utilities.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libsolutil/CommonData.h>

View File

@ -22,7 +22,7 @@
#pragma once
#include <libsolutil/Common.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
namespace solidity::yul
{

View File

@ -21,8 +21,8 @@
#include <libyul/backends/evm/AsmCodeGen.h>
#include <libyul/AsmData.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AST.h>
#include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/backends/evm/EVMCodeTransform.h>

View File

@ -23,7 +23,7 @@
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/backends/evm/EVMMetrics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libsolutil/CommonData.h>

View File

@ -25,7 +25,7 @@
#include <libyul/YulString.h>
#include <libyul/Dialect.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmData.h>
#include <libyul/ASTForward.h>
#include <liblangutil/SourceLocation.h>

View File

@ -23,7 +23,7 @@
#include <libyul/optimiser/NameCollector.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <liblangutil/Exceptions.h>

View File

@ -25,7 +25,7 @@
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/AsmScope.h>
#include <optional>

View File

@ -22,7 +22,7 @@
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Object.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmParser.h>

View File

@ -24,7 +24,7 @@
#include <libyul/Dialect.h>
#include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/AsmData.h>
#include <libyul/ASTForward.h>
#include <liblangutil/EVMVersion.h>
#include <map>

View File

@ -21,7 +21,7 @@
#include <libyul/backends/evm/EVMMetrics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libyul/Utilities.h>
#include <libyul/backends/evm/EVMDialect.h>

View File

@ -21,6 +21,7 @@
#include <libyul/backends/evm/NoOutputAssembly.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libevmasm/Instruction.h>

View File

@ -107,33 +107,24 @@ bytes toBytes(Export _export)
return toBytes(uint8_t(_export));
}
// NOTE: This is a subset of WebAssembly opcodes.
// Those available as a builtin are listed further down.
enum class Opcode: uint8_t
{
Unreachable = 0x00,
Nop = 0x01,
Block = 0x02,
Loop = 0x03,
If = 0x04,
Else = 0x05,
Try = 0x06,
Catch = 0x07,
Throw = 0x08,
Rethrow = 0x09,
BrOnExn = 0x0a,
End = 0x0b,
Br = 0x0c,
BrIf = 0x0d,
BrTable = 0x0e,
BrTable = 0x0e, // Not used yet.
Return = 0x0f,
Call = 0x10,
CallIndirect = 0x11,
ReturnCall = 0x12,
ReturnCallIndirect = 0x13,
Drop = 0x1a,
Select = 0x1b,
CallIndirect = 0x11, // Not used yet.
LocalGet = 0x20,
LocalSet = 0x21,
LocalTee = 0x22,
LocalTee = 0x22, // Not used yet.
GlobalGet = 0x23,
GlobalSet = 0x24,
I32Const = 0x41,
@ -156,6 +147,10 @@ Opcode constOpcodeFor(ValueType _type)
}
static map<string, uint8_t> const builtins = {
{"unreachable", 0x00},
{"nop", 0x01},
{"i32.drop", 0x1a},
{"i64.drop", 0x1a},
{"i32.select", 0x1b},
{"i64.select", 0x1b},
{"i32.load", 0x28},
@ -381,30 +376,21 @@ bytes BinaryTransform::operator()(BuiltinCall const& _call)
return toBytes(Opcode::I64Const) + lebEncodeSigned(static_cast<int64_t>(m_subModulePosAndSize.at(name).second));
}
yulAssert(builtins.count(_call.functionName), "Builtin " + _call.functionName + " not found");
// NOTE: the dialect ensures we have the right amount of arguments
bytes args = visit(_call.arguments);
bytes ret = move(args) + toBytes(builtins.at(_call.functionName));
if (
_call.functionName.find(".load") != string::npos ||
_call.functionName.find(".store") != string::npos
)
// Alignment hint and offset. Interpreters ignore the alignment. JITs/AOTs can take it
// into account to generate more efficient code but if the hint is invalid it could
// actually be more expensive. It's best to hint at 1-byte alignment if we don't plan
// to control the memory layout accordingly.
ret += bytes{{0, 0}}; // 2^0 == 1-byte alignment
if (_call.functionName == "unreachable")
return toBytes(Opcode::Unreachable);
else if (_call.functionName == "nop")
return toBytes(Opcode::Nop);
else if (_call.functionName == "i32.drop" || _call.functionName == "i64.drop")
return toBytes(Opcode::Drop);
else
{
yulAssert(builtins.count(_call.functionName), "Builtin " + _call.functionName + " not found");
bytes ret = move(args) + toBytes(builtins.at(_call.functionName));
if (
_call.functionName.find(".load") != string::npos ||
_call.functionName.find(".store") != string::npos
)
// Alignment hint and offset. Interpreters ignore the alignment. JITs/AOTs can take it
// into account to generate more efficient code but if the hint is invalid it could
// actually be more expensive. It's best to hint at 1-byte alignment if we don't plan
// to control the memory layout accordingly.
ret += bytes{{0, 0}}; // 2^0 == 1-byte alignment
return ret;
}
return ret;
}
bytes BinaryTransform::operator()(FunctionCall const& _call)

View File

@ -35,6 +35,7 @@
#include <libyul/AsmParser.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/AST.h>
#include <libyul/Object.h>
#include <liblangutil/ErrorReporter.h>

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/Dialect.h>

View File

@ -122,8 +122,11 @@ string TextTransform::operator()(wasm::BuiltinCall const& _builtinCall)
{
string args = joinTransformed(_builtinCall.arguments);
string funcName = _builtinCall.functionName;
// These are prefixed in the dialect, but are actually overloaded instructions in WebAssembly.
if (funcName == "i32.drop" || funcName == "i64.drop")
funcName = "drop";
else if (funcName == "i32.select" || funcName == "i64.select")
funcName = "select";
return "(" + funcName + (args.empty() ? "" : " " + args) + ")";
}

View File

@ -25,7 +25,7 @@
#include <libyul/optimiser/NameCollector.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
#include <libyul/Utilities.h>
#include <libyul/Exceptions.h>

View File

@ -22,7 +22,7 @@
#pragma once
#include <libyul/backends/wasm/WasmAST.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/Dialect.h>
#include <libyul/optimiser/NameDispenser.h>
#include <libyul/optimiser/TypeInfo.h>

View File

@ -21,7 +21,7 @@
#include <libyul/backends/wasm/WasmDialect.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
using namespace std;

View File

@ -38,7 +38,7 @@ struct Object;
*
* Builtin functions are a subset of the wasm instructions.
*
* There is a builtin function `i32.drop` that takes an i32, while `drop` takes i64.
* There is a builtin function `i32.drop` that takes an i32, while `i64.drop` takes i64.
*
*/
struct WasmDialect: public Dialect

View File

@ -16,7 +16,7 @@
*/
// SPDX-License-Identifier: GPL-3.0
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/backends/wasm/WordSizeTransform.h>
#include <libyul/Utilities.h>
#include <libyul/Dialect.h>

View File

@ -23,7 +23,7 @@
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/Common.h>

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>

View File

@ -21,7 +21,7 @@
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <boost/range/adaptor/reversed.hpp>

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/Exceptions.h>
#include <libyul/YulString.h>

View File

@ -15,10 +15,13 @@
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
#include <libyul/optimiser/BlockFlattener.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/Visitor.h>
#include <libsolutil/CommonData.h>
#include <functional>
using namespace std;

View File

@ -21,7 +21,9 @@
#include <libyul/optimiser/BlockHasher.h>
#include <libyul/optimiser/SyntacticalEquality.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libsolutil/CommonData.h>
using namespace std;

View File

@ -21,9 +21,8 @@
#pragma once
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>
#include <libyul/AsmData.h>
namespace solidity::yul
{

View File

@ -19,7 +19,7 @@
* Specific AST walker that generates the call graph.
*/
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/optimiser/CallGraphGenerator.h>
#include <stack>

View File

@ -19,7 +19,7 @@
#include <libyul/optimiser/CallGraphGenerator.h>
#include <libyul/optimiser/OptimizerUtilities.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/Algorithms.h>

View File

@ -27,7 +27,7 @@
#include <libyul/optimiser/Semantics.h>
#include <libyul/SideEffects.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
using namespace std;

View File

@ -17,7 +17,7 @@
// SPDX-License-Identifier: GPL-3.0
#include <libyul/optimiser/ConditionalSimplifier.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libyul/optimiser/NameCollector.h>
#include <libsolutil/CommonData.h>

View File

@ -19,6 +19,7 @@
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/ASTForward.h>
#include <libyul/Dialect.h>
#include <libsolutil/Common.h>

View File

@ -17,7 +17,7 @@
// SPDX-License-Identifier: GPL-3.0
#include <libyul/optimiser/ConditionalUnsimplifier.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libyul/optimiser/NameCollector.h>
#include <libsolutil/CommonData.h>

View File

@ -19,7 +19,7 @@
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/TypeInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libyul/Dialect.h>
#include <libsolutil/CommonData.h>

View File

@ -24,8 +24,8 @@
#include <libyul/optimiser/NameCollector.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/AST.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libsolutil/CommonData.h>
@ -39,7 +39,6 @@ using namespace solidity;
using namespace solidity::util;
using namespace solidity::yul;
void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
{
if (auto vars = isSimpleStore(evmasm::Instruction::SSTORE, _statement))

View File

@ -26,7 +26,7 @@
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/optimiser/KnowledgeBase.h>
#include <libyul/YulString.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h> // Needed for m_zero below.
#include <libyul/SideEffects.h>
// TODO avoid

View File

@ -22,7 +22,7 @@
#include <libyul/optimiser/DeadCodeEliminator.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libevmasm/SemanticInformation.h>
#include <libevmasm/AssemblyItem.h>

View File

@ -22,7 +22,7 @@
#include <libyul/optimiser/Disambiguator.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/AsmScope.h>
#include <libyul/Dialect.h>

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/optimiser/NameDispenser.h>

View File

@ -20,7 +20,7 @@
*/
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/CommonData.h>
using namespace std;

View File

@ -23,7 +23,7 @@
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/optimiser/EquivalentFunctionDetector.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
namespace solidity::yul
{

View File

@ -22,7 +22,7 @@
#include <libyul/optimiser/EquivalentFunctionDetector.h>
#include <libyul/optimiser/SyntacticalEquality.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/optimiser/Metrics.h>
using namespace std;

View File

@ -22,7 +22,7 @@
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/optimiser/BlockHasher.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
namespace solidity::yul
{

View File

@ -28,7 +28,7 @@
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
using namespace std;
using namespace solidity;

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <optional>
#include <set>

View File

@ -25,7 +25,7 @@
#include <libyul/optimiser/NameCollector.h>
#include <libyul/optimiser/OptimizerUtilities.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/CommonData.h>

View File

@ -21,7 +21,7 @@
*/
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/optimiser/ASTWalker.h>
#include <map>
@ -32,7 +32,6 @@ namespace solidity::yul
class NameCollector;
struct OptimiserStepContext;
/**
* Optimiser component that modifies an AST in place, turning sequences
* of variable declarations into complex expressions, if the variables

View File

@ -23,7 +23,7 @@
#include <libyul/optimiser/SimplificationRules.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
using namespace std;
using namespace solidity;

View File

@ -21,7 +21,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/optimiser/DataFlowAnalyzer.h>

View File

@ -26,7 +26,7 @@
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/TypeInfo.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
#include <libsolutil/CommonData.h>

View File

@ -21,7 +21,7 @@
*/
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/optimiser/NameDispenser.h>

View File

@ -18,7 +18,8 @@
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/CommonData.h>
using namespace std;

View File

@ -18,8 +18,9 @@
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Utilities.h>
#include <libsolutil/CommonData.h>
using namespace std;

View File

@ -16,8 +16,10 @@
*/
// SPDX-License-Identifier: GPL-3.0
#include <libyul/optimiser/ForLoopInitRewriter.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libsolutil/CommonData.h>
#include <functional>
using namespace std;

View File

@ -30,7 +30,7 @@
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/CallGraphGenerator.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <libyul/Dialect.h>
#include <libsolutil/CommonData.h>

View File

@ -20,7 +20,7 @@
*/
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libyul/optimiser/ASTWalker.h>

View File

@ -16,7 +16,7 @@
*/
#include <libyul/optimiser/FunctionCallFinder.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
using namespace std;
using namespace solidity;

View File

@ -22,7 +22,7 @@
#include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/AsmData.h>
#include <libyul/AST.h>
#include <boost/range/algorithm_ext/erase.hpp>

View File

@ -22,7 +22,7 @@
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/ASTForward.h>
namespace solidity::yul
{

Some files were not shown because too many files have changed in this diff Show More