@ -43,6 +43,26 @@ using TypePointer = std::shared_ptr<Type const>;
using FunctionTypePointer = std : : shared_ptr < FunctionType const > ;
using FunctionTypePointer = std : : shared_ptr < FunctionType const > ;
using TypePointers = std : : vector < TypePointer > ;
using TypePointers = std : : vector < TypePointer > ;
/**
* Helper class to compute storage offsets of members of structs and contracts .
*/
class StorageOffsets
{
public :
/// Resets the StorageOffsets objects and determines the position in storage for each
/// of the elements of @a _types.
void computeOffsets ( TypePointers const & _types ) ;
/// @returns the offset of the given member, might be null if the member is not part of storage.
std : : pair < u256 , unsigned > const * getOffset ( size_t _index ) const ;
/// @returns the total number of slots occupied by all members.
u256 const & getStorageSize ( ) const { return m_storageSize ; }
private :
u256 m_storageSize ;
std : : map < size_t , std : : pair < u256 , unsigned > > m_offsets ;
} ;
/**
/**
* List of members of a type .
* List of members of a type .
*/
*/
@ -53,6 +73,7 @@ public:
MemberList ( ) { }
MemberList ( ) { }
explicit MemberList ( MemberMap const & _members ) : m_memberTypes ( _members ) { }
explicit MemberList ( MemberMap const & _members ) : m_memberTypes ( _members ) { }
MemberList & operator = ( MemberList & & _other ) ;
TypePointer getMemberType ( std : : string const & _name ) const
TypePointer getMemberType ( std : : string const & _name ) const
{
{
for ( auto const & it : m_memberTypes )
for ( auto const & it : m_memberTypes )
@ -60,12 +81,18 @@ public:
return it . second ;
return it . second ;
return TypePointer ( ) ;
return TypePointer ( ) ;
}
}
/// @returns the offset of the given member in storage slots and bytes inside a slot or
/// a nullptr if the member is not part of storage.
std : : pair < u256 , unsigned > const * getMemberStorageOffset ( std : : string const & _name ) const ;
/// @returns the number of storage slots occupied by the members.
u256 const & getStorageSize ( ) const ;
MemberMap : : const_iterator begin ( ) const { return m_memberTypes . begin ( ) ; }
MemberMap : : const_iterator begin ( ) const { return m_memberTypes . begin ( ) ; }
MemberMap : : const_iterator end ( ) const { return m_memberTypes . end ( ) ; }
MemberMap : : const_iterator end ( ) const { return m_memberTypes . end ( ) ; }
private :
private :
MemberMap m_memberTypes ;
MemberMap m_memberTypes ;
mutable std : : unique_ptr < StorageOffsets > m_storageOffsets ;
} ;
} ;
/**
/**
@ -97,6 +124,8 @@ public:
/// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
/// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
static TypePointer commonType ( TypePointer const & _a , TypePointer const & _b ) ;
static TypePointer commonType ( TypePointer const & _a , TypePointer const & _b ) ;
/// Calculates the
virtual Category getCategory ( ) const = 0 ;
virtual Category getCategory ( ) const = 0 ;
virtual bool isImplicitlyConvertibleTo ( Type const & _other ) const { return * this = = _other ; }
virtual bool isImplicitlyConvertibleTo ( Type const & _other ) const { return * this = = _other ; }
virtual bool isExplicitlyConvertibleTo ( Type const & _convertTo ) const
virtual bool isExplicitlyConvertibleTo ( Type const & _convertTo ) const
@ -126,9 +155,15 @@ public:
unsigned getCalldataEncodedSize ( ) const { return getCalldataEncodedSize ( true ) ; }
unsigned getCalldataEncodedSize ( ) const { return getCalldataEncodedSize ( true ) ; }
/// @returns true if the type is dynamically encoded in calldata
/// @returns true if the type is dynamically encoded in calldata
virtual bool isDynamicallySized ( ) const { return false ; }
virtual bool isDynamicallySized ( ) const { return false ; }
/// @returns number of byte s required to hold this value in storage.
/// @returns the number of storage slot s required to hold this value in storage.
/// For dynamically "allocated" types, it returns the size of the statically allocated head,
/// For dynamically "allocated" types, it returns the size of the statically allocated head,
virtual u256 getStorageSize ( ) const { return 1 ; }
virtual u256 getStorageSize ( ) const { return 1 ; }
/// Multiple small types can be packed into a single storage slot. If such a packing is possible
/// this function @returns the size in bytes smaller than 32. Data is moved to the next slot if
/// it does not fit.
/// In order to avoid computation at runtime of whether such moving is necessary, structs and
/// array data (not each element) always start a new slot.
virtual unsigned getStorageBytes ( ) const { return 32 ; }
/// Returns true if the type can be stored in storage.
/// Returns true if the type can be stored in storage.
virtual bool canBeStored ( ) const { return true ; }
virtual bool canBeStored ( ) const { return true ; }
/// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping.
/// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping.
@ -179,6 +214,7 @@ public:
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual unsigned getCalldataEncodedSize ( bool _padded = true ) const override { return _padded ? 32 : m_bits / 8 ; }
virtual unsigned getCalldataEncodedSize ( bool _padded = true ) const override { return _padded ? 32 : m_bits / 8 ; }
virtual unsigned getStorageBytes ( ) const override { return m_bits / 8 ; }
virtual bool isValueType ( ) const override { return true ; }
virtual bool isValueType ( ) const override { return true ; }
virtual MemberList const & getMembers ( ) const { return isAddress ( ) ? AddressMemberList : EmptyMemberList ; }
virtual MemberList const & getMembers ( ) const { return isAddress ( ) ? AddressMemberList : EmptyMemberList ; }
@ -251,6 +287,7 @@ public:
virtual TypePointer binaryOperatorResult ( Token : : Value _operator , TypePointer const & _other ) const override ;
virtual TypePointer binaryOperatorResult ( Token : : Value _operator , TypePointer const & _other ) const override ;
virtual unsigned getCalldataEncodedSize ( bool _padded ) const override { return _padded & & m_bytes > 0 ? 32 : m_bytes ; }
virtual unsigned getCalldataEncodedSize ( bool _padded ) const override { return _padded & & m_bytes > 0 ? 32 : m_bytes ; }
virtual unsigned getStorageBytes ( ) const override { return m_bytes ; }
virtual bool isValueType ( ) const override { return true ; }
virtual bool isValueType ( ) const override { return true ; }
virtual std : : string toString ( ) const override { return " bytes " + dev : : toString ( m_bytes ) ; }
virtual std : : string toString ( ) const override { return " bytes " + dev : : toString ( m_bytes ) ; }
@ -275,6 +312,7 @@ public:
virtual TypePointer binaryOperatorResult ( Token : : Value _operator , TypePointer const & _other ) const override ;
virtual TypePointer binaryOperatorResult ( Token : : Value _operator , TypePointer const & _other ) const override ;
virtual unsigned getCalldataEncodedSize ( bool _padded ) const { return _padded ? 32 : 1 ; }
virtual unsigned getCalldataEncodedSize ( bool _padded ) const { return _padded ? 32 : 1 ; }
virtual unsigned getStorageBytes ( ) const override { return 1 ; }
virtual bool isValueType ( ) const override { return true ; }
virtual bool isValueType ( ) const override { return true ; }
virtual std : : string toString ( ) const override { return " bool " ; }
virtual std : : string toString ( ) const override { return " bool " ; }
@ -284,6 +322,9 @@ public:
/**
/**
* The type of an array . The flavours are byte array ( bytes ) , statically - ( < type > [ < length > ] )
* The type of an array . The flavours are byte array ( bytes ) , statically - ( < type > [ < length > ] )
* and dynamically - sized array ( < type > [ ] ) .
* and dynamically - sized array ( < type > [ ] ) .
* In storage , all arrays are packed tightly ( as long as more than one elementary type fits in
* one slot ) . Dynamically sized arrays ( including byte arrays ) start with their size as a uint and
* thus start on their own slot .
*/
*/
class ArrayType : public Type
class ArrayType : public Type
{
{
@ -345,6 +386,7 @@ public:
virtual bool isExplicitlyConvertibleTo ( Type const & _convertTo ) const override ;
virtual bool isExplicitlyConvertibleTo ( Type const & _convertTo ) const override ;
virtual TypePointer unaryOperatorResult ( Token : : Value _operator ) const override ;
virtual TypePointer unaryOperatorResult ( Token : : Value _operator ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual unsigned getStorageBytes ( ) const override { return 20 ; }
virtual bool isValueType ( ) const override { return true ; }
virtual bool isValueType ( ) const override { return true ; }
virtual std : : string toString ( ) const override ;
virtual std : : string toString ( ) const override ;
@ -384,12 +426,12 @@ public:
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual u256 getStorageSize ( ) const override ;
virtual u256 getStorageSize ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override ;
virtual unsigned getSizeOnStack ( ) const override { return 1 ; /*@todo*/ }
virtual unsigned getSizeOnStack ( ) const override { return 2 ; }
virtual std : : string toString ( ) const override ;
virtual std : : string toString ( ) const override ;
virtual MemberList const & getMembers ( ) const override ;
virtual MemberList const & getMembers ( ) const override ;
u256 getStorageOffset OfMember( std : : string const & _name ) const ;
std : : pair < u256 , unsigned > const & getStorageOffsets OfMember( std : : string const & _name ) const ;
private :
private :
StructDefinition const & m_struct ;
StructDefinition const & m_struct ;
@ -408,6 +450,7 @@ public:
virtual TypePointer unaryOperatorResult ( Token : : Value _operator ) const override ;
virtual TypePointer unaryOperatorResult ( Token : : Value _operator ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual unsigned getSizeOnStack ( ) const override { return 1 ; }
virtual unsigned getSizeOnStack ( ) const override { return 1 ; }
virtual unsigned getStorageBytes ( ) const override ;
virtual std : : string toString ( ) const override ;
virtual std : : string toString ( ) const override ;
virtual bool isValueType ( ) const override { return true ; }
virtual bool isValueType ( ) const override { return true ; }
@ -477,7 +520,7 @@ public:
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual std : : string toString ( ) const override ;
virtual std : : string toString ( ) const override ;
virtual bool canBeStored ( ) const override { return false ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual u256 getStorageSize ( ) const override { BOOST_THROW_EXCEPTION ( InternalCompilerError ( ) < < errinfo_comment ( " Storage size of non-storable function type requested. " ) ) ; }
virtual u256 getStorageSize ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual unsigned getSizeOnStack ( ) const override ;
virtual unsigned getSizeOnStack ( ) const override ;
virtual MemberList const & getMembers ( ) const override ;
virtual MemberList const & getMembers ( ) const override ;
@ -527,6 +570,7 @@ private:
/**
/**
* The type of a mapping , there is one distinct type per key / value type pair .
* The type of a mapping , there is one distinct type per key / value type pair .
* Mappings always occupy their own storage slot , but do not actually use it .
*/
*/
class MappingType : public Type
class MappingType : public Type
{
{
@ -537,6 +581,7 @@ public:
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual std : : string toString ( ) const override ;
virtual std : : string toString ( ) const override ;
virtual unsigned getSizeOnStack ( ) const override { return 2 ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
TypePointer const & getKeyType ( ) const { return m_keyType ; }
TypePointer const & getKeyType ( ) const { return m_keyType ; }
@ -560,7 +605,7 @@ public:
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual std : : string toString ( ) const override { return " void " ; }
virtual std : : string toString ( ) const override { return " void " ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual u256 getStorageSize ( ) const override { BOOST_THROW_EXCEPTION ( InternalCompilerError ( ) < < errinfo_comment ( " Storage size of non-storable void type requested. " ) ) ; }
virtual u256 getStorageSize ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
} ;
} ;
@ -580,7 +625,7 @@ public:
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool canBeStored ( ) const override { return false ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual u256 getStorageSize ( ) const override { BOOST_THROW_EXCEPTION ( InternalCompilerError ( ) < < errinfo_comment ( " Storage size of non-storable type type requested. " ) ) ; }
virtual u256 getStorageSize ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
virtual std : : string toString ( ) const override { return " type( " + m_actualType - > toString ( ) + " ) " ; }
virtual std : : string toString ( ) const override { return " type( " + m_actualType - > toString ( ) + " ) " ; }
@ -606,7 +651,7 @@ public:
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual TypePointer binaryOperatorResult ( Token : : Value , TypePointer const & ) const override { return TypePointer ( ) ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual bool canBeStored ( ) const override { return false ; }
virtual u256 getStorageSize ( ) const override { BOOST_THROW_EXCEPTION ( InternalCompilerError ( ) < < errinfo_comment ( " Storage size of non-storable type type requested. " ) ) ; }
virtual u256 getStorageSize ( ) const override ;
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual bool canLiveOutsideStorage ( ) const override { return false ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
virtual unsigned getSizeOnStack ( ) const override { return 0 ; }
virtual bool operator = = ( Type const & _other ) const override ;
virtual bool operator = = ( Type const & _other ) const override ;