mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Tests apart from new one work fine.
This commit is contained in:
parent
9cc7402c95
commit
421dcf4c1a
@ -252,7 +252,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
eth::AssemblyItem returnTag = m_context.pushNewTag();
|
||||
fallback->accept(*this);
|
||||
m_context << returnTag;
|
||||
appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes());
|
||||
appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary());
|
||||
}
|
||||
else
|
||||
m_context << eth::Instruction::STOP; // function not found
|
||||
@ -268,7 +268,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
appendCalldataUnpacker(functionType->parameterTypes());
|
||||
m_context.appendJumpTo(m_context.functionEntryLabel(functionType->declaration()));
|
||||
m_context << returnTag;
|
||||
appendReturnValuePacker(functionType->returnParameterTypes());
|
||||
appendReturnValuePacker(functionType->returnParameterTypes(), _contract.isLibrary());
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,7 +283,7 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool
|
||||
for (TypePointer const& parameterType: _typeParameters)
|
||||
{
|
||||
// stack: v1 v2 ... v(k-1) base_offset current_offset
|
||||
TypePointer type = parameterType->encodingType();
|
||||
TypePointer type = parameterType->decodingType();
|
||||
if (type->category() == Type::Category::Array)
|
||||
{
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(*type);
|
||||
@ -340,7 +340,6 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool
|
||||
CompilerUtils(m_context).moveToStackTop(1 + arrayType.sizeOnStack());
|
||||
m_context << eth::Instruction::SWAP1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -354,7 +353,7 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool
|
||||
m_context << eth::Instruction::POP << eth::Instruction::POP;
|
||||
}
|
||||
|
||||
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)
|
||||
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters, bool _isLibrary)
|
||||
{
|
||||
CompilerUtils utils(m_context);
|
||||
if (_typeParameters.empty())
|
||||
@ -364,7 +363,7 @@ void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)
|
||||
utils.fetchFreeMemoryPointer();
|
||||
//@todo optimization: if we return a single memory array, there should be enough space before
|
||||
// its data to add the needed parts and we avoid a memory copy.
|
||||
utils.encodeToMemory(_typeParameters, _typeParameters);
|
||||
utils.encodeToMemory(_typeParameters, _typeParameters, true, false, _isLibrary);
|
||||
utils.toSizeAfterFreeMemoryPointer();
|
||||
m_context << eth::Instruction::RETURN;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ private:
|
||||
/// From memory if @a _fromMemory is true, otherwise from call data.
|
||||
/// Expects source offset on the stack, which is removed.
|
||||
void appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false);
|
||||
void appendReturnValuePacker(TypePointers const& _typeParameters);
|
||||
void appendReturnValuePacker(TypePointers const& _typeParameters, bool _isLibrary);
|
||||
|
||||
void registerStateVariables(ContractDefinition const& _contract);
|
||||
void initializeStateVariables(ContractDefinition const& _contract);
|
||||
|
@ -153,14 +153,15 @@ void CompilerUtils::encodeToMemory(
|
||||
TypePointers const& _givenTypes,
|
||||
TypePointers const& _targetTypes,
|
||||
bool _padToWordBoundaries,
|
||||
bool _copyDynamicDataInPlace
|
||||
bool _copyDynamicDataInPlace,
|
||||
bool _encodeAsLibraryTypes
|
||||
)
|
||||
{
|
||||
// stack: <v1> <v2> ... <vn> <mem>
|
||||
TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes;
|
||||
solAssert(targetTypes.size() == _givenTypes.size(), "");
|
||||
for (TypePointer& t: targetTypes)
|
||||
t = t->mobileType()->encodingType();
|
||||
t = t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType();
|
||||
|
||||
// Stack during operation:
|
||||
// <v1> <v2> ... <vn> <mem_start> <dyn_head_1> ... <dyn_head_r> <end_of_mem>
|
||||
|
@ -91,13 +91,16 @@ public:
|
||||
/// @param _padToWordBoundaries if false, all values are concatenated without padding.
|
||||
/// @param _copyDynamicDataInPlace if true, dynamic types is stored (without length)
|
||||
/// together with fixed-length data.
|
||||
/// @param _encodeAsLibraryTypes if true, encodes for a library function, e.g. does not
|
||||
/// convert storage pointer types to memory types.
|
||||
/// @note the locations of target reference types are ignored, because it will always be
|
||||
/// memory.
|
||||
void encodeToMemory(
|
||||
TypePointers const& _givenTypes = {},
|
||||
TypePointers const& _targetTypes = {},
|
||||
bool _padToWordBoundaries = true,
|
||||
bool _copyDynamicDataInPlace = false
|
||||
bool _copyDynamicDataInPlace = false,
|
||||
bool _encodeAsLibraryTypes = false
|
||||
);
|
||||
|
||||
/// Uses a CALL to the identity contract to perform a memory-to-memory copy.
|
||||
|
@ -109,42 +109,40 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
|
||||
// As an exception, "storage" is allowed for library functions.
|
||||
if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
|
||||
{
|
||||
if (_variable.isCallableParameter())
|
||||
if (_variable.isExternalCallableParameter())
|
||||
{
|
||||
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
||||
if (_variable.isExternalCallableParameter())
|
||||
if (contract.isLibrary())
|
||||
{
|
||||
if (contract.isLibrary())
|
||||
{
|
||||
if (loc == Location::Memory)
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError(
|
||||
"Location has to be calldata or storage for external "
|
||||
"library functions (remove the \"memory\" keyword)."
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
// force location of external function parameters (not return) to calldata
|
||||
if (loc != Location::Default)
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError(
|
||||
"Location has to be calldata for external functions "
|
||||
"(remove the \"memory\" or \"storage\" keyword)."
|
||||
));
|
||||
}
|
||||
if (loc == Location::Default)
|
||||
type = ref->copyForLocation(DataLocation::CallData, true);
|
||||
}
|
||||
else if (_variable.isCallableParameter() && _variable.scope()->isPublic())
|
||||
{
|
||||
// force locations of public or external function (return) parameters to memory
|
||||
if (loc == Location::Storage && !contract.isLibrary())
|
||||
if (loc == Location::Memory)
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError(
|
||||
"Location has to be memory for publicly visible functions "
|
||||
"(remove the \"storage\" keyword)."
|
||||
"Location has to be calldata or storage for external "
|
||||
"library functions (remove the \"memory\" keyword)."
|
||||
));
|
||||
if (loc == Location::Default)
|
||||
type = ref->copyForLocation(DataLocation::Memory, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// force location of external function parameters (not return) to calldata
|
||||
if (loc != Location::Default)
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError(
|
||||
"Location has to be calldata for external functions "
|
||||
"(remove the \"memory\" or \"storage\" keyword)."
|
||||
));
|
||||
}
|
||||
if (loc == Location::Default)
|
||||
type = ref->copyForLocation(DataLocation::CallData, true);
|
||||
}
|
||||
else if (_variable.isCallableParameter() && _variable.scope()->isPublic())
|
||||
{
|
||||
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
||||
// force locations of public or external function (return) parameters to memory
|
||||
if (loc == Location::Storage && !contract.isLibrary())
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError(
|
||||
"Location has to be memory for publicly visible functions "
|
||||
"(remove the \"storage\" keyword)."
|
||||
));
|
||||
if (loc == Location::Default || !contract.isLibrary())
|
||||
type = ref->copyForLocation(DataLocation::Memory, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -847,6 +847,14 @@ TypePointer ArrayType::encodingType() const
|
||||
return this->copyForLocation(DataLocation::Memory, true);
|
||||
}
|
||||
|
||||
TypePointer ArrayType::decodingType() const
|
||||
{
|
||||
if (location() == DataLocation::Storage)
|
||||
return make_shared<IntegerType>(256);
|
||||
else
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
TypePointer ArrayType::interfaceType(bool _inLibrary) const
|
||||
{
|
||||
if (_inLibrary && location() == DataLocation::Storage)
|
||||
|
@ -230,6 +230,8 @@ public:
|
||||
/// This for example returns address for contract types.
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
virtual TypePointer encodingType() const { return TypePointer(); }
|
||||
/// @returns a (simpler) type that is used when decoding this type in calldata.
|
||||
virtual TypePointer decodingType() const { return encodingType(); }
|
||||
/// @returns a type that will be used outside of Solidity for e.g. function signatures.
|
||||
/// This for example returns address for contract types.
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
@ -504,6 +506,7 @@ public:
|
||||
return isString() ? EmptyMemberList : s_arrayTypeMemberList;
|
||||
}
|
||||
virtual TypePointer encodingType() const override;
|
||||
virtual TypePointer decodingType() const override;
|
||||
virtual TypePointer interfaceType(bool _inLibrary) const override;
|
||||
|
||||
/// @returns true if this is a byte array or a string
|
||||
|
Loading…
Reference in New Issue
Block a user