diff options
author | chriseth <c@ethdev.com> | 2015-03-13 17:52:34 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-17 01:07:14 +0800 |
commit | 7f64584b7fb151459500ade84612d3cd48f13f18 (patch) | |
tree | 1ba321f8d98d048ef3e89a38b6b90335fc8a568c /Types.cpp | |
parent | fff3f98f58345d45dcf518d7dccbfa0d0a4e67b7 (diff) | |
download | dexon-solidity-7f64584b7fb151459500ade84612d3cd48f13f18.tar.gz dexon-solidity-7f64584b7fb151459500ade84612d3cd48f13f18.tar.zst dexon-solidity-7f64584b7fb151459500ade84612d3cd48f13f18.zip |
Compute packing offsets.
Diffstat (limited to 'Types.cpp')
-rw-r--r-- | Types.cpp | 95 |
1 files changed, 89 insertions, 6 deletions
@@ -35,6 +35,56 @@ namespace dev namespace solidity { +std::pair<u256, unsigned> const* MemberList::getMemberStorageOffset(string const& _name) const +{ + if (!m_storageOffsets) + { + bigint slotOffset = 0; + unsigned byteOffset = 0; + map<string, pair<u256, unsigned>> offsets; + for (auto const& nameAndType: m_memberTypes) + { + TypePointer const& type = nameAndType.second; + if (!type->canBeStored()) + continue; + if (byteOffset + type->getStorageBytes() > 32) + { + // would overflow, go to next slot + ++slotOffset; + byteOffset = 0; + } + if (slotOffset >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage.")); + offsets[nameAndType.first] = make_pair(u256(slotOffset), byteOffset); + solAssert(type->getStorageSize() >= 1, "Invalid storage size."); + if (type->getStorageSize() == 1 && byteOffset + type->getStorageBytes() <= 32) + byteOffset += type->getStorageBytes(); + else + { + slotOffset += type->getStorageSize(); + byteOffset = 0; + } + } + if (byteOffset > 0) + ++slotOffset; + if (slotOffset >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage.")); + m_storageSize = u256(slotOffset); + m_storageOffsets.reset(new decltype(offsets)(move(offsets))); + } + if (m_storageOffsets->count(_name)) + return &((*m_storageOffsets)[_name]); + else + return nullptr; +} + +u256 const& MemberList::getStorageSize() const +{ + // trigger lazy computation + getMemberStorageOffset(""); + return m_storageSize; +} + TypePointer Type::fromElementaryTypeName(Token::Value _typeToken) { char const* tokenCstr = Token::toString(_typeToken); @@ -751,12 +801,7 @@ bool StructType::operator==(Type const& _other) const u256 StructType::getStorageSize() const { - bigint size = 0; - for (pair<string, TypePointer> const& member: getMembers()) - size += member.second->getStorageSize(); - if (size >= bigint(1) << 256) - BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Struct too large for storage.")); - return max<u256>(1, u256(size)); + return max<u256>(1, getMembers().getStorageSize()); } bool StructType::canLiveOutsideStorage() const @@ -787,6 +832,7 @@ MemberList const& StructType::getMembers() const u256 StructType::getStorageOffsetOfMember(string const& _name) const { + //@todo cache member offset? u256 offset; for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers()) @@ -811,6 +857,15 @@ bool EnumType::operator==(Type const& _other) const return other.m_enum == m_enum; } +unsigned EnumType::getStorageBytes() const +{ + size_t elements = m_enum.getMembers().size(); + if (elements <= 1) + return 1; + else + return dev::bytesRequired(elements - 1); +} + string EnumType::toString() const { return string("enum ") + m_enum.getName(); @@ -955,6 +1010,13 @@ string FunctionType::toString() const return name + ")"; } +u256 FunctionType::getStorageSize() const +{ + BOOST_THROW_EXCEPTION( + InternalCompilerError() + << errinfo_comment("Storage size of non-storable function type requested.")); +} + unsigned FunctionType::getSizeOnStack() const { Location location = m_location; @@ -1077,6 +1139,13 @@ string MappingType::toString() const return "mapping(" + getKeyType()->toString() + " => " + getValueType()->toString() + ")"; } +u256 VoidType::getStorageSize() const +{ + BOOST_THROW_EXCEPTION( + InternalCompilerError() + << errinfo_comment("Storage size of non-storable void type requested.")); +} + bool TypeType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -1085,6 +1154,13 @@ bool TypeType::operator==(Type const& _other) const return *getActualType() == *other.getActualType(); } +u256 TypeType::getStorageSize() const +{ + BOOST_THROW_EXCEPTION( + InternalCompilerError() + << errinfo_comment("Storage size of non-storable type type requested.")); +} + MemberList const& TypeType::getMembers() const { // We need to lazy-initialize it because of recursive references. @@ -1122,6 +1198,13 @@ ModifierType::ModifierType(const ModifierDefinition& _modifier) swap(params, m_parameterTypes); } +u256 ModifierType::getStorageSize() const +{ + BOOST_THROW_EXCEPTION( + InternalCompilerError() + << errinfo_comment("Storage size of non-storable type type requested.")); +} + bool ModifierType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) |