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.
|
||||
unsigned dataOffset = CompilerUtils::dataStartOffset; // the 4 bytes of the function hash signature
|
||||
|
||||
unsigned offset(CompilerUtils::dataStartOffset);
|
||||
bool const c_padToWords = true;
|
||||
|
||||
unsigned dynamicParameterCount = 0;
|
||||
for (TypePointer const& type: _typeParameters)
|
||||
dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, *type, !_fromMemory, c_padToWords);
|
||||
return dataOffset;
|
||||
if (type->isDynamicallySized())
|
||||
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)
|
||||
|
@ -52,8 +52,8 @@ private:
|
||||
void appendConstructorCall(FunctionDefinition const& _constructor);
|
||||
void appendFunctionSelector(ContractDefinition const& _contract);
|
||||
/// 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.
|
||||
unsigned appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false);
|
||||
/// From memory if @a _fromMemory is true, otherwise from call data.
|
||||
void appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false);
|
||||
void appendReturnValuePacker(TypePointers const& _typeParameters);
|
||||
|
||||
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.
|
||||
/// Note that irrespective of this size, each calldata element is padded to a multiple of 32 bytes.
|
||||
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.
|
||||
/// For dynamically "allocated" types, it returns the size of the statically allocated head,
|
||||
virtual u256 getStorageSize() const { return 1; }
|
||||
@ -289,6 +291,7 @@ public:
|
||||
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
|
||||
virtual bool operator==(const Type& _other) const override;
|
||||
virtual bool isDynamicallySized() const { return true; }
|
||||
virtual unsigned getSizeOnStack() const override;
|
||||
virtual std::string toString() const override { return "bytes"; }
|
||||
virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; }
|
||||
|
Loading…
Reference in New Issue
Block a user