2019-03-05 16:20:28 +00:00
/*
This file is part of solidity .
solidity is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
solidity is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with solidity . If not , see < http : //www.gnu.org/licenses/>.
*/
2020-07-17 14:54:12 +00:00
// SPDX-License-Identifier: GPL-3.0
2019-03-05 16:20:28 +00:00
/**
* Component that can generate various useful Yul functions .
*/
# pragma once
# include <liblangutil/EVMVersion.h>
2020-02-10 10:58:36 +00:00
# include <libsolidity/ast/Types.h>
2019-03-05 16:20:28 +00:00
# include <libsolidity/codegen/MultiUseYulFunctionCollector.h>
2020-01-22 14:48:56 +00:00
# include <libsolidity/interface/DebugSettings.h>
2020-10-12 14:01:45 +00:00
# include <libsolutil/ErrorCodes.h>
2019-03-05 16:20:28 +00:00
# include <memory>
# include <string>
2019-05-02 20:33:47 +00:00
# include <vector>
2019-03-05 16:20:28 +00:00
2019-12-11 16:31:36 +00:00
namespace solidity : : frontend
2019-03-05 16:20:28 +00:00
{
class Type ;
class ArrayType ;
2019-05-02 10:48:34 +00:00
class MappingType ;
2019-05-23 14:12:32 +00:00
class IntegerType ;
2020-03-02 20:42:46 +00:00
class StructType ;
2019-03-05 16:20:28 +00:00
/**
* Component that can generate various useful Yul functions .
*/
class YulUtilFunctions
{
public :
explicit YulUtilFunctions (
langutil : : EVMVersion _evmVersion ,
2020-01-22 14:48:56 +00:00
RevertStrings _revertStrings ,
2020-03-02 17:08:19 +00:00
MultiUseYulFunctionCollector & _functionCollector
2019-03-05 16:20:28 +00:00
) :
m_evmVersion ( _evmVersion ) ,
2020-01-22 14:48:56 +00:00
m_revertStrings ( _revertStrings ) ,
2020-03-02 17:08:19 +00:00
m_functionCollector ( _functionCollector )
2019-03-05 16:20:28 +00:00
{ }
2021-08-05 11:21:08 +00:00
/// @returns the name of a function that returns its argument.
/// Sometimes needed to satisfy templates.
std : : string identityFunction ( ) ;
2019-03-05 16:20:28 +00:00
/// @returns a function that combines the address and selector to a single value
/// for use in the ABI.
std : : string combineExternalFunctionIdFunction ( ) ;
/// @returns a function that splits the address and selector from a single value
/// for use in the ABI.
std : : string splitExternalFunctionIdFunction ( ) ;
/// @returns a function that copies raw bytes of dynamic length from calldata
/// or memory to memory.
/// Pads with zeros and might write more than exactly length.
std : : string copyToMemoryFunction ( bool _fromCalldata ) ;
2020-12-22 14:48:31 +00:00
/// @returns the name of a function that copies a string literal to memory
/// and returns a pointer to the memory area containing the string literal.
2020-12-11 15:33:10 +00:00
/// signature: () -> memPtr
2020-12-22 14:48:31 +00:00
std : : string copyLiteralToMemoryFunction ( std : : string const & _literal ) ;
/// @returns the name of a function that stores a string literal at a specific location in memory
/// signature: (memPtr) ->
std : : string storeLiteralInMemoryFunction ( std : : string const & _literal ) ;
2020-12-11 15:33:10 +00:00
2021-05-05 06:57:19 +00:00
/// @returns the name of a function that stores a string literal at a specific location in storage
/// signature: (slot) ->
std : : string copyLiteralToStorageFunction ( std : : string const & _literal ) ;
2019-04-30 17:08:02 +00:00
// @returns the name of a function that has the equivalent logic of an
// `assert` or `require` call.
std : : string requireOrAssertFunction ( bool _assert , Type const * _messageType = nullptr ) ;
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that takes a (cleaned) value of the given value type and
/// left-aligns it, usually for use in non-padded encoding.
std : : string leftAlignFunction ( Type const & _type ) ;
std : : string shiftLeftFunction ( size_t _numBits ) ;
2019-06-17 13:26:40 +00:00
std : : string shiftLeftFunctionDynamic ( ) ;
2019-03-05 16:20:28 +00:00
std : : string shiftRightFunction ( size_t _numBits ) ;
2019-06-17 13:26:40 +00:00
std : : string shiftRightFunctionDynamic ( ) ;
2020-04-20 21:16:42 +00:00
std : : string shiftRightSignedFunctionDynamic ( ) ;
/// @returns the name of a function that performs a left shift and subsequent cleanup
/// and, if needed, prior cleanup.
/// signature: (value, amountToShift) -> result
std : : string typedShiftLeftFunction ( Type const & _type , Type const & _amountType ) ;
std : : string typedShiftRightFunction ( Type const & _type , Type const & _amountType ) ;
2019-03-18 10:39:15 +00:00
2019-06-13 15:31:38 +00:00
/// @returns the name of a function which replaces the
2019-04-30 16:32:56 +00:00
/// _numBytes bytes starting at byte position _shiftBytes (counted from the least significant
/// byte) by the _numBytes least significant bytes of `toInsert`.
2019-06-13 15:31:38 +00:00
/// signature: (value, toInsert) -> result
2019-04-30 16:32:56 +00:00
std : : string updateByteSliceFunction ( size_t _numBytes , size_t _shiftBytes ) ;
2019-06-05 17:32:30 +00:00
/// signature: (value, shiftBytes, toInsert) -> result
2019-06-17 13:26:40 +00:00
std : : string updateByteSliceFunctionDynamic ( size_t _numBytes ) ;
2019-06-05 17:32:30 +00:00
2020-10-20 15:29:11 +00:00
/// Function that sets all but the first ``bytes`` bytes of ``value`` to zero.
2020-10-21 07:48:22 +00:00
/// @note ``bytes`` has to be small enough not to overflow ``8 * bytes``.
2020-10-20 15:29:11 +00:00
/// signature: (value, bytes) -> result
std : : string maskBytesFunctionDynamic ( ) ;
2020-11-12 13:46:10 +00:00
/// Zeroes out all bytes above the first ``_bytes`` lower order bytes.
/// signature: (value) -> result
std : : string maskLowerOrderBytesFunction ( size_t _bytes ) ;
/// Zeroes out all bytes above the first ``bytes`` lower order bytes.
/// @note ``bytes`` has to be small enough not to overflow ``8 * bytes``.
/// signature: (value, bytes) -> result
std : : string maskLowerOrderBytesFunctionDynamic ( ) ;
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that rounds its input to the next multiple
/// of 32 or the input if it is a multiple of 32.
2021-05-05 08:12:12 +00:00
/// Ignores overflow.
2019-06-13 15:31:38 +00:00
/// signature: (value) -> result
2019-03-05 16:20:28 +00:00
std : : string roundUpFunction ( ) ;
2021-05-05 08:12:12 +00:00
/// @returns the name of a function that divides by 32 and rounds up during the division.
/// In other words, on input x it returns the smallest y such that y * 32 >= x.
/// Ignores overflow.
/// signature: (x) -> y
std : : string divide32CeilFunction ( ) ;
2019-06-13 15:31:38 +00:00
/// signature: (x, y) -> sum
2019-06-12 09:24:19 +00:00
std : : string overflowCheckedIntAddFunction ( IntegerType const & _type ) ;
2020-07-22 08:28:04 +00:00
/// signature: (x, y) -> sum
std : : string wrappingIntAddFunction ( IntegerType const & _type ) ;
2019-03-18 10:21:41 +00:00
2019-06-13 15:31:38 +00:00
/// signature: (x, y) -> product
2019-06-12 12:06:13 +00:00
std : : string overflowCheckedIntMulFunction ( IntegerType const & _type ) ;
2020-07-22 08:28:04 +00:00
/// signature: (x, y) -> product
std : : string wrappingIntMulFunction ( IntegerType const & _type ) ;
2019-05-20 14:42:27 +00:00
2019-05-23 14:12:32 +00:00
/// @returns name of function to perform division on integers.
/// Checks for division by zero and the special case of
/// signed division of the smallest number by -1.
std : : string overflowCheckedIntDivFunction ( IntegerType const & _type ) ;
2020-07-22 08:28:04 +00:00
/// @returns name of function to perform division on integers.
/// Checks for division by zero.
std : : string wrappingIntDivFunction ( IntegerType const & _type ) ;
2019-05-23 14:12:32 +00:00
2019-06-12 14:27:26 +00:00
/// @returns name of function to perform modulo on integers.
/// Reverts for modulo by zero.
2020-07-22 08:28:04 +00:00
std : : string intModFunction ( IntegerType const & _type ) ;
2019-06-12 14:27:26 +00:00
2019-05-08 19:25:47 +00:00
/// @returns computes the difference between two values.
/// Assumes the input to be in range for the type.
2019-06-13 15:31:38 +00:00
/// signature: (x, y) -> diff
2019-06-12 11:07:06 +00:00
std : : string overflowCheckedIntSubFunction ( IntegerType const & _type ) ;
2019-05-08 19:25:47 +00:00
2020-07-22 08:28:04 +00:00
/// @returns computes the difference between two values.
/// signature: (x, y) -> diff
std : : string wrappingIntSubFunction ( IntegerType const & _type ) ;
2020-07-22 14:52:28 +00:00
/// @returns the name of the exponentiation function.
/// signature: (base, exponent) -> power
std : : string overflowCheckedIntExpFunction ( IntegerType const & _type , IntegerType const & _exponentType ) ;
2020-09-15 20:42:48 +00:00
/// @returns the name of the exponentiation function, specialized for literal base.
/// signature: exponent -> power
std : : string overflowCheckedIntLiteralExpFunction (
RationalNumberType const & _baseType ,
IntegerType const & _exponentType ,
IntegerType const & _commonType
) ;
2020-07-22 14:52:28 +00:00
/// Generic unsigned checked exponentiation function.
/// Reverts if the result is larger than max.
/// signature: (base, exponent, max) -> power
std : : string overflowCheckedUnsignedExpFunction ( ) ;
/// Generic signed checked exponentiation function.
/// Reverts if the result is smaller than min or larger than max.
/// The code relies on max <= |min| and min < 0.
/// signature: (base, exponent, min, max) -> power
std : : string overflowCheckedSignedExpFunction ( ) ;
2020-09-15 12:33:36 +00:00
/// Helper function for the two checked exponentiation functions.
/// signature: (power, base, exponent, max) -> power
std : : string overflowCheckedExpLoopFunction ( ) ;
2020-07-22 08:28:04 +00:00
/// @returns the name of the exponentiation function.
/// signature: (base, exponent) -> power
std : : string wrappingIntExpFunction ( IntegerType const & _type , IntegerType const & _exponentType ) ;
2019-06-13 15:31:38 +00:00
/// @returns the name of a function that fetches the length of the given
/// array
/// signature: (array) -> length
2019-03-05 16:20:28 +00:00
std : : string arrayLengthFunction ( ArrayType const & _type ) ;
2019-06-06 12:07:40 +00:00
2020-11-09 14:43:57 +00:00
/// @returns function name that extracts and returns byte array length from the value
/// stored at the slot.
/// Causes a Panic if the length encoding is wrong.
/// signature: (data) -> length
std : : string extractByteArrayLengthFunction ( ) ;
2019-06-06 12:07:40 +00:00
/// @returns the name of a function that resizes a storage array
2020-11-26 16:15:41 +00:00
/// for statically sized arrays, it will just clean-up elements of array starting from newLen until the end
2019-06-06 12:07:40 +00:00
/// signature: (array, newLen)
2020-11-26 16:15:41 +00:00
std : : string resizeArrayFunction ( ArrayType const & _type ) ;
2019-06-06 12:07:40 +00:00
2021-04-22 07:47:12 +00:00
/// @returns the name of a function that zeroes all storage array elements from `startIndex` to `len` (excluding).
/// Assumes that `len` is the array length. Does nothing if `startIndex >= len`. Does not modify the stored length.
/// signature: (array, len, startIndex)
std : : string cleanUpStorageArrayEndFunction ( ArrayType const & _type ) ;
2019-11-07 20:22:58 +00:00
/// @returns the name of a function that reduces the size of a storage array by one element
/// signature: (array)
std : : string storageArrayPopFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that pushes an element to a storage array
2020-12-10 09:13:16 +00:00
/// @param _fromType represents the type of the element being pushed.
/// If _fromType is ReferenceType the function will perform deep copy.
2019-11-28 17:05:11 +00:00
/// signature: (array, value)
2021-03-22 16:12:05 +00:00
std : : string storageArrayPushFunction ( ArrayType const & _type , Type const * _fromType = nullptr ) ;
2019-11-07 20:22:58 +00:00
2019-11-28 17:49:28 +00:00
/// @returns the name of a function that pushes the base type's zero element to a storage array and returns storage slot and offset of the added element.
2019-11-28 17:05:11 +00:00
/// signature: (array) -> slot, offset
std : : string storageArrayPushZeroFunction ( ArrayType const & _type ) ;
2019-06-06 12:07:40 +00:00
/// @returns the name of a function that will clear the storage area given
2019-07-10 10:41:31 +00:00
/// by the start and end (exclusive) parameters (slots).
2019-06-06 12:07:40 +00:00
/// signature: (start, end)
std : : string clearStorageRangeFunction ( Type const & _type ) ;
2019-07-10 10:41:31 +00:00
/// @returns the name of a function that will clear the given storage array
/// signature: (slot) ->
std : : string clearStorageArrayFunction ( ArrayType const & _type ) ;
2020-11-12 13:46:10 +00:00
/// @returns the name of a function that will copy an array to storage
2020-10-08 18:31:13 +00:00
/// signature (to_slot, from_ptr) ->
2020-10-20 13:49:54 +00:00
std : : string copyArrayToStorageFunction ( ArrayType const & _fromType , ArrayType const & _toType ) ;
2020-10-08 18:31:13 +00:00
2020-11-12 13:46:10 +00:00
/// @returns the name of a function that will copy a byte array to storage
2020-10-20 15:05:58 +00:00
/// signature (to_slot, from_ptr) ->
std : : string copyByteArrayToStorageFunction ( ArrayType const & _fromType , ArrayType const & _toType ) ;
2020-10-08 18:31:13 +00:00
2020-11-12 13:46:10 +00:00
/// @returns the name of a function that will copy an array of value types from storage to storage.
/// signature (to_slot, from_slot) ->
std : : string copyValueArrayStorageToStorageFunction ( ArrayType const & _fromType , ArrayType const & _toType ) ;
2019-06-06 12:07:40 +00:00
/// Returns the name of a function that will convert a given length to the
/// size in memory (number of storage slots or calldata/memory bytes) it
/// will require.
/// signature: (length) -> size
std : : string arrayConvertLengthToSize ( ArrayType const & _type ) ;
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that computes the number of bytes required
/// to store an array in memory given its length (internally encoded, not ABI encoded).
/// The function reverts for too large lengths.
std : : string arrayAllocationSizeFunction ( ArrayType const & _type ) ;
2020-03-02 20:42:46 +00:00
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that converts a storage slot number
2019-03-15 17:26:17 +00:00
/// a memory pointer or a calldata pointer to the slot number / memory pointer / calldata pointer
/// for the data position of an array which is stored in that slot / memory area / calldata area.
2019-03-05 16:20:28 +00:00
std : : string arrayDataAreaFunction ( ArrayType const & _type ) ;
2019-06-13 15:22:24 +00:00
/// @returns the name of a function that returns the slot and offset for the
/// given array and index
/// signature: (array, index) -> slot, offset
std : : string storageArrayIndexAccessFunction ( ArrayType const & _type ) ;
2019-06-27 11:36:06 +00:00
/// @returns the name of a function that returns the memory address for the
/// given array base ref and index.
/// Causes invalid opcode on out of range access.
/// signature: (baseRef, index) -> address
std : : string memoryArrayIndexAccessFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that returns the calldata address for the
/// given array base ref and index.
2020-02-11 16:43:43 +00:00
/// signature: (baseRef, index) -> offset[, length]
2019-06-27 11:36:06 +00:00
std : : string calldataArrayIndexAccessFunction ( ArrayType const & _type ) ;
2020-03-06 19:59:34 +00:00
/// @returns the name of a function that returns offset and length for array slice
/// for the given array offset, length and start and end indices for slice
/// signature: (arrayOffset, arrayLength, sliceStart, sliceEnd) -> offset, length
std : : string calldataArrayIndexRangeAccess ( ArrayType const & _type ) ;
2020-02-11 16:43:43 +00:00
/// @returns the name of a function that follows a calldata tail while performing
/// bounds checks.
/// signature: (baseRef, tailPointer) -> offset[, length]
std : : string accessCalldataTailFunction ( Type const & _type ) ;
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that advances an array data pointer to the next element.
2019-06-19 02:46:05 +00:00
/// Only works for memory arrays, calldata arrays and storage arrays that every item occupies one or multiple full slots.
2019-03-05 16:20:28 +00:00
std : : string nextArrayElementFunction ( ArrayType const & _type ) ;
2020-10-01 17:42:42 +00:00
/// @returns the name of a function that allocates a memory array and copies the contents
/// of the storage array into it.
std : : string copyArrayFromStorageToMemoryFunction ( ArrayType const & _from , ArrayType const & _to ) ;
2021-02-23 13:40:46 +00:00
/// @returns the name of a function that does concatenation of variadic number of bytes
/// or fixed bytes
std : : string bytesConcatFunction ( std : : vector < Type const * > const & _argumentTypes ) ;
2019-05-02 10:48:34 +00:00
/// @returns the name of a function that performs index access for mappings.
/// @param _mappingType the type of the mapping
/// @param _keyType the type of the value provided
std : : string mappingIndexAccessFunction ( MappingType const & _mappingType , Type const & _keyType ) ;
2020-08-19 11:13:05 +00:00
/// @returns a function that reads a type from storage.
2019-05-02 09:05:02 +00:00
/// @param _splitFunctionTypes if false, returns the address and function signature in a
/// single variable.
std : : string readFromStorage ( Type const & _type , size_t _offset , bool _splitFunctionTypes ) ;
2019-06-17 13:26:40 +00:00
std : : string readFromStorageDynamic ( Type const & _type , bool _splitFunctionTypes ) ;
2019-05-02 09:05:02 +00:00
2020-05-04 12:21:48 +00:00
/// @returns a function that reads a value type from memory. Performs cleanup.
2019-06-27 11:36:06 +00:00
/// signature: (addr) -> value
std : : string readFromMemory ( Type const & _type ) ;
/// @returns a function that reads a value type from calldata.
/// Reverts on invalid input.
/// signature: (addr) -> value
std : : string readFromCalldata ( Type const & _type ) ;
2019-05-02 09:05:02 +00:00
/// @returns a function that extracts a value type from storage slot that has been
/// retrieved already.
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
2020-11-03 10:15:49 +00:00
///
/// For external function types, input and output is in "compressed"/"unsplit" form.
std : : string extractFromStorageValue ( Type const & _type , size_t _offset ) ;
std : : string extractFromStorageValueDynamic ( Type const & _type ) ;
2019-06-05 17:32:30 +00:00
/// Returns the name of a function will write the given value to
/// the specified slot and offset. If offset is not given, it is expected as
/// runtime parameter.
2020-11-17 11:58:54 +00:00
/// For reference types, offset is checked to be zero at runtime.
2019-06-05 17:32:30 +00:00
/// signature: (slot, [offset,] value)
2020-07-27 08:04:19 +00:00
std : : string updateStorageValueFunction (
2020-09-01 12:43:40 +00:00
Type const & _fromType ,
2020-07-27 08:04:19 +00:00
Type const & _toType ,
std : : optional < unsigned > const & _offset = std : : optional < unsigned > ( )
) ;
2019-05-02 09:05:02 +00:00
2019-06-27 11:36:06 +00:00
/// Returns the name of a function that will write the given value to
/// the specified address.
/// Performs a cleanup before writing for value types.
/// signature: (memPtr, value) ->
std : : string writeToMemoryFunction ( Type const & _type ) ;
2019-05-02 09:05:02 +00:00
/// Performs cleanup after reading from a potentially compressed storage slot.
/// The function does not perform any validation, it just masks or sign-extends
/// higher order bytes or left-aligns (in case of bytesNN).
/// The storage cleanup expects the value to be right-aligned with potentially
/// dirty higher order bytes.
2020-11-03 10:15:49 +00:00
/// For external functions, input and output is in "compressed"/"unsplit" form.
std : : string cleanupFromStorageFunction ( Type const & _type ) ;
2019-05-02 09:05:02 +00:00
2019-04-30 16:32:56 +00:00
/// @returns the name of a function that prepares a value of the given type
/// for being stored in storage. This usually includes cleanup and right-alignment
/// to fit the number of bytes in storage.
/// The resulting value might still have dirty higher order bits.
std : : string prepareStoreFunction ( Type const & _type ) ;
2019-03-05 16:20:28 +00:00
/// @returns the name of a function that allocates memory.
/// Modifies the "free memory pointer"
2021-01-14 16:13:51 +00:00
/// signature: (size) -> memPtr
2019-03-05 16:20:28 +00:00
std : : string allocationFunction ( ) ;
2021-01-14 16:13:51 +00:00
/// @returns the name of the function that allocates memory whose size might be defined later.
/// The allocation can be finalized using finalizeAllocationFunction.
/// Any other allocation will invalidate the memory pointer unless finalizeAllocationFunction
/// is called.
/// signature: () -> memPtr
std : : string allocateUnboundedFunction ( ) ;
2020-04-09 19:59:17 +00:00
2021-01-14 16:13:51 +00:00
/// @returns the name of the function that finalizes an unbounded memory allocation,
/// i.e. sets its size and makes the allocation permanent.
/// signature: (memPtr, size) ->
std : : string finalizeAllocationFunction ( ) ;
2020-04-09 19:59:17 +00:00
2020-03-02 20:42:46 +00:00
/// @returns the name of a function that zeroes an array.
/// signature: (dataStart, dataSizeInBytes) ->
std : : string zeroMemoryArrayFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that zeroes a chunk of memory.
/// signature: (dataStart, dataSizeInBytes) ->
std : : string zeroMemoryFunction ( Type const & _type ) ;
/// @returns the name of a function that zeroes an array
/// where the base does not have simple zero value in memory.
/// signature: (dataStart, dataSizeInBytes) ->
std : : string zeroComplexMemoryArrayFunction ( ArrayType const & _type ) ;
2020-07-20 12:37:19 +00:00
/// @returns the name of a function that allocates a memory array.
/// For dynamic arrays it adds space for length and stores it.
/// The contents of the data area are unspecified.
/// signature: (length) -> memPtr
std : : string allocateMemoryArrayFunction ( ArrayType const & _type ) ;
2020-03-02 20:42:46 +00:00
/// @returns the name of a function that allocates and zeroes a memory array.
2019-06-27 11:36:06 +00:00
/// For dynamic arrays it adds space for length and stores it.
/// signature: (length) -> memPtr
2020-03-02 20:42:46 +00:00
std : : string allocateAndInitializeMemoryArrayFunction ( ArrayType const & _type ) ;
2020-06-24 16:14:29 +00:00
/// @returns the name of a function that allocates a memory struct (no
/// initialization takes place).
/// signature: () -> memPtr
std : : string allocateMemoryStructFunction ( StructType const & _type ) ;
2020-03-02 20:42:46 +00:00
/// @returns the name of a function that allocates and zeroes a memory struct.
2020-06-24 16:14:29 +00:00
/// signature: () -> memPtr
2020-03-02 20:42:46 +00:00
std : : string allocateAndInitializeMemoryStructFunction ( StructType const & _type ) ;
2019-06-27 11:36:06 +00:00
2019-04-09 13:30:54 +00:00
/// @returns the name of the function that converts a value of type @a _from
/// to a value of type @a _to. The resulting vale is guaranteed to be in range
/// (i.e. "clean"). Asserts on failure.
///
/// This is used for data being encoded or general type conversions in the code.
std : : string conversionFunction ( Type const & _from , Type const & _to ) ;
2021-03-04 09:09:37 +00:00
/// @returns the name of a function that converts bytes array to fixed bytes type
/// signature: (array) -> value
std : : string bytesToFixedBytesConversionFunction ( ArrayType const & _from , FixedBytesType const & _to ) ;
2019-04-09 13:30:54 +00:00
/// @returns the name of the cleanup function for the given type and
/// adds its implementation to the requested functions.
/// The cleanup function defers to the validator function with "assert"
/// if there is no reasonable way to clean a value.
std : : string cleanupFunction ( Type const & _type ) ;
/// @returns the name of the validator function for the given type and
/// adds its implementation to the requested functions.
/// @param _revertOnFailure if true, causes revert on invalid data,
/// otherwise an assertion failure.
///
/// This is used for data decoded from external sources.
2020-10-08 17:43:16 +00:00
std : : string validatorFunction ( Type const & _type , bool _revertOnFailure ) ;
2019-04-09 13:30:54 +00:00
2019-05-02 20:33:47 +00:00
std : : string packedHashFunction ( std : : vector < Type const * > const & _givenTypes , std : : vector < Type const * > const & _targetTypes ) ;
2019-05-06 17:48:31 +00:00
/// @returns the name of a function that reverts and uses returndata (if available)
/// as reason string.
std : : string forwardingRevertFunction ( ) ;
2019-05-13 13:26:55 +00:00
std : : string incrementCheckedFunction ( Type const & _type ) ;
2020-07-22 08:28:04 +00:00
std : : string incrementWrappingFunction ( Type const & _type ) ;
2019-05-13 13:26:55 +00:00
std : : string decrementCheckedFunction ( Type const & _type ) ;
2020-07-22 08:28:04 +00:00
std : : string decrementWrappingFunction ( Type const & _type ) ;
2019-05-13 13:26:55 +00:00
2019-05-16 16:59:29 +00:00
std : : string negateNumberCheckedFunction ( Type const & _type ) ;
2020-07-22 08:28:04 +00:00
std : : string negateNumberWrappingFunction ( Type const & _type ) ;
2019-05-16 16:59:29 +00:00
2019-05-22 10:25:00 +00:00
/// @returns the name of a function that returns the zero value for the
2020-03-02 20:42:46 +00:00
/// provided type.
/// @param _splitFunctionTypes if false, returns two zeroes
std : : string zeroValueFunction ( Type const & _type , bool _splitFunctionTypes = true ) ;
2019-07-10 10:41:31 +00:00
/// @returns the name of a function that will set the given storage item to
/// zero
/// signature: (slot, offset) ->
std : : string storageSetToZeroFunction ( Type const & _type ) ;
2020-01-22 14:48:56 +00:00
2021-03-15 15:45:00 +00:00
/// If revertStrings is debug, @returns the name of a function that
2020-01-22 14:48:56 +00:00
/// stores @param _message in memory position 0 and reverts.
2021-03-15 15:45:00 +00:00
/// Otherwise returns the name of a function that uses "revert(0, 0)".
std : : string revertReasonIfDebugFunction ( std : : string const & _message = " " ) ;
2020-01-22 14:48:56 +00:00
2021-03-15 15:45:00 +00:00
/// @returns the function body of ``revertReasonIfDebug``.
/// Should only be used internally and by the old code generator.
static std : : string revertReasonIfDebugBody (
RevertStrings _revertStrings ,
std : : string const & _allocation ,
std : : string const & _message
) ;
2020-02-10 10:58:36 +00:00
2020-10-12 14:01:45 +00:00
/// Reverts with ``Panic(uint256)`` and the given code.
std : : string panicFunction ( util : : PanicCode _code ) ;
2020-09-15 16:57:59 +00:00
2020-10-20 13:30:46 +00:00
/// @returns the name of a function that returns the return data selector.
/// Returns zero if return data is too short.
std : : string returnDataSelectorFunction ( ) ;
/// @returns the name of a function that tries to abi-decode a string from offset 4 in the
/// return data. On failure, returns 0, otherwise a pointer to the newly allocated string.
/// Does not check the return data signature.
/// signature: () -> ptr
2020-02-10 10:58:36 +00:00
std : : string tryDecodeErrorMessageFunction ( ) ;
2020-10-20 13:30:46 +00:00
/// @returns the name of a function that tries to abi-decode a uint256 value from offset 4 in the
/// return data.
/// Does not check the return data signature.
/// signature: () -> success, value
std : : string tryDecodePanicDataFunction ( ) ;
2020-02-10 10:58:36 +00:00
/// Returns a function name that returns a newly allocated `bytes` array that contains the return data.
///
/// If returndatacopy() is not supported by the underlying target, a empty array will be returned instead.
std : : string extractReturndataFunction ( ) ;
2020-04-06 15:26:59 +00:00
/// @returns function name that returns constructor arguments copied to memory
/// signature: () -> arguments
std : : string copyConstructorArgumentsToMemoryFunction (
ContractDefinition const & _contract ,
std : : string const & _creationObjectName
) ;
2020-12-10 13:37:26 +00:00
/// @returns the name of a function that copies code from a given address to a newly
/// allocated byte array in memory.
/// Signature: (address) -> mpos
std : : string externalCodeFunction ( ) ;
2019-05-13 13:26:55 +00:00
private :
2020-12-10 09:13:16 +00:00
/// @returns the name of a function that copies a struct from calldata or memory to storage
2020-12-21 16:58:08 +00:00
/// signature: (slot, value) ->
std : : string copyStructToStorageFunction ( StructType const & _from , StructType const & _to ) ;
2020-11-06 11:23:31 +00:00
/// Special case of conversion functions - handles all array conversions.
std : : string arrayConversionFunction ( ArrayType const & _from , ArrayType const & _to ) ;
2019-05-02 14:24:54 +00:00
/// Special case of conversionFunction - handles everything that does not
/// use exactly one variable to hold the value.
std : : string conversionFunctionSpecial ( Type const & _from , Type const & _to ) ;
2020-05-05 17:53:17 +00:00
/// @returns the name of a function that reduces the size of a storage byte array by one element
/// signature: (byteArray)
std : : string storageByteArrayPopFunction ( ArrayType const & _type ) ;
2019-06-27 11:36:06 +00:00
std : : string readFromMemoryOrCalldata ( Type const & _type , bool _fromCalldata ) ;
2020-08-19 11:13:05 +00:00
/// @returns a function that reads a value type from storage.
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
/// @param _splitFunctionTypes if false, returns the address and function signature in a
/// single variable.
2020-11-03 10:15:49 +00:00
/// @param _offset if provided, read from static offset, otherwise offset is a parameter of the Yul function.
std : : string readFromStorageValueType ( Type const & _type , std : : optional < size_t > _offset , bool _splitFunctionTypes ) ;
2020-08-19 11:13:05 +00:00
/// @returns a function that reads a reference type from storage to memory (performing a deep copy).
std : : string readFromStorageReferenceType ( Type const & _type ) ;
2020-09-18 13:10:23 +00:00
/// @returns the name of a function that will clear given storage slot
/// starting with given offset until the end of the slot
/// signature: (slot, offset)
std : : string partialClearStorageSlotFunction ( ) ;
2020-09-18 10:37:38 +00:00
/// @returns the name of a function that will clear the given storage struct
/// signature: (slot) ->
std : : string clearStorageStructFunction ( StructType const & _type ) ;
2020-10-06 14:00:32 +00:00
/// @returns the name of a function that resizes a storage byte array
/// signature: (array, newLen)
std : : string resizeDynamicByteArrayFunction ( ArrayType const & _type ) ;
2021-04-22 07:47:12 +00:00
/// @returns the name of a function that cleans up elements of a storage byte array starting from startIndex.
/// It will not copy elements in case of transformation to short byte array, and will not change array length.
/// In case of startIndex is greater than len, doesn't do anything.
/// In case of short byte array (< 32 bytes) doesn't do anything.
/// If the first slot to be cleaned up is partially occupied, does not touch it. Cleans up only completely unused slots.
/// signature: (array, len, startIndex)
std : : string cleanUpDynamicByteArrayEndSlotsFunction ( ArrayType const & _type ) ;
2020-10-06 14:00:32 +00:00
/// @returns the name of a function that increases size of byte array
/// when we resize byte array frextractUsedSetLenom < 32 elements to >= 32 elements or we push to byte array of size 31 copying of data will occur
/// signature: (array, data, oldLen, newLen)
std : : string increaseByteArraySizeFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that decreases size of byte array
/// when we resize byte array from >= 32 elements to < 32 elements or we pop from byte array of size 32 copying of data will occur
/// signature: (array, data, oldLen, newLen)
std : : string decreaseByteArraySizeFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that sets size of short byte array while copying data
/// should be called when we resize from long byte array (more than 32 elements) to short byte array
/// signature: (array, data, len)
std : : string byteArrayTransitLongToShortFunction ( ArrayType const & _type ) ;
/// @returns the name of a function that extracts only used part of slot that represents short byte array
/// signature: (data, len) -> data
std : : string shortByteArrayEncodeUsedAreaSetLengthFunction ( ) ;
2021-04-20 16:06:06 +00:00
/// @returns the name of a function that calculates slot and offset for index
/// Doesn't perform length checks, assumes that index is in bounds
/// signature: (array, index)
std : : string longByteArrayStorageIndexAccessNoCheckFunction ( ) ;
2019-03-05 16:20:28 +00:00
langutil : : EVMVersion m_evmVersion ;
2020-01-22 14:48:56 +00:00
RevertStrings m_revertStrings ;
2020-03-02 17:08:19 +00:00
MultiUseYulFunctionCollector & m_functionCollector ;
2019-03-05 16:20:28 +00:00
} ;
}