mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add verbatim builtin.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user