Use plain members and references instead of shared pointers for MultiUseYulFunctionCollector

This commit is contained in:
Daniel Kirchner 2020-03-02 18:08:19 +01:00
parent 27a4670ad8
commit 857ed12b05
9 changed files with 74 additions and 76 deletions

View File

@ -1492,7 +1492,7 @@ string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type,
string ABIFunctions::createFunction(string const& _name, function<string ()> const& _creator)
{
return m_functionCollector->createFunction(_name, _creator);
return m_functionCollector.createFunction(_name, _creator);
}
size_t ABIFunctions::headSize(TypePointers const& _targetTypes)

View File

@ -57,11 +57,11 @@ public:
explicit ABIFunctions(
langutil::EVMVersion _evmVersion,
RevertStrings _revertStrings,
std::shared_ptr<MultiUseYulFunctionCollector> _functionCollector = std::make_shared<MultiUseYulFunctionCollector>()
MultiUseYulFunctionCollector& _functionCollector
):
m_evmVersion(_evmVersion),
m_revertStrings(_revertStrings),
m_functionCollector(std::move(_functionCollector)),
m_functionCollector(_functionCollector),
m_utils(_evmVersion, m_revertStrings, m_functionCollector)
{}
@ -247,7 +247,7 @@ private:
langutil::EVMVersion m_evmVersion;
RevertStrings const m_revertStrings;
std::shared_ptr<MultiUseYulFunctionCollector> m_functionCollector;
MultiUseYulFunctionCollector& m_functionCollector;
YulUtilFunctions m_utils;
};

View File

@ -151,7 +151,7 @@ pair<string, set<string>> CompilerContext::requestedYulFunctions()
{
set<string> empty;
swap(empty, m_externallyUsedYulFunctions);
return make_pair(m_yulFunctionCollector->requestedFunctions(), std::move(empty));
return {m_yulFunctionCollector.requestedFunctions(), std::move(empty)};
}
void CompilerContext::addVariable(

View File

@ -371,7 +371,7 @@ private:
/// An index of low-level function labels by name.
std::map<std::string, evmasm::AssemblyItem> m_lowLevelFunctions;
/// Collector for yul functions.
std::shared_ptr<MultiUseYulFunctionCollector> m_yulFunctionCollector = std::make_shared<MultiUseYulFunctionCollector>();
MultiUseYulFunctionCollector m_yulFunctionCollector;
/// Set of externally used yul functions.
std::set<std::string> m_externallyUsedYulFunctions;
/// Container for ABI functions to be generated.

View File

@ -39,7 +39,7 @@ using namespace solidity::frontend;
string YulUtilFunctions::combineExternalFunctionIdFunction()
{
string functionName = "combine_external_function_id";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(addr, selector) -> combined {
combined := <shl64>(or(<shl32>(addr), and(selector, 0xffffffff)))
@ -55,7 +55,7 @@ string YulUtilFunctions::combineExternalFunctionIdFunction()
string YulUtilFunctions::splitExternalFunctionIdFunction()
{
string functionName = "split_external_function_id";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(combined) -> addr, selector {
combined := <shr64>(combined)
@ -73,7 +73,7 @@ string YulUtilFunctions::splitExternalFunctionIdFunction()
string YulUtilFunctions::copyToMemoryFunction(bool _fromCalldata)
{
string functionName = "copy_" + string(_fromCalldata ? "calldata" : "memory") + "_to_memory";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (_fromCalldata)
{
return Whiskers(R"(
@ -116,7 +116,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess
solAssert(!_assert || !_messageType, "Asserts can't have messages!");
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (!_messageType)
return Whiskers(R"(
function <functionName>(condition) {
@ -166,7 +166,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess
string YulUtilFunctions::leftAlignFunction(Type const& _type)
{
string functionName = string("leftAlign_") + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(value) -> aligned {
<body>
@ -228,7 +228,7 @@ string YulUtilFunctions::shiftLeftFunction(size_t _numBits)
solAssert(_numBits < 256, "");
string functionName = "shift_left_" + to_string(_numBits);
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(value) -> newValue {
@ -251,7 +251,7 @@ string YulUtilFunctions::shiftLeftFunction(size_t _numBits)
string YulUtilFunctions::shiftLeftFunctionDynamic()
{
string functionName = "shift_left_dynamic";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(bits, value) -> newValue {
@ -277,7 +277,7 @@ string YulUtilFunctions::shiftRightFunction(size_t _numBits)
// the opcodes SAR and SDIV behave differently with regards to rounding!
string functionName = "shift_right_" + to_string(_numBits) + "_unsigned";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(value) -> newValue {
@ -303,7 +303,7 @@ string YulUtilFunctions::shiftRightFunctionDynamic()
// the opcodes SAR and SDIV behave differently with regards to rounding!
string const functionName = "shift_right_unsigned_dynamic";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(bits, value) -> newValue {
@ -328,7 +328,7 @@ string YulUtilFunctions::updateByteSliceFunction(size_t _numBytes, size_t _shift
size_t numBits = _numBytes * 8;
size_t shiftBits = _shiftBytes * 8;
string functionName = "update_byte_slice_" + to_string(_numBytes) + "_shift_" + to_string(_shiftBytes);
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(value, toInsert) -> result {
@ -350,7 +350,7 @@ string YulUtilFunctions::updateByteSliceFunctionDynamic(size_t _numBytes)
solAssert(_numBytes <= 32, "");
size_t numBits = _numBytes * 8;
string functionName = "update_byte_slice_dynamic" + to_string(_numBytes);
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(value, shiftBytes, toInsert) -> result {
@ -371,7 +371,7 @@ string YulUtilFunctions::updateByteSliceFunctionDynamic(size_t _numBytes)
string YulUtilFunctions::roundUpFunction()
{
string functionName = "round_up_to_mul_of_32";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(value) -> result {
@ -389,7 +389,7 @@ string YulUtilFunctions::overflowCheckedIntAddFunction(IntegerType const& _type)
// TODO: Consider to add a special case for unsigned 256-bit integers
// and use the following instead:
// sum := add(x, y) if lt(sum, x) { revert(0, 0) }
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(x, y) -> sum {
@ -416,7 +416,7 @@ string YulUtilFunctions::overflowCheckedIntAddFunction(IntegerType const& _type)
string YulUtilFunctions::overflowCheckedIntMulFunction(IntegerType const& _type)
{
string functionName = "checked_mul_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
// Multiplication by zero could be treated separately and directly return zero.
Whiskers(R"(
@ -448,7 +448,7 @@ string YulUtilFunctions::overflowCheckedIntMulFunction(IntegerType const& _type)
string YulUtilFunctions::overflowCheckedIntDivFunction(IntegerType const& _type)
{
string functionName = "checked_div_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(x, y) -> r {
@ -473,7 +473,7 @@ string YulUtilFunctions::overflowCheckedIntDivFunction(IntegerType const& _type)
string YulUtilFunctions::checkedIntModFunction(IntegerType const& _type)
{
string functionName = "checked_mod_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return
Whiskers(R"(
function <functionName>(x, y) -> r {
@ -490,7 +490,7 @@ string YulUtilFunctions::checkedIntModFunction(IntegerType const& _type)
string YulUtilFunctions::overflowCheckedIntSubFunction(IntegerType const& _type)
{
string functionName = "checked_sub_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
return
Whiskers(R"(
function <functionName>(x, y) -> diff {
@ -516,7 +516,7 @@ string YulUtilFunctions::overflowCheckedIntSubFunction(IntegerType const& _type)
string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
{
string functionName = "array_length_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers w(R"(
function <functionName>(value) -> length {
<?dynamic>
@ -564,7 +564,7 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type)
solUnimplementedAssert(_type.baseType()->storageSize() == 1, "");
string functionName = "resize_array_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array, newLen) {
if gt(newLen, <maxArrayLength>) {
@ -604,7 +604,7 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
string functionName = "array_pop_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array) {
let oldLen := <fetchLength>(array)
@ -632,7 +632,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type)
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
string functionName = "array_push_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array, value) {
let oldLen := <fetchLength>(array)
@ -659,7 +659,7 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
string functionName = "array_push_zero_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array) -> slot, offset {
let oldLen := <fetchLength>(array)
@ -684,7 +684,7 @@ string YulUtilFunctions::clearStorageRangeFunction(Type const& _type)
solAssert(_type.storageBytes() >= 32, "Expected smaller value for storage bytes");
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(start, end) {
for {} lt(start, end) { start := add(start, <increment>) }
@ -715,7 +715,7 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type)
string functionName = "clear_storage_array_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(slot) {
<?dynamic>
@ -745,7 +745,7 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type)
string YulUtilFunctions::arrayConvertLengthToSize(ArrayType const& _type)
{
string functionName = "array_convert_length_to_size_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Type const& baseType = *_type.baseType();
switch (_type.location())
@ -798,7 +798,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
string functionName = "array_allocation_size_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers w(R"(
function <functionName>(length) -> size {
// Make sure we can allocate memory without overflow
@ -825,7 +825,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
string YulUtilFunctions::arrayDataAreaFunction(ArrayType const& _type)
{
string functionName = "array_dataslot_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
// No special processing for calldata arrays, because they are stored as
// offset of the data area and length on the stack, so the offset already
// points to the data area.
@ -858,7 +858,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
solUnimplementedAssert(_type.baseType()->storageBytes() > 16, "");
string functionName = "storage_array_index_access_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(array, index) -> slot, offset {
if iszero(lt(index, <arrayLen>(array))) {
@ -886,7 +886,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
string YulUtilFunctions::memoryArrayIndexAccessFunction(ArrayType const& _type)
{
string functionName = "memory_array_index_access_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(baseRef, index) -> addr {
if iszero(lt(index, <arrayLen>(baseRef))) {
@ -912,7 +912,7 @@ string YulUtilFunctions::calldataArrayIndexAccessFunction(ArrayType const& _type
{
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
string functionName = "calldata_array_index_access_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(base_ref<?dynamicallySized>, length</dynamicallySized>, index) -> addr<?dynamicallySizedBase>, len</dynamicallySizedBase> {
if iszero(lt(index, <?dynamicallySized>length<!dynamicallySized><arrayLen></dynamicallySized>)) { invalid() }
@ -938,7 +938,7 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type)
solAssert(_type.isDynamicallyEncoded(), "");
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
string functionName = "access_calldata_tail_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(base_ref, ptr_to_tail) -> addr<?dynamicallySized>, length</dynamicallySized> {
let rel_offset_of_tail := calldataload(ptr_to_tail)
@ -966,7 +966,7 @@ string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
if (_type.dataStoredIn(DataLocation::Storage))
solAssert(_type.baseType()->storageBytes() > 16, "");
string functionName = "array_nextElement_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(ptr) -> next {
next := add(ptr, <advance>)
@ -1002,7 +1002,7 @@ string YulUtilFunctions::mappingIndexAccessFunction(MappingType const& _mappingT
solAssert(_keyType.sizeOnStack() <= 1, "");
string functionName = "mapping_index_access_" + _mappingType.identifier() + "_of_" + _keyType.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (_mappingType.keyType()->isDynamicallySized())
return Whiskers(R"(
function <functionName>(slot <comma> <key>) -> dataSlot {
@ -1050,7 +1050,7 @@ string YulUtilFunctions::readFromStorage(Type const& _type, size_t _offset, bool
to_string(_offset) +
"_" +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
solAssert(_type.sizeOnStack() == 1, "");
return Whiskers(R"(
function <functionName>(slot) -> value {
@ -1071,7 +1071,7 @@ string YulUtilFunctions::readFromStorageDynamic(Type const& _type, bool _splitFu
string(_splitFunctionTypes ? "split_" : "") +
"_" +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
solAssert(_type.sizeOnStack() == 1, "");
return Whiskers(R"(
function <functionName>(slot, offset) -> value {
@ -1101,7 +1101,7 @@ string YulUtilFunctions::updateStorageValueFunction(Type const& _type, std::opti
(_offset.has_value() ? ("offset_" + to_string(*_offset)) : "") +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
if (_type.isValueType())
{
solAssert(_type.storageBytes() <= 32, "Invalid storage bytes size.");
@ -1141,7 +1141,7 @@ string YulUtilFunctions::writeToMemoryFunction(Type const& _type)
string("write_to_memory_") +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
solAssert(!dynamic_cast<StringLiteralType const*>(&_type), "");
if (auto ref = dynamic_cast<ReferenceType const*>(&_type))
{
@ -1201,7 +1201,7 @@ string YulUtilFunctions::extractFromStorageValueDynamic(Type const& _type, bool
"extract_from_storage_value_dynamic" +
string(_splitFunctionTypes ? "split_" : "") +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
return Whiskers(R"(
function <functionName>(slot_value, offset) -> value {
value := <cleanupStorage>(<shr>(mul(offset, 8), slot_value))
@ -1224,7 +1224,7 @@ string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offs
"offset_" +
to_string(_offset) +
_type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
return Whiskers(R"(
function <functionName>(slot_value) -> value {
value := <cleanupStorage>(<shr>(slot_value))
@ -1243,7 +1243,7 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _spl
solUnimplementedAssert(!_splitFunctionTypes, "");
string functionName = string("cleanup_from_storage_") + (_splitFunctionTypes ? "split_" : "") + _type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
Whiskers templ(R"(
function <functionName>(value) -> cleaned {
cleaned := <cleaned>
@ -1275,7 +1275,7 @@ string YulUtilFunctions::prepareStoreFunction(Type const& _type)
solUnimplementedAssert(_type.category() != Type::Category::Function, "");
string functionName = "prepare_store_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(value) -> ret {
ret := <actualPrepare>
@ -1293,7 +1293,7 @@ string YulUtilFunctions::prepareStoreFunction(Type const& _type)
string YulUtilFunctions::allocationFunction()
{
string functionName = "allocateMemory";
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(size) -> memPtr {
memPtr := mload(<freeMemoryPointer>)
@ -1314,7 +1314,7 @@ string YulUtilFunctions::allocateMemoryArrayFunction(ArrayType const& _type)
solUnimplementedAssert(!_type.isByteArray(), "");
string functionName = "allocate_memory_array_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(length) -> memPtr {
memPtr := <alloc>(<allocSize>(length))
@ -1341,7 +1341,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
_from.identifier() +
"_to_" +
_to.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(value) -> converted {
<body>
@ -1519,7 +1519,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
string YulUtilFunctions::cleanupFunction(Type const& _type)
{
string functionName = string("cleanup_") + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(value) -> cleaned {
<body>
@ -1606,7 +1606,7 @@ string YulUtilFunctions::cleanupFunction(Type const& _type)
string YulUtilFunctions::validatorFunction(Type const& _type, bool _revertOnFailure)
{
string functionName = string("validator_") + (_revertOnFailure ? "revert_" : "assert_") + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(value) {
if iszero(<condition>) { <failure> }
@ -1667,7 +1667,7 @@ string YulUtilFunctions::packedHashFunction(
size_t sizeOnStack = 0;
for (Type const* t: _givenTypes)
sizeOnStack += t->sizeOnStack();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>(<variables>) -> hash {
let pos := mload(<freeMemoryPointer>)
@ -1688,7 +1688,7 @@ string YulUtilFunctions::forwardingRevertFunction()
{
bool forward = m_evmVersion.supportsReturndata();
string functionName = "revert_forward_" + to_string(forward);
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (forward)
return Whiskers(R"(
function <functionName>() {
@ -1715,7 +1715,7 @@ std::string YulUtilFunctions::decrementCheckedFunction(Type const& _type)
string const functionName = "decrement_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
u256 minintval;
// Smallest admissible value to decrement
@ -1743,7 +1743,7 @@ std::string YulUtilFunctions::incrementCheckedFunction(Type const& _type)
string const functionName = "increment_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
u256 maxintval;
// Biggest admissible value to increment
@ -1774,7 +1774,7 @@ string YulUtilFunctions::negateNumberCheckedFunction(Type const& _type)
u256 const minintval = 0 - (u256(1) << (type.numBits() - 1)) + 1;
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(_value) -> ret {
if slt(_value, <minval>) { revert(0,0) }
@ -1794,7 +1794,7 @@ string YulUtilFunctions::zeroValueFunction(Type const& _type)
string const functionName = "zero_value_for_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>() -> ret {
<body>
@ -1810,7 +1810,7 @@ string YulUtilFunctions::storageSetToZeroFunction(Type const& _type)
{
string const functionName = "storage_set_to_zero_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (_type.isValueType())
return Whiskers(R"(
function <functionName>(slot, offset) {
@ -1842,7 +1842,7 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
_from.identifier() +
"_to_" +
_to.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&]() {
if (
auto fromTuple = dynamic_cast<TupleType const*>(&_from), toTuple = dynamic_cast<TupleType const*>(&_to);
fromTuple && toTuple && fromTuple->components().size() == toTuple->components().size()
@ -1950,7 +1950,7 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC
if (_fromCalldata)
solAssert(!_type.isDynamicallyEncoded(), "");
return m_functionCollector->createFunction(functionName, [&] {
return m_functionCollector.createFunction(functionName, [&] {
if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
{
solAssert(refType->sizeOnStack() == 1, "");

View File

@ -47,11 +47,11 @@ public:
explicit YulUtilFunctions(
langutil::EVMVersion _evmVersion,
RevertStrings _revertStrings,
std::shared_ptr<MultiUseYulFunctionCollector> _functionCollector
MultiUseYulFunctionCollector& _functionCollector
):
m_evmVersion(_evmVersion),
m_revertStrings(_revertStrings),
m_functionCollector(std::move(_functionCollector))
m_functionCollector(_functionCollector)
{}
/// @returns a function that combines the address and selector to a single value
@ -306,7 +306,7 @@ private:
langutil::EVMVersion m_evmVersion;
RevertStrings m_revertStrings;
std::shared_ptr<MultiUseYulFunctionCollector> m_functionCollector;
MultiUseYulFunctionCollector& m_functionCollector;
};
}

View File

@ -100,7 +100,7 @@ string IRGenerationContext::newYulVariable()
string IRGenerationContext::internalDispatch(size_t _in, size_t _out)
{
string funName = "dispatch_internal_in_" + to_string(_in) + "_out_" + to_string(_out);
return m_functions->createFunction(funName, [&]() {
return m_functions.createFunction(funName, [&]() {
Whiskers templ(R"(
function <functionName>(fun <comma> <in>) <arrow> <out> {
switch fun

View File

@ -56,11 +56,10 @@ public:
):
m_evmVersion(_evmVersion),
m_revertStrings(_revertStrings),
m_optimiserSettings(std::move(_optimiserSettings)),
m_functions(std::make_shared<MultiUseYulFunctionCollector>())
m_optimiserSettings(std::move(_optimiserSettings))
{}
std::shared_ptr<MultiUseYulFunctionCollector> functionCollector() const { return m_functions; }
MultiUseYulFunctionCollector& functionCollector() { return m_functions; }
/// Sets the current inheritance hierarchy from derived to base.
void setInheritanceHierarchy(std::vector<ContractDefinition const*> _hierarchy)
@ -108,7 +107,7 @@ private:
std::map<VariableDeclaration const*, IRVariable> m_localVariables;
/// Storage offsets of state variables
std::map<VariableDeclaration const*, std::pair<u256, unsigned>> m_stateVariables;
std::shared_ptr<MultiUseYulFunctionCollector> m_functions;
MultiUseYulFunctionCollector m_functions;
size_t m_varCounter = 0;
};

View File

@ -107,7 +107,7 @@ string IRGenerator::generate(ContractDefinition const& _contract)
for (auto const* contract: _contract.annotation().linearizedBaseContracts)
for (auto const* fun: contract->definedFunctions())
generateFunction(*fun);
t("functions", m_context.functionCollector()->requestedFunctions());
t("functions", m_context.functionCollector().requestedFunctions());
resetContext(_contract);
m_context.setInheritanceHierarchy(_contract.annotation().linearizedBaseContracts);
@ -116,7 +116,7 @@ string IRGenerator::generate(ContractDefinition const& _contract)
for (auto const* contract: _contract.annotation().linearizedBaseContracts)
for (auto const* fun: contract->definedFunctions())
generateFunction(*fun);
t("runtimeFunctions", m_context.functionCollector()->requestedFunctions());
t("runtimeFunctions", m_context.functionCollector().requestedFunctions());
return t.render();
}
@ -130,7 +130,7 @@ string IRGenerator::generate(Block const& _block)
string IRGenerator::generateFunction(FunctionDefinition const& _function)
{
string functionName = m_context.functionName(_function);
return m_context.functionCollector()->createFunction(functionName, [&]() {
return m_context.functionCollector().createFunction(functionName, [&]() {
Whiskers t(R"(
function <functionName>(<params>) <returns> {
<body>
@ -160,7 +160,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
solAssert(_varDecl.isStateVariable(), "");
if (auto const* mappingType = dynamic_cast<MappingType const*>(type))
return m_context.functionCollector()->createFunction(functionName, [&]() {
return m_context.functionCollector().createFunction(functionName, [&]() {
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
solAssert(slot_offset.second == 0, "");
FunctionType funType(_varDecl);
@ -209,7 +209,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
{
solUnimplementedAssert(type->isValueType(), "");
return m_context.functionCollector()->createFunction(functionName, [&]() {
return m_context.functionCollector().createFunction(functionName, [&]() {
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
return Whiskers(R"(
@ -383,11 +383,10 @@ string IRGenerator::memoryInit()
void IRGenerator::resetContext(ContractDefinition const& _contract)
{
solAssert(
m_context.functionCollector()->requestedFunctions().empty(),
m_context.functionCollector().requestedFunctions().empty(),
"Reset context while it still had functions."
);
m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings);
m_utils = YulUtilFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
m_context.setInheritanceHierarchy(_contract.annotation().linearizedBaseContracts);
for (auto const& var: ContractType(_contract).stateVariables())