mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Unpacking of dynamically sized arguments.
This commit is contained in:
parent
d630a67812
commit
971cc9b5b9
35
Compiler.cpp
35
Compiler.cpp
@ -178,15 +178,40 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory)
|
void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory)
|
||||||
{
|
{
|
||||||
// We do not check the calldata size, everything is zero-padded.
|
// We do not check the calldata size, everything is zero-padded.
|
||||||
unsigned dataOffset = CompilerUtils::dataStartOffset; // the 4 bytes of the function hash signature
|
unsigned offset(CompilerUtils::dataStartOffset);
|
||||||
|
|
||||||
bool const c_padToWords = true;
|
bool const c_padToWords = true;
|
||||||
|
|
||||||
|
unsigned dynamicParameterCount = 0;
|
||||||
for (TypePointer const& type: _typeParameters)
|
for (TypePointer const& type: _typeParameters)
|
||||||
dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, *type, !_fromMemory, c_padToWords);
|
if (type->isDynamicallySized())
|
||||||
return dataOffset;
|
dynamicParameterCount++;
|
||||||
|
offset += dynamicParameterCount * 32;
|
||||||
|
unsigned currentDynamicParameter = 0;
|
||||||
|
for (TypePointer const& type: _typeParameters)
|
||||||
|
if (type->isDynamicallySized())
|
||||||
|
{
|
||||||
|
// value on stack: [memory_offset] (only if we are already in dynamic mode)
|
||||||
|
if (currentDynamicParameter == 0)
|
||||||
|
// switch from static to dynamic
|
||||||
|
m_context << u256(offset);
|
||||||
|
CompilerUtils(m_context).loadFromMemory(
|
||||||
|
CompilerUtils::dataStartOffset + currentDynamicParameter * 32,
|
||||||
|
IntegerType(256), !_fromMemory, c_padToWords);
|
||||||
|
// store new memory pointer
|
||||||
|
m_context << eth::Instruction::DUP2 << eth::Instruction::DUP2 << eth::Instruction::ADD;
|
||||||
|
currentDynamicParameter++;
|
||||||
|
// value on stack: offset length next_memory_offset
|
||||||
|
}
|
||||||
|
else if (currentDynamicParameter == 0)
|
||||||
|
// we can still use static load
|
||||||
|
offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords);
|
||||||
|
else
|
||||||
|
CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords);
|
||||||
|
if (dynamicParameterCount > 0)
|
||||||
|
m_context << eth::Instruction::POP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)
|
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)
|
||||||
|
@ -52,8 +52,8 @@ private:
|
|||||||
void appendConstructorCall(FunctionDefinition const& _constructor);
|
void appendConstructorCall(FunctionDefinition const& _constructor);
|
||||||
void appendFunctionSelector(ContractDefinition const& _contract);
|
void appendFunctionSelector(ContractDefinition const& _contract);
|
||||||
/// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers.
|
/// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers.
|
||||||
/// From memory if @a _fromMemory is true, otherwise from call data. @returns the size of the data in bytes.
|
/// From memory if @a _fromMemory is true, otherwise from call data.
|
||||||
unsigned appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false);
|
void appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false);
|
||||||
void appendReturnValuePacker(TypePointers const& _typeParameters);
|
void appendReturnValuePacker(TypePointers const& _typeParameters);
|
||||||
|
|
||||||
void registerStateVariables(ContractDefinition const& _contract);
|
void registerStateVariables(ContractDefinition const& _contract);
|
||||||
|
3
Types.h
3
Types.h
@ -122,6 +122,8 @@ public:
|
|||||||
/// is not a simple big-endian encoding or the type cannot be stored in calldata.
|
/// is not a simple big-endian encoding or the type cannot be stored in calldata.
|
||||||
/// Note that irrespective of this size, each calldata element is padded to a multiple of 32 bytes.
|
/// Note that irrespective of this size, each calldata element is padded to a multiple of 32 bytes.
|
||||||
virtual unsigned getCalldataEncodedSize() const { return 0; }
|
virtual unsigned getCalldataEncodedSize() const { return 0; }
|
||||||
|
/// @returns true if the type is dynamically encoded in calldata
|
||||||
|
virtual bool isDynamicallySized() const { return false; }
|
||||||
/// @returns number of bytes required to hold this value in storage.
|
/// @returns number of bytes 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; }
|
||||||
@ -289,6 +291,7 @@ public:
|
|||||||
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 bool isDynamicallySized() const { return true; }
|
||||||
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; }
|
virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; }
|
||||||
|
Loading…
Reference in New Issue
Block a user