mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1029 from chriseth/sol_bytesContinuation
length member for bytes
This commit is contained in:
commit
0e40b21c56
@ -184,17 +184,14 @@ void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType,
|
|||||||
<< eth::Instruction::SWAP1;
|
<< eth::Instruction::SWAP1;
|
||||||
// stack here: target_ref target_data_end target_data_ref
|
// stack here: target_ref target_data_end target_data_ref
|
||||||
// store length (in bytes)
|
// store length (in bytes)
|
||||||
if (_sourceType.getOffset() == 0)
|
m_context << eth::Instruction::CALLDATASIZE;
|
||||||
m_context << eth::Instruction::CALLDATASIZE;
|
|
||||||
else
|
|
||||||
m_context << _sourceType.getOffset() << eth::Instruction::CALLDATASIZE << eth::Instruction::SUB;
|
|
||||||
m_context << eth::Instruction::DUP1 << eth::Instruction::DUP5 << eth::Instruction::SSTORE;
|
m_context << eth::Instruction::DUP1 << eth::Instruction::DUP5 << eth::Instruction::SSTORE;
|
||||||
// jump to end if length is zero
|
// jump to end if length is zero
|
||||||
m_context << eth::Instruction::ISZERO;
|
m_context << eth::Instruction::ISZERO;
|
||||||
eth::AssemblyItem copyLoopEnd = m_context.newTag();
|
eth::AssemblyItem copyLoopEnd = m_context.newTag();
|
||||||
m_context.appendConditionalJumpTo(copyLoopEnd);
|
m_context.appendConditionalJumpTo(copyLoopEnd);
|
||||||
|
// store start offset
|
||||||
m_context << _sourceType.getOffset();
|
m_context << u256(0);
|
||||||
// stack now: target_ref target_data_end target_data_ref calldata_offset
|
// stack now: target_ref target_data_end target_data_ref calldata_offset
|
||||||
eth::AssemblyItem copyLoopStart = m_context.newTag();
|
eth::AssemblyItem copyLoopStart = m_context.newTag();
|
||||||
m_context << copyLoopStart
|
m_context << copyLoopStart
|
||||||
|
@ -504,6 +504,12 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
|||||||
}
|
}
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
|
||||||
}
|
}
|
||||||
|
case Type::Category::ByteArray:
|
||||||
|
{
|
||||||
|
solAssert(member == "length", "Illegal bytearray member.");
|
||||||
|
m_context << eth::Instruction::SLOAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
|
||||||
}
|
}
|
||||||
|
14
Types.cpp
14
Types.cpp
@ -58,7 +58,7 @@ TypePointer Type::fromElementaryTypeName(Token::Value _typeToken)
|
|||||||
else if (Token::String0 <= _typeToken && _typeToken <= Token::String32)
|
else if (Token::String0 <= _typeToken && _typeToken <= Token::String32)
|
||||||
return make_shared<StaticStringType>(int(_typeToken) - int(Token::String0));
|
return make_shared<StaticStringType>(int(_typeToken) - int(Token::String0));
|
||||||
else if (_typeToken == Token::Bytes)
|
else if (_typeToken == Token::Bytes)
|
||||||
return make_shared<ByteArrayType>(ByteArrayType::Location::Storage, 0, 0, true);
|
return make_shared<ByteArrayType>(ByteArrayType::Location::Storage);
|
||||||
else
|
else
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
|
||||||
std::string(Token::toString(_typeToken)) + " to type."));
|
std::string(Token::toString(_typeToken)) + " to type."));
|
||||||
@ -515,12 +515,7 @@ TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const
|
|||||||
|
|
||||||
bool ByteArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
|
bool ByteArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
|
||||||
{
|
{
|
||||||
if (*this == _convertTo)
|
return _convertTo.getCategory() == getCategory();
|
||||||
return true;
|
|
||||||
if (_convertTo.getCategory() != Category::ByteArray)
|
|
||||||
return false;
|
|
||||||
auto const& other = dynamic_cast<ByteArrayType const&>(_convertTo);
|
|
||||||
return (m_dynamicLength == other.m_dynamicLength || m_length == other.m_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypePointer ByteArrayType::unaryOperatorResult(Token::Value _operator) const
|
TypePointer ByteArrayType::unaryOperatorResult(Token::Value _operator) const
|
||||||
@ -535,8 +530,7 @@ bool ByteArrayType::operator==(Type const& _other) const
|
|||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
return false;
|
return false;
|
||||||
ByteArrayType const& other = dynamic_cast<ByteArrayType const&>(_other);
|
ByteArrayType const& other = dynamic_cast<ByteArrayType const&>(_other);
|
||||||
return other.m_location == m_location && other.m_dynamicLength == m_dynamicLength
|
return other.m_location == m_location;
|
||||||
&& other.m_length == m_length && other.m_offset == m_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ByteArrayType::getSizeOnStack() const
|
unsigned ByteArrayType::getSizeOnStack() const
|
||||||
@ -547,6 +541,8 @@ unsigned ByteArrayType::getSizeOnStack() const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MemberList ByteArrayType::s_byteArrayMemberList = MemberList({{"length", make_shared<IntegerType >(256)}});
|
||||||
|
|
||||||
bool ContractType::operator==(Type const& _other) const
|
bool ContractType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
|
12
Types.h
12
Types.h
@ -286,25 +286,19 @@ public:
|
|||||||
enum class Location { Storage, CallData, Memory };
|
enum class Location { Storage, CallData, Memory };
|
||||||
|
|
||||||
virtual Category getCategory() const override { return Category::ByteArray; }
|
virtual Category getCategory() const override { return Category::ByteArray; }
|
||||||
explicit ByteArrayType(Location _location, u256 const& _offset = 0, u256 const& _length = 0,
|
explicit ByteArrayType(Location _location): m_location(_location) {}
|
||||||
bool _dynamicLength = false):
|
|
||||||
m_location(_location), m_offset(_offset), m_length(_length), m_dynamicLength(_dynamicLength) {}
|
|
||||||
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||||
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
|
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
|
||||||
virtual bool operator==(const Type& _other) const override;
|
virtual bool operator==(const Type& _other) const override;
|
||||||
virtual unsigned getSizeOnStack() const override;
|
virtual unsigned getSizeOnStack() const override;
|
||||||
virtual std::string toString() const override { return "bytes"; }
|
virtual std::string toString() const override { return "bytes"; }
|
||||||
|
virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; }
|
||||||
|
|
||||||
Location getLocation() const { return m_location; }
|
Location getLocation() const { return m_location; }
|
||||||
u256 const& getOffset() const { return m_offset; }
|
|
||||||
u256 const& getLength() const { return m_length; }
|
|
||||||
bool hasDynamicLength() const { return m_dynamicLength; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Location m_location;
|
Location m_location;
|
||||||
u256 m_offset;
|
static const MemberList s_byteArrayMemberList;
|
||||||
u256 m_length;
|
|
||||||
bool m_dynamicLength;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user