Add verbatim builtin.

This commit is contained in:
chriseth
2021-04-26 19:56:44 +02:00
parent 2969bc0f3e
commit e2d8005737
34 changed files with 371 additions and 13 deletions
+3
View File
@@ -77,6 +77,9 @@ public:
/// Currently, we assume that the value is always a 20 byte number.
virtual void appendLinkerSymbol(std::string const& _name) = 0;
/// Append raw bytes that stay untouched by the optimizer.
virtual void appendVerbatim(bytes const& _data, int _stackDifference) = 0;
/// Append a jump instruction.
/// @param _stackDiffAfter the stack adjustment after this instruction.
/// This is helpful to stack height analysis if there is no continuing control flow.
+5
View File
@@ -99,6 +99,11 @@ void EthAssemblyAdapter::appendLinkerSymbol(std::string const& _linkerSymbol)
m_assembly.appendLibraryAddress(_linkerSymbol);
}
void EthAssemblyAdapter::appendVerbatim(bytes const& _data, int _stackDifference)
{
m_assembly.appendVerbatim(_data, _stackDifference);
}
void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType)
{
appendJumpInstruction(evmasm::Instruction::JUMP, _jumpType);
+1
View File
@@ -50,6 +50,7 @@ public:
size_t newLabelId() override;
size_t namedLabel(std::string const& _name) override;
void appendLinkerSymbol(std::string const& _linkerSymbol) override;
void appendVerbatim(bytes const& _data, int _stackDifference) override;
void appendJump(int _stackDiffAfter, JumpType _jumpType) override;
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
+50
View File
@@ -34,6 +34,9 @@
#include <liblangutil/Exceptions.h>
#include <range/v3/view/reverse.hpp>
#include <range/v3/view/tail.hpp>
#include <regex>
using namespace std;
using namespace solidity;
@@ -280,6 +283,12 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
return builtins;
}
regex const& verbatimPattern()
{
regex static const pattern{"verbatim_([1-9]?[0-9])i_([1-9]?[0-9])o"};
return pattern;
}
}
@@ -293,6 +302,12 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess):
BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const
{
if (m_objectAccess)
{
smatch match;
if (regex_match(_name.str(), match, verbatimPattern()))
return verbatimFunction(stoul(match[1]), stoul(match[2]));
}
auto it = m_functions.find(_name);
if (it != m_functions.end())
return &it->second;
@@ -302,6 +317,9 @@ BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const
bool EVMDialect::reservedIdentifier(YulString _name) const
{
if (m_objectAccess)
if (_name.str().substr(0, "verbatim"s.size()) == "verbatim")
return true;
return m_reserved.count(_name) != 0;
}
@@ -342,6 +360,38 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio
};
}
BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const
{
pair<size_t, size_t> key{_arguments, _returnVariables};
shared_ptr<BuiltinFunctionForEVM const>& function = m_verbatimFunctions[key];
if (!function)
{
BuiltinFunctionForEVM builtinFunction = createFunction(
"verbatim_" + to_string(_arguments) + "i_" + to_string(_returnVariables) + "o",
1 + _arguments,
_returnVariables,
SideEffects::worst(),
vector<optional<LiteralKind>>{LiteralKind::String} + vector<optional<LiteralKind>>(_arguments),
[=](
FunctionCall const& _call,
AbstractAssembly& _assembly,
BuiltinContext&,
std::function<void(Expression const&)> _visitExpression
) {
yulAssert(_call.arguments.size() == (1 + _arguments), "");
for (Expression const& arg: _call.arguments | ranges::views::tail | ranges::views::reverse)
_visitExpression(arg);
Expression const& bytecode = _call.arguments.front();
int diff = static_cast<int>(_returnVariables) - static_cast<int>(_arguments);
_assembly.appendVerbatim(asBytes(std::get<Literal>(bytecode).value.str()), diff);
}
).second;
builtinFunction.isMSize = true;
function = make_shared<BuiltinFunctionForEVM const>(move(builtinFunction));
}
return function.get();
}
EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess):
EVMDialect(_evmVersion, _objectAccess)
{
+3
View File
@@ -93,9 +93,12 @@ struct EVMDialect: public Dialect
static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction);
protected:
BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const;
bool const m_objectAccess;
langutil::EVMVersion const m_evmVersion;
std::map<YulString, BuiltinFunctionForEVM> m_functions;
std::map<std::pair<size_t, size_t>, std::shared_ptr<BuiltinFunctionForEVM const>> mutable m_verbatimFunctions;
std::set<YulString> m_reserved;
};
+5
View File
@@ -69,6 +69,11 @@ void NoOutputAssembly::appendLinkerSymbol(string const&)
yulAssert(false, "Linker symbols not yet implemented.");
}
void NoOutputAssembly::appendVerbatim(bytes const&, int _stackDifference)
{
m_stackHeight += _stackDifference;
}
void NoOutputAssembly::appendJump(int _stackDiffAfter, JumpType)
{
appendInstruction(evmasm::Instruction::JUMP);
+1
View File
@@ -58,6 +58,7 @@ public:
LabelID newLabelId() override;
LabelID namedLabel(std::string const& _name) override;
void appendLinkerSymbol(std::string const& _name) override;
void appendVerbatim(bytes const& _data, int _stackDifference) override;
void appendJump(int _stackDiffAfter, JumpType _jumpType) override;
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;