Define stack slot names in types.

This commit is contained in:
Daniel Kirchner
2020-02-12 12:36:14 +01:00
parent e786650bef
commit 6abe0a50b1
2 changed files with 94 additions and 37 deletions
+47 -13
View File
@@ -259,7 +259,26 @@ public:
/// Returns true if the type can be stored as a value (as opposed to a reference) on the stack,
/// i.e. it behaves differently in lvalue context and in value context.
virtual bool isValueType() const { return false; }
virtual unsigned sizeOnStack() const { return 1; }
std::vector<std::tuple<std::string, TypePointer>> const& stackSlots() const
{
if (!m_stackSlots)
m_stackSlots = makeStackSlots();
return *m_stackSlots;
}
unsigned sizeOnStack() const
{
if (!m_stackSize)
{
size_t sizeOnStack = 0;
for (auto const& slot: stackSlots())
if (std::get<1>(slot))
sizeOnStack += std::get<1>(slot)->sizeOnStack();
else
++sizeOnStack;
m_stackSize = sizeOnStack;
}
return *m_stackSize;
}
/// If it is possible to initialize such a value in memory by just writing zeros
/// of the size memoryHeadSize().
virtual bool hasSimpleZeroValueInMemory() const { return true; }
@@ -336,9 +355,16 @@ protected:
{
return MemberList::MemberMap();
}
virtual std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const
{
return {std::make_tuple(std::string(), nullptr)};
}
/// List of member types (parameterised by scape), will be lazy-initialized.
mutable std::map<ContractDefinition const*, std::unique_ptr<MemberList>> m_members;
mutable std::optional<std::vector<std::tuple<std::string, TypePointer>>> m_stackSlots;
mutable std::optional<size_t> m_stackSize;
};
/**
@@ -562,7 +588,6 @@ public:
bool canBeStored() const override { return false; }
bool canLiveOutsideStorage() const override { return false; }
unsigned sizeOnStack() const override { return 0; }
std::string toString(bool) const override;
TypePointer mobileType() const override;
@@ -571,6 +596,8 @@ public:
std::string const& value() const { return m_value; }
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
private:
std::string m_value;
};
@@ -725,7 +752,6 @@ public:
bool isDynamicallyEncoded() const override;
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); }
unsigned sizeOnStack() const override;
std::string toString(bool _short) const override;
std::string canonicalName() const override;
std::string signatureInExternalFunction(bool _structsByName) const override;
@@ -756,6 +782,8 @@ public:
void clearCache() const override;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
/// String is interpreted as a subtype of Bytes.
enum class ArrayKind { Ordinary, Bytes, String };
@@ -785,7 +813,6 @@ public:
bool isDynamicallySized() const override { return true; }
bool isDynamicallyEncoded() const override { return true; }
bool canLiveOutsideStorage() const override { return m_arrayType.canLiveOutsideStorage(); }
unsigned sizeOnStack() const override { return 2; }
std::string toString(bool _short) const override;
/// @returns true if this is valid to be stored in calldata
@@ -796,6 +823,8 @@ public:
std::unique_ptr<ReferenceType> copyForLocation(DataLocation, bool) const override { solAssert(false, ""); }
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
ArrayType const& m_arrayType;
};
@@ -825,7 +854,6 @@ public:
unsigned storageBytes() const override { solAssert(!isSuper(), ""); return 20; }
bool leftAligned() const override { solAssert(!isSuper(), ""); return false; }
bool canLiveOutsideStorage() const override { return !isSuper(); }
unsigned sizeOnStack() const override { return m_super ? 0 : 1; }
bool isValueType() const override { return !isSuper(); }
std::string toString(bool _short) const override;
std::string canonicalName() const override;
@@ -856,7 +884,8 @@ public:
/// @returns a list of all state variables (including inherited) of the contract and their
/// offsets in storage.
std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
ContractDefinition const& m_contract;
/// If true, this is a special "super" type of m_contract containing only members that m_contract inherited
@@ -989,7 +1018,6 @@ public:
bool canBeStored() const override { return false; }
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return false; }
unsigned sizeOnStack() const override;
bool hasSimpleZeroValueInMemory() const override { return false; }
TypePointer mobileType() const override;
/// Converts components to their temporary types and performs some wildcard matching.
@@ -997,6 +1025,8 @@ public:
std::vector<TypePointer> const& components() const { return m_components; }
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
std::vector<TypePointer> const m_components;
};
@@ -1158,7 +1188,6 @@ public:
unsigned storageBytes() const override;
bool isValueType() const override { return true; }
bool canLiveOutsideStorage() const override { return m_kind == Kind::Internal || m_kind == Kind::External; }
unsigned sizeOnStack() const override;
bool hasSimpleZeroValueInMemory() const override { return false; }
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
TypePointer encodingType() const override;
@@ -1252,6 +1281,8 @@ public:
/// @param _bound if true, the function type is set to be bound.
FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
static TypePointers parseElementaryTypeVector(strings const& _types);
@@ -1321,12 +1352,13 @@ public:
bool canBeStored() const override { return false; }
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return false; }
unsigned sizeOnStack() const override;
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
std::string toString(bool _short) const override { return "type(" + m_actualType->toString(_short) + ")"; }
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
private:
TypePointer m_actualType;
};
@@ -1346,12 +1378,13 @@ public:
bool canBeStored() const override { return false; }
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return false; }
unsigned sizeOnStack() const override { return 0; }
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
std::string toString(bool _short) const override;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
private:
TypePointers m_parameterTypes;
};
@@ -1374,11 +1407,12 @@ public:
bool canBeStored() const override { return false; }
bool canLiveOutsideStorage() const override { return true; }
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
unsigned sizeOnStack() const override { return 0; }
MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
std::string toString(bool _short) const override;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
private:
SourceUnit const& m_sourceUnit;
};
@@ -1413,7 +1447,6 @@ public:
bool canBeStored() const override { return false; }
bool canLiveOutsideStorage() const override { return true; }
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
unsigned sizeOnStack() const override { return 0; }
MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
std::string toString(bool _short) const override;
@@ -1422,6 +1455,8 @@ public:
TypePointer typeArgument() const;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
private:
Kind m_kind;
/// Contract type used for contract metadata magic.
@@ -1445,7 +1480,6 @@ public:
bool canBeStored() const override { return false; }
bool canLiveOutsideStorage() const override { return false; }
bool isValueType() const override { return true; }
unsigned sizeOnStack() const override { return 1; }
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
std::string toString(bool) const override { return "inaccessible dynamic type"; }
TypePointer decodingType() const override;