mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use IRVariable's in IR code generation and implement tuples.
This commit is contained in:
+25
-17
@@ -151,7 +151,7 @@ util::Result<TypePointers> transformParametersToExternal(TypePointers const& _pa
|
||||
void Type::clearCache() const
|
||||
{
|
||||
m_members.clear();
|
||||
m_stackSlots.reset();
|
||||
m_stackItems.reset();
|
||||
m_stackSize.reset();
|
||||
}
|
||||
|
||||
@@ -1703,14 +1703,22 @@ u256 ArrayType::storageSize() const
|
||||
return max<u256>(1, u256(size));
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> ArrayType::makeStackSlots() const
|
||||
vector<tuple<string, TypePointer>> ArrayType::makeStackItems() const
|
||||
{
|
||||
if (m_location == DataLocation::CallData && isDynamicallySized())
|
||||
return {std::make_tuple("offset", TypeProvider::uint256()), std::make_tuple("length", TypeProvider::uint256())};
|
||||
else
|
||||
// storage slot or memory offset
|
||||
// byte offset inside storage value is omitted
|
||||
return {std::make_tuple(string(), nullptr)};
|
||||
switch (m_location)
|
||||
{
|
||||
case DataLocation::CallData:
|
||||
if (isDynamicallySized())
|
||||
return {std::make_tuple("offset", TypeProvider::uint256()), std::make_tuple("length", TypeProvider::uint256())};
|
||||
else
|
||||
return {std::make_tuple("offset", TypeProvider::uint256())};
|
||||
case DataLocation::Memory:
|
||||
return {std::make_tuple("mpos", TypeProvider::uint256())};
|
||||
case DataLocation::Storage:
|
||||
// byte offset inside storage value is omitted
|
||||
return {std::make_tuple("slot", TypeProvider::uint256())};
|
||||
}
|
||||
solAssert(false, "");
|
||||
}
|
||||
|
||||
string ArrayType::toString(bool _short) const
|
||||
@@ -1892,7 +1900,7 @@ string ArraySliceType::toString(bool _short) const
|
||||
return m_arrayType.toString(_short) + " slice";
|
||||
}
|
||||
|
||||
std::vector<std::tuple<std::string, TypePointer>> ArraySliceType::makeStackSlots() const
|
||||
std::vector<std::tuple<std::string, TypePointer>> ArraySliceType::makeStackItems() const
|
||||
{
|
||||
return {{"offset", TypeProvider::uint256()}, {"length", TypeProvider::uint256()}};
|
||||
}
|
||||
@@ -1995,12 +2003,12 @@ vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::stateVar
|
||||
return variablesAndOffsets;
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> ContractType::makeStackSlots() const
|
||||
vector<tuple<string, TypePointer>> ContractType::makeStackItems() const
|
||||
{
|
||||
if (m_super)
|
||||
return {};
|
||||
else
|
||||
return {make_tuple("address", isPayable() ? TypeProvider::payableAddress() :TypeProvider::address())};
|
||||
return {make_tuple("address", isPayable() ? TypeProvider::payableAddress() : TypeProvider::address())};
|
||||
}
|
||||
|
||||
void StructType::clearCache() const
|
||||
@@ -2436,7 +2444,7 @@ u256 TupleType::storageSize() const
|
||||
solAssert(false, "Storage size of non-storable tuple type requested.");
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> TupleType::makeStackSlots() const
|
||||
vector<tuple<string, TypePointer>> TupleType::makeStackItems() const
|
||||
{
|
||||
vector<tuple<string, TypePointer>> slots;
|
||||
unsigned i = 1;
|
||||
@@ -2902,7 +2910,7 @@ unsigned FunctionType::storageBytes() const
|
||||
solAssert(false, "Storage size of non-storable function type requested.");
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> FunctionType::makeStackSlots() const
|
||||
vector<tuple<string, TypePointer>> FunctionType::makeStackItems() const
|
||||
{
|
||||
vector<tuple<string, TypePointer>> slots;
|
||||
Kind kind = m_kind;
|
||||
@@ -2927,12 +2935,12 @@ vector<tuple<string, TypePointer>> FunctionType::makeStackSlots() const
|
||||
slots = {make_tuple("address", TypeProvider::address())};
|
||||
break;
|
||||
case Kind::Internal:
|
||||
slots = {make_tuple(string(), nullptr)};
|
||||
slots = {make_tuple("functionIdentifier", TypeProvider::uint256())};
|
||||
break;
|
||||
case Kind::ArrayPush:
|
||||
case Kind::ArrayPop:
|
||||
case Kind::ByteArrayPush:
|
||||
slots = {make_tuple(string(), nullptr)};
|
||||
slots = {make_tuple("slot", TypeProvider::uint256())};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2945,7 +2953,7 @@ vector<tuple<string, TypePointer>> FunctionType::makeStackSlots() const
|
||||
if (m_saltSet)
|
||||
slots.emplace_back("salt", TypeProvider::uint256());
|
||||
if (bound())
|
||||
for (auto const& [boundName, boundType]: m_parameterTypes.front()->stackSlots())
|
||||
for (auto const& [boundName, boundType]: m_parameterTypes.front()->stackItems())
|
||||
slots.emplace_back("self_" + boundName, boundType);
|
||||
return slots;
|
||||
}
|
||||
@@ -3441,7 +3449,7 @@ u256 TypeType::storageSize() const
|
||||
solAssert(false, "Storage size of non-storable type type requested.");
|
||||
}
|
||||
|
||||
vector<tuple<string, TypePointer>> TypeType::makeStackSlots() const
|
||||
vector<tuple<string, TypePointer>> TypeType::makeStackItems() const
|
||||
{
|
||||
if (auto contractType = dynamic_cast<ContractType const*>(m_actualType))
|
||||
if (contractType->contractDefinition().isLibrary())
|
||||
|
||||
+26
-17
@@ -259,18 +259,25 @@ 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; }
|
||||
std::vector<std::tuple<std::string, TypePointer>> const& stackSlots() const
|
||||
/// @returns a list of named and typed stack items that determine the layout of this type on the stack.
|
||||
/// A stack item either has an empty name and type ``nullptr`` referring to a single stack slot, or
|
||||
/// has a non-empty name and a valid type referring to the stack layout of that type.
|
||||
/// The complete layout of a type on the stack can be obtained from its stack items recursively as follows:
|
||||
/// - Each unnamed stack item is untyped (its type is ``nullptr``) and contributes exactly one stack slot.
|
||||
/// - Each named stack item is typed and contributes the stack slots given by the stack items of its type.
|
||||
std::vector<std::tuple<std::string, TypePointer>> const& stackItems() const
|
||||
{
|
||||
if (!m_stackSlots)
|
||||
m_stackSlots = makeStackSlots();
|
||||
return *m_stackSlots;
|
||||
if (!m_stackItems)
|
||||
m_stackItems = makeStackItems();
|
||||
return *m_stackItems;
|
||||
}
|
||||
/// Total number of stack slots occupied by this type. This is the sum of ``sizeOnStack`` of all ``stackItems()``.
|
||||
unsigned sizeOnStack() const
|
||||
{
|
||||
if (!m_stackSize)
|
||||
{
|
||||
size_t sizeOnStack = 0;
|
||||
for (auto const& slot: stackSlots())
|
||||
for (auto const& slot: stackItems())
|
||||
if (std::get<1>(slot))
|
||||
sizeOnStack += std::get<1>(slot)->sizeOnStack();
|
||||
else
|
||||
@@ -355,7 +362,9 @@ protected:
|
||||
{
|
||||
return MemberList::MemberMap();
|
||||
}
|
||||
virtual std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const
|
||||
/// Generates the stack items to be returned by ``stackItems()``. Defaults
|
||||
/// to exactly one unnamed and untyped stack item referring to a single stack slot.
|
||||
virtual std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const
|
||||
{
|
||||
return {std::make_tuple(std::string(), nullptr)};
|
||||
}
|
||||
@@ -363,7 +372,7 @@ protected:
|
||||
|
||||
/// 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<std::vector<std::tuple<std::string, TypePointer>>> m_stackItems;
|
||||
mutable std::optional<size_t> m_stackSize;
|
||||
};
|
||||
|
||||
@@ -597,7 +606,7 @@ public:
|
||||
std::string const& value() const { return m_value; }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
@@ -783,7 +792,7 @@ public:
|
||||
void clearCache() const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
private:
|
||||
/// String is interpreted as a subtype of Bytes.
|
||||
enum class ArrayKind { Ordinary, Bytes, String };
|
||||
@@ -824,7 +833,7 @@ public:
|
||||
std::unique_ptr<ReferenceType> copyForLocation(DataLocation, bool) const override { solAssert(false, ""); }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
private:
|
||||
ArrayType const& m_arrayType;
|
||||
};
|
||||
@@ -885,7 +894,7 @@ public:
|
||||
/// offsets in storage.
|
||||
std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const;
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() 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
|
||||
@@ -1026,7 +1035,7 @@ public:
|
||||
std::vector<TypePointer> const& components() const { return m_components; }
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
private:
|
||||
std::vector<TypePointer> const m_components;
|
||||
};
|
||||
@@ -1282,7 +1291,7 @@ public:
|
||||
FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
private:
|
||||
static TypePointers parseElementaryTypeVector(strings const& _types);
|
||||
|
||||
@@ -1358,7 +1367,7 @@ public:
|
||||
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override;
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||
private:
|
||||
TypePointer m_actualType;
|
||||
};
|
||||
@@ -1384,7 +1393,7 @@ public:
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
TypePointers m_parameterTypes;
|
||||
};
|
||||
@@ -1412,7 +1421,7 @@ public:
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
SourceUnit const& m_sourceUnit;
|
||||
};
|
||||
@@ -1456,7 +1465,7 @@ public:
|
||||
TypePointer typeArgument() const;
|
||||
|
||||
protected:
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackSlots() const override { return {}; }
|
||||
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override { return {}; }
|
||||
private:
|
||||
Kind m_kind;
|
||||
/// Contract type used for contract metadata magic.
|
||||
|
||||
Reference in New Issue
Block a user