Merge pull request #21240 from rjmccall/remove-xi-witnesses-5.0
[5.0] Remove the extra-inhabitant value witnesses
diff --git a/docs/Runtime.md b/docs/Runtime.md
index 2af89aa..a4fe69c 100644
--- a/docs/Runtime.md
+++ b/docs/Runtime.md
@@ -260,9 +260,7 @@
0000000000023a40 T _swift_assignExistentialWithCopy
000000000001dbf0 T _swift_copyPOD
000000000001c560 T _swift_getEnumCaseMultiPayload
-000000000001be60 T _swift_getEnumCaseSinglePayload
000000000001c400 T _swift_storeEnumTagMultiPayload
-000000000001bf90 T _swift_storeEnumTagSinglePayload
```
## Type metadata lookup
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index 99832e9..dc59061 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -295,10 +295,9 @@
// Handle the data witnesses explicitly so we can use more specific
// types for the flags enums.
typedef size_t size;
- typedef ValueWitnessFlags flags;
typedef size_t stride;
- typedef ExtraInhabitantFlags extraInhabitantFlags;
-
+ typedef ValueWitnessFlags flags;
+ typedef uint32_t extraInhabitantCount;
};
struct TypeLayout;
@@ -376,16 +375,9 @@
/// The number of extra inhabitants, that is, bit patterns that do not form
/// valid values of the type, in this type's binary representation.
- unsigned getNumExtraInhabitants() const;
-
- /// Assert that this value witness table is an extra-inhabitants
- /// value witness table and return it as such.
- ///
- /// This has an awful name because it's supposed to be internal to
- /// this file. Code outside this file should use LLVM's cast/dyn_cast.
- /// We don't want to use those here because we need to avoid accidentally
- /// introducing ABI dependencies on LLVM structures.
- const struct ExtraInhabitantsValueWitnessTable *_asXIVWT() const;
+ unsigned getNumExtraInhabitants() const {
+ return extraInhabitantCount;
+ }
/// Assert that this value witness table is an enum value witness table
/// and return it as such.
@@ -608,13 +600,6 @@
#define DATA_VALUE_WITNESS(LOWER, UPPER, TYPE)
#include "swift/ABI/ValueWitness.def"
- int vw_getExtraInhabitantIndex(const OpaqueValue *value) const {
- return getValueWitnesses()->_asXIVWT()->getExtraInhabitantIndex(value, this);
- }
- void vw_storeExtraInhabitant(OpaqueValue *value, int index) const {
- getValueWitnesses()->_asXIVWT()->storeExtraInhabitant(value, index, this);
- }
-
unsigned vw_getEnumTag(const OpaqueValue *value) const {
return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast<OpaqueValue*>(value), this);
}
@@ -637,6 +622,10 @@
return getValueWitnesses()->getStride();
}
+ unsigned vw_getNumExtraInhabitants() const {
+ return getValueWitnesses()->getNumExtraInhabitants();
+ }
+
/// Allocate an out-of-line buffer if values of this type don't fit in the
/// ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index fde8311..bf2ce18 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -121,24 +121,27 @@
// flags of the field types can be mostly bitwise-or'ed together to derive the
// flags for the struct. (The "non-inline" and "has-extra-inhabitants" bits
// still require additional fixup.)
- enum : int_type {
+ enum : uint32_t {
AlignmentMask = 0x000000FF,
+ // unused 0x0000FF00,
IsNonPOD = 0x00010000,
IsNonInline = 0x00020000,
- HasExtraInhabitants = 0x00040000,
+ // unused 0x00040000,
HasSpareBits = 0x00080000,
IsNonBitwiseTakable = 0x00100000,
HasEnumWitnesses = 0x00200000,
Incomplete = 0x00400000,
-
- // Everything else is reserved.
+ // unused 0xFF800000,
};
+ static constexpr const uint32_t MaxNumExtraInhabitants = 0x7FFFFFFF;
+
private:
- int_type Data;
+ uint32_t Data;
+
+ explicit constexpr TargetValueWitnessFlags(uint32_t data) : Data(data) {}
public:
- explicit constexpr TargetValueWitnessFlags(int_type data) : Data(data) {}
constexpr TargetValueWitnessFlags() : Data(0) {}
/// The required alignment of the first byte of an object of this
@@ -192,22 +195,12 @@
return TargetValueWitnessFlags((Data & ~IsNonBitwiseTakable) |
(isBT ? 0 : IsNonBitwiseTakable));
}
- /// True if this type's binary representation has extra inhabitants, that is,
- /// bit patterns that do not form valid values of the type.
- ///
- /// If true, then the extra inhabitant value witness table entries are
- /// available in this type's value witness table.
- bool hasExtraInhabitants() const { return Data & HasExtraInhabitants; }
+
/// True if this type's binary representation is that of an enum, and the
/// enum value witness table entries are available in this type's value
/// witness table.
bool hasEnumWitnesses() const { return Data & HasEnumWitnesses; }
constexpr TargetValueWitnessFlags
- withExtraInhabitants(bool hasExtraInhabitants) const {
- return TargetValueWitnessFlags((Data & ~HasExtraInhabitants) |
- (hasExtraInhabitants ? HasExtraInhabitants : 0));
- }
- constexpr TargetValueWitnessFlags
withEnumWitnesses(bool hasEnumWitnesses) const {
return TargetValueWitnessFlags((Data & ~HasEnumWitnesses) |
(hasEnumWitnesses ? HasEnumWitnesses : 0));
@@ -223,44 +216,12 @@
(isIncomplete ? Incomplete : 0));
}
- constexpr int_type getOpaqueValue() const { return Data; }
- static constexpr TargetValueWitnessFlags getFromOpaqueValue(int_type data) {
- return TargetValueWitnessFlags(data);
+ constexpr uint32_t getOpaqueValue() const {
+ return Data;
}
};
using ValueWitnessFlags = TargetValueWitnessFlags<size_t>;
-/// Flags stored in a value-witness table with extra inhabitants.
-template <typename int_type>
-class TargetExtraInhabitantFlags {
-public:
- enum : int_type {
- NumExtraInhabitantsMask = 0x7FFFFFFFU,
- ExtraInhabitantFlags
- };
- int_type Data;
-
- constexpr TargetExtraInhabitantFlags(int_type data) : Data(data) {}
-
-public:
- constexpr TargetExtraInhabitantFlags() : Data(0) {}
- /// The number of extra inhabitants in the type's representation.
- int getNumExtraInhabitants() const { return Data & NumExtraInhabitantsMask; }
-
- constexpr TargetExtraInhabitantFlags
- withNumExtraInhabitants(unsigned numExtraInhabitants) const {
- return TargetExtraInhabitantFlags((Data & ~NumExtraInhabitantsMask) |
- numExtraInhabitants);
- }
-
- constexpr int_type getOpaqueValue() const { return Data; }
- static constexpr TargetExtraInhabitantFlags getFromOpaqueValue(int_type data){
- return TargetExtraInhabitantFlags(data);
- }
-};
-using ExtraInhabitantFlags =
- TargetExtraInhabitantFlags<size_t>;
-
/// Flags for dynamic-cast operations.
enum class DynamicCastFlags : size_t {
/// All flags clear.
diff --git a/include/swift/ABI/ValueWitness.def b/include/swift/ABI/ValueWitness.def
index bc43600..d07eca2 100644
--- a/include/swift/ABI/ValueWitness.def
+++ b/include/swift/ABI/ValueWitness.def
@@ -23,7 +23,6 @@
#if defined(WANT_ALL_VALUE_WITNESSES)
#undef WANT_ALL_VALUE_WITNESSES
#define WANT_REQUIRED_VALUE_WITNESSES 1
-#define WANT_EXTRA_INHABITANT_VALUE_WITNESSES 1
#define WANT_ENUM_VALUE_WITNESSES 1
/// WANT_ONLY_REQUIRED_VALUE_WITNESSES
@@ -31,15 +30,6 @@
#elif defined(WANT_ONLY_REQUIRED_VALUE_WITNESSES)
#undef WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define WANT_REQUIRED_VALUE_WITNESSES 1
-#define WANT_EXTRA_INHABITANT_VALUE_WITNESSES 0
-#define WANT_ENUM_VALUE_WITNESSES 0
-
-/// WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
-/// Define this to expand only the extra-inhabitant value witnesses.
-#elif defined(WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES)
-#undef WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
-#define WANT_REQUIRED_VALUE_WITNESSES 0
-#define WANT_EXTRA_INHABITANT_VALUE_WITNESSES 1
#define WANT_ENUM_VALUE_WITNESSES 0
/// WANT_ONLY_ENUM_VALUE_WITNESSES
@@ -47,15 +37,13 @@
#elif defined(WANT_ONLY_ENUM_VALUE_WITNESSES)
#undef WANT_ONLY_ENUM_VALUE_WITNESSES
#define WANT_REQUIRED_VALUE_WITNESSES 0
-#define WANT_EXTRA_INHABITANT_VALUE_WITNESSES 0
#define WANT_ENUM_VALUE_WITNESSES 1
/// WANT_REQUIRED_VALUE_WITNESSES
-/// WANT_EXTRA_INHABITANT_VALUE_WITNESSES
/// WANT_ENUM_VALUE_WITNESSES
/// Define all of these to control exactly what to expand.
#else
-#if !defined(WANT_REQUIRED_VALUE_WITNESSES) || !defined(WANT_EXTRA_INHABITANT_VALUE_WITNESSES) || !defined(WANT_ENUM_VALUE_WITNESSES)
+#if !defined(WANT_REQUIRED_VALUE_WITNESSES) || !defined(WANT_ENUM_VALUE_WITNESSES)
#error failed to define a WANT macro; possible typo?
#endif
#endif
@@ -206,7 +194,16 @@
BEGIN_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
Size)
-/// SIZE_TYPE flags;
+/// SIZE_TYPE stride;
+///
+/// The required size per element of an array of this type. It is at least
+/// one, even for zero-sized types, like the empty tuple.
+DATA_VALUE_WITNESS(stride,
+ Stride,
+ SIZE_TYPE)
+
+
+/// UINT_TYPE flags;
///
/// The ValueWitnessAlignmentMask bits represent the required
/// alignment of the first byte of an object of this type, expressed
@@ -222,10 +219,9 @@
/// The ValueWitnessIsNonInline bit is set if the type cannot be
/// represented in a fixed-size buffer or if it is not bitwise takable.
///
-/// The Enum_HasExtraInhabitants bit is set if the type's binary
-/// representation has "extra inhabitants" that do not form valid values of
-/// the type, and the value witness table contains the ExtraInhabitantWitness
-/// entries.
+/// The ExtraInhabitantsMask bits represent the number of "extra inhabitants"
+/// of the bit representation of the value that do not form valid values of
+/// the type.
///
/// The Enum_HasSpareBits bit is set if the type's binary representation
/// has unused bits.
@@ -233,86 +229,25 @@
/// The HasEnumWitnesses bit is set if the type is an enum type.
DATA_VALUE_WITNESS(flags,
Flags,
- SIZE_TYPE)
+ UINT_TYPE)
-/// SIZE_TYPE stride;
+/// UINT_TYPE extraInhabitantCount;
///
-/// The required size per element of an array of this type. It is at least
-/// one, even for zero-sized types, like the empty tuple.
-DATA_VALUE_WITNESS(stride,
- Stride,
- SIZE_TYPE)
+/// The number of extra inhabitants in the type.
+DATA_VALUE_WITNESS(extraInhabitantCount,
+ ExtraInhabitantCount,
+ UINT_TYPE)
END_VALUE_WITNESS_RANGE(RequiredTypeLayoutWitness,
- Stride)
+ ExtraInhabitantCount)
END_VALUE_WITNESS_RANGE(RequiredValueWitness,
- Stride)
-
-#endif /* WANT_REQUIRED_VALUE_WITNESSES */
-
-#if WANT_EXTRA_INHABITANT_VALUE_WITNESSES
-
-// The following value witnesses are conditionally present based on
-// the Enum_HasExtraInhabitants bit of the flags.
-
-/// SIZE_TYPE extraInhabitantFlags;
-///
-/// These bits are always present if the extra inhabitants witnesses are:
-///
-/// - The NumExtraInhabitantsMask bits contain the number of extra
-/// inhabitants of the type representation.
-///
-/// If the Enum_HasSpareBits flag is set in the value witness flags, these
-/// additional flags are available:
-///
-/// - The NumSpareBitsMask bits contain the number of (host-endian) contiguous
-/// spare bits in the type representation.
-/// - The SpareBitsShiftMask bits contain the (host-endian) bit offset of the
-/// lowest spare bit.
-DATA_VALUE_WITNESS(extraInhabitantFlags,
- ExtraInhabitantFlags,
- SIZE_TYPE)
-
-BEGIN_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitness,
- ExtraInhabitantFlags)
+ ExtraInhabitantCount)
END_VALUE_WITNESS_RANGE(TypeLayoutWitness,
- ExtraInhabitantFlags)
+ ExtraInhabitantCount)
-/// void (*storeExtraInhabitant)(T *obj, int index, M *self);
-///
-/// Given an invalid object of this type, store the representation of an
-/// extra inhabitant of the type. The object will remain invalid, because
-/// an extra inhabitant is by definition an invalid representation of the
-/// type. index must be less than numExtraInhabitants.
-FUNCTION_VALUE_WITNESS(storeExtraInhabitant,
- StoreExtraInhabitant,
- VOID_TYPE,
- (MUTABLE_VALUE_TYPE, INT_TYPE, TYPE_TYPE))
-
-BEGIN_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitnessFunction,
- StoreExtraInhabitant)
-
-/// int (*getExtraInhabitantIndex)(T *obj, M *self);
-///
-/// Given an invalid object of this type with an extra inhabitant
-/// representation, returns the index of the extra inhabitant representation.
-/// Returns -1 if the object is a valid value of the type. If non-negative,
-/// the return value is the same index that can be passed to
-/// storeExtraInhabitant to reproduce the representation.
-FUNCTION_VALUE_WITNESS(getExtraInhabitantIndex,
- GetExtraInhabitantIndex,
- INT_TYPE,
- (IMMUTABLE_VALUE_TYPE, TYPE_TYPE))
-
-END_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitnessFunction,
- GetExtraInhabitantIndex)
-
-END_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitness,
- GetExtraInhabitantIndex)
-
-#endif /* WANT_EXTRA_INHABITANT_VALUE_WITNESSES */
+#endif /* WANT_REQUIRED_VALUE_WITNESSES */
#if WANT_ENUM_VALUE_WITNESSES
@@ -372,9 +307,7 @@
#undef FUNCTION_VALUE_WITNESS
#undef VALUE_WITNESS
#undef ENUM_VALUE_WITNESS
-#undef EXTRA_INHABITANT_VALUE_WITNESS
#undef NON_REQUIRED_VALUE_WITNESS
#undef REQUIRED_VALUE_WITNESS
#undef WANT_ENUM_VALUE_WITNESSES
-#undef WANT_EXTRA_INHABITANT_VALUE_WITNESSES
#undef WANT_REQUIRED_VALUE_WITNESSES
diff --git a/include/swift/Runtime/Enum.h b/include/swift/Runtime/Enum.h
index aba2436..2d0d2c9 100644
--- a/include/swift/Runtime/Enum.h
+++ b/include/swift/Runtime/Enum.h
@@ -58,37 +58,50 @@
const TypeLayout *payload,
unsigned emptyCases);
-/// \brief Faster variant of the above which avoids digging into the enum type
-/// metadata when the caller already has the payload information handy.
+using getExtraInhabitantTag_t =
+ SWIFT_CC(swift) unsigned (const OpaqueValue *vaue,
+ unsigned numExtraInhabitants,
+ const Metadata *payloadType);
+
+/// Implement getEnumTagSinglePayload generically in terms of a
+/// payload type with a getExtraInhabitantIndex function.
///
/// \param value - pointer to the enum value.
-/// \param payload - type metadata for the payload case of the enum.
+/// \param payloadType - type metadata for the payload case of the enum.
/// \param emptyCases - the number of empty cases in the enum.
///
/// \returns 0 if the payload case is inhabited. If an empty case is inhabited,
/// returns a value greater than or equal to one and less than or equal
/// emptyCases.
-SWIFT_RUNTIME_EXPORT
-unsigned swift_getEnumCaseSinglePayload(const OpaqueValue *value,
- const Metadata *payload,
- unsigned emptyCases);
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+unsigned swift_getEnumTagSinglePayloadGeneric(const OpaqueValue *value,
+ unsigned emptyCases,
+ const Metadata *payloadType,
+ getExtraInhabitantTag_t *getTag);
-/// \brief Store the tag value for the given case into a single-payload enum,
-/// whose associated payload (if any) has already been initialized.
+using storeExtraInhabitantTag_t =
+ SWIFT_CC(swift) void (OpaqueValue *value,
+ unsigned whichCase,
+ unsigned numExtraInhabitants,
+ const Metadata *payloadType);
+
+/// Implement storeEnumTagSinglePayload generically in terms of a
+/// payload type with a storeExtraInhabitant function.
///
/// \param value - pointer to the enum value. If the case being initialized is
/// the payload case (0), then the payload should be
/// initialized.
-/// \param payload - type metadata for the payload case of the enum.
+/// \param payloadType - type metadata for the payload case of the enum.
/// \param whichCase - unique value identifying the case. 0 for the payload
/// case, or a value greater than or equal to one and less
/// than or equal emptyCases for an empty case.
/// \param emptyCases - the number of empty cases in the enum.
-SWIFT_RUNTIME_EXPORT
-void swift_storeEnumTagSinglePayload(OpaqueValue *value,
- const Metadata *payload,
- unsigned whichCase,
- unsigned emptyCases);
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+void swift_storeEnumTagSinglePayloadGeneric(OpaqueValue *value,
+ unsigned whichCase,
+ unsigned emptyCases,
+ const Metadata *payloadType,
+ storeExtraInhabitantTag_t *storeTag);
/// \brief Initialize the type metadata for a generic, multi-payload
/// enum instance.
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 0aec2af..265b3bb 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -90,56 +90,26 @@
OpaqueValue *src,
const Metadata *self);
-/// A value-witness table with extra inhabitants entry points.
-/// These entry points are available only if the HasExtraInhabitants flag bit is
-/// set in the 'flags' field.
-struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
-#define WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
- ValueWitnessTypes::LOWER_ID LOWER_ID;
-#include "swift/ABI/ValueWitness.def"
-
-#define SET_WITNESS(NAME) base.NAME,
-
- constexpr ExtraInhabitantsValueWitnessTable()
- : ValueWitnessTable{}, extraInhabitantFlags(),
- storeExtraInhabitant(nullptr),
- getExtraInhabitantIndex(nullptr) {}
- constexpr ExtraInhabitantsValueWitnessTable(
- const ValueWitnessTable &base,
- ValueWitnessTypes::extraInhabitantFlags eif,
- ValueWitnessTypes::storeExtraInhabitant sei,
- ValueWitnessTypes::getExtraInhabitantIndex geii)
- : ValueWitnessTable(base),
- extraInhabitantFlags(eif),
- storeExtraInhabitant(sei),
- getExtraInhabitantIndex(geii) {}
-
- static bool classof(const ValueWitnessTable *table) {
- return table->flags.hasExtraInhabitants();
- }
-};
-
/// A value-witness table with enum entry points.
/// These entry points are available only if the HasEnumWitnesses flag bit is
/// set in the 'flags' field.
-struct EnumValueWitnessTable : ExtraInhabitantsValueWitnessTable {
+struct EnumValueWitnessTable : ValueWitnessTable {
#define WANT_ONLY_ENUM_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
ValueWitnessTypes::LOWER_ID LOWER_ID;
#include "swift/ABI/ValueWitness.def"
constexpr EnumValueWitnessTable()
- : ExtraInhabitantsValueWitnessTable(),
+ : ValueWitnessTable{},
getEnumTag(nullptr),
destructiveProjectEnumData(nullptr),
destructiveInjectEnumTag(nullptr) {}
constexpr EnumValueWitnessTable(
- const ExtraInhabitantsValueWitnessTable &base,
+ const ValueWitnessTable &base,
ValueWitnessTypes::getEnumTag getEnumTag,
ValueWitnessTypes::destructiveProjectEnumData destructiveProjectEnumData,
ValueWitnessTypes::destructiveInjectEnumTag destructiveInjectEnumTag)
- : ExtraInhabitantsValueWitnessTable(base),
+ : ValueWitnessTable(base),
getEnumTag(getEnumTag),
destructiveProjectEnumData(destructiveProjectEnumData),
destructiveInjectEnumTag(destructiveInjectEnumTag) {}
@@ -155,47 +125,44 @@
/// extra inhabitants, and miscellaneous flags about the type.
struct TypeLayout {
ValueWitnessTypes::size size;
- ValueWitnessTypes::flags flags;
ValueWitnessTypes::stride stride;
+ ValueWitnessTypes::flags flags;
+ ValueWitnessTypes::extraInhabitantCount extraInhabitantCount;
private:
- // Only available if the "hasExtraInhabitants" flag is set.
- ValueWitnessTypes::extraInhabitantFlags extraInhabitantFlags;
-
void _static_assert_layout();
public:
TypeLayout() = default;
constexpr TypeLayout(ValueWitnessTypes::size size,
- ValueWitnessTypes::flags flags,
ValueWitnessTypes::stride stride,
- ValueWitnessTypes::extraInhabitantFlags eiFlags =
- ValueWitnessTypes::extraInhabitantFlags())
- : size(size), flags(flags), stride(stride),
- extraInhabitantFlags(eiFlags) {}
-
- ValueWitnessTypes::extraInhabitantFlags getExtraInhabitantFlags() const {
- assert(flags.hasExtraInhabitants());
- return extraInhabitantFlags;
- }
+ ValueWitnessTypes::flags flags,
+ ValueWitnessTypes::extraInhabitantCount xiCount)
+ : size(size), stride(stride), flags(flags), extraInhabitantCount(xiCount) {}
const TypeLayout *getTypeLayout() const { return this; }
/// The number of extra inhabitants, that is, bit patterns that do not form
/// valid values of the type, in this type's binary representation.
- unsigned getNumExtraInhabitants() const;
+ unsigned getNumExtraInhabitants() const {
+ return extraInhabitantCount;
+ }
+
+ bool hasExtraInhabitants() const {
+ return extraInhabitantCount != 0;
+ }
};
inline void TypeLayout::_static_assert_layout() {
#define CHECK_TYPE_LAYOUT_OFFSET(FIELD) \
- static_assert(offsetof(ExtraInhabitantsValueWitnessTable, FIELD) \
- - offsetof(ExtraInhabitantsValueWitnessTable, size) \
+ static_assert(offsetof(ValueWitnessTable, FIELD) \
+ - offsetof(ValueWitnessTable, size) \
== offsetof(TypeLayout, FIELD), \
"layout of " #FIELD " in TypeLayout doesn't match " \
"value witness table")
CHECK_TYPE_LAYOUT_OFFSET(size);
CHECK_TYPE_LAYOUT_OFFSET(flags);
+ CHECK_TYPE_LAYOUT_OFFSET(extraInhabitantCount);
CHECK_TYPE_LAYOUT_OFFSET(stride);
- CHECK_TYPE_LAYOUT_OFFSET(extraInhabitantFlags);
#undef CHECK_TYPE_LAYOUT_OFFSET
}
@@ -204,6 +171,7 @@
inline void ValueWitnessTable::publishLayout(const TypeLayout &layout) {
size = layout.size;
stride = layout.stride;
+ extraInhabitantCount = layout.extraInhabitantCount;
// Currently there is nothing in the runtime or ABI which tries to
// asynchronously check completion, so we can just do a normal store here.
@@ -221,53 +189,32 @@
}
template <>
-inline const ExtraInhabitantsValueWitnessTable *
-ValueWitnessTable::_asXIVWT() const {
- assert(ExtraInhabitantsValueWitnessTable::classof(this));
- return static_cast<const ExtraInhabitantsValueWitnessTable *>(this);
-}
-
-template <>
inline const EnumValueWitnessTable *ValueWitnessTable::_asEVWT() const {
assert(EnumValueWitnessTable::classof(this));
return static_cast<const EnumValueWitnessTable *>(this);
}
-template <> inline unsigned ValueWitnessTable::getNumExtraInhabitants() const {
- // If the table does not have extra inhabitant witnesses, then there are zero.
- if (!flags.hasExtraInhabitants())
- return 0;
- return this->_asXIVWT()->extraInhabitantFlags.getNumExtraInhabitants();
-}
-
-inline unsigned TypeLayout::getNumExtraInhabitants() const {
- // If the table does not have extra inhabitant witnesses, then there are zero.
- if (!flags.hasExtraInhabitants())
- return 0;
- return extraInhabitantFlags.getNumExtraInhabitants();
-}
-
// Standard value-witness tables.
#define BUILTIN_TYPE(Symbol, _) \
SWIFT_RUNTIME_EXPORT const ValueWitnessTable VALUE_WITNESS_SYM(Symbol);
#define BUILTIN_POINTER_TYPE(Symbol, _) \
- SWIFT_RUNTIME_EXPORT const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(Symbol);
+ SWIFT_RUNTIME_EXPORT const ValueWitnessTable VALUE_WITNESS_SYM(Symbol);
#include "swift/Runtime/BuiltinTypes.def"
// The () -> () table can be used for arbitrary function types.
SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
VALUE_WITNESS_SYM(FUNCTION_MANGLING); // () -> ()
// The @escaping () -> () table can be used for arbitrary escaping function types.
SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING); // @noescape () -> ()
// The @convention(thin) () -> () table can be used for arbitrary thin function types.
SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
VALUE_WITNESS_SYM(THIN_FUNCTION_MANGLING); // @convention(thin) () -> ()
// The () table can be used for arbitrary empty types.
@@ -276,7 +223,7 @@
// The table for aligned-pointer-to-pointer types.
SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable METATYPE_VALUE_WITNESS_SYM(Bo); // Builtin.NativeObject.Type
+const ValueWitnessTable METATYPE_VALUE_WITNESS_SYM(Bo); // Builtin.NativeObject.Type
/// Return the value witnesses for unmanaged pointers.
static inline const ValueWitnessTable &getUnmanagedPointerValueWitnesses() {
@@ -289,7 +236,7 @@
/// Return value witnesses for a pointer-aligned pointer type.
static inline
-const ExtraInhabitantsValueWitnessTable &
+const ValueWitnessTable &
getUnmanagedPointerPointerValueWitnesses() {
return METATYPE_VALUE_WITNESS_SYM(Bo);
}
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 4723fe5..cb6a0d2 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -863,15 +863,6 @@
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo(0)),
ATTRS(NoUnwind))
-// int swift_getEnumCaseSinglePayload(opaque_t *obj, Metadata *payload,
-// unsigned num_empty_cases);
-FUNCTION(GetEnumCaseSinglePayload,
- swift_getEnumCaseSinglePayload,
- C_CC,
- RETURNS(Int32Ty),
- ARGS(OpaquePtrTy, TypeMetadataPtrTy, Int32Ty),
- ATTRS(NoUnwind, ReadOnly))
-
// int swift_getEnumCaseMultiPayload(opaque_t *obj, Metadata *enumTy);
FUNCTION(GetEnumCaseMultiPayload,
swift_getEnumCaseMultiPayload,
@@ -880,14 +871,39 @@
ARGS(OpaquePtrTy, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadOnly))
-// void swift_storeEnumTagSinglePayload(opaque_t *obj, Metadata *payload,
-// unsigned case_index,
-// unsigned num_empty_cases);
-FUNCTION(StoreEnumTagSinglePayload,
- swift_storeEnumTagSinglePayload,
- C_CC,
+// int swift_getEnumTagSinglePayloadGeneric(opaque_t *obj,
+// unsigned num_empty_cases,
+// Metadata *payloadType,
+// int (*getExtraInhabitantIndex)(opaque_t *obj,
+// unsigned numPayloadXI,
+// Metadata *payload));
+FUNCTION(GetEnumTagSinglePayloadGeneric,
+ swift_getEnumTagSinglePayloadGeneric,
+ SwiftCC,
+ RETURNS(Int32Ty),
+ ARGS(OpaquePtrTy, Int32Ty, TypeMetadataPtrTy,
+ llvm::FunctionType::get(Int32Ty, {OpaquePtrTy, Int32Ty,
+ TypeMetadataPtrTy},
+ false)->getPointerTo()),
+ ATTRS(NoUnwind, ReadOnly))
+
+
+// void swift_storeEnumTagSinglePayloadGeneric(opaque_t *obj,
+// unsigned case_index,
+// unsigned num_empty_cases,
+// Metadata *payloadType,
+// void (*storeExtraInhabitant)(opaque_t *obj,
+// unsigned case_index,
+// unsigned numPayloadXI,
+// Metadata *payload));
+FUNCTION(StoreEnumTagSinglePayloadGeneric,
+ swift_storeEnumTagSinglePayloadGeneric,
+ SwiftCC,
RETURNS(VoidTy),
- ARGS(OpaquePtrTy, TypeMetadataPtrTy, Int32Ty, Int32Ty),
+ ARGS(OpaquePtrTy, Int32Ty, Int32Ty, TypeMetadataPtrTy,
+ llvm::FunctionType::get(VoidTy, {OpaquePtrTy, Int32Ty, Int32Ty,
+ TypeMetadataPtrTy},
+ false)->getPointerTo()),
ATTRS(NoUnwind))
// void swift_storeEnumTagMultiPayload(opaque_t *obj, Metadata *enumTy,
diff --git a/lib/IRGen/ExtraInhabitants.cpp b/lib/IRGen/ExtraInhabitants.cpp
index 7805656..1bd0564 100644
--- a/lib/IRGen/ExtraInhabitants.cpp
+++ b/lib/IRGen/ExtraInhabitants.cpp
@@ -19,6 +19,7 @@
#include "IRGenModule.h"
#include "IRGenFunction.h"
#include "SwiftTargetInfo.h"
+#include "swift/ABI/MetadataValues.h"
using namespace swift;
using namespace irgen;
@@ -44,8 +45,9 @@
uint64_t rawCount =
IGM.TargetInfo.LeastValidPointerValue >> numReservedLowBits;
- // The runtime limits the count to INT_MAX.
- return std::min((uint64_t)INT_MAX, rawCount);
+ // The runtime limits the count.
+ return std::min(uint64_t(ValueWitnessFlags::MaxNumExtraInhabitants),
+ rawCount);
}
unsigned irgen::getHeapObjectExtraInhabitantCount(const IRGenModule &IGM) {
diff --git a/lib/IRGen/FixedTypeInfo.h b/lib/IRGen/FixedTypeInfo.h
index 97981f2..2834622 100644
--- a/lib/IRGen/FixedTypeInfo.h
+++ b/lib/IRGen/FixedTypeInfo.h
@@ -167,9 +167,9 @@
/// Map an extra inhabitant representation in memory to a unique 31-bit
/// identifier, and map a valid representation of the type to -1.
- llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address src, SILType T,
- bool isOutlined) const override {
+ virtual llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
+ Address src, SILType T,
+ bool isOutlined) const {
return getSpareBitExtraInhabitantIndex(IGF, src);
}
@@ -180,10 +180,10 @@
/// Store the extra inhabitant representation indexed by a 31-bit identifier
/// to memory.
- void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address dest, SILType T,
- bool isOutlined) const override {
+ virtual void storeExtraInhabitant(IRGenFunction &IGF,
+ llvm::Value *index,
+ Address dest, SILType T,
+ bool isOutlined) const {
storeSpareBitExtraInhabitant(IGF, index, dest);
}
@@ -236,16 +236,30 @@
llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const override;
+ SILType T,
+ bool isOutlined) const override;
void storeEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address enumAddr,
- SILType T) const override;
+ SILType T, bool isOutlined) const override;
static bool classof(const FixedTypeInfo *type) { return true; }
static bool classof(const TypeInfo *type) { return type->isFixedSize(); }
};
+llvm::Value *getFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
+ const FixedTypeInfo &fixedTI,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T, bool isOutlined);
+
+void storeFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
+ const FixedTypeInfo &fixedTI,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T, bool isOutlined);
+
}
}
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index c1caaff..72c78a0 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -649,7 +649,7 @@
return llvm::ConstantInt::getSigned(IGF.IGM.Int32Ty, -1);
}
- return getSingleton()->getExtraInhabitantIndex(IGF,
+ return getFixedSingleton()->getExtraInhabitantIndex(IGF,
getSingletonAddress(IGF, src),
getSingletonType(IGF.IGM, T),
isOutlined);
@@ -663,10 +663,44 @@
// Nothing to store for empty singletons.
return;
}
- getSingleton()->storeExtraInhabitant(IGF, index,
- getSingletonAddress(IGF, dest),
- getSingletonType(IGF.IGM, T),
+ getFixedSingleton()->storeExtraInhabitant(IGF, index,
+ getSingletonAddress(IGF, dest),
+ getSingletonType(IGF.IGM, T),
+ isOutlined);
+ }
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ if (!getSingleton()) {
+ return getFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ numEmptyCases, src, T,
+ isOutlined);
+ }
+
+ return getSingleton()->getEnumTagSinglePayload(IGF, numEmptyCases,
+ getSingletonAddress(IGF, src),
+ getSingletonType(IGF.IGM, T),
+ isOutlined);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ if (!getSingleton()) {
+ storeFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ index, numEmptyCases, src, T,
isOutlined);
+ return;
+ }
+
+ getSingleton()->storeEnumTagSinglePayload(IGF, index, numEmptyCases,
+ getSingletonAddress(IGF, src),
+ getSingletonType(IGF.IGM, T),
+ isOutlined);
}
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
@@ -1007,7 +1041,9 @@
assert(bits < 32 && "freakishly huge no-payload enum");
size_t shifted = static_cast<size_t>(static_cast<size_t>(1) << bits);
- return shifted - ElementsWithNoPayload.size();
+ size_t rawCount = shifted - ElementsWithNoPayload.size();
+ return std::min(rawCount,
+ size_t(ValueWitnessFlags::MaxNumExtraInhabitants));
}
APInt getFixedExtraInhabitantValue(IRGenModule &IGM,
@@ -1061,6 +1097,25 @@
llvm::ConstantInt::get(payloadTy, ElementsWithNoPayload.size()));
IGF.Builder.CreateStore(index, dest);
}
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ return getFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ numEmptyCases, src, T,
+ isOutlined);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ storeFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ index, numEmptyCases, src, T,
+ isOutlined);
+ }
};
/// Implementation strategy for C-compatible enums, where none of the cases
@@ -1137,6 +1192,25 @@
llvm_unreachable("no extra inhabitants");
}
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ return getFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ numEmptyCases, src, T,
+ isOutlined);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ storeFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ index, numEmptyCases, src, T,
+ isOutlined);
+ }
+
bool isReflectable() const override {
// C enums have arbitrary values and we don't preserve the mapping
// between the case and raw value at runtime, so don't mark it as
@@ -2927,10 +3001,17 @@
bool isOutlined) const override {
auto payload = projectPayloadData(IGF, src);
llvm::Value *index
- = getPayloadTypeInfo().getExtraInhabitantIndex(IGF, payload,
+ = getFixedPayloadTypeInfo().getExtraInhabitantIndex(IGF, payload,
getPayloadType(IGF.IGM, T),
isOutlined);
+ return adjustPayloadExtraInhabitantIndex(IGF, index);
+ }
+
+ /// Given an extra inhabitant index for the payload type, adjust it to
+ /// be an appropriate extra inhabitant index for the enum type.
+ llvm::Value *adjustPayloadExtraInhabitantIndex(IRGenFunction &IGF,
+ llvm::Value *index) const {
// Offset the payload extra inhabitant index by the number of inhabitants
// we used. If less than zero, it's a valid value of the enum type.
index = IGF.Builder.CreateSub(index,
@@ -2947,16 +3028,147 @@
llvm::Value *index,
Address dest, SILType T,
bool isOutlined) const override {
- // Offset the index to skip the extra inhabitants we used.
- index = IGF.Builder.CreateAdd(index,
- llvm::ConstantInt::get(IGF.IGM.Int32Ty, ElementsWithNoPayload.size()));
-
+ index = adjustExtraInhabitantIndexForPayload(IGF, index);
auto payload = projectPayloadData(IGF, dest);
- getPayloadTypeInfo().storeExtraInhabitant(IGF, index, payload,
+ getFixedPayloadTypeInfo().storeExtraInhabitant(IGF, index, payload,
getPayloadType(IGF.IGM, T),
isOutlined);
}
-
+
+ /// Given an extra inhabitant index, adjust it to be an appropriate
+ /// extra inhabitant index for the payload type.
+ llvm::Value *adjustExtraInhabitantIndexForPayload(IRGenFunction &IGF,
+ llvm::Value *index) const{
+ // Skip the extra inhabitants this enum uses.
+ index = IGF.Builder.CreateAdd(index,
+ llvm::ConstantInt::get(IGF.IGM.Int32Ty, ElementsWithNoPayload.size()));
+ return index;
+ }
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address addr, SILType T,
+ bool isOutlined) const override {
+ if (TIK >= Fixed) {
+ return getFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ numEmptyCases, addr, T,
+ isOutlined);
+ }
+
+ // If we're not emitting an outlined copy, just call the value witness.
+ if (!isOutlined) {
+ return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, addr);
+ }
+
+ // Otherwise, fall back on a generic implementation.
+ // TODO: consider inlining some of this so that we don't have to
+ // bounce into the runtime when e.g. dynamically working with
+ // double-optionals.
+ return emitGetEnumTagSinglePayloadGenericCall(IGF, T, *TI, numEmptyCases,
+ addr,
+ [this, T](IRGenFunction &IGF, Address addr,
+ llvm::Value *numXI) -> llvm::Value* {
+ auto payloadType = getPayloadType(IGF.IGM, T);
+ auto payloadAddr = projectPayloadData(IGF, addr);
+
+ // For the case count, we just use the XI count from the payload type.
+ auto payloadNumExtraCases = numXI;
+
+ llvm::Value *tag
+ = getPayloadTypeInfo().getEnumTagSinglePayload(IGF,
+ payloadNumExtraCases,
+ payloadAddr,
+ payloadType,
+ /*outlined*/ false);
+
+ // We need to adjust that for the number of cases we're using
+ // in this enum.
+ return adjustPayloadExtraInhabitantTag(IGF, tag);
+ });
+ }
+
+ /// Given an extra inhabitant tag for the payload type, adjust it to
+ /// be an appropriate extra inhabitant tag for the enum type.
+ llvm::Value *adjustPayloadExtraInhabitantTag(IRGenFunction &IGF,
+ llvm::Value *tag) const {
+ auto numExtraCases = IGF.IGM.getInt32(ElementsWithNoPayload.size());
+
+ // Adjust the tag.
+ llvm::Value *adjustedTag = IGF.Builder.CreateSub(tag, numExtraCases);
+
+ // If tag <= numExtraCases, then this is a valid value of the enum type,
+ // and the proper tag to return is 0.
+ auto isEnumValue = IGF.Builder.CreateICmpULE(tag, numExtraCases);
+ adjustedTag = IGF.Builder.CreateSelect(isEnumValue,
+ IGF.IGM.getInt32(0),
+ adjustedTag);
+ return adjustedTag;
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *tag,
+ llvm::Value *numEmptyCases,
+ Address dest, SILType T,
+ bool isOutlined) const override {
+ if (TIK >= Fixed) {
+ storeFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ tag, numEmptyCases, dest, T,
+ isOutlined);
+ return;
+ }
+
+ // If we're not emitting an outlined copy, just call the value witness.
+ if (!isOutlined) {
+ emitStoreEnumTagSinglePayloadCall(IGF, T, tag, numEmptyCases, dest);
+ return;
+ }
+
+ // Otherwise, fall back on a generic implementation.
+ // TODO: consider inlining some of this so that we don't have to
+ // bounce into the runtime when e.g. dynamically working with
+ // double-optionals.
+ emitStoreEnumTagSinglePayloadGenericCall(IGF, T, *TI, tag,
+ numEmptyCases, dest,
+ [this, T](IRGenFunction &IGF, Address dest, llvm::Value *tag,
+ llvm::Value *payloadNumXI) {
+ auto payloadType = getPayloadType(IGF.IGM, T);
+ auto payloadDest = projectPayloadData(IGF, dest);
+ auto payloadTag = adjustExtraInhabitantTagForPayload(IGF, tag,
+ /*nonzero*/false);
+
+ getPayloadTypeInfo().storeEnumTagSinglePayload(IGF, payloadTag,
+ payloadNumXI,
+ payloadDest,
+ payloadType,
+ /*outlined*/ false);
+ });
+ }
+
+ /// Given an extra inhabitant tag for the payload type, which is known
+ /// not to be 0, adjust it to be an appropriate extra inhabitant tag
+ /// for the enum type.
+ llvm::Value *adjustExtraInhabitantTagForPayload(IRGenFunction &IGF,
+ llvm::Value *tag,
+ bool isKnownNonZero) const {
+ auto numExtraCases = IGF.IGM.getInt32(ElementsWithNoPayload.size());
+
+ // Adjust the tag.
+ llvm::Value *adjustedTag = IGF.Builder.CreateAdd(tag, numExtraCases);
+
+ // Preserve the zero tag so that we don't pass down a meaningless XI
+ // value that the payload will waste time installing before we
+ // immediately overwrite it.
+ if (!isKnownNonZero) {
+ // If tag <= numExtraCases, then this is a valid value of the enum type,
+ // and the proper tag to return is 0.
+ auto isEnumValue = IGF.Builder.CreateIsNull(tag);
+ adjustedTag = IGF.Builder.CreateSelect(isEnumValue,
+ IGF.IGM.getInt32(0),
+ adjustedTag);
+ }
+ return adjustedTag;
+ }
+
APInt
getFixedExtraInhabitantMask(IRGenModule &IGM) const override {
auto &payloadTI = getFixedPayloadTypeInfo();
@@ -4874,11 +5086,15 @@
Address src,
SILType T,
bool isOutlined) const override {
- // For dynamic layouts, the runtime provides a value witness to do this.
- if (TIK < Fixed) {
- return emitGetExtraInhabitantIndexCall(IGF, T, src);
- }
-
+ assert(TIK >= Fixed);
+ return getExtraInhabitantIndexImpl(IGF, src, T, isOutlined,
+ getFixedExtraInhabitantCount(IGF.IGM));
+ }
+
+ llvm::Value *getExtraInhabitantIndexImpl(IRGenFunction &IGF,
+ Address src, SILType T,
+ bool isOutlined,
+ unsigned xiCount) const {
llvm::Value *tag;
if (CommonSpareBits.count()) {
auto payload = EnumPayload::load(IGF, projectPayload(IGF, src),
@@ -4932,8 +5148,7 @@
llvm::ConstantInt::get(IGF.IGM.Int32Ty, maxTag),
tag);
auto isExtraInhabitant = IGF.Builder.CreateICmpULT(index,
- llvm::ConstantInt::get(IGF.IGM.Int32Ty,
- getFixedExtraInhabitantCount(IGF.IGM)));
+ llvm::ConstantInt::get(IGF.IGM.Int32Ty, xiCount));
return IGF.Builder.CreateSelect(isExtraInhabitant,
index, llvm::ConstantInt::get(IGF.IGM.Int32Ty, -1));
}
@@ -4943,11 +5158,7 @@
Address dest,
SILType T,
bool isOutlined) const override {
- // For dynamic layouts, the runtime provides a value witness to do this.
- if (TIK < Fixed) {
- emitStoreExtraInhabitantCall(IGF, T, index, dest);
- return;
- }
+ assert(TIK >= Fixed);
auto indexValue = IGF.Builder.CreateNot(index);
@@ -4995,6 +5206,36 @@
IGF.Builder.CreateStore(indexValue, tagAddr);
}
}
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ if (TIK < Fixed) {
+ // For dynamic layouts, the runtime provides a value witness to do this.
+ return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, src);
+ }
+
+ return getFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ numEmptyCases, src, T,
+ isOutlined);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ if (TIK < Fixed) {
+ // For dynamic layouts, the runtime provides a value witness to do this.
+ emitStoreEnumTagSinglePayloadCall(IGF, T, index, numEmptyCases, src);
+ return;
+ }
+
+ storeFixedTypeEnumTagSinglePayload(IGF, cast<FixedTypeInfo>(*TI),
+ index, numEmptyCases, src, T,
+ isOutlined);
+ }
APInt
getFixedExtraInhabitantMask(IRGenModule &IGM) const override {
@@ -5014,9 +5255,12 @@
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
unsigned totalTagBits = CommonSpareBits.count() + getExtraTagBitCountForExtraInhabitants();
if (totalTagBits >= 32)
- return INT_MAX;
+ return ValueWitnessFlags::MaxNumExtraInhabitants;
unsigned totalTags = 1u << totalTagBits;
- return totalTags - ElementsWithPayload.size() - NumEmptyElementTags;
+ unsigned rawCount =
+ totalTags - ElementsWithPayload.size() - NumEmptyElementTags;
+ return std::min(rawCount,
+ unsigned(ValueWitnessFlags::MaxNumExtraInhabitants));
}
APInt
@@ -5433,7 +5677,7 @@
Address src,
SILType T,
bool isOutlined) const override {
- return emitGetExtraInhabitantIndexCall(IGF, T, src);
+ llvm_unreachable("resilient enums are never fixed-layout types");
}
void storeExtraInhabitant(IRGenFunction &IGF,
@@ -5441,7 +5685,22 @@
Address dest,
SILType T,
bool isOutlined) const override {
- emitStoreExtraInhabitantCall(IGF, T, index, dest);
+ llvm_unreachable("resilient enums are never fixed-layout types");
+ }
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, src);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address src, SILType T,
+ bool isOutlined) const override {
+ emitStoreEnumTagSinglePayloadCall(IGF, T, index, numEmptyCases, src);
}
APInt
@@ -5663,18 +5922,22 @@
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
return Strategy.mayHaveExtraInhabitants(IGM);
}
- llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address src,
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
SILType T,
bool isOutlined) const override {
- return Strategy.getExtraInhabitantIndex(IGF, src, T, isOutlined);
+ return Strategy.getEnumTagSinglePayload(IGF, numEmptyCases, enumAddr, T,
+ isOutlined);
}
- void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address dest,
- SILType T,
- bool isOutlined) const override {
- return Strategy.storeExtraInhabitant(IGF, index, dest, T, isOutlined);
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *whichCase,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T,
+ bool isOutlined) const override {
+ return Strategy.storeEnumTagSinglePayload(IGF, whichCase, numEmptyCases,
+ enumAddr, T, isOutlined);
}
bool isSingleRetainablePointer(ResilienceExpansion expansion,
ReferenceCounting *rc) const override {
@@ -5682,15 +5945,13 @@
}
};
- /// TypeInfo for fixed-layout, address-only enum types.
- class FixedEnumTypeInfo : public EnumTypeInfoBase<FixedTypeInfo> {
+ template <class Base>
+ class FixedEnumTypeInfoBase : public EnumTypeInfoBase<Base> {
+ protected:
+ using EnumTypeInfoBase<Base>::EnumTypeInfoBase;
+
public:
- FixedEnumTypeInfo(EnumImplStrategy &strategy,
- llvm::StructType *T, Size S, SpareBitVector SB,
- Alignment A, IsPOD_t isPOD, IsBitwiseTakable_t isBT,
- IsFixedSize_t alwaysFixedSize)
- : EnumTypeInfoBase(strategy, T, S, std::move(SB), A, isPOD, isBT,
- alwaysFixedSize) {}
+ using EnumTypeInfoBase<Base>::Strategy;
/// \group Methods delegated to the EnumImplStrategy
@@ -5708,18 +5969,43 @@
APInt getFixedExtraInhabitantMask(IRGenModule &IGM) const override {
return Strategy.getFixedExtraInhabitantMask(IGM);
}
+
+ llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
+ Address src,
+ SILType T,
+ bool isOutlined) const override {
+ return Strategy.getExtraInhabitantIndex(IGF, src, T, isOutlined);
+ }
+ void storeExtraInhabitant(IRGenFunction &IGF,
+ llvm::Value *index,
+ Address dest,
+ SILType T,
+ bool isOutlined) const override {
+ return Strategy.storeExtraInhabitant(IGF, index, dest, T, isOutlined);
+ }
+ };
+
+ /// TypeInfo for fixed-layout but address-only enum types.
+ class FixedEnumTypeInfo : public FixedEnumTypeInfoBase<FixedTypeInfo> {
+ public:
+ FixedEnumTypeInfo(EnumImplStrategy &strategy,
+ llvm::StructType *T, Size S, SpareBitVector SB,
+ Alignment A, IsPOD_t isPOD, IsBitwiseTakable_t isBT,
+ IsFixedSize_t alwaysFixedSize)
+ : FixedEnumTypeInfoBase(strategy, T, S, std::move(SB), A, isPOD, isBT,
+ alwaysFixedSize) {}
};
/// TypeInfo for loadable enum types.
- class LoadableEnumTypeInfo : public EnumTypeInfoBase<LoadableTypeInfo> {
+ class LoadableEnumTypeInfo : public FixedEnumTypeInfoBase<LoadableTypeInfo> {
public:
// FIXME: Derive spare bits from element layout.
LoadableEnumTypeInfo(EnumImplStrategy &strategy,
llvm::StructType *T, Size S, SpareBitVector SB,
Alignment A, IsPOD_t isPOD,
IsFixedSize_t alwaysFixedSize)
- : EnumTypeInfoBase(strategy, T, S, std::move(SB), A, isPOD,
- alwaysFixedSize) {}
+ : FixedEnumTypeInfoBase(strategy, T, S, std::move(SB), A, isPOD,
+ alwaysFixedSize) {}
void addToAggLowering(IRGenModule &IGM, SwiftAggLowering &lowering,
Size offset) const override {
@@ -5772,20 +6058,6 @@
unsigned offset) const override {
return Strategy.unpackFromEnumPayload(IGF, payload, dest, offset);
}
- unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
- return Strategy.getFixedExtraInhabitantCount(IGM);
- }
-
- APInt getFixedExtraInhabitantValue(IRGenModule &IGM,
- unsigned bits,
- unsigned index)
- const override {
- return Strategy.getFixedExtraInhabitantValue(IGM, bits, index);
- }
-
- APInt getFixedExtraInhabitantMask(IRGenModule &IGM) const override {
- return Strategy.getFixedExtraInhabitantMask(IGM);
- }
LoadedRef loadRefcountedPtr(IRGenFunction &IGF,
SourceLoc loc, Address addr) const override {
return LoadedRef(Strategy.loadRefcountedPtr(IGF, loc, addr), false);
diff --git a/lib/IRGen/GenEnum.h b/lib/IRGen/GenEnum.h
index 50f56e0..d392f60 100644
--- a/lib/IRGen/GenEnum.h
+++ b/lib/IRGen/GenEnum.h
@@ -373,15 +373,28 @@
virtual bool mayHaveExtraInhabitants(IRGenModule &IGM) const = 0;
+ // Only ever called for fixed types.
virtual llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
Address src,
SILType T,
bool isOutlined) const = 0;
+ // Only ever called for fixed types.
virtual void storeExtraInhabitant(IRGenFunction &IGF,
llvm::Value *index,
Address dest,
SILType T,
bool isOutlined) const = 0;
+ virtual llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T,
+ bool isOutlined) const = 0;
+ virtual void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *whichCase,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T,
+ bool isOutlined) const = 0;
/// \group Delegated FixedTypeInfo operations
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index de170fa..c7cab4d 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -28,6 +28,7 @@
#include "swift/IRGen/ValueWitness.h"
#include "Callee.h"
+#include "Explosion.h"
#include "FixedTypeInfo.h"
#include "IRGenFunction.h"
#include "IRGenModule.h"
@@ -85,28 +86,6 @@
return llvm::FunctionType::get(ptrTy, args, /*isVarArg*/ false);
}
- /// void (*storeExtraInhabitant)(T *obj, unsigned index, M *self);
- case ValueWitness::StoreExtraInhabitant: {
- llvm::Type *ptrTy = IGM.OpaquePtrTy;
- llvm::Type *indexTy = IGM.Int32Ty;
- llvm::Type *metaTy = IGM.TypeMetadataPtrTy;
- llvm::Type *voidTy = IGM.VoidTy;
- llvm::Type *args[] = {ptrTy, indexTy, metaTy};
-
- return llvm::FunctionType::get(voidTy, args, /*isVarArg*/ false);
- }
-
- /// int (*getExtraInhabitantIndex)(T *obj, M *self);
- case ValueWitness::GetExtraInhabitantIndex: {
- llvm::Type *ptrTy = IGM.OpaquePtrTy;
- llvm::Type *metaTy = IGM.TypeMetadataPtrTy;
- llvm::Type *indexTy = IGM.Int32Ty;
-
- llvm::Type *args[] = {ptrTy, metaTy};
-
- return llvm::FunctionType::get(indexTy, args, /*isVarArg*/ false);
- }
-
/// unsigned (*getEnumTag)(T *obj, M *self);
case ValueWitness::GetEnumTag: {
llvm::Type *ptrTy = IGM.OpaquePtrTy;
@@ -166,11 +145,11 @@
}
case ValueWitness::Size:
- case ValueWitness::Flags:
case ValueWitness::Stride:
- case ValueWitness::ExtraInhabitantFlags:
- // Non-function witnesses all have type size_t.
return IGM.SizeTy;
+ case ValueWitness::Flags:
+ case ValueWitness::ExtraInhabitantCount:
+ return IGM.Int32Ty;
}
llvm_unreachable("bad value witness!");
@@ -196,8 +175,6 @@
case ValueWitness::DestructiveInjectEnumTag:
case ValueWitness::DestructiveProjectEnumData:
case ValueWitness::GetEnumTag:
- case ValueWitness::GetExtraInhabitantIndex:
- case ValueWitness::StoreExtraInhabitant:
case ValueWitness::StoreEnumTagSinglePayload:
return attrs.addAttribute(ctx, 1, llvm::Attribute::NoAlias);
@@ -217,8 +194,8 @@
case ValueWitness::Size:
case ValueWitness::Flags:
+ case ValueWitness::ExtraInhabitantCount:
case ValueWitness::Stride:
- case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("not a function value witness");
}
llvm_unreachable("bad witness");
@@ -260,14 +237,10 @@
return "size";
case ValueWitness::Flags:
return "flags";
+ case ValueWitness::ExtraInhabitantCount:
+ return "extraInhabitantCount";
case ValueWitness::Stride:
return "stride";
- case ValueWitness::StoreExtraInhabitant:
- return "storeExtraInhabitant";
- case ValueWitness::GetExtraInhabitantIndex:
- return "getExtraInhabitantIndex";
- case ValueWitness::ExtraInhabitantFlags:
- return "extraInhabitantFlags";
case ValueWitness::GetEnumTag:
return "getEnumTag";
case ValueWitness::DestructiveProjectEnumData:
@@ -282,6 +255,58 @@
llvm_unreachable("bad value witness index");
}
+static llvm::PointerType *
+getOrCreateValueWitnessTablePtrTy(IRGenModule &IGM, llvm::PointerType *&cache,
+ StringRef name, bool includeEnumWitnesses) {
+ if (cache) return cache;
+
+ SmallVector<llvm::Type*, 16> types;
+
+#define FUNC(lowerId, upperId, retTy, paramTys) \
+ types.push_back(IGM.Int8PtrTy);
+#define DATA(lowerId, upperId, ty) \
+ types.push_back(IGM.getValueWitnessTy(ValueWitness::upperId));
+
+ // Add the base value witnesses.
+#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
+#define FUNCTION_VALUE_WITNESS FUNC
+#define DATA_VALUE_WITNESS DATA
+#include "swift/ABI/ValueWitness.def"
+
+ // Add the enum value witnesses.
+ if (includeEnumWitnesses) {
+#define WANT_ONLY_ENUM_VALUE_WITNESSES
+#define FUNCTION_VALUE_WITNESS FUNC
+#define DATA_VALUE_WITNESS DATA
+#include "swift/ABI/ValueWitness.def"
+ }
+
+#undef DATA
+#undef FUNC
+
+ auto structTy = llvm::StructType::create(types, name);
+ auto ptrTy = structTy->getPointerTo();
+ cache = ptrTy;
+ return ptrTy;
+}
+
+llvm::StructType *IRGenModule::getValueWitnessTableTy() {
+ return cast<llvm::StructType>(getValueWitnessTablePtrTy()->getElementType());
+}
+llvm::PointerType *IRGenModule::getValueWitnessTablePtrTy() {
+ return getOrCreateValueWitnessTablePtrTy(*this, ValueWitnessTablePtrTy,
+ "swift.vwtable", false);
+}
+
+llvm::StructType *IRGenModule::getEnumValueWitnessTableTy() {
+ return cast<llvm::StructType>(getEnumValueWitnessTablePtrTy()
+ ->getElementType());
+}
+llvm::PointerType *IRGenModule::getEnumValueWitnessTablePtrTy() {
+ return getOrCreateValueWitnessTablePtrTy(*this, EnumValueWitnessTablePtrTy,
+ "swift.enum_vwtable", true);
+}
+
/// Load a specific witness from a known table. The result is
/// always an i8*.
llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF,
@@ -321,12 +346,31 @@
/// The result has the appropriate type for the witness.
static llvm::Value *emitLoadOfValueWitnessValue(IRGenFunction &IGF,
llvm::Value *table,
- ValueWitness index) {
- assert(!isValueWitnessFunction(index));
- llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index);
- auto label = getValueWitnessLabel(index);
- auto type = IGF.IGM.getValueWitnessTy(index);
- return IGF.Builder.CreatePtrToInt(witness, type, label);
+ ValueWitness witness) {
+ assert(!isValueWitnessFunction(witness));
+ assert(unsigned(witness) <= unsigned(ValueWitness::ExtraInhabitantCount) &&
+ "extraInhabitantCount not the last non-function value witness");
+
+ auto pointerSize = IGF.IGM.getPointerSize();
+
+ // Most of the witnesses are at an offset that's just a multiple of the
+ // pointer size, but the extra-inhabitant count is packed in after the
+ // 32-bit flags.
+ // This computation is correct for all pointer sizes, including 16.
+ // It would be wrong if size_t is ever a different size from the pointer
+ // size, though.
+ Size offset =
+ (witness == ValueWitness::ExtraInhabitantCount
+ ? unsigned(ValueWitness::Flags) * pointerSize + Size(4)
+ : unsigned(witness) * pointerSize);
+
+ Address addr = Address(table, IGF.IGM.getPointerAlignment());
+ addr = IGF.Builder.CreateBitCast(addr, IGF.IGM.getValueWitnessTablePtrTy());
+ addr = IGF.Builder.CreateStructGEP(addr, unsigned(witness), offset);
+
+ auto load = IGF.Builder.CreateLoad(addr, getValueWitnessLabel(witness));
+ IGF.setInvariantLoad(load);
+ return load;
}
/// Given a type metadata pointer, load one of the value witnesses from its
@@ -345,7 +389,23 @@
llvm::Value *table,
ValueWitness index) {
assert(isValueWitnessFunction(index));
- llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index);
+
+ WitnessIndex windex = [&] {
+ unsigned i = unsigned(index);
+ if (i > unsigned(ValueWitness::Flags)) {
+ if (IGF.IGM.getPointerSize() == Size(8)) {
+ i--; // one pointer width skips both flags and xiCount
+ } else if (IGF.IGM.getPointerSize() == Size(4)) {
+ // no adjustment required
+ } else {
+ assert(IGF.IGM.getPointerSize() == Size(2));
+ i += 2; // flags and xiCount take up two pointers apiece
+ }
+ }
+ return WitnessIndex(i, false);
+ }();
+
+ llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, windex);
auto label = getValueWitnessLabel(index);
auto signature = IGF.IGM.getValueWitnessSignature(index);
@@ -665,36 +725,6 @@
IGF.Builder.CreateCall(IGF.IGM.getArrayDestroyFn(), {obj, count, metadata});
}
-/// Emit a call to the 'getExtraInhabitantIndex' operation.
-/// The type must be dynamically known to have extra inhabitant witnesses.
-llvm::Value *irgen::emitGetExtraInhabitantIndexCall(IRGenFunction &IGF,
- SILType T,
- Address srcObject) {
- llvm::Value *metadata;
- auto fn = IGF.emitValueWitnessFunctionRef(T, metadata,
- ValueWitness::GetExtraInhabitantIndex);
-
- auto src = emitCastToOpaquePtr(IGF, srcObject);
- llvm::CallInst *call =
- IGF.Builder.CreateCall(fn, {src, metadata});
- return call;
-}
-
-/// Emit a call to the 'storeExtraInhabitant' operation.
-/// The type must be dynamically known to have extra inhabitant witnesses.
-llvm::Value *irgen::emitStoreExtraInhabitantCall(IRGenFunction &IGF,
- SILType T,
- llvm::Value *index,
- Address destObject) {
- llvm::Value *metadata;
- auto fn = IGF.emitValueWitnessFunctionRef(T, metadata,
- ValueWitness::StoreExtraInhabitant);
- auto dest = emitCastToOpaquePtr(IGF, destObject);
- llvm::CallInst *call =
- IGF.Builder.CreateCall(fn, {dest, index, metadata});
- return call;
-}
-
/// Emit a trampoline to call the getEnumTagSinglePayload witness. API:
/// UINT_TYPE (const T* enum, UINT_TYPE emptyCases, M *self)
static llvm::Constant *
@@ -774,7 +804,7 @@
return result;
}
-llvm::Value *irgen::emitStoreEnumTagSinglePayloadCall(
+void irgen::emitStoreEnumTagSinglePayloadCall(
IRGenFunction &IGF, SILType T, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address destObject) {
if (!IGF.optimizeForSize()) {
@@ -782,17 +812,14 @@
auto fn = IGF.emitValueWitnessFunctionRef(
T, metadata, ValueWitness::StoreEnumTagSinglePayload);
auto dest = emitCastToOpaquePtr(IGF, destObject);
- llvm::CallInst *call = IGF.Builder.CreateCall(
- fn, {dest, whichCase, numEmptyCases, metadata});
- return call;
+ IGF.Builder.CreateCall(fn, {dest, whichCase, numEmptyCases, metadata});
+ return;
}
auto *metadata = IGF.emitTypeMetadataRefForLayout(T);
auto *func = getStoreEnumTagSinglePayloadTrampolineFn(IGF.IGM);
auto dest = emitCastToOpaquePtr(IGF, destObject);
- auto *result = IGF.Builder.CreateCall(func,
- {dest, whichCase, numEmptyCases, metadata});
- return result;
+ IGF.Builder.CreateCall(func, {dest, whichCase, numEmptyCases, metadata});
}
/// Emit a call to the 'getEnumTag' operation.
@@ -842,47 +869,36 @@
/// Load the 'alignmentMask' value witness from the given table as a size_t.
llvm::Value *irgen::emitLoadOfAlignmentMask(IRGenFunction &IGF, SILType T) {
auto flags = IGF.emitValueWitnessValue(T, ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::AlignmentMask));
- return IGF.Builder.CreateAnd(flags, mask,
- flags->getName() + ".alignmentMask");
+ return emitAlignMaskFromFlags(IGF, flags);
}
/// Load the 'isPOD' valueWitness from the given table as an i1.
llvm::Value *irgen::emitLoadOfIsPOD(IRGenFunction &IGF, SILType T) {
auto flags = IGF.emitValueWitnessValue(T, ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::IsNonPOD));
+ auto mask = IGF.IGM.getInt32(ValueWitnessFlags::IsNonPOD);
auto masked = IGF.Builder.CreateAnd(flags, mask);
- return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getSize(Size(0)),
+ return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getInt32(0),
flags->getName() + ".isPOD");
}
/// Load the 'isBitwiseTakable' valueWitness from the given table as an i1.
llvm::Value *irgen::emitLoadOfIsBitwiseTakable(IRGenFunction &IGF, SILType T) {
auto flags = IGF.emitValueWitnessValue(T, ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::IsNonBitwiseTakable));
+ auto mask = IGF.IGM.getInt32(ValueWitnessFlags::IsNonBitwiseTakable);
auto masked = IGF.Builder.CreateAnd(flags, mask);
- return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getSize(Size(0)),
+ return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getInt32(0),
flags->getName() + ".isBitwiseTakable");
}
/// Load the 'isInline' valueWitness from the given table as an i1.
llvm::Value *irgen::emitLoadOfIsInline(IRGenFunction &IGF, SILType T) {
auto flags = IGF.emitValueWitnessValue(T, ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::IsNonInline));
+ auto mask = IGF.IGM.getInt32(ValueWitnessFlags::IsNonInline);
auto masked = IGF.Builder.CreateAnd(flags, mask);
- return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getSize(Size(0)),
+ return IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getInt32(0),
flags->getName() + ".isInline");
}
-/// Load the 'hasExtraInhabitants' valueWitness from the given table as an i1.
-llvm::Value *irgen::emitLoadOfHasExtraInhabitants(IRGenFunction &IGF, SILType T) {
- auto flags = IGF.emitValueWitnessValue(T, ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::HasExtraInhabitants));
- auto masked = IGF.Builder.CreateAnd(flags, mask);
- return IGF.Builder.CreateICmpNE(masked, IGF.IGM.getSize(Size(0)),
- flags->getName() + ".hasExtraInhabitants");
-}
-
/// Load the 'stride' value witness from the given table as a size_t.
llvm::Value *irgen::emitLoadOfStride(IRGenFunction &IGF, SILType T) {
return IGF.emitValueWitnessValue(T, ValueWitness::Stride);
@@ -890,22 +906,17 @@
llvm::Value *irgen::emitLoadOfExtraInhabitantCount(IRGenFunction &IGF,
SILType T) {
- auto xiFlags =
- IGF.emitValueWitnessValue(T, ValueWitness::ExtraInhabitantFlags);
- auto mask = IGF.IGM.getSize(
- Size(ExtraInhabitantFlags::NumExtraInhabitantsMask));
- return IGF.Builder.CreateAnd(xiFlags, mask,
- xiFlags->getName() + ".extraInhabitantCount");
+ return IGF.emitValueWitnessValue(T, ValueWitness::ExtraInhabitantCount);
}
std::pair<llvm::Value *, llvm::Value *>
irgen::emitLoadOfIsInline(IRGenFunction &IGF, llvm::Value *metadata) {
auto *flags = emitLoadOfValueWitnessValueFromMetadata(IGF, metadata,
ValueWitness::Flags);
- auto mask = IGF.IGM.getSize(Size(ValueWitnessFlags::IsNonInline));
+ auto mask = IGF.IGM.getInt32(ValueWitnessFlags::IsNonInline);
auto masked = IGF.Builder.CreateAnd(flags, mask);
return std::make_pair(
- IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getSize(Size(0)),
+ IGF.Builder.CreateICmpEQ(masked, IGF.IGM.getInt32(0),
flags->getName() + ".isInline"),
flags);
}
@@ -918,8 +929,9 @@
llvm::Value *irgen::emitAlignMaskFromFlags(IRGenFunction &IGF,
llvm::Value *flags) {
+ auto flagsAsSize = IGF.Builder.CreateZExtOrTrunc(flags, IGF.IGM.SizeTy);
auto *alignMask = IGF.IGM.getSize(Size(ValueWitnessFlags::AlignmentMask));
- return IGF.Builder.CreateAnd(flags, alignMask,
+ return IGF.Builder.CreateAnd(flagsAsSize, alignMask,
flags->getName() + ".alignmentMask");
}
@@ -1246,3 +1258,190 @@
call->setCallingConv(IGF.IGM.DefaultCC);
call->setDoesNotThrow();
}
+
+llvm::Value *
+irgen::emitGetEnumTagSinglePayloadGenericCall(IRGenFunction &IGF,
+ SILType payloadType,
+ const TypeInfo &payloadTI,
+ llvm::Value *numExtraCases,
+ Address address,
+ GetExtraInhabitantTagEmitter emitter) {
+ auto getExtraInhabitantTagFn =
+ getOrCreateGetExtraInhabitantTagFunction(IGF.IGM, payloadType,
+ payloadTI, emitter);
+
+ // We assume this is never a reabstracted type.
+ auto type = payloadType.getASTType();
+ assert(type->isLegalFormalType());
+ auto metadata = IGF.emitTypeMetadataRef(type);
+
+ auto ptr = IGF.Builder.CreateBitCast(address.getAddress(),
+ IGF.IGM.OpaquePtrTy);
+
+ auto getEnumTagGenericFn =
+ IGF.IGM.getGetEnumTagSinglePayloadGenericFn();
+ auto call = IGF.Builder.CreateCall(getEnumTagGenericFn,
+ {ptr,
+ numExtraCases,
+ metadata,
+ getExtraInhabitantTagFn});
+ call->setCallingConv(IGF.IGM.SwiftCC);
+ return call;
+}
+
+llvm::Constant *
+irgen::getOrCreateGetExtraInhabitantTagFunction(IRGenModule &IGM,
+ SILType objectType,
+ const TypeInfo &objectTI,
+ GetExtraInhabitantTagEmitter emitter) {
+ // We assume this is never a reabstracted type.
+ CanType type = objectType.getASTType();
+ assert(type->isLegalFormalType());
+
+ auto fnTy = llvm::FunctionType::get(IGM.Int32Ty,
+ {IGM.OpaquePtrTy,
+ IGM.Int32Ty,
+ IGM.TypeMetadataPtrTy},
+ false);
+
+ // TODO: use a meaningful mangled name and internal/shared linkage.
+ auto fn = llvm::Function::Create(fnTy, llvm::Function::PrivateLinkage,
+ "__swift_get_extra_inhabitant_index",
+ &IGM.Module);
+ fn->setCallingConv(IGM.SwiftCC);
+ IRGenFunction IGF(IGM, fn);
+ auto parameters = IGF.collectParameters();
+ auto ptr = parameters.claimNext();
+ auto xiCount = parameters.claimNext();
+ auto metadata = parameters.claimNext();
+
+ // Bind the metadata to make any archetypes available.
+ IGF.bindLocalTypeDataFromTypeMetadata(type, IsExact, metadata,
+ MetadataState::Complete);
+
+ // Form a well-typed address from the opaque pointer.
+ ptr = IGF.Builder.CreateBitCast(ptr,
+ objectTI.getStorageType()->getPointerTo());
+ Address addr = objectTI.getAddressForPointer(ptr);
+
+ auto tag = emitter(IGF, addr, xiCount);
+ IGF.Builder.CreateRet(tag);
+
+ return fn;
+}
+
+void
+irgen::emitStoreEnumTagSinglePayloadGenericCall(IRGenFunction &IGF,
+ SILType payloadType,
+ const TypeInfo &payloadTI,
+ llvm::Value *whichCase,
+ llvm::Value *numExtraCases,
+ Address address,
+ StoreExtraInhabitantTagEmitter emitter) {
+ auto storeExtraInhabitantTagFn =
+ getOrCreateStoreExtraInhabitantTagFunction(IGF.IGM, payloadType,
+ payloadTI, emitter);
+
+ // We assume this is never a reabstracted type.
+ auto type = payloadType.getASTType();
+ assert(type->isLegalFormalType());
+ auto metadata = IGF.emitTypeMetadataRef(type);
+
+ auto ptr = IGF.Builder.CreateBitCast(address.getAddress(),
+ IGF.IGM.OpaquePtrTy);
+
+ auto storeEnumTagGenericFn =
+ IGF.IGM.getStoreEnumTagSinglePayloadGenericFn();
+ auto call = IGF.Builder.CreateCall(storeEnumTagGenericFn,
+ {ptr,
+ whichCase,
+ numExtraCases,
+ metadata,
+ storeExtraInhabitantTagFn});
+ call->setCallingConv(IGF.IGM.SwiftCC);
+}
+
+llvm::Constant *
+irgen::getOrCreateStoreExtraInhabitantTagFunction(IRGenModule &IGM,
+ SILType objectType,
+ const TypeInfo &objectTI,
+ StoreExtraInhabitantTagEmitter emitter) {
+ // We assume this is never a reabstracted type.
+ CanType type = objectType.getASTType();
+ assert(type->isLegalFormalType());
+
+ auto fnTy = llvm::FunctionType::get(IGM.VoidTy,
+ {IGM.OpaquePtrTy,
+ IGM.Int32Ty,
+ IGM.Int32Ty,
+ IGM.TypeMetadataPtrTy},
+ false);
+
+ // TODO: use a meaningful mangled name and internal/shared linkage.
+ auto fn = llvm::Function::Create(fnTy, llvm::Function::PrivateLinkage,
+ "__swift_get_extra_inhabitant_index",
+ &IGM.Module);
+ fn->setCallingConv(IGM.SwiftCC);
+ IRGenFunction IGF(IGM, fn);
+ auto parameters = IGF.collectParameters();
+ auto ptr = parameters.claimNext();
+ auto tag = parameters.claimNext();
+ auto xiCount = parameters.claimNext();
+ auto metadata = parameters.claimNext();
+
+ // Bind the metadata to make any archetypes available.
+ IGF.bindLocalTypeDataFromTypeMetadata(type, IsExact, metadata,
+ MetadataState::Complete);
+
+ // Form a well-typed address from the opaque pointer.
+ ptr = IGF.Builder.CreateBitCast(ptr,
+ objectTI.getStorageType()->getPointerTo());
+ Address addr = objectTI.getAddressForPointer(ptr);
+
+ emitter(IGF, addr, tag, xiCount);
+ IGF.Builder.CreateRetVoid();
+
+ return fn;
+}
+
+llvm::Value *TypeInfo::getExtraInhabitantTagDynamic(IRGenFunction &IGF,
+ Address address,
+ SILType T,
+ llvm::Value *knownXICount,
+ bool isOutlined) const {
+ if (auto fixedTI = dyn_cast<FixedTypeInfo>(this)) {
+ auto index = fixedTI->getExtraInhabitantIndex(IGF, address, T, isOutlined);
+ // The runtime APIs expect that 0 means the payload case and 1+
+ // means the extra cases, but in IRGen, getExtraInhabitantIndex
+ // returns -1 for the payload case and 0+ for extra inhabitants.
+ // This is an easy adjustment to make.
+ auto one = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1);
+ auto tag = IGF.Builder.CreateAdd(index, one);
+ return tag;
+ } else {
+ if (!knownXICount)
+ knownXICount = emitLoadOfExtraInhabitantCount(IGF, T);
+
+ auto tag = getEnumTagSinglePayload(IGF, /*num extra cases*/ knownXICount,
+ address, T, isOutlined);
+ return tag;
+ }
+}
+
+void TypeInfo::storeExtraInhabitantTagDynamic(IRGenFunction &IGF,
+ llvm::Value *tag,
+ Address address,
+ SILType T,
+ bool isOutlined) const {
+ if (auto fixedTI = dyn_cast<FixedTypeInfo>(this)) {
+ // The runtime APIs expect that 0 means the payload case and 1+
+ // means the extra cases, but in IRGen, storeExtraInhabitant
+ // expects extra inhabitants to be indexed as 0+.
+ // This is an easy adjustment to make.
+ auto one = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1);
+ auto index = IGF.Builder.CreateSub(tag, one);
+ fixedTI->storeExtraInhabitant(IGF, index, address, T, isOutlined);
+ } else {
+ storeEnumTagSinglePayload(IGF, tag, tag, address, T, isOutlined);
+ }
+}
\ No newline at end of file
diff --git a/lib/IRGen/GenOpaque.h b/lib/IRGen/GenOpaque.h
index 6cb9f8d..b5c8116 100644
--- a/lib/IRGen/GenOpaque.h
+++ b/lib/IRGen/GenOpaque.h
@@ -28,6 +28,7 @@
class Address;
class IRGenFunction;
class IRGenModule;
+ class TypeInfo;
enum class ValueWitness : unsigned;
class WitnessIndex;
@@ -164,29 +165,16 @@
Address object,
llvm::Value *count);
- /// Emit a call to the 'getExtraInhabitantIndex' operation.
- /// The type must be dynamically known to have extra inhabitant witnesses.
- llvm::Value *emitGetExtraInhabitantIndexCall(IRGenFunction &IGF,
- SILType T,
- Address srcObject);
-
- /// Emit a call to the 'storeExtraInhabitant' operation.
- /// The type must be dynamically known to have extra inhabitant witnesses.
- llvm::Value *emitStoreExtraInhabitantCall(IRGenFunction &IGF,
- SILType T,
- llvm::Value *index,
- Address destObject);
-
/// Emit a call to the 'getEnumTagSinglePayload' operation.
llvm::Value *emitGetEnumTagSinglePayloadCall(IRGenFunction &IGF, SILType T,
llvm::Value *numEmptyCases,
Address destObject);
/// Emit a call to the 'storeEnumTagSinglePayload' operation.
- llvm::Value *emitStoreEnumTagSinglePayloadCall(IRGenFunction &IGF, SILType T,
- llvm::Value *whichCase,
- llvm::Value *numEmptyCases,
- Address destObject);
+ void emitStoreEnumTagSinglePayloadCall(IRGenFunction &IGF, SILType T,
+ llvm::Value *whichCase,
+ llvm::Value *numEmptyCases,
+ Address destObject);
/// Emit a call to the 'getEnumTag' operation.
llvm::Value *emitGetEnumTagCall(IRGenFunction &IGF,
@@ -224,11 +212,7 @@
/// Emit a load of the 'isInline' value witness.
llvm::Value *emitLoadOfIsInline(IRGenFunction &IGF, SILType T);
- /// Emit a load of the 'hasExtraInhabitants' value witness.
- llvm::Value *emitLoadOfHasExtraInhabitants(IRGenFunction &IGF, SILType T);
-
/// Emit a load of the 'extraInhabitantCount' value witness.
- /// The type must be dynamically known to have extra inhabitant witnesses.
llvm::Value *emitLoadOfExtraInhabitantCount(IRGenFunction &IGF, SILType T);
/// Returns the IsInline flag and the loaded flags value.
@@ -251,6 +235,46 @@
void emitDeallocateValueInBuffer(IRGenFunction &IGF,
SILType type,
Address buffer);
+
+
+ using GetExtraInhabitantTagEmitter =
+ llvm::function_ref<llvm::Value*(IRGenFunction &IGF,
+ Address addr,
+ llvm::Value *xiCount)>;
+
+ llvm::Constant *
+ getOrCreateGetExtraInhabitantTagFunction(IRGenModule &IGM,
+ SILType objectType,
+ const TypeInfo &objectTI,
+ GetExtraInhabitantTagEmitter emit);
+
+ llvm::Value *
+ emitGetEnumTagSinglePayloadGenericCall(IRGenFunction &IGF,
+ SILType payloadType,
+ const TypeInfo &payloadTI,
+ llvm::Value *numExtraCases,
+ Address address,
+ GetExtraInhabitantTagEmitter emit);
+
+ using StoreExtraInhabitantTagEmitter =
+ llvm::function_ref<void(IRGenFunction &IGF,
+ Address addr,
+ llvm::Value *tag,
+ llvm::Value *xiCount)>;
+
+ llvm::Constant *
+ getOrCreateStoreExtraInhabitantTagFunction(IRGenModule &IGM,
+ SILType objectType,
+ const TypeInfo &objectTI,
+ StoreExtraInhabitantTagEmitter emit);
+
+ void emitStoreEnumTagSinglePayloadGenericCall(IRGenFunction &IGF,
+ SILType payloadType,
+ const TypeInfo &payloadTI,
+ llvm::Value *index,
+ llvm::Value *numExtraCases,
+ Address address,
+ StoreExtraInhabitantTagEmitter emit);
} // end namespace irgen
} // end namespace swift
diff --git a/lib/IRGen/GenRecord.h b/lib/IRGen/GenRecord.h
index b9c261a..9bdb2ef 100644
--- a/lib/IRGen/GenRecord.h
+++ b/lib/IRGen/GenRecord.h
@@ -303,21 +303,17 @@
llvm::Value *withExtraInhabitantProvidingField(IRGenFunction &IGF,
Address structAddr,
SILType structType,
- bool isOutlined,
+ llvm::Value *knownStructNumXI,
llvm::Type *resultTy,
- llvm::function_ref<llvm::Value* (const FieldImpl &field)> body,
- llvm::function_ref<llvm::Value* ()> outline) const {
+ llvm::function_ref<llvm::Value* (const FieldImpl &field,
+ llvm::Value *numXI)> body) const {
// If we know one field consistently provides extra inhabitants, delegate
// to that field.
if (auto field = asImpl().getFixedExtraInhabitantProvidingField(IGF.IGM)){
- return body(*field);
+ return body(*field, knownStructNumXI);
}
// Otherwise, we have to figure out which field at runtime.
- // The decision tree could be rather large, so invoke the value witness
- // unless we're emitting the value witness.
- if (!isOutlined)
- return outline();
// The number of extra inhabitants the instantiated type has can be used
// to figure out which field the runtime chose. The runtime uses the same
@@ -351,7 +347,9 @@
// Loop through checking to see whether we picked the fixed candidate
// (if any) or one of the unknown-layout fields.
llvm::Value *instantiatedCount
- = emitLoadOfExtraInhabitantCount(IGF, structType);
+ = (knownStructNumXI
+ ? knownStructNumXI
+ : emitLoadOfExtraInhabitantCount(IGF, structType));
auto contBB = IGF.createBasicBlock("chose_field_for_xi");
llvm::PHINode *contPhi = nullptr;
@@ -376,7 +374,7 @@
if (&field != fixedCandidate)
continue;
- fieldCount = llvm::ConstantInt::get(IGF.IGM.SizeTy, fixedCount);
+ fieldCount = IGF.IGM.getInt32(fixedCount);
} else {
auto fieldTy = field.getType(IGF.IGM, structType);
// If this field has the same type as a field we already tested,
@@ -395,7 +393,7 @@
IGF.Builder.CreateCondBr(equalsCount, yesBB, noBB);
IGF.Builder.emitBlock(yesBB);
- auto value = body(field);
+ auto value = body(field, instantiatedCount);
if (contPhi)
contPhi->addIncoming(value, IGF.Builder.GetInsertBlock());
IGF.Builder.CreateBr(contBB);
@@ -414,46 +412,6 @@
return contPhi;
}
- llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address structAddr,
- SILType structType,
- bool isOutlined) const override {
- return withExtraInhabitantProvidingField(IGF, structAddr, structType,
- isOutlined,
- IGF.IGM.Int32Ty,
- [&](const FieldImpl &field) -> llvm::Value* {
- Address fieldAddr = asImpl().projectFieldAddress(
- IGF, structAddr, structType, field);
- return field.getTypeInfo().getExtraInhabitantIndex(IGF, fieldAddr,
- field.getType(IGF.IGM, structType),
- false /*not outlined for field*/);
- },
- [&]() -> llvm::Value * {
- return emitGetExtraInhabitantIndexCall(IGF, structType, structAddr);
- });
- }
-
- void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address structAddr,
- SILType structType,
- bool isOutlined) const override {
- withExtraInhabitantProvidingField(IGF, structAddr, structType, isOutlined,
- IGF.IGM.VoidTy,
- [&](const FieldImpl &field) -> llvm::Value* {
- Address fieldAddr = asImpl().projectFieldAddress(
- IGF, structAddr, structType, field);
- field.getTypeInfo().storeExtraInhabitant(IGF, index, fieldAddr,
- field.getType(IGF.IGM, structType),
- false /*not outlined for field*/);
- return nullptr;
- },
- [&]() -> llvm::Value * {
- emitStoreExtraInhabitantCall(IGF, structType, index, structAddr);
- return nullptr;
- });
- }
-
const FieldImpl *
getFixedExtraInhabitantProvidingField(IRGenModule &IGM) const {
if (!ExtraInhabitantProvidingField.hasValue()) {
@@ -658,6 +616,33 @@
fieldMask = fieldMask.shl(field->getFixedByteOffset().getValueInBits());
return fieldMask;
}
+
+ llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ auto field = *asImpl().getFixedExtraInhabitantProvidingField(IGF.IGM);
+ Address fieldAddr =
+ asImpl().projectFieldAddress(IGF, structAddr, structType, field);
+ auto &fieldTI = cast<FixedTypeInfo>(field.getTypeInfo());
+ return fieldTI.getExtraInhabitantIndex(IGF, fieldAddr,
+ field.getType(IGF.IGM, structType),
+ false /*not outlined for field*/);
+ }
+
+ void storeExtraInhabitant(IRGenFunction &IGF,
+ llvm::Value *index,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ auto field = *asImpl().getFixedExtraInhabitantProvidingField(IGF.IGM);
+ Address fieldAddr =
+ asImpl().projectFieldAddress(IGF, structAddr, structType, field);
+ auto &fieldTI = cast<FixedTypeInfo>(field.getTypeInfo());
+ fieldTI.storeExtraInhabitant(IGF, index, fieldAddr,
+ field.getType(IGF.IGM, structType),
+ false /*not outlined for field*/);
+ }
};
/// An implementation of RecordTypeInfo for loadable types.
diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp
index e2b273b..036afaa 100644
--- a/lib/IRGen/GenStruct.cpp
+++ b/lib/IRGen/GenStruct.cpp
@@ -472,6 +472,67 @@
return StructNonFixedOffsets(T).getFieldAccessStrategy(IGM,
field.getNonFixedElementIndex());
}
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ // If we're not emitting the value witness table's implementation,
+ // just call that.
+ if (!isOutlined) {
+ return emitGetEnumTagSinglePayloadCall(IGF, structType, numEmptyCases,
+ structAddr);
+ }
+
+ return emitGetEnumTagSinglePayloadGenericCall(IGF, structType, *this,
+ numEmptyCases, structAddr,
+ [this,structType](IRGenFunction &IGF, Address structAddr,
+ llvm::Value *structNumXI) {
+ return withExtraInhabitantProvidingField(IGF, structAddr, structType,
+ structNumXI, IGF.IGM.Int32Ty,
+ [&](const FieldImpl &field, llvm::Value *numXI) -> llvm::Value* {
+ Address fieldAddr = asImpl().projectFieldAddress(
+ IGF, structAddr, structType, field);
+ auto fieldTy = field.getType(IGF.IGM, structType);
+ return field.getTypeInfo()
+ .getExtraInhabitantTagDynamic(IGF, fieldAddr, fieldTy,
+ numXI, /*outlined*/ false);
+ });
+ });
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *whichCase,
+ llvm::Value *numEmptyCases,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ // If we're not emitting the value witness table's implementation,
+ // just call that.
+ if (!isOutlined) {
+ return emitStoreEnumTagSinglePayloadCall(IGF, structType, whichCase,
+ numEmptyCases, structAddr);
+ }
+
+ emitStoreEnumTagSinglePayloadGenericCall(IGF, structType, *this,
+ whichCase, numEmptyCases,
+ structAddr,
+ [this,structType](IRGenFunction &IGF, Address structAddr,
+ llvm::Value *tag, llvm::Value *structNumXI) {
+ withExtraInhabitantProvidingField(IGF, structAddr, structType,
+ structNumXI, IGF.IGM.VoidTy,
+ [&](const FieldImpl &field, llvm::Value *numXI) -> llvm::Value* {
+ Address fieldAddr = asImpl().projectFieldAddress(
+ IGF, structAddr, structType, field);
+ auto fieldTy = field.getType(IGF.IGM, structType);
+ field.getTypeInfo()
+ .storeExtraInhabitantTagDynamic(IGF, tag, fieldAddr, fieldTy,
+ /*outlined*/ false);
+ return nullptr;
+ });
+ });
+ }
};
class StructTypeBuilder :
diff --git a/lib/IRGen/GenTuple.cpp b/lib/IRGen/GenTuple.cpp
index 6d2e564..cbc3252 100644
--- a/lib/IRGen/GenTuple.cpp
+++ b/lib/IRGen/GenTuple.cpp
@@ -295,6 +295,29 @@
SILType T) const {
return TupleNonFixedOffsets(T);
}
+
+ llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *numEmptyCases,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ // The runtime will overwrite this with a concrete implementation
+ // in the value witness table.
+ return emitGetEnumTagSinglePayloadCall(IGF, structType, numEmptyCases,
+ structAddr);
+ }
+
+ void storeEnumTagSinglePayload(IRGenFunction &IGF,
+ llvm::Value *index,
+ llvm::Value *numEmptyCases,
+ Address structAddr,
+ SILType structType,
+ bool isOutlined) const override {
+ // The runtime will overwrite this with a concrete implementation
+ // in the value witness table.
+ emitStoreEnumTagSinglePayloadCall(IGF, structType, index,
+ numEmptyCases, structAddr);
+ }
};
class TupleTypeBuilder :
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index adecc37..5045a83 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -240,15 +240,16 @@
unsigned FixedTypeInfo::getSpareBitExtraInhabitantCount() const {
if (SpareBits.none())
return 0;
- // The runtime supports a max of 0x7FFFFFFF extra inhabitants, which ought
- // to be enough for anybody.
+ // Make sure the arithmetic below doesn't overflow.
if (getFixedSize().getValue() >= 4)
- return 0x7FFFFFFF;
+ return ValueWitnessFlags::MaxNumExtraInhabitants;
unsigned spareBitCount = SpareBits.count();
assert(spareBitCount <= getFixedSize().getValueInBits()
&& "more spare bits than storage bits?!");
unsigned inhabitedBitCount = getFixedSize().getValueInBits() - spareBitCount;
- return ((1U << spareBitCount) - 1U) << inhabitedBitCount;
+ unsigned rawCount = ((1U << spareBitCount) - 1U) << inhabitedBitCount;
+ return std::min(rawCount,
+ unsigned(ValueWitnessFlags::MaxNumExtraInhabitants));
}
void FixedTypeInfo::applyFixedSpareBitsMask(SpareBitVector &mask,
@@ -426,15 +427,26 @@
llvm::Value *FixedTypeInfo::getEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const {
+ SILType T,
+ bool isOutlined) const {
+ return getFixedTypeEnumTagSinglePayload(IGF, *this, numEmptyCases, enumAddr,
+ T, isOutlined);
+}
+
+llvm::Value *irgen::getFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
+ const FixedTypeInfo &ti,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T,
+ bool isOutlined) {
auto &IGM = IGF.IGM;
auto &Ctx = IGF.IGM.getLLVMContext();
auto &Builder = IGF.Builder;
- auto *size = getSize(IGF, T);
- Size fixedSize = getFixedSize();
+ auto *size = ti.getSize(IGF, T);
+ Size fixedSize = ti.getFixedSize();
auto *numExtraInhabitants =
- llvm::ConstantInt::get(IGM.Int32Ty, getFixedExtraInhabitantCount(IGM));
+ llvm::ConstantInt::get(IGM.Int32Ty, ti.getFixedExtraInhabitantCount(IGM));
auto *zero = llvm::ConstantInt::get(IGM.Int32Ty, 0U);
auto *one = llvm::ConstantInt::get(IGM.Int32Ty, 1U);
@@ -513,8 +525,8 @@
Builder.emitBlock(noExtraTagBitsBB);
// If there are extra inhabitants, see whether the payload is valid.
llvm::Value *result0;
- if (mayHaveExtraInhabitants(IGM)) {
- result0 = getExtraInhabitantIndex(IGF, enumAddr, T, false);
+ if (ti.mayHaveExtraInhabitants(IGM)) {
+ result0 = ti.getExtraInhabitantIndex(IGF, enumAddr, T, false);
noExtraTagBitsBB = Builder.GetInsertBlock();
} else {
result0 = llvm::ConstantInt::getSigned(IGM.Int32Ty, -1);
@@ -605,7 +617,19 @@
llvm::Value *whichCase,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const {
+ SILType T,
+ bool isOutlined) const {
+ storeFixedTypeEnumTagSinglePayload(IGF, *this, whichCase, numEmptyCases,
+ enumAddr, T, isOutlined);
+}
+
+void irgen::storeFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
+ const FixedTypeInfo &ti,
+ llvm::Value *whichCase,
+ llvm::Value *numEmptyCases,
+ Address enumAddr,
+ SILType T,
+ bool isOutlined) {
auto &IGM = IGF.IGM;
auto &Ctx = IGF.IGM.getLLVMContext();
auto &Builder = IGF.Builder;
@@ -616,15 +640,15 @@
auto *four = llvm::ConstantInt::get(int32Ty, 4U);
auto *eight = llvm::ConstantInt::get(int32Ty, 8U);
- auto fixedSize = getFixedSize();
+ auto fixedSize = ti.getFixedSize();
Address valueAddr = Builder.CreateElementBitCast(enumAddr, IGM.Int8Ty);
Address extraTagBitsAddr =
Builder.CreateConstByteArrayGEP(valueAddr, fixedSize);
auto *numExtraInhabitants =
- llvm::ConstantInt::get(IGM.Int32Ty, getFixedExtraInhabitantCount(IGM));
- auto *size = getSize(IGF, T);
+ llvm::ConstantInt::get(IGM.Int32Ty, ti.getFixedExtraInhabitantCount(IGM));
+ auto *size = ti.getSize(IGF, T);
// Do we need extra tag bytes.
auto *entryBB = Builder.GetInsertBlock();
@@ -666,11 +690,11 @@
Builder.CreateCondBr(isPayload, returnBB, storeInhabitantBB);
Builder.emitBlock(storeInhabitantBB);
- if (mayHaveExtraInhabitants(IGM)) {
+ if (ti.mayHaveExtraInhabitants(IGM)) {
// Store an index in the range [0..ElementsWithNoPayload-1].
auto *nonPayloadElementIndex = Builder.CreateSub(whichCase, one);
- storeExtraInhabitant(IGF, nonPayloadElementIndex, enumAddr, T,
- /*outlined*/ false);
+ ti.storeExtraInhabitant(IGF, nonPayloadElementIndex, enumAddr, T,
+ /*outlined*/ false);
}
Builder.CreateBr(returnBB);
@@ -728,30 +752,6 @@
Builder.emitBlock(returnBB);
}
-llvm::Value *irgen::emitGetEnumTagSinglePayload(IRGenFunction &IGF,
- llvm::Value *numEmptyCases,
- Address enumAddr, SILType T) {
- auto metadata = IGF.emitTypeMetadataRefForLayout(T);
- auto opaqueAddr =
- IGF.Builder.CreateBitCast(enumAddr.getAddress(), IGF.IGM.OpaquePtrTy);
-
- return IGF.Builder.CreateCall(IGF.IGM.getGetEnumCaseSinglePayloadFn(),
- {opaqueAddr, metadata, numEmptyCases});
-}
-
-void irgen::emitStoreEnumTagSinglePayload(IRGenFunction &IGF,
- llvm::Value *whichCase,
- llvm::Value *numEmptyCases,
- Address enumAddr,
- SILType T) {
- auto metadata = IGF.emitTypeMetadataRefForLayout(T);
- auto opaqueAddr =
- IGF.Builder.CreateBitCast(enumAddr.getAddress(), IGF.IGM.OpaquePtrTy);
-
- IGF.Builder.CreateCall(IGF.IGM.getStoreEnumTagSinglePayloadFn(),
- {opaqueAddr, metadata, whichCase, numEmptyCases});
-}
-
void
FixedTypeInfo::storeSpareBitExtraInhabitant(IRGenFunction &IGF,
llvm::Value *index,
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 072c564..6650383 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -56,15 +56,13 @@
CASE(InitializeBufferWithCopyOfBuffer)
CASE(InitializeWithCopy)
CASE(InitializeWithTake)
- CASE(StoreExtraInhabitant)
- CASE(GetExtraInhabitantIndex)
CASE(GetEnumTag)
CASE(DestructiveProjectEnumData)
CASE(DestructiveInjectEnumTag)
CASE(Size)
CASE(Flags)
+ CASE(ExtraInhabitantCount)
CASE(Stride)
- CASE(ExtraInhabitantFlags)
CASE(GetEnumTagSinglePayload)
CASE(StoreEnumTagSinglePayload)
#undef CASE
@@ -510,27 +508,6 @@
return;
}
- case ValueWitness::StoreExtraInhabitant: {
- Address dest = getArgAs(IGF, argv, type, "dest");
- llvm::Value *index = getArg(argv, "index");
- getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
-
- type.storeExtraInhabitant(IGF, index, dest, concreteType,
- /*outlined*/ true);
- IGF.Builder.CreateRetVoid();
- return;
- }
-
- case ValueWitness::GetExtraInhabitantIndex: {
- Address src = getArgAs(IGF, argv, type, "src");
- getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
-
- llvm::Value *idx = type.getExtraInhabitantIndex(IGF, src, concreteType,
- /*outlined*/ true);
- IGF.Builder.CreateRet(idx);
- return;
- }
-
case ValueWitness::GetEnumTag: {
auto &strategy = getEnumImplStrategy(IGM, concreteType);
@@ -593,7 +570,7 @@
llvm::Value *idx = type.getEnumTagSinglePayload(
IGF, numEmptyCases, Address(value, type.getBestKnownAlignment()),
- concreteType);
+ concreteType, true);
IGF.Builder.CreateRet(idx);
return;
}
@@ -610,15 +587,15 @@
type.storeEnumTagSinglePayload(IGF, whichCase, numEmptyCases,
Address(value, type.getBestKnownAlignment()),
- concreteType);
+ concreteType, true);
IGF.Builder.CreateRetVoid();
return;
}
case ValueWitness::Size:
case ValueWitness::Flags:
+ case ValueWitness::ExtraInhabitantCount:
case ValueWitness::Stride:
- case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("these value witnesses aren't functions");
}
llvm_unreachable("bad value witness kind!");
@@ -753,7 +730,7 @@
/// Find a witness to the fact that a type is a value type.
/// Always adds an i8*.
static void addValueWitness(IRGenModule &IGM,
- ConstantArrayBuilder &B,
+ ConstantStructBuilder &B,
ValueWitness index,
FixedPacking packing,
CanType abstractType,
@@ -815,10 +792,10 @@
case ValueWitness::Size: {
if (auto value = concreteTI.getStaticSize(IGM))
- return B.add(llvm::ConstantExpr::getIntToPtr(value, IGM.Int8PtrTy));
+ return B.add(value);
- // Just fill in null here if the type can't be statically laid out.
- return B.add(llvm::ConstantPointerNull::get(IGM.Int8PtrTy));
+ // Just fill in 0 here if the type can't be statically laid out.
+ return B.addSize(Size(0));
}
case ValueWitness::Flags: {
@@ -836,8 +813,6 @@
flags = flags.withAlignment(fixedTI->getFixedAlignment().getValue())
.withPOD(fixedTI->isPOD(ResilienceExpansion::Maximal))
.withInlineStorage(isInline)
- .withExtraInhabitants(
- fixedTI->getFixedExtraInhabitantCount(IGM) > 0)
.withBitwiseTakable(isBitwiseTakable);
} else {
flags = flags.withIncomplete(true);
@@ -846,50 +821,23 @@
if (concreteType.getEnumOrBoundGenericEnum())
flags = flags.withEnumWitnesses(true);
- auto value = IGM.getSize(Size(flags.getOpaqueValue()));
- return B.add(llvm::ConstantExpr::getIntToPtr(value, IGM.Int8PtrTy));
+ return B.addInt32(flags.getOpaqueValue());
+ }
+
+ case ValueWitness::ExtraInhabitantCount: {
+ unsigned value = 0;
+ if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&concreteTI)) {
+ value = fixedTI->getFixedExtraInhabitantCount(IGM);
+ }
+ return B.addInt32(value);
}
case ValueWitness::Stride: {
if (auto value = concreteTI.getStaticStride(IGM))
- return B.add(llvm::ConstantExpr::getIntToPtr(value, IGM.Int8PtrTy));
+ return B.add(value);
// Just fill in null here if the type can't be statically laid out.
- return B.add(llvm::ConstantPointerNull::get(IGM.Int8PtrTy));
- }
-
- case ValueWitness::StoreExtraInhabitant:
- case ValueWitness::GetExtraInhabitantIndex: {
- if (!concreteTI.mayHaveExtraInhabitants(IGM)) {
- assert(concreteType.getEnumOrBoundGenericEnum());
- return B.addNullPointer(IGM.Int8PtrTy);
- }
-
- goto standard;
- }
-
- case ValueWitness::ExtraInhabitantFlags: {
- if (!concreteTI.mayHaveExtraInhabitants(IGM)) {
- assert(concreteType.getEnumOrBoundGenericEnum());
- return B.add(llvm::ConstantPointerNull::get(IGM.Int8PtrTy));
- }
-
- // If we locally know that the type has fixed layout, we can emit
- // meaningful flags for it.
- if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&concreteTI)) {
- ExtraInhabitantFlags flags;
-
- uint64_t numExtraInhabitants = fixedTI->getFixedExtraInhabitantCount(IGM);
- assert(numExtraInhabitants <= ExtraInhabitantFlags::NumExtraInhabitantsMask);
- flags = flags.withNumExtraInhabitants(numExtraInhabitants);
-
- auto value = IGM.getSize(Size(flags.getOpaqueValue()));
- return B.add(llvm::ConstantExpr::getIntToPtr(value, IGM.Int8PtrTy));
- }
-
- // Otherwise, just fill in null here if the type can't be statically
- // queried for extra inhabitants.
- return B.add(llvm::ConstantPointerNull::get(IGM.Int8PtrTy));
+ return B.addSize(Size(0));
}
case ValueWitness::GetEnumTagSinglePayload:
@@ -914,9 +862,21 @@
addFunction(fn);
}
+static bool shouldAddEnumWitnesses(CanType abstractType) {
+ // Needs to handle UnboundGenericType.
+ return dyn_cast_or_null<EnumDecl>(abstractType.getAnyNominal()) != nullptr;
+}
+
+static llvm::StructType *getValueWitnessTableType(IRGenModule &IGM,
+ CanType abstractType) {
+ return shouldAddEnumWitnesses(abstractType)
+ ? IGM.getEnumValueWitnessTableTy()
+ : IGM.getValueWitnessTableTy();
+}
+
/// Collect the value witnesses for a particular type.
static void addValueWitnesses(IRGenModule &IGM,
- ConstantArrayBuilder &B,
+ ConstantStructBuilder &B,
FixedPacking packing,
CanType abstractType,
SILType concreteType,
@@ -925,16 +885,7 @@
addValueWitness(IGM, B, ValueWitness(i), packing,
abstractType, concreteType, concreteTI);
}
- if (concreteType.getEnumOrBoundGenericEnum() ||
- concreteTI.mayHaveExtraInhabitants(IGM)) {
- for (auto i = unsigned(ValueWitness::First_ExtraInhabitantValueWitness);
- i <= unsigned(ValueWitness::Last_ExtraInhabitantValueWitness);
- ++i) {
- addValueWitness(IGM, B, ValueWitness(i), packing,
- abstractType, concreteType, concreteTI);
- }
- }
- if (concreteType.getEnumOrBoundGenericEnum()) {
+ if (shouldAddEnumWitnesses(abstractType)) {
for (auto i = unsigned(ValueWitness::First_EnumValueWitness);
i <= unsigned(ValueWitness::Last_EnumValueWitness);
++i) {
@@ -952,7 +903,7 @@
}
static void addValueWitnessesForAbstractType(IRGenModule &IGM,
- ConstantArrayBuilder &B,
+ ConstantStructBuilder &B,
CanType abstractType,
bool &canBeConstant) {
CanType concreteFormalType = getFormalTypeInContext(abstractType);
@@ -1095,7 +1046,8 @@
"emitting VWT pattern for fixed-layout type");
ConstantInitBuilder builder(IGM);
- auto witnesses = builder.beginArray(IGM.Int8PtrTy);
+ auto witnesses =
+ builder.beginStruct(getValueWitnessTableType(IGM, abstractType));
bool canBeConstant = false;
addValueWitnessesForAbstractType(IGM, witnesses, abstractType, canBeConstant);
@@ -1159,7 +1111,7 @@
// Emit the layout values.
ConstantInitBuilder builder(*this);
- auto witnesses = builder.beginArray(Int8PtrTy);
+ auto witnesses = builder.beginStruct();
FixedPacking packing = ti.getFixedPacking(*this);
for (auto witness = ValueWitness::First_TypeLayoutWitness;
witness <= ValueWitness::Last_RequiredTypeLayoutWitness;
@@ -1167,12 +1119,6 @@
addValueWitness(*this, witnesses, witness, packing, t, silTy, ti);
}
- if (ti.mayHaveExtraInhabitants(*this))
- for (auto witness = ValueWitness::First_ExtraInhabitantValueWitness;
- witness <= ValueWitness::Last_TypeLayoutWitness;
- witness = ValueWitness(unsigned(witness) + 1))
- addValueWitness(*this, witnesses, witness, packing, t, silTy, ti);
-
auto layoutVar
= witnesses.finishAndCreateGlobal(
"type_layout_" + llvm::Twine(size)
@@ -1184,10 +1130,8 @@
/*constant*/ true,
llvm::GlobalValue::PrivateLinkage);
- auto zero = llvm::ConstantInt::get(Int32Ty, 0);
- llvm::Constant *indices[] = {zero, zero};
- auto layout = llvm::ConstantExpr::getGetElementPtr(layoutVar->getValueType(),
- layoutVar, indices);
+ // Cast to the standard currency type for type layouts.
+ auto layout = llvm::ConstantExpr::getBitCast(layoutVar, Int8PtrPtrTy);
PrivateFixedLayouts.insert({key, layout});
return layout;
diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp
index 0714f3d..8e48720 100644
--- a/lib/IRGen/IRGenMangler.cpp
+++ b/lib/IRGen/IRGenMangler.cpp
@@ -49,16 +49,14 @@
GET_MANGLING(AssignWithTake) \
GET_MANGLING(GetEnumTagSinglePayload) \
GET_MANGLING(StoreEnumTagSinglePayload) \
- GET_MANGLING(StoreExtraInhabitant) \
- GET_MANGLING(GetExtraInhabitantIndex) \
GET_MANGLING(GetEnumTag) \
GET_MANGLING(DestructiveProjectEnumData) \
GET_MANGLING(DestructiveInjectEnumTag)
#undef GET_MANGLING
case ValueWitness::Size:
case ValueWitness::Flags:
+ case ValueWitness::ExtraInhabitantCount:
case ValueWitness::Stride:
- case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("not a function witness");
}
appendOperator("w", Code);
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 69c33d2..bf3c9cb 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -848,6 +848,10 @@
llvm::AttributeList::FunctionIndex, b);
}
+llvm::Constant *IRGenModule::getInt32(uint32_t value) {
+ return llvm::ConstantInt::get(Int32Ty, value);
+}
+
llvm::Constant *IRGenModule::getSize(Size size) {
return llvm::ConstantInt::get(SizeTy, size.getValue());
}
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 47df73b..6d41125 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -629,7 +629,7 @@
/// Get the bit width of an integer type for the target platform.
unsigned getBuiltinIntegerWidth(BuiltinIntegerType *t);
unsigned getBuiltinIntegerWidth(BuiltinIntegerWidth w);
-
+
Size getPointerSize() const { return PtrSize; }
Alignment getPointerAlignment() const {
// We always use the pointer's width as its swift ABI alignment.
@@ -703,6 +703,11 @@
llvm::StructType *getIntegerLiteralTy();
+ llvm::StructType *getValueWitnessTableTy();
+ llvm::StructType *getEnumValueWitnessTableTy();
+ llvm::PointerType *getValueWitnessTablePtrTy();
+ llvm::PointerType *getEnumValueWitnessTablePtrTy();
+
void unimplemented(SourceLoc, StringRef Message);
LLVM_ATTRIBUTE_NORETURN
void fatal_unimplemented(SourceLoc, StringRef Message);
@@ -733,7 +738,9 @@
llvm::FunctionType *AssociatedTypeWitnessTableAccessFunctionTy = nullptr;
llvm::StructType *GenericWitnessTableCacheTy = nullptr;
llvm::StructType *IntegerLiteralTy = nullptr;
-
+ llvm::PointerType *ValueWitnessTablePtrTy = nullptr;
+ llvm::PointerType *EnumValueWitnessTablePtrTy = nullptr;
+
llvm::DenseMap<llvm::Type *, SpareBitVector> SpareBitsForTypes;
//--- Types -----------------------------------------------------------------
@@ -1189,6 +1196,7 @@
ForeignFunctionInfo *foreignInfo=nullptr);
ForeignFunctionInfo getForeignFunctionInfo(CanSILFunctionType type);
+ llvm::Constant *getInt32(uint32_t value);
llvm::Constant *getSize(Size size);
llvm::Constant *getAlignment(Alignment align);
llvm::Constant *getBool(bool condition);
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index aacb934..d43e396 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -799,7 +799,7 @@
case Kind::ReflectionFieldDescriptor:
case Kind::ReflectionAssociatedTypeDescriptor:
return IGM.FieldDescriptorTy;
- case Kind::ValueWitnessTable:
+ case Kind::ValueWitnessTable: // TODO: use ValueWitnessTableTy
case Kind::ProtocolWitnessTable:
case Kind::ProtocolWitnessTablePattern:
return IGM.WitnessTableTy;
diff --git a/lib/IRGen/NonFixedTypeInfo.h b/lib/IRGen/NonFixedTypeInfo.h
index 171ea3d..f64a1d2 100644
--- a/lib/IRGen/NonFixedTypeInfo.h
+++ b/lib/IRGen/NonFixedTypeInfo.h
@@ -30,16 +30,6 @@
namespace swift {
namespace irgen {
-/// Emits the generic implementation for getEnumTagSinglePayload.
-llvm::Value *emitGetEnumTagSinglePayload(IRGenFunction &IGF,
- llvm::Value *numEmptyCases,
- Address enumAddr, SILType T);
-
-/// Emits the generic implementation for storeEnumTagSinglePayload.
-void emitStoreEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase,
- llvm::Value *numEmptyCases, Address enumAddr,
- SILType T);
-
/// An abstract CRTP class designed for types whose storage size,
/// alignment, and stride need to be fetched from the value witness
/// table for the type.
@@ -119,19 +109,7 @@
return emitLoadOfIsInline(IGF, T);
}
- /// FIXME: Dynamic extra inhabitant lookup.
- bool mayHaveExtraInhabitants(IRGenModule &) const override { return false; }
- llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address src, SILType T,
- bool isOutlined) const override {
- llvm_unreachable("dynamic extra inhabitants not supported");
- }
- void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address dest, SILType T,
- bool isOutlined) const override {
- llvm_unreachable("dynamic extra inhabitants not supported");
- }
+ bool mayHaveExtraInhabitants(IRGenModule &) const override { return true; }
llvm::Constant *getStaticSize(IRGenModule &IGM) const override {
return nullptr;
@@ -142,19 +120,6 @@
llvm::Constant *getStaticStride(IRGenModule &IGM) const override {
return nullptr;
}
-
- llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
- llvm::Value *numEmptyCases,
- Address enumAddr,
- SILType T) const override {
- return emitGetEnumTagSinglePayload(IGF, numEmptyCases, enumAddr, T);
- }
-
- void storeEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase,
- llvm::Value *numEmptyCases, Address enumAddr,
- SILType T) const override {
- emitStoreEnumTagSinglePayload(IGF, whichCase, numEmptyCases, enumAddr, T);
- }
};
}
}
diff --git a/lib/IRGen/ResilientTypeInfo.h b/lib/IRGen/ResilientTypeInfo.h
index 65418e5..65beaa7 100644
--- a/lib/IRGen/ResilientTypeInfo.h
+++ b/lib/IRGen/ResilientTypeInfo.h
@@ -137,30 +137,18 @@
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
return true;
}
- llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address src,
- SILType T,
- bool isOutlined) const override {
- return emitGetExtraInhabitantIndexCall(IGF, T, src);
- }
- void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address dest,
- SILType T,
- bool isOutlined) const override {
- emitStoreExtraInhabitantCall(IGF, T, index, dest);
- }
llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const override {
+ SILType T,
+ bool isOutlined) const override {
return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, enumAddr);
}
void storeEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address enumAddr,
- SILType T) const override {
+ SILType T, bool isOutlined) const override {
emitStoreEnumTagSinglePayloadCall(IGF, T, whichCase, numEmptyCases, enumAddr);
}
diff --git a/lib/IRGen/TypeInfo.h b/lib/IRGen/TypeInfo.h
index 94665f8..921681e 100644
--- a/lib/IRGen/TypeInfo.h
+++ b/lib/IRGen/TypeInfo.h
@@ -402,42 +402,48 @@
/// Does this type statically have extra inhabitants, or may it dynamically
/// have extra inhabitants based on type arguments?
virtual bool mayHaveExtraInhabitants(IRGenModule &IGM) const = 0;
-
- /// Map an extra inhabitant representation in memory to a unique 31-bit
- /// identifier, and map a valid representation of the type to -1.
- ///
- /// Calls to this witness must be dominated by a runtime check that the type
- /// has extra inhabitants.
- virtual llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
- Address src,
- SILType T,
- bool isOutlined) const = 0;
-
- /// Store the extra inhabitant representation indexed by a 31-bit identifier
- /// to memory.
- ///
- /// Calls to this witness must be dominated by a runtime check that the type
- /// has extra inhabitants.
- virtual void storeExtraInhabitant(IRGenFunction &IGF,
- llvm::Value *index,
- Address dest,
- SILType T,
- bool isOutlined) const = 0;
-
+
/// Get the tag of a single payload enum with a payload of this type (\p T) e.g
/// Optional<T>.
virtual llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const = 0;
+ SILType T,
+ bool isOutlined) const = 0;
/// Store the tag of a single payload enum with a payload of this type.
virtual void storeEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *whichCase,
llvm::Value *numEmptyCases,
Address enumAddr,
- SILType T) const = 0;
-
+ SILType T,
+ bool isOutlined) const = 0;
+
+ /// Return an extra-inhabitant tag for the given type, which will be
+ /// 0 for a value that's not an extra inhabitant or else a value in
+ /// 1...extraInhabitantCount. Note that the range is off by one relative
+ /// to the expectations of FixedTypeInfo::getExtraInhabitantIndex!
+ ///
+ /// Most places in IRGen shouldn't be using this.
+ ///
+ /// knownXICount can be null.
+ llvm::Value *getExtraInhabitantTagDynamic(IRGenFunction &IGF,
+ Address address,
+ SILType T,
+ llvm::Value *knownXICount,
+ bool isOutlined) const;
+
+ /// Store an extra-inhabitant tag for the given type, which is known to be
+ /// in 1...extraInhabitantCount. Note that the range is off by one
+ /// relative to the expectations of FixedTypeInfo::storeExtraInhabitant!
+ ///
+ /// Most places in IRGen shouldn't be using this.
+ void storeExtraInhabitantTagDynamic(IRGenFunction &IGF,
+ llvm::Value *index,
+ Address address,
+ SILType T,
+ bool isOutlined) const;
+
/// Compute the packing of values of this type into a fixed-size buffer.
/// A value might not be stored in the fixed-size buffer because it does not
/// fit or because it is not bit-wise takable. Non bit-wise takable values are
diff --git a/lib/IRGen/TypeLayoutVerifier.cpp b/lib/IRGen/TypeLayoutVerifier.cpp
index d7e67a9..37e91f1 100644
--- a/lib/IRGen/TypeLayoutVerifier.cpp
+++ b/lib/IRGen/TypeLayoutVerifier.cpp
@@ -96,17 +96,12 @@
"is-bitwise-takable bit");
unsigned xiCount = fixedTI->getFixedExtraInhabitantCount(IGM);
verifyValues(metadata,
- emitLoadOfHasExtraInhabitants(*this, layoutType),
- getBoolConstant(xiCount != 0),
- "has-extra-inhabitants bit");
+ emitLoadOfExtraInhabitantCount(*this, layoutType),
+ IGM.getInt32(xiCount),
+ "extra inhabitant count");
// Check extra inhabitants.
if (xiCount > 0) {
- verifyValues(metadata,
- emitLoadOfExtraInhabitantCount(*this, layoutType),
- getSizeConstant(Size(xiCount)),
- "extra inhabitant count");
-
// Verify that the extra inhabitant representations are consistent.
// TODO: Update for EnumPayload implementation changes.
@@ -122,10 +117,12 @@
auto xiMask = fixedTI->getFixedExtraInhabitantMask(IGM);
auto xiSchema = EnumPayloadSchema::withBitSize(xiMask.getBitWidth());
+ auto maxXiCount = std::min(xiCount, 256u);
+ auto numCases = llvm::ConstantInt::get(IGM.Int32Ty, maxXiCount);
+
// TODO: Randomize the set of extra inhabitants we check.
unsigned bits = fixedTI->getFixedSize().getValueInBits();
- for (unsigned i = 0, e = std::min(xiCount, 256u);
- i < e; ++i) {
+ for (unsigned i = 0, e = maxXiCount; i < e; ++i) {
// Initialize the buffer with junk, to help ensure we're insensitive to
// insignificant bits.
// TODO: Randomize the filler.
@@ -135,8 +132,9 @@
fixedTI->getFixedAlignment().getValue());
// Ask the runtime to store an extra inhabitant.
- auto index = llvm::ConstantInt::get(IGM.Int32Ty, i);
- emitStoreExtraInhabitantCall(*this, layoutType, index, xiOpaque);
+ auto tag = llvm::ConstantInt::get(IGM.Int32Ty, i+1);
+ emitStoreEnumTagSinglePayloadCall(*this, layoutType, tag,
+ numCases, xiOpaque);
// Compare the stored extra inhabitant against the fixed extra
// inhabitant pattern.
@@ -171,11 +169,12 @@
fixedXIValue, xiSchema);
maskedXIPayload.store(*this, fixedXIBuf);
- auto runtimeIndex = emitGetExtraInhabitantIndexCall(*this, layoutType,
- fixedXIOpaque);
+ auto runtimeTag =
+ emitGetEnumTagSinglePayloadCall(*this, layoutType, numCases,
+ fixedXIOpaque);
verifyValues(metadata,
- runtimeIndex, index,
- llvm::Twine("extra inhabitant index calculation ")
+ runtimeTag, tag,
+ llvm::Twine("extra inhabitant tag calculation ")
+ numberBuf.str());
}
}
diff --git a/lib/IRGen/WitnessIndex.h b/lib/IRGen/WitnessIndex.h
index 25717e4..5b64087 100644
--- a/lib/IRGen/WitnessIndex.h
+++ b/lib/IRGen/WitnessIndex.h
@@ -32,7 +32,6 @@
unsigned IsPrefix : 1;
public:
WitnessIndex() = default;
- WitnessIndex(ValueWitness index) : Value(int(index)) {}
explicit WitnessIndex(int index, bool isPrefix)
: Value(index), IsPrefix(isPrefix) {}
diff --git a/stdlib/public/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp
index b01397c..84873fe 100644
--- a/stdlib/public/Reflection/TypeLowering.cpp
+++ b/stdlib/public/Reflection/TypeLowering.cpp
@@ -1076,10 +1076,12 @@
// Dynamic multi-payload enums use the tag representations not assigned
// to cases for extra inhabitants.
if (tagCounts.numTagBytes >= 32) {
- NumExtraInhabitants = INT_MAX;
+ NumExtraInhabitants = ValueWitnessFlags::MaxNumExtraInhabitants;
} else {
NumExtraInhabitants =
(1 << (tagCounts.numTagBytes * 8)) - tagCounts.numTags;
+ NumExtraInhabitants = std::min(NumExtraInhabitants,
+ unsigned(ValueWitnessFlags::MaxNumExtraInhabitants));
}
}
}
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 2d97e46..39b3575 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -1876,7 +1876,7 @@
const Metadata *payloadType =
cast<EnumMetadata>(srcType)->getGenericArgs()[0];
unsigned enumCase =
- swift_getEnumCaseSinglePayload(src, payloadType, 1 /*emptyCases=*/);
+ payloadType->vw_getEnumTagSinglePayload(src, /*emptyCases=*/1);
if (enumCase != 0) {
// Allow Optional<T>.none -> Optional<U>.none
if (targetType->getKind() != MetadataKind::Optional) {
@@ -1889,8 +1889,8 @@
cast<EnumMetadata>(targetType)->getGenericArgs()[0];
// Inject the .none tag
- swift_storeEnumTagSinglePayload(dest, targetPayloadType, enumCase,
- 1 /*emptyCases=*/);
+ targetPayloadType->vw_storeEnumTagSinglePayload(dest, enumCase,
+ /*emptyCases=*/1);
// We don't have to destroy the source, because it was nil.
return {true, nullptr};
@@ -2314,8 +2314,8 @@
const Metadata *payloadType =
cast<EnumMetadata>(targetType)->getGenericArgs()[0];
if (swift_dynamicCast(dest, src, srcType, payloadType, flags)) {
- swift_storeEnumTagSinglePayload(dest, payloadType, 0 /*case*/,
- 1 /*emptyCases*/);
+ payloadType->vw_storeEnumTagSinglePayload(dest, /*case*/ 0,
+ /*emptyCases*/ 1);
return true;
}
return false;
@@ -2720,8 +2720,8 @@
}
// Initialize the buffer as an empty optional.
- swift_storeEnumTagSinglePayload((OpaqueValue *)optDestBuffer, targetType,
- 1, 1);
+ targetType->vw_storeEnumTagSinglePayload((OpaqueValue *)optDestBuffer,
+ 1, 1);
// Perform the bridging operation.
bool success;
diff --git a/stdlib/public/runtime/Enum.cpp b/stdlib/public/runtime/Enum.cpp
index 83a519a..e693495 100644
--- a/stdlib/public/runtime/Enum.cpp
+++ b/stdlib/public/runtime/Enum.cpp
@@ -55,11 +55,6 @@
layout.stride = payloadLayout->stride;
layout.flags = payloadLayout->flags.withEnumWitnesses(true);
- if (payloadLayout->flags.hasExtraInhabitants()) {
- auto ew = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
- ew->extraInhabitantFlags = payloadLayout->getExtraInhabitantFlags();
- }
-
vwtable->publishLayout(layout);
}
@@ -93,10 +88,11 @@
TypeLayout layout;
layout.size = size;
layout.flags =
- payloadLayout->flags.withExtraInhabitants(unusedExtraInhabitants > 0)
+ payloadLayout->flags
.withEnumWitnesses(true)
.withInlineStorage(
ValueWitnessTable::isValueInline(isBT, size, align));
+ layout.extraInhabitantCount = unusedExtraInhabitants;
auto rawStride = llvm::alignTo(size, align);
layout.stride = rawStride == 0 ? 1 : rawStride;
@@ -127,53 +123,39 @@
}
#endif
-
- // If the payload has extra inhabitants left over after the ones we used,
- // forward them as our own.
- if (unusedExtraInhabitants > 0) {
- auto xiVWTable = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
- xiVWTable->extraInhabitantFlags = ExtraInhabitantFlags()
- .withNumExtraInhabitants(unusedExtraInhabitants);
- }
-
vwtable->publishLayout(layout);
}
-unsigned swift::swift_getEnumCaseSinglePayload(const OpaqueValue *value,
- const Metadata *payload,
- unsigned emptyCases) {
-
- auto *payloadWitnesses = payload->getValueWitnesses();
- auto size = payloadWitnesses->getSize();
- auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
- auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
-
- return getEnumTagSinglePayloadImpl(value, emptyCases, payload, size,
+unsigned
+swift::swift_getEnumTagSinglePayloadGeneric(const OpaqueValue *value,
+ unsigned emptyCases,
+ const Metadata *payloadType,
+ getExtraInhabitantTag_t *getExtraInhabitantTag) {
+ auto size = payloadType->vw_size();
+ auto numExtraInhabitants = payloadType->vw_getNumExtraInhabitants();
+ return getEnumTagSinglePayloadImpl(value, emptyCases, payloadType, size,
numExtraInhabitants,
- getExtraInhabitantIndex);
+ getExtraInhabitantTag);
}
-void swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
- const Metadata *payload,
- unsigned whichCase,
- unsigned emptyCases) {
-
- auto *payloadWitnesses = payload->getValueWitnesses();
- auto size = payloadWitnesses->getSize();
- auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
- auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
-
- storeEnumTagSinglePayloadImpl(value, whichCase, emptyCases, payload, size,
- numExtraInhabitants, storeExtraInhabitant);
+void swift::swift_storeEnumTagSinglePayloadGeneric(OpaqueValue *value,
+ unsigned whichCase,
+ unsigned emptyCases,
+ const Metadata *payloadType,
+ storeExtraInhabitantTag_t *storeExtraInhabitantTag) {
+ auto size = payloadType->vw_size();
+ auto numExtraInhabitants = payloadType->vw_getNumExtraInhabitants();
+ storeEnumTagSinglePayloadImpl(value, whichCase, emptyCases, payloadType, size,
+ numExtraInhabitants, storeExtraInhabitantTag);
}
-static int32_t getMultiPayloadExtraInhabitantIndex(const OpaqueValue *value,
- const Metadata *enumType);
-static void storeMultiPayloadExtraInhabitant(OpaqueValue *value,
- int32_t index,
- const Metadata *enumType);
+static uint32_t getMultiPayloadEnumTagSinglePayload(const OpaqueValue *value,
+ uint32_t numExtraCases,
+ const Metadata *enumType);
+static void storeMultiPayloadEnumTagSinglePayload(OpaqueValue *value,
+ uint32_t index,
+ uint32_t numExtraCases,
+ const Metadata *enumType);
void
swift::swift_initEnumMetadataMultiPayload(EnumMetadata *enumType,
@@ -205,32 +187,32 @@
unsigned numExtraInhabitants = tagCounts.numTagBytes == 4
? INT_MAX
: (1 << (tagCounts.numTagBytes * 8)) - tagCounts.numTags;
+ numExtraInhabitants = std::min(numExtraInhabitants,
+ unsigned(ValueWitnessFlags::MaxNumExtraInhabitants));
auto vwtable = getMutableVWTableForInit(enumType, layoutFlags);
// Set up the layout info in the vwtable.
auto rawStride = (totalSize + alignMask) & ~alignMask;
TypeLayout layout{totalSize,
+ rawStride == 0 ? 1 : rawStride,
ValueWitnessFlags()
.withAlignmentMask(alignMask)
.withPOD(isPOD)
.withBitwiseTakable(isBT)
- .withExtraInhabitants(numExtraInhabitants > 0)
.withEnumWitnesses(true)
.withInlineStorage(ValueWitnessTable::isValueInline(
isBT, totalSize, alignMask + 1)),
- rawStride == 0 ? 1 : rawStride,
- numExtraInhabitants > 0
- ? ExtraInhabitantFlags()
- .withNumExtraInhabitants(numExtraInhabitants)
- : ExtraInhabitantFlags()};
+ numExtraInhabitants};
installCommonValueWitnesses(layout, vwtable);
- if (numExtraInhabitants > 0) {
- vwtable->extraInhabitantFlags = layout.getExtraInhabitantFlags();
- vwtable->storeExtraInhabitant = storeMultiPayloadExtraInhabitant;
- vwtable->getExtraInhabitantIndex = getMultiPayloadExtraInhabitantIndex;
- }
+
+ // Unconditionally overwrite the enum-tag witnesses.
+ // The compiler does not generate meaningful enum-tag witnesses for
+ // enums in this state.
+ vwtable->getEnumTagSinglePayload = getMultiPayloadEnumTagSinglePayload;
+ vwtable->storeEnumTagSinglePayload = storeMultiPayloadEnumTagSinglePayload;
+
vwtable->publishLayout(layout);
}
@@ -320,22 +302,45 @@
return payloadValue;
}
-static int32_t getMultiPayloadExtraInhabitantIndex(const OpaqueValue *value,
- const Metadata *enumType) {
+SWIFT_CC(swift)
+static unsigned getMultiPayloadExtraInhabitantTag(const OpaqueValue *value,
+ unsigned enumNumXI,
+ const Metadata *enumType) {
auto layout = getMultiPayloadLayout(cast<EnumMetadata>(enumType));
unsigned index = ~loadMultiPayloadTag(value, layout, ~0u);
if (index >= enumType->getValueWitnesses()->getNumExtraInhabitants())
- return -1;
- return index;
-}
-static void storeMultiPayloadExtraInhabitant(OpaqueValue *value,
- int32_t index,
- const Metadata *enumType) {
- auto layout = getMultiPayloadLayout(cast<EnumMetadata>(enumType));
- storeMultiPayloadTag(value, layout, ~index);
+ return 0;
+ return index + 1;
}
+SWIFT_CC(swift)
+static void storeMultiPayloadExtraInhabitantTag(OpaqueValue *value,
+ unsigned tag,
+ unsigned enumNumXI,
+ const Metadata *enumType) {
+ auto layout = getMultiPayloadLayout(cast<EnumMetadata>(enumType));
+ storeMultiPayloadTag(value, layout, ~(tag - 1));
+}
+
+static uint32_t getMultiPayloadEnumTagSinglePayload(const OpaqueValue *value,
+ uint32_t numExtraCases,
+ const Metadata *enumType) {
+ return getEnumTagSinglePayloadImpl(value, numExtraCases, enumType,
+ enumType->vw_size(),
+ enumType->vw_getNumExtraInhabitants(),
+ getMultiPayloadExtraInhabitantTag);
+}
+
+static void storeMultiPayloadEnumTagSinglePayload(OpaqueValue *value,
+ uint32_t index,
+ uint32_t numExtraCases,
+ const Metadata *enumType) {
+ storeEnumTagSinglePayloadImpl(value, index, numExtraCases, enumType,
+ enumType->vw_size(),
+ enumType->vw_getNumExtraInhabitants(),
+ storeMultiPayloadExtraInhabitantTag);
+}
void
swift::swift_storeEnumTagMultiPayload(OpaqueValue *value,
diff --git a/stdlib/public/runtime/EnumImpl.h b/stdlib/public/runtime/EnumImpl.h
index d0471f9..755504b 100644
--- a/stdlib/public/runtime/EnumImpl.h
+++ b/stdlib/public/runtime/EnumImpl.h
@@ -17,6 +17,7 @@
#define SWIFT_RUNTIME_ENUMIMPL_H
#include "swift/ABI/Enum.h"
+#include "swift/Runtime/Enum.h"
namespace swift {
@@ -63,8 +64,8 @@
inline unsigned getEnumTagSinglePayloadImpl(
const OpaqueValue *enumAddr, unsigned emptyCases, const Metadata *payload,
- size_t payloadSize, size_t payloadNumExtraInhabitants,
- int (*getExtraInhabitantIndex)(const OpaqueValue *, const Metadata *)) {
+ size_t payloadSize, unsigned payloadNumExtraInhabitants,
+ getExtraInhabitantTag_t *getExtraInhabitantTag) {
// If there are extra tag bits, check them.
if (emptyCases > payloadNumExtraInhabitants) {
@@ -116,7 +117,7 @@
// If there are extra inhabitants, see whether the payload is valid.
if (payloadNumExtraInhabitants > 0) {
- return getExtraInhabitantIndex(enumAddr, payload) + 1;
+ return getExtraInhabitantTag(enumAddr, payloadNumExtraInhabitants, payload);
}
// Otherwise, we have always have a valid payload.
@@ -126,9 +127,8 @@
inline void storeEnumTagSinglePayloadImpl(
OpaqueValue *value, unsigned whichCase, unsigned emptyCases,
const Metadata *payload, size_t payloadSize,
- size_t payloadNumExtraInhabitants,
- void (*storeExtraInhabitant)(OpaqueValue *, int whichCase,
- const Metadata *)) {
+ unsigned payloadNumExtraInhabitants,
+ storeExtraInhabitantTag_t *storeExtraInhabitantTag) {
auto *valueAddr = reinterpret_cast<uint8_t *>(value);
auto *extraTagBitAddr = valueAddr + payloadSize;
@@ -150,8 +150,8 @@
return;
// Store the extra inhabitant.
- unsigned noPayloadIndex = whichCase - 1;
- storeExtraInhabitant(value, noPayloadIndex, payload);
+ storeExtraInhabitantTag(value, whichCase, payloadNumExtraInhabitants,
+ payload);
return;
}
diff --git a/stdlib/public/runtime/ExistentialMetadataImpl.h b/stdlib/public/runtime/ExistentialMetadataImpl.h
index 1eed70b..e8951c5 100644
--- a/stdlib/public/runtime/ExistentialMetadataImpl.h
+++ b/stdlib/public/runtime/ExistentialMetadataImpl.h
@@ -331,16 +331,16 @@
static constexpr unsigned numExtraInhabitants =
swift_getHeapObjectExtraInhabitantCount();
- static void storeExtraInhabitant(Container *dest, int index) {
+ static void storeExtraInhabitantTag(Container *dest, unsigned tag) {
swift_storeHeapObjectExtraInhabitant(
const_cast<HeapObject **>(
reinterpret_cast<const HeapObject **>(&dest->Header.Type)),
- index);
+ tag - 1);
}
- static int getExtraInhabitantIndex(const Container *src) {
+ static unsigned getExtraInhabitantTag(const Container *src) {
return swift_getHeapObjectExtraInhabitantIndex(const_cast<HeapObject **>(
- reinterpret_cast<const HeapObject *const *>(&src->Header.Type)));
+ reinterpret_cast<const HeapObject *const *>(&src->Header.Type))) + 1;
}
};
@@ -387,14 +387,14 @@
static constexpr unsigned numExtraInhabitants =
swift_getHeapObjectExtraInhabitantCount();
- static void storeExtraInhabitant(Container *dest, int index) {
+ static void storeExtraInhabitantTag(Container *dest, unsigned tag) {
swift_storeHeapObjectExtraInhabitant(
- (HeapObject**)(uintptr_t)&dest->Header.Type, index);
+ (HeapObject**)(uintptr_t)&dest->Header.Type, tag - 1);
}
- static int getExtraInhabitantIndex(const Container *src) {
+ static unsigned getExtraInhabitantTag(const Container *src) {
return swift_getHeapObjectExtraInhabitantIndex(
- (HeapObject* const *)(uintptr_t)&src->Header.Type);
+ (HeapObject* const *)(uintptr_t)&src->Header.Type) + 1;
}
};
@@ -452,15 +452,15 @@
}
template <class Container, class... A>
- static void storeExtraInhabitant(Container *dest, int index, A... args) {
+ static void storeExtraInhabitantTag(Container *dest, unsigned tag, A... args) {
swift_storeHeapObjectExtraInhabitant((HeapObject**) dest->getValueSlot(),
- index);
+ tag - 1);
}
template <class Container, class... A>
- static int getExtraInhabitantIndex(const Container *src, A... args) {
+ static int getExtraInhabitantTag(const Container *src, A... args) {
return swift_getHeapObjectExtraInhabitantIndex(
- (HeapObject* const *) src->getValueSlot());
+ (HeapObject* const *) src->getValueSlot()) + 1;
}
};
@@ -574,17 +574,17 @@
}
template <class Container, class... A>
- static void storeExtraInhabitant(Container *dest, int index, A... args) {
+ static void storeExtraInhabitantTag(Container *dest, unsigned tag, A... args) {
Metadata **MD = const_cast<Metadata **>(dest->getValueSlot());
swift_storeHeapObjectExtraInhabitant(reinterpret_cast<HeapObject **>(MD),
- index);
+ tag - 1);
}
template <class Container, class... A>
- static int getExtraInhabitantIndex(const Container *src, A... args) {
+ static int getExtraInhabitantTag(const Container *src, A... args) {
Metadata **MD = const_cast<Metadata **>(src->getValueSlot());
return swift_getHeapObjectExtraInhabitantIndex(
- reinterpret_cast<HeapObject *const *>(MD));
+ reinterpret_cast<HeapObject *const *>(MD)) + 1;
}
};
diff --git a/stdlib/public/runtime/KnownMetadata.cpp b/stdlib/public/runtime/KnownMetadata.cpp
index bc9b49e..2c24db7 100644
--- a/stdlib/public/runtime/KnownMetadata.cpp
+++ b/stdlib/public/runtime/KnownMetadata.cpp
@@ -157,7 +157,7 @@
BuiltinType<ctypes::Symbol>::Alignment>>::table;
#define BUILTIN_POINTER_TYPE(Symbol, Name) \
-const ExtraInhabitantsValueWitnessTable swift::VALUE_WITNESS_SYM(Symbol) = \
+const ValueWitnessTable swift::VALUE_WITNESS_SYM(Symbol) = \
ValueWitnessTableForBox<pointer_types::Symbol>::table;
#define BUILTIN_VECTOR_TYPE(ElementSymbol, _, Width) \
@@ -169,7 +169,7 @@
#include "swift/Runtime/BuiltinTypes.def"
/// The value-witness table for pointer-aligned unmanaged pointer types.
-const ExtraInhabitantsValueWitnessTable swift::METATYPE_VALUE_WITNESS_SYM(Bo) =
+const ValueWitnessTable swift::METATYPE_VALUE_WITNESS_SYM(Bo) =
ValueWitnessTableForBox<PointerPointerBox>::table;
/*** Functions ***************************************************************/
@@ -182,12 +182,12 @@
static constexpr unsigned numExtraInhabitants =
FunctionPointerBox::numExtraInhabitants;
- static void storeExtraInhabitant(char *dest, int index) {
- FunctionPointerBox::storeExtraInhabitant((void**) dest, index);
+ static void storeExtraInhabitantTag(char *dest, unsigned tag) {
+ FunctionPointerBox::storeExtraInhabitantTag((void**) dest, tag);
}
- static int getExtraInhabitantIndex(const char *src) {
- return FunctionPointerBox::getExtraInhabitantIndex((void * const *) src);
+ static unsigned getExtraInhabitantTag(const char *src) {
+ return FunctionPointerBox::getExtraInhabitantTag((void * const *) src);
}
};
/// @noescape function types.
@@ -197,28 +197,28 @@
static constexpr unsigned numExtraInhabitants =
FunctionPointerBox::numExtraInhabitants;
- static void storeExtraInhabitant(char *dest, int index) {
- FunctionPointerBox::storeExtraInhabitant((void **)dest, index);
+ static void storeExtraInhabitantTag(char *dest, unsigned tag) {
+ FunctionPointerBox::storeExtraInhabitantTag((void **)dest, tag);
}
- static int getExtraInhabitantIndex(const char *src) {
- return FunctionPointerBox::getExtraInhabitantIndex((void *const *)src);
+ static unsigned getExtraInhabitantTag(const char *src) {
+ return FunctionPointerBox::getExtraInhabitantTag((void *const *)src);
}
};
} // end anonymous namespace
/// The basic value-witness table for escaping function types.
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
swift::VALUE_WITNESS_SYM(FUNCTION_MANGLING) =
ValueWitnessTableForBox<ThickFunctionBox>::table;
/// The basic value-witness table for @noescape function types.
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
swift::VALUE_WITNESS_SYM(NOESCAPE_FUNCTION_MANGLING) =
ValueWitnessTableForBox<TrivialThickFunctionBox>::table;
/// The basic value-witness table for thin function types.
-const ExtraInhabitantsValueWitnessTable
+const ValueWitnessTable
swift::VALUE_WITNESS_SYM(THIN_FUNCTION_MANGLING) =
ValueWitnessTableForBox<FunctionPointerBox>::table;
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index a6c93e6..91654b9 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1039,7 +1039,7 @@
// NOTE: if you change the layout of this type, you'll also need
// to update tuple_getValueWitnesses().
unsigned ExtraInhabitantProvidingElement;
- ExtraInhabitantsValueWitnessTable Witnesses;
+ ValueWitnessTable Witnesses;
FullMetadata<TupleTypeMetadata> Data;
struct Key {
@@ -1151,7 +1151,7 @@
/// Given a metatype pointer, produce the value-witness table for it.
/// This is equivalent to metatype->ValueWitnesses but more efficient.
static const ValueWitnessTable *tuple_getValueWitnesses(const Metadata *metatype) {
- return ((const ExtraInhabitantsValueWitnessTable*) asFullMetadata(metatype)) - 1;
+ return ((const ValueWitnessTable*) asFullMetadata(metatype)) - 1;
}
/// Generic tuple value witness for 'projectBuffer'.
@@ -1309,29 +1309,37 @@
return tuple_projectBuffer<IsPOD, IsInline>(dest, metatype);
}
-static void tuple_storeExtraInhabitant(OpaqueValue *tuple,
- int index,
- const Metadata *_metatype) {
+SWIFT_CC(swift)
+static void tuple_storeExtraInhabitantTag(OpaqueValue *tuple,
+ unsigned tag,
+ unsigned xiCount,
+ const Metadata *_metatype) {
auto &metatype = *(const TupleTypeMetadata*) _metatype;
auto cacheEntry = TupleCacheStorage::resolveExistingEntry(&metatype);
auto &eltInfo =
metatype.getElement(cacheEntry->ExtraInhabitantProvidingElement);
+ assert(xiCount == eltInfo.Type->vw_getNumExtraInhabitants());
auto *elt = (OpaqueValue*)((uintptr_t)tuple + eltInfo.Offset);
- eltInfo.Type->vw_storeExtraInhabitant(elt, index);
+ assert(tag >= 1);
+ assert(tag <= xiCount);
+ eltInfo.Type->vw_storeEnumTagSinglePayload(elt, tag, xiCount);
}
-static int tuple_getExtraInhabitantIndex(const OpaqueValue *tuple,
- const Metadata *_metatype) {
+SWIFT_CC(swift)
+static unsigned tuple_getExtraInhabitantTag(const OpaqueValue *tuple,
+ unsigned xiCount,
+ const Metadata *_metatype) {
auto &metatype = *(const TupleTypeMetadata*) _metatype;
auto cacheEntry = TupleCacheStorage::resolveExistingEntry(&metatype);
auto &eltInfo =
metatype.getElement(cacheEntry->ExtraInhabitantProvidingElement);
+ assert(xiCount == eltInfo.Type->vw_getNumExtraInhabitants());
auto *elt = (const OpaqueValue*)((uintptr_t)tuple + eltInfo.Offset);
- return eltInfo.Type->vw_getExtraInhabitantIndex(elt);
+ return eltInfo.Type->vw_getEnumTagSinglePayload(elt, xiCount);
}
template <bool IsPOD, bool IsInline>
@@ -1342,12 +1350,11 @@
auto *witnesses = tuple_getValueWitnesses(self);
auto size = witnesses->getSize();
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
- auto getExtraInhabitantIndex = numExtraInhabitants > 0
- ? tuple_getExtraInhabitantIndex : nullptr;
+ auto getExtraInhabitantTag = tuple_getExtraInhabitantTag;
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
numExtraInhabitants,
- getExtraInhabitantIndex);
+ getExtraInhabitantTag);
}
template <bool IsPOD, bool IsInline>
@@ -1357,11 +1364,10 @@
auto *witnesses = tuple_getValueWitnesses(self);
auto size = witnesses->getSize();
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
- auto storeExtraInhabitant = numExtraInhabitants > 0
- ? tuple_storeExtraInhabitant : nullptr;
+ auto storeExtraInhabitantTag = tuple_storeExtraInhabitantTag;
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
- numExtraInhabitants, storeExtraInhabitant);
+ numExtraInhabitants, storeExtraInhabitantTag);
}
/// Various standard witness table for tuples.
@@ -1371,6 +1377,7 @@
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
#include "swift/ABI/ValueWitness.def"
0,
+ 0,
ValueWitnessFlags(),
0
};
@@ -1380,6 +1387,7 @@
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
#include "swift/ABI/ValueWitness.def"
0,
+ 0,
ValueWitnessFlags(),
0
};
@@ -1389,6 +1397,7 @@
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
#include "swift/ABI/ValueWitness.def"
0,
+ 0,
ValueWitnessFlags(),
0
};
@@ -1398,18 +1407,20 @@
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
#include "swift/ABI/ValueWitness.def"
0,
+ 0,
ValueWitnessFlags(),
0
};
static constexpr TypeLayout getInitialLayoutForValueType() {
- return {0, ValueWitnessFlags().withAlignment(1).withPOD(true), 0};
+ return {0, 0, ValueWitnessFlags().withAlignment(1).withPOD(true), 0};
}
static constexpr TypeLayout getInitialLayoutForHeapObject() {
return {sizeof(HeapObject),
+ sizeof(HeapObject),
ValueWitnessFlags().withAlignment(alignof(HeapObject)),
- sizeof(HeapObject)};
+ 0};
}
static size_t roundUpToAlignMask(size_t size, size_t alignMask) {
@@ -1460,6 +1471,7 @@
.withPOD(isPOD)
.withBitwiseTakable(isBitwiseTakable)
.withInlineStorage(isInline);
+ layout.extraInhabitantCount = 0;
layout.stride = std::max(size_t(1), roundUpToAlignMask(size, alignMask));
}
@@ -1505,10 +1517,9 @@
if (numExtraInhabitants > 0) {
*result = TypeLayout(result->size,
- result->flags.withExtraInhabitants(true),
result->stride,
- ExtraInhabitantFlags()
- .withNumExtraInhabitants(numExtraInhabitants));
+ result->flags,
+ numExtraInhabitants);
}
}
@@ -1649,22 +1660,16 @@
unsigned extraInhabitantProvidingElement = ~0u;
unsigned numExtraInhabitants = 0;
for (unsigned i = 0, e = Data.NumElements; i < e; ++i) {
- if (auto eltEIVWI = dyn_cast<ExtraInhabitantsValueWitnessTable>(
- Data.getElement(i).Type->getValueWitnesses())) {
- unsigned eltEI = eltEIVWI->extraInhabitantFlags.getNumExtraInhabitants();
- if (eltEI > numExtraInhabitants) {
- extraInhabitantProvidingElement = i;
- numExtraInhabitants = eltEI;
- }
+ unsigned eltEI = Data.getElement(i).Type->getValueWitnesses()
+ ->getNumExtraInhabitants();
+ if (eltEI > numExtraInhabitants) {
+ extraInhabitantProvidingElement = i;
+ numExtraInhabitants = eltEI;
}
}
+ Witnesses.extraInhabitantCount = numExtraInhabitants;
if (numExtraInhabitants > 0) {
ExtraInhabitantProvidingElement = extraInhabitantProvidingElement;
- Witnesses.flags = Witnesses.flags.withExtraInhabitants(true);
- Witnesses.extraInhabitantFlags = ExtraInhabitantFlags()
- .withNumExtraInhabitants(numExtraInhabitants);
- Witnesses.storeExtraInhabitant = tuple_storeExtraInhabitant;
- Witnesses.getExtraInhabitantIndex = tuple_getExtraInhabitantIndex;
}
// Copy the function witnesses in, either from the proposed
@@ -1882,61 +1887,21 @@
return reinterpret_cast<OpaqueValue *>(bytePtr + byteOffset);
}
-static void pod_noop(void *object, const Metadata *self) {
-}
-#define pod_direct_destroy \
- pointer_function_cast<ValueWitnessTypes::destroy>(pod_noop)
-#define pod_indirect_destroy pod_direct_destroy
+static void pod_destroy(OpaqueValue *object, const Metadata *self) {}
-static OpaqueValue *pod_direct_initializeWithCopy(OpaqueValue *dest,
- OpaqueValue *src,
- const Metadata *self) {
+static OpaqueValue *pod_copy(OpaqueValue *dest, OpaqueValue *src,
+ const Metadata *self) {
memcpy(dest, src, self->getValueWitnesses()->size);
return dest;
}
-#define pod_indirect_initializeWithCopy pod_direct_initializeWithCopy
-#define pod_direct_initializeBufferWithCopyOfBuffer \
- pointer_function_cast<ValueWitnessTypes::initializeBufferWithCopyOfBuffer> \
- (pod_direct_initializeWithCopy)
-#define pod_direct_assignWithCopy pod_direct_initializeWithCopy
-#define pod_indirect_assignWithCopy pod_direct_initializeWithCopy
-#define pod_direct_initializeWithTake pod_direct_initializeWithCopy
-#define pod_indirect_initializeWithTake pod_direct_initializeWithCopy
-#define pod_direct_assignWithTake pod_direct_initializeWithCopy
-#define pod_indirect_assignWithTake pod_direct_initializeWithCopy
-static unsigned pod_direct_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
- unsigned numEmptyCases,
- const Metadata *self) {
- auto *witnesses = self->getValueWitnesses();
- auto size = witnesses->getSize();
- auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
- auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
-
- return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
- numExtraInhabitants,
- getExtraInhabitantIndex);
+static OpaqueValue *pod_direct_initializeBufferWithCopyOfBuffer(
+ ValueBuffer *dest, ValueBuffer *src, const Metadata *self) {
+ return pod_copy(reinterpret_cast<OpaqueValue*>(dest),
+ reinterpret_cast<OpaqueValue*>(src),
+ self);
}
-static void pod_direct_storeEnumTagSinglePayload(OpaqueValue *enumAddr,
- unsigned whichCase,
- unsigned numEmptyCases,
- const Metadata *self) {
- auto *witnesses = self->getValueWitnesses();
- auto size = witnesses->getSize();
- auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
- auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
-
- storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
- numExtraInhabitants, storeExtraInhabitant);
-}
-
-#define pod_indirect_getEnumTagSinglePayload pod_direct_getEnumTagSinglePayload
-#define pod_indirect_storeEnumTagSinglePayload \
- pod_direct_storeEnumTagSinglePayload
-
static constexpr uint64_t sizeWithAlignmentMask(uint64_t size,
uint64_t alignmentMask,
uint64_t hasExtraInhabitants) {
@@ -1951,25 +1916,26 @@
// If the value has a common size and alignment, use specialized value
// witnesses we already have lying around for the builtin types.
const ValueWitnessTable *commonVWT;
- bool hasExtraInhabitants = flags.hasExtraInhabitants();
+ bool hasExtraInhabitants = layout.hasExtraInhabitants();
switch (sizeWithAlignmentMask(layout.size, flags.getAlignmentMask(),
hasExtraInhabitants)) {
default:
// For uncommon layouts, use value witnesses that work with an arbitrary
// size and alignment.
if (flags.isInlineStorage()) {
-#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
- vwtable->LOWER_ID = pod_direct_##LOWER_ID;
-#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
-#include "swift/ABI/ValueWitness.def"
+ vwtable->initializeBufferWithCopyOfBuffer =
+ pod_direct_initializeBufferWithCopyOfBuffer;
} else {
-#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
- vwtable->LOWER_ID = pod_indirect_##LOWER_ID;
-#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
-#include "swift/ABI/ValueWitness.def"
+ vwtable->initializeBufferWithCopyOfBuffer =
+ pod_indirect_initializeBufferWithCopyOfBuffer;
}
+ vwtable->destroy = pod_destroy;
+ vwtable->initializeWithCopy = pod_copy;
+ vwtable->initializeWithTake = pod_copy;
+ vwtable->assignWithCopy = pod_copy;
+ vwtable->assignWithTake = pod_copy;
+ // getEnumTagSinglePayload and storeEnumTagSinglePayload are not
+ // interestingly optimizable based on POD-ness.
return;
case sizeWithAlignmentMask(1, 0, 0):
@@ -2006,11 +1972,7 @@
if (flags.isBitwiseTakable()) {
// Use POD value witnesses for operations that do an initializeWithTake.
- if (flags.isInlineStorage()) {
- vwtable->initializeWithTake = pod_direct_initializeWithTake;
- } else {
- vwtable->initializeWithTake = pod_indirect_initializeWithTake;
- }
+ vwtable->initializeWithTake = pod_copy;
return;
}
@@ -2021,8 +1983,7 @@
/***************************************************************************/
static ValueWitnessTable *getMutableVWTableForInit(StructMetadata *self,
- StructLayoutFlags flags,
- bool hasExtraInhabitants) {
+ StructLayoutFlags flags) {
auto oldTable = self->getValueWitnesses();
// If we can alter the existing table in-place, do so.
@@ -2030,17 +1991,9 @@
return const_cast<ValueWitnessTable*>(oldTable);
// Otherwise, allocate permanent memory for it and copy the existing table.
- ValueWitnessTable *newTable;
- if (hasExtraInhabitants) {
- void *memory = allocateMetadata(sizeof(ExtraInhabitantsValueWitnessTable),
- alignof(ExtraInhabitantsValueWitnessTable));
- newTable = new (memory) ExtraInhabitantsValueWitnessTable(
- *static_cast<const ExtraInhabitantsValueWitnessTable*>(oldTable));
- } else {
- void *memory = allocateMetadata(sizeof(ValueWitnessTable),
- alignof(ValueWitnessTable));
- newTable = new (memory) ValueWitnessTable(*oldTable);
- }
+ void *memory = allocateMetadata(sizeof(ValueWitnessTable),
+ alignof(ValueWitnessTable));
+ auto newTable = new (memory) ValueWitnessTable(*oldTable);
// If we ever need to check layout-completeness asynchronously from
// initialization, we'll need this to be a store-release (and rely on
@@ -2066,33 +2019,18 @@
});
// We have extra inhabitants if any element does. Use the field with the most.
- unsigned extraInhabitantField = ~0u;
unsigned extraInhabitantCount = 0;
for (unsigned i = 0; i < numFields; ++i) {
- if (!fieldTypes[i]->flags.hasExtraInhabitants())
- continue;
unsigned fieldExtraInhabitantCount =
- fieldTypes[i]->getExtraInhabitantFlags().getNumExtraInhabitants();
+ fieldTypes[i]->getNumExtraInhabitants();
if (fieldExtraInhabitantCount > extraInhabitantCount) {
- extraInhabitantField = i;
extraInhabitantCount = fieldExtraInhabitantCount;
}
}
-
- auto vwtable =
- getMutableVWTableForInit(structType, layoutFlags,
- extraInhabitantCount > 0);
- if (extraInhabitantCount > 0) {
- layout.flags = layout.flags.withExtraInhabitants(true);
- auto xiVWT = static_cast<ExtraInhabitantsValueWitnessTable*>(vwtable);
- xiVWT->extraInhabitantFlags =
- fieldTypes[extraInhabitantField]->getExtraInhabitantFlags();
+ auto vwtable = getMutableVWTableForInit(structType, layoutFlags);
- // The compiler should already have initialized these.
- assert(xiVWT->storeExtraInhabitant);
- assert(xiVWT->getExtraInhabitantIndex);
- }
+ layout.extraInhabitantCount = extraInhabitantCount;
// Substitute in better value witnesses if we have them.
installCommonValueWitnesses(layout, vwtable);
@@ -2878,7 +2816,7 @@
/// A cache entry for existential metatype witness tables.
class ExistentialMetatypeValueWitnessTableCacheEntry {
public:
- ExtraInhabitantsValueWitnessTable Data;
+ ValueWitnessTable Data;
unsigned getNumWitnessTables() const {
return (Data.size - sizeof(ExistentialMetatypeContainer))
@@ -2934,16 +2872,16 @@
/// The uniquing structure for existential metatype type metadata.
static SimpleGlobalCache<ExistentialMetatypeCacheEntry> ExistentialMetatypes;
-static const ExtraInhabitantsValueWitnessTable
+static const ValueWitnessTable
ExistentialMetatypeValueWitnesses_1 =
ValueWitnessTableForBox<ExistentialMetatypeBox<1>>::table;
-static const ExtraInhabitantsValueWitnessTable
+static const ValueWitnessTable
ExistentialMetatypeValueWitnesses_2 =
ValueWitnessTableForBox<ExistentialMetatypeBox<2>>::table;
/// Instantiate a value witness table for an existential metatype
/// container with the given number of witness table pointers.
-static const ExtraInhabitantsValueWitnessTable *
+static const ValueWitnessTable *
getExistentialMetatypeValueWitnesses(unsigned numWitnessTables) {
if (numWitnessTables == 0)
return &getUnmanagedPointerPointerValueWitnesses();
@@ -2977,11 +2915,9 @@
.withAlignment(Box::Container::getAlignment(numWitnessTables))
.withPOD(true)
.withBitwiseTakable(true)
- .withInlineStorage(false)
- .withExtraInhabitants(true);
+ .withInlineStorage(false);
Data.stride = Box::Container::getStride(numWitnessTables);
- Data.extraInhabitantFlags = ExtraInhabitantFlags()
- .withNumExtraInhabitants(Witnesses::numExtraInhabitants);
+ Data.extraInhabitantCount = Witnesses::numExtraInhabitants;
assert(getNumWitnessTables() == numWitnessTables);
}
@@ -3073,7 +3009,7 @@
class OpaqueExistentialValueWitnessTableCacheEntry {
public:
- ExtraInhabitantsValueWitnessTable Data;
+ ValueWitnessTable Data;
OpaqueExistentialValueWitnessTableCacheEntry(unsigned numTables);
@@ -3100,7 +3036,7 @@
class ClassExistentialValueWitnessTableCacheEntry {
public:
- ExtraInhabitantsValueWitnessTable Data;
+ ValueWitnessTable Data;
ClassExistentialValueWitnessTableCacheEntry(unsigned numTables);
@@ -3130,10 +3066,10 @@
/// The uniquing structure for existential type metadata.
static SimpleGlobalCache<ExistentialCacheEntry> ExistentialTypes;
-static const ExtraInhabitantsValueWitnessTable
+static const ValueWitnessTable
OpaqueExistentialValueWitnesses_0 =
ValueWitnessTableForBox<OpaqueExistentialBox<0>>::table;
-static const ExtraInhabitantsValueWitnessTable
+static const ValueWitnessTable
OpaqueExistentialValueWitnesses_1 =
ValueWitnessTableForBox<OpaqueExistentialBox<1>>::table;
@@ -3201,22 +3137,16 @@
.withAlignment(Box::Container::getAlignment(numWitnessTables))
.withPOD(false)
.withBitwiseTakable(true)
- .withInlineStorage(false)
- .withExtraInhabitants(true);
+ .withInlineStorage(false);
+ Data.extraInhabitantCount = Witnesses::numExtraInhabitants;
Data.stride = Box::Container::getStride(numWitnessTables);
-
- // Extra inhabitant behavior does not change with the number of witnesses.
- constexpr auto extraInhabitantFlags = Witnesses::extraInhabitantFlags;
- Data.extraInhabitantFlags = extraInhabitantFlags;
- Data.getExtraInhabitantIndex = Witnesses::getExtraInhabitantIndex;
- Data.storeExtraInhabitant = Witnesses::storeExtraInhabitant;
assert(getNumWitnessTables() == numWitnessTables);
}
-static const ExtraInhabitantsValueWitnessTable ClassExistentialValueWitnesses_1 =
+static const ValueWitnessTable ClassExistentialValueWitnesses_1 =
ValueWitnessTableForBox<ClassExistentialBox<1>>::table;
-static const ExtraInhabitantsValueWitnessTable ClassExistentialValueWitnesses_2 =
+static const ValueWitnessTable ClassExistentialValueWitnesses_2 =
ValueWitnessTableForBox<ClassExistentialBox<2>>::table;
/// The uniquing structure for class existential value witness tables.
@@ -3225,7 +3155,7 @@
/// Instantiate a value witness table for a class-constrained existential
/// container with the given number of witness table pointers.
-static const ExtraInhabitantsValueWitnessTable *
+static const ValueWitnessTable *
getClassExistentialValueWitnesses(const Metadata *superclass,
unsigned numWitnessTables) {
// FIXME: If the superclass is not @objc, use native reference counting.
@@ -3266,11 +3196,9 @@
.withAlignment(Box::Container::getAlignment(numWitnessTables))
.withPOD(false)
.withBitwiseTakable(true)
- .withInlineStorage(false)
- .withExtraInhabitants(true);
+ .withInlineStorage(false);
+ Data.extraInhabitantCount = Witnesses::numExtraInhabitants;
Data.stride = Box::Container::getStride(numWitnessTables);
- Data.extraInhabitantFlags = ExtraInhabitantFlags()
- .withNumExtraInhabitants(Witnesses::numExtraInhabitants);
assert(getNumWitnessTables() == numWitnessTables);
}
diff --git a/stdlib/public/runtime/MetadataImpl.h b/stdlib/public/runtime/MetadataImpl.h
index b6677ff..29b63ae 100644
--- a/stdlib/public/runtime/MetadataImpl.h
+++ b/stdlib/public/runtime/MetadataImpl.h
@@ -71,8 +71,8 @@
// static T *assignWithCopy(T *dest, T *src);
// static T *assignWithTake(T *dest, T *src);
// // Only if numExtraInhabitants is non-zero:
-// static void storeExtraInhabitant(T *dest, int index);
-// static int getExtraInhabitantIndex(const T *src);
+// static void storeExtraInhabitantTag(T *dest, unsigned index);
+// static unsigned getExtraInhabitantTag(const T *src);
// };
/// A box class implemented in terms of C/C++ primitive operations.
@@ -178,12 +178,12 @@
static constexpr unsigned numExtraInhabitants =
swift_getHeapObjectExtraInhabitantCount();
- static void storeExtraInhabitant(T *dest, int index) {
- swift_storeHeapObjectExtraInhabitant((HeapObject**) dest, index);
+ static void storeExtraInhabitantTag(T *dest, unsigned tag) {
+ swift_storeHeapObjectExtraInhabitant((HeapObject**) dest, tag - 1);
}
- static int getExtraInhabitantIndex(const T *src) {
- return swift_getHeapObjectExtraInhabitantIndex((HeapObject* const *) src);
+ static unsigned getExtraInhabitantTag(const T *src) {
+ return swift_getHeapObjectExtraInhabitantIndex((HeapObject* const *) src) +1;
}
};
@@ -233,13 +233,13 @@
// disabled.
static constexpr unsigned numExtraInhabitants = 1;
- static void storeExtraInhabitant(HeapObject **dest, int index) {
- assert(index == 0);
+ static void storeExtraInhabitant(HeapObject **dest, unsigned index) {
+ assert(index == 1);
*dest = nullptr;
}
- static int getExtraInhabitantIndex(const HeapObject * const *src) {
- return (*src == nullptr ? 0 : -1);
+ static unsigned getExtraInhabitantTag(const HeapObject * const *src) {
+ return (*src == nullptr ? 1 : 0);
}
#endif
};
@@ -311,12 +311,12 @@
: WeakRetainableBoxBase<ObjCUnownedRetainableBox, UnownedReference> {
static constexpr unsigned numExtraInhabitants = 1;
- static void storeExtraInhabitant(UnownedReference *dest, int index) {
- assert(index == 0);
+ static void storeExtraInhabitantTag(UnownedReference *dest, unsigned index) {
+ assert(index == 1);
dest->Value = nullptr;
}
- static int getExtraInhabitantIndex(const UnownedReference *src) {
- return (src->Value == nullptr ? 0 : -1);
+ static unsigned getExtraInhabitantTag(const UnownedReference *src) {
+ return (src->Value == nullptr ? 1 : 0);
}
static void destroy(UnownedReference *ref) {
@@ -424,12 +424,12 @@
static constexpr unsigned numExtraInhabitants =
swift_getHeapObjectExtraInhabitantCount();
- static void storeExtraInhabitant(void ***dest, int index) {
- swift_storeHeapObjectExtraInhabitant((HeapObject**) dest, index);
+ static void storeExtraInhabitantTag(void ***dest, unsigned tag) {
+ swift_storeHeapObjectExtraInhabitant((HeapObject**) dest, tag - 1);
}
- static int getExtraInhabitantIndex(void ** const *src) {
- return swift_getHeapObjectExtraInhabitantIndex((HeapObject* const *) src);
+ static unsigned getExtraInhabitantTag(void ** const *src) {
+ return swift_getHeapObjectExtraInhabitantIndex((HeapObject* const *) src)+1;
}
};
@@ -440,12 +440,13 @@
struct RawPointerBox : NativeBox<void*> {
static constexpr unsigned numExtraInhabitants = 1;
- static void storeExtraInhabitant(void **dest, int index) {
+ static void storeExtraInhabitantTag(void **dest, unsigned tag) {
+ assert(tag == 1);
*dest = nullptr;
}
- static int getExtraInhabitantIndex(void* const *src) {
- return *src == nullptr ? 0 : -1;
+ static unsigned getExtraInhabitantTag(void* const *src) {
+ return *src == nullptr ? 1 : 0;
}
};
@@ -456,12 +457,12 @@
static constexpr unsigned numExtraInhabitants =
swift_getFunctionPointerExtraInhabitantCount();
- static void storeExtraInhabitant(void **dest, int index) {
- swift_storeFunctionPointerExtraInhabitant(dest, index);
+ static void storeExtraInhabitantTag(void **dest, unsigned tag) {
+ swift_storeFunctionPointerExtraInhabitant(dest, tag - 1);
}
- static int getExtraInhabitantIndex(void * const *src) {
- return swift_getFunctionPointerExtraInhabitantIndex(src);
+ static unsigned getExtraInhabitantTag(void * const *src) {
+ return swift_getFunctionPointerExtraInhabitantIndex(src) + 1;
}
};
@@ -709,8 +710,8 @@
unsigned numEmptyCases,
const Metadata *self) {
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, Size,
- Impl::numExtraInhabitants,
- Impl::getExtraInhabitantIndex);
+ Impl::extraInhabitantCount,
+ Impl::getExtraInhabitantTag);
}
static void storeEnumTagSinglePayload(OpaqueValue *enumAddr,
@@ -718,8 +719,8 @@
unsigned numEmptyCases,
const Metadata *self) {
return storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases,
- self, Size, Impl::numExtraInhabitants,
- Impl::storeExtraInhabitant);
+ self, Size, Impl::extraInhabitantCount,
+ Impl::storeExtraInhabitantTag);
}
};
@@ -768,16 +769,13 @@
static constexpr size_t alignment = Box::alignment;
static constexpr bool isPOD = Box::isPOD;
static constexpr bool isBitwiseTakable = Box::isBitwiseTakable;
- static constexpr unsigned numExtraInhabitants = Box::numExtraInhabitants;
- static constexpr bool hasExtraInhabitants = (numExtraInhabitants != 0);
+ static constexpr unsigned extraInhabitantCount = Box::numExtraInhabitants;
+ static constexpr bool hasExtraInhabitants = (extraInhabitantCount != 0);
static constexpr ValueWitnessFlags flags =
ValueWitnessFlags().withAlignmentMask(alignment - 1)
.withInlineStorage(Base::isInline && isBitwiseTakable)
.withPOD(isPOD)
- .withBitwiseTakable(isBitwiseTakable)
- .withExtraInhabitants(hasExtraInhabitants);
- static constexpr ExtraInhabitantFlags extraInhabitantFlags =
- ExtraInhabitantFlags().withNumExtraInhabitants(numExtraInhabitants);
+ .withBitwiseTakable(isBitwiseTakable);
static void destroy(OpaqueValue *value, const Metadata *self) {
return Box::destroy((typename Box::type*) value);
@@ -810,14 +808,17 @@
// These should not get instantiated if the type doesn't have extra
// inhabitants.
- static void storeExtraInhabitant(OpaqueValue *dest, int index,
- const Metadata *self) {
- Box::storeExtraInhabitant((typename Box::type*) dest, index);
+ SWIFT_CC(swift)
+ static void storeExtraInhabitantTag(OpaqueValue *dest, unsigned tag,
+ unsigned xiCount, const Metadata *self) {
+ Box::storeExtraInhabitantTag((typename Box::type*) dest, tag);
}
- static int getExtraInhabitantIndex(const OpaqueValue *src,
- const Metadata *self) {
- return Box::getExtraInhabitantIndex((typename Box::type const *) src);
+ SWIFT_CC(swift)
+ static unsigned getExtraInhabitantTag(const OpaqueValue *src,
+ unsigned xiCount,
+ const Metadata *self) {
+ return Box::getExtraInhabitantTag((typename Box::type const *) src);
}
};
@@ -839,8 +840,6 @@
static constexpr unsigned numExtraInhabitants = Box::numExtraInhabitants;
static constexpr bool hasExtraInhabitants = (numExtraInhabitants != 0);
- static constexpr ExtraInhabitantFlags extraInhabitantFlags =
- ExtraInhabitantFlags().withNumExtraInhabitants(numExtraInhabitants);
static void destroy(OpaqueValue *value, const Metadata *self) {
return Box::destroy((typename Box::type*) value, self);
@@ -879,12 +878,11 @@
const Metadata *self) {
auto *payloadWitnesses = self->getValueWitnesses();
auto size = payloadWitnesses->getSize();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
- auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
+ auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
numExtraInhabitants,
- getExtraInhabitantIndex);
+ getExtraInhabitantTag);
}
static void storeEnumTagSinglePayload(OpaqueValue *enumAddr,
@@ -894,34 +892,32 @@
auto *payloadWitnesses = self->getValueWitnesses();
auto size = payloadWitnesses->getSize();
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
- auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
- auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self,
size, numExtraInhabitants,
- storeExtraInhabitant);
+ storeExtraInhabitantTag);
}
// These should not get instantiated if the type doesn't have extra
// inhabitants.
- static void storeExtraInhabitant(OpaqueValue *dest, int index,
- const Metadata *self) {
- Box::storeExtraInhabitant((typename Box::type*) dest, index);
+ SWIFT_CC(swift)
+ static void storeExtraInhabitantTag(OpaqueValue *dest, unsigned tag,
+ unsigned xiCount, const Metadata *self) {
+ Box::storeExtraInhabitantTag((typename Box::type*) dest, tag);
}
- static int getExtraInhabitantIndex(const OpaqueValue *src,
- const Metadata *self) {
- return Box::getExtraInhabitantIndex((typename Box::type const *) src);
+ SWIFT_CC(swift)
+ static unsigned getExtraInhabitantTag(const OpaqueValue *src,
+ unsigned xiCount,
+ const Metadata *self) {
+ return Box::getExtraInhabitantTag((typename Box::type const *) src);
}
};
/// A class which defines a ValueWitnessTable.
-template <class Witnesses,
- bool HasExtraInhabitants = Witnesses::hasExtraInhabitants>
-struct ValueWitnessTableGenerator;
-
-template <class Witnesses> struct ValueWitnessTableGenerator<Witnesses, false> {
+template <class Witnesses>
+struct ValueWitnessTableGenerator {
static constexpr const ValueWitnessTable table = {
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) Witnesses::LOWER_ID,
@@ -929,20 +925,6 @@
};
};
-/// A class which defines an ExtraInhabitantsValueWitnessTable.
-template <class Witnesses> struct ValueWitnessTableGenerator<Witnesses, true> {
- static constexpr const ExtraInhabitantsValueWitnessTable table = {
- {
-#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) Witnesses::LOWER_ID,
-#include "swift/ABI/ValueWitness.def"
- },
-#define WANT_ONLY_EXTRA_INHABITANT_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) Witnesses::LOWER_ID,
-#include "swift/ABI/ValueWitness.def"
- };
-};
-
/// A convenient way to get the value witness table for a box class.
template <class Box>
using ValueWitnessTableForBox = ValueWitnessTableGenerator<ValueWitnesses<Box>>;
diff --git a/test/IRGen/builtins.swift b/test/IRGen/builtins.swift
index 68132b5..99b61b4 100644
--- a/test/IRGen/builtins.swift
+++ b/test/IRGen/builtins.swift
@@ -183,14 +183,13 @@
// CHECK: define hidden {{.*}}void @"$s8builtins27generic_sizeof_alignof_testyyxlF"
func generic_sizeof_alignof_test<T>(_: T) {
- // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 8
- // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 0, i32 8
+ // CHECK-NEXT: [[SIZE:%.*]] = load i64, i64* [[T0]]
// CHECK-NEXT: store i64 [[SIZE]], i64* [[S:%.*]]
var s = Builtin.sizeof(T.self)
- // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
- // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: [[T2:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 0, i32 10
+ // CHECK-NEXT: [[FLAGS:%.*]] = load i32, i32* [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = zext i32 [[FLAGS]] to i64
// CHECK-NEXT: [[T3:%.*]] = and i64 [[T2]], 255
// CHECK-NEXT: [[ALIGN:%.*]] = add i64 [[T3]], 1
// CHECK-NEXT: store i64 [[ALIGN]], i64* [[A:%.*]]
@@ -199,9 +198,8 @@
// CHECK: define hidden {{.*}}void @"$s8builtins21generic_strideof_testyyxlF"
func generic_strideof_test<T>(_: T) {
- // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
- // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: [[STRIDE:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 9
+ // CHECK-NEXT: [[STRIDE:%.*]] = load i64, i64* [[T0]]
// CHECK-NEXT: store i64 [[STRIDE]], i64* [[S:%.*]]
var s = Builtin.strideof(T.self)
}
@@ -681,11 +679,10 @@
// CHECK-LABEL: define {{.*}} @{{.*}}generic_ispod_test
func generic_ispod_test<T>(_: T) {
- // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
- // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
- // CHECK-NEXT: [[ISNOTPOD:%.*]] = and i64 [[FLAGS]], 65536
- // CHECK-NEXT: [[ISPOD:%.*]] = icmp eq i64 [[ISNOTPOD]], 0
+ // CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 10
+ // CHECK-NEXT: [[FLAGS:%.*]] = load i32, i32* [[T0]]
+ // CHECK-NEXT: [[ISNOTPOD:%.*]] = and i32 [[FLAGS]], 65536
+ // CHECK-NEXT: [[ISPOD:%.*]] = icmp eq i32 [[ISNOTPOD]], 0
// CHECK-NEXT: store i1 [[ISPOD]], i1* [[S:%.*]]
var s = Builtin.ispod(T.self)
}
@@ -700,11 +697,10 @@
// CHECK-LABEL: define {{.*}} @{{.*}}generic_isbitwisetakable_test
func generic_isbitwisetakable_test<T>(_: T) {
- // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
- // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
- // CHECK-NEXT: [[ISNOTBITWISETAKABLE:%.*]] = and i64 [[FLAGS]], 1048576
- // CHECK-NEXT: [[ISBITWISETAKABLE:%.*]] = icmp eq i64 [[ISNOTBITWISETAKABLE]], 0
+ // CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 10
+ // CHECK-NEXT: [[FLAGS:%.*]] = load i32, i32* [[T0]]
+ // CHECK-NEXT: [[ISNOTBITWISETAKABLE:%.*]] = and i32 [[FLAGS]], 1048576
+ // CHECK-NEXT: [[ISBITWISETAKABLE:%.*]] = icmp eq i32 [[ISNOTBITWISETAKABLE]], 0
// CHECK-NEXT: store i1 [[ISBITWISETAKABLE]], i1* [[S:%.*]]
var s = Builtin.isbitwisetakable(T.self)
}
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 29eee07..5d756c2 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -1,7 +1,7 @@
// #if directives don't work with SIL keywords, therefore please put ObjC tests
// in `enum_objc.sil`.
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -enable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-objc --check-prefix=CHECK-objc-%target-ptrsize --check-prefix=CHECK-objc-%target-ptrsize-simulator-%target-is-simulator
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -disable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-native --check-prefix=CHECK-native-%target-ptrsize
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -enable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-objc --check-prefix=CHECK-objc-%target-ptrsize --check-prefix=CHECK-objc-%target-ptrsize-simulator-%target-is-simulator -DWORD=i%target-ptrsize
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -disable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-native --check-prefix=CHECK-native-%target-ptrsize -DWORD=i%target-ptrsize
// REQUIRES: CPU=i386 || CPU=x86_64
@@ -104,13 +104,17 @@
// -- Dynamic metadata template carries a value witness table pattern
// we fill in on instantiation.
-// The witness table pattern includes extra inhabitant witness
-// implementations which are used if the instance has extra inhabitants.
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
// CHECK: @"$s4enum16DynamicSingletonOWV" =
-// CHECK-SAME: i8* null
-// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s4enum16DynamicSingletonOwxs" to i8*)
-// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s4enum16DynamicSingletonOwxg" to i8*)
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: [[WORD]] 0,
+// 6291456 == 0x600000 (enum, incomplete)
+// CHECK-SAME: i32 6291456,
+// CHECK-SAME: i32 0,
+// Enum witnesses.
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s4enum16DynamicSingletonOwug" to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$s4enum16DynamicSingletonOwup" to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s4enum16DynamicSingletonOwui" to i8*)
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [17 x i8] c"DynamicSingleton\00"
// CHECK: @"$s4enum16DynamicSingletonOMn" = hidden constant <{
@@ -129,62 +133,55 @@
// CHECK: @"$s4enum16DynamicSingletonOMP" = internal constant <{ {{.*}} }> <{
// CHECK-SAME: @"$s4enum16DynamicSingletonOMi"
-// CHECK-SAME: [17 x i8*]* @"$s4enum16DynamicSingletonOWV"
+// CHECK-SAME: %swift.enum_vwtable* @"$s4enum16DynamicSingletonOWV"
// -- No-payload enums have extra inhabitants in
// their value witness table.
-// CHECK: @"$s4enum10NoPayloadsOWV" = internal constant [17 x i8*] [
+// CHECK: @"$s4enum10NoPayloadsOWV" = internal constant %swift.enum_vwtable {
// -- ...
// -- size
-// CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
-// -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses
-// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: [[WORD]] 1,
// -- stride
-// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: [[WORD]] 1,
+// -- flags (0x20_0000: alignment 1 and enum witnesses)
+// CHECK-SAME: i32 2097152,
// -- num extra inhabitants (256 - 3 valid states)
-// CHECK-SAME: i8* inttoptr ([[WORD]] 253 to i8*)
-// -- storeExtraInhabitant
-// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s4enum10NoPayloadsOwxs" to i8*)
-// -- getExtraInhabitantIndex
-// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s4enum10NoPayloadsOwxg" to i8*)
-// CHECK-SAME: ]
+// CHECK-SAME: i32 253,
+// CHECK-SAME: }, align
// -- Single-payload enums take unused extra inhabitants from their payload
// as their own.
-// CHECK: @"$s4enum19SinglePayloadNestedOWV" = internal constant [17 x i8*] [
+// CHECK: @"$s4enum19SinglePayloadNestedOWV" = internal constant %swift.enum_vwtable {
// -- ...
// -- size
-// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
-// -- flags 0x4_0000 - alignment 1, has extra inhabitants
-// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: [[WORD]] 1,
// -- stride
-// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: [[WORD]] 1,
+// -- flags (0x20_0000: alignment 1 and enum witnesses)
+// CHECK-SAME: i32 2097152,
// -- num extra inhabitants (253 from payload - 3 empty cases)
-// CHECK-SAME: i8* inttoptr ([[WORD]] 250 to i8*)
-// -- storeExtraInhabitant
-// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s4enum19SinglePayloadNestedOwxs" to i8*)
-// -- getExtraInhabitantIndex
-// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s4enum19SinglePayloadNestedOwxg" to i8*)
-// CHECK-SAME: ]
+// CHECK-SAME: i32 250,
+// CHECK-SAME: }
-// CHECK: @"$s4enum20DynamicSinglePayloadOWV" = internal constant [17 x i8*] [
-// CHECK-SAME: i8* null
-// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s4enum20DynamicSinglePayloadOwxs" to i8*)
-// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s4enum20DynamicSinglePayloadOwxg" to i8*)
+// CHECK: @"$s4enum20DynamicSinglePayloadOWV" = internal constant %swift.enum_vwtable {
+// -- flags (0x60_0000: alignment 1, incomplete, enum witnesses)
+// CHECK-SAME: i32 6291456,
+// -- num extra inhabitants (253 from payload - 3 empty cases)
+// CHECK-SAME: i32 0,
// CHECK: @"$s4enum20DynamicSinglePayloadOMP" = internal constant <{ {{.*}} }> <{
// CHECK-SAME: @"$s4enum20DynamicSinglePayloadOMi"
-// CHECK-SAME: [17 x i8*]* @"$s4enum20DynamicSinglePayloadOWV"
+// CHECK-SAME: %swift.enum_vwtable* @"$s4enum20DynamicSinglePayloadOWV"
-// CHECK: @"$s4enum18MultiPayloadNestedOWV" = internal constant [17 x i8*] [
+// CHECK: @"$s4enum18MultiPayloadNestedOWV" = internal constant %swift.enum_vwtable {
// -- size
-// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
-// CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*),
-// -- flags 0x250003 - alignment 4
-// CHECK-32-SAME: i8* inttoptr ([[WORD]] {{2686979|2359299}} to i8*)
-// -- flags 0x240007 - alignment 8, extra inhabitants
-// CHECK-64-SAME: i8* inttoptr ([[WORD]] 2359303 to i8*)
-// CHECK-SAME: ]
+// CHECK-32-SAME: [[WORD]] 5,
+// CHECK-64-SAME: [[WORD]] 9,
+// -- flags (0x250003: alignment 4, enum)
+// -- flags (0x200007: alignment 8, enum)
+// CHECK-32-SAME: i32 2097155,
+// CHECK-64-SAME: i32 2097159,
+// CHECK-SAME: }
enum Empty {}
@@ -2688,18 +2685,19 @@
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 8
// CHECK: call void @swift_initEnumMetadataSinglePayload(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]], i32 3)
-// CHECK-64-LABEL: define internal void @"$s4enum17StructWithWeakVarVwxs"(%swift.opaque* noalias %dest, i32 %index, %swift.type* %StructWithWeakVar)
+// CHECK-64-LABEL: define internal void @"$s4enum17StructWithWeakVarVwst"(%swift.opaque* noalias %value, i32 %whichCase, i32 %numEmptyCases, %swift.type* %StructWithWeakVar)
// -- TODO: some pointless masking here.
// -- TODO: should use EnumPayload word-chunking.
-// CHECK-64: %1 = zext i32 %index to i128
+// CHECK-64: [[INDEX:%.*]] = sub i32 %whichCase, 1
+// CHECK-64: [[T0:%.*]] = zext i32 [[INDEX]] to i128
// -- 0xFFFF_FFFF_FFFF_FFFF
-// CHECK-64: %2 = and i128 %1, 18446744073709551615
-// CHECK-64: %3 = shl i128 %1, 3
+// CHECK-64: [[T1:%.*]] = and i128 [[T0]], 18446744073709551615
+// CHECK-64: [[T2:%.*]] = shl i128 [[T0]], 3
// -- 0xFFFF_FFFF_FFFF_FFF8__0000_0000_0000_0000
-// CHECK-64: %4 = and i128 %3, 1329227995784915725329854470603931648
-// CHECK-64: %5 = or i128 %2, %4
+// CHECK-64: [[T3:%.*]] = and i128 [[T2]], 1329227995784915725329854470603931648
+// CHECK-64: [[T4:%.*]] = or i128 [[T1]], [[T3]]
// -- 0x1__0000_0000_0000_0000
-// CHECK-64: %6 = or i128 %5, 18446744073709551616
+// CHECK-64: [[T5:%.*]] = or i128 [[T4]], 18446744073709551616
// CHECK-LABEL: define internal i32 @"$s4enum40MultiPayloadLessThan32BitsWithEmptyCasesOwug"(%swift.opaque* noalias %value
// CHECK: [[VAL00:%.*]] = bitcast %swift.opaque* %value to %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO*
diff --git a/test/IRGen/enum_objc.sil b/test/IRGen/enum_objc.sil
index c2d044e..f82d428 100644
--- a/test/IRGen/enum_objc.sil
+++ b/test/IRGen/enum_objc.sil
@@ -127,6 +127,3 @@
x:
return undef : $()
}
-
-// Weak existentials allow extra inhabitants if not @objc, therefore StructWithWeakVar must emit:
-// CHECK: define internal void @"$s9enum_objc17StructWithWeakVarVwxs"
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index 31f7697..2975d77 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -6,7 +6,7 @@
// RUN: %target-swift-frontend -emit-ir -enable-resilience -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift | %FileCheck %t/enum_resilience.swift --check-prefix=ENUM_RES
// RUN: %target-swift-frontend -emit-ir -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift | %FileCheck %t/enum_resilience.swift --check-prefix=ENUM_NOT_RES
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
-// RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience %s | %FileCheck %t/enum_resilience.swift -DINT=i%target-ptrsize
+// RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience %s | %FileCheck %t/enum_resilience.swift --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
// RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience -O %s
import resilient_enum
@@ -133,7 +133,9 @@
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 16
+// CHECK-16-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 16
+// CHECK-32-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 14
+// CHECK-64-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 13
// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK-NEXT: [[WITNESS_FN:%.*]] = bitcast i8* [[WITNESS]]
// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA]])
@@ -162,7 +164,9 @@
// CHECK-NEXT: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR2]], [[INT]] -1
// CHECK-NEXT: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
-// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 16
+// CHECK-16-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 16
+// CHECK-32-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 14
+// CHECK-64-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 13
// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK-NEXT: [[WITNESS_FN:%destructiveInjectEnumTag]] = bitcast i8* [[WITNESS]]
// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA2]])
@@ -179,9 +183,9 @@
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
-// CHECK: [[WITNESS_FOR_SIZE:%size]] = ptrtoint i8* [[WITNESS]]
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[WITNESS_FOR_SIZE:%size]] = load [[INT]], [[INT]]* [[WITNESS_ADDR]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
// CHECK: [[ENUM_STORAGE:%.*]] = bitcast i8* [[ALLOCA]] to %swift.opaque*
@@ -191,7 +195,9 @@
// CHECK: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
// CHECK: [[ENUM_COPY:%.*]] = call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.opaque* noalias %0, %swift.type* [[METADATA]])
-// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 14
+// CHECK-16-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 14
+// CHECK-32-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 12
+// CHECK-64-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 11
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS_FN:%getEnumTag]] = bitcast i8* [[WITNESS]]
// CHECK: [[TAG:%.*]] = call i32 [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.type* [[METADATA]])
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index 23bb584..027b094 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -95,7 +95,7 @@
}
-// CHECK-LABEL: @"$s20enum_value_semantics20SinglePayloadTrivialOWV" = internal constant [17 x i8*] [
+// CHECK-LABEL: @"$s20enum_value_semantics20SinglePayloadTrivialOWV" = internal constant %swift.enum_vwtable {
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
@@ -104,49 +104,45 @@
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i32 (%swift.opaque*, i32, %swift.type*)* @"$s20enum_value_semantics20SinglePayloadTrivialOwet" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, i32, i32, %swift.type*)* @"$s20enum_value_semantics20SinglePayloadTrivialOwst" to i8*),
-// CHECK: i8* inttoptr (i64 9 to i8*),
-// CHECK: i8* inttoptr (i64 2097159 to i8*),
-// CHECK: i8* inttoptr (i64 16 to i8*),
-// CHECK: i8* null,
-// CHECK: i8* null,
-// CHECK: i8* null,
+// CHECK: i64 9,
+// CHECK: i64 16,
+// CHECK: i32 2097159,
+// CHECK: i32 0,
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics20SinglePayloadTrivialOwug" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics20SinglePayloadTrivialOwup" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s20enum_value_semantics20SinglePayloadTrivialOwui" to i8*)
-// CHECK: ]
+// CHECK: }
// CHECK-LABEL: @"$s20enum_value_semantics20SinglePayloadTrivialOMf" =
// CHECK-SAME: internal constant <{ {{.*}} }> <{
-// CHECK-SAME: i8** getelementptr inbounds ([17 x i8*], [17 x i8*]* @"$s20enum_value_semantics20SinglePayloadTrivialOWV", i32 0, i32 0),
+// CHECK-SAME: i8** getelementptr inbounds (%swift.enum_vwtable, %swift.enum_vwtable* @"$s20enum_value_semantics20SinglePayloadTrivialOWV", i32 0, i32 0),
// CHECK-SAME: i64 513,
// CHECK-SAME: {{.*}}* @"$s20enum_value_semantics20SinglePayloadTrivialOMn"
// CHECK-SAME: }>
-// CHECK-LABEL: @"$s20enum_value_semantics23SinglePayloadNontrivialOWV" = internal constant [17 x i8*] [
+// CHECK-LABEL: @"$s20enum_value_semantics23SinglePayloadNontrivialOWV" = internal constant %swift.enum_vwtable {
// CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwCP" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwxx" to i8*),
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwcp" to i8*),
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwca" to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy8_8 to i8*),
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwta" to i8*),
-// CHECK: i8* inttoptr (i64 8 to i8*),
-// -- 0x250007
-// CHECK: i8* inttoptr (i64 2424839 to i8*),
-// CHECK: i8* inttoptr (i64 8 to i8*),
+// CHECK: i64 8,
+// CHECK: i64 8,
+// -- 0x210007
+// CHECK: i32 2162695,
// -- On Darwin, the first 4 GiB are unmapped: 0x7ffffffc
// -- Otherwise, one can only assume the first page (4 KiB) is unmapped: 0xffd
-// CHECK-ios: i8* inttoptr (i64 2147483644 to i8*)
-// CHECK-macosx: i8* inttoptr (i64 2147483644 to i8*)
-// CHECK-watchos: i8* inttoptr (i64 2147483644 to i8*)
-// CHECK-darwin: i8* inttoptr (i64 2147483644 to i8*)
-// CHECK-objc-linux-gnu: i8* inttoptr (i64 2045 to i8*)
-// CHECK-native-linux-gnu: i8* inttoptr (i64 4093 to i8*)
-// CHECK-objc-windows: i8* inttoptr (i64 2045 to i8*)
-// CHECK-native-windows: i8* inttoptr (i64 4093 to i8*)
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwxs" to i8*)
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwxg" to i8*)
+// CHECK-ios: i32 2147483644
+// CHECK-macosx: i32 2147483644
+// CHECK-watchos: i32 2147483644
+// CHECK-darwin: i32 2147483644
+// CHECK-objc-linux-gnu: i32 2045
+// CHECK-native-linux-gnu: i32 4093
+// CHECK-objc-windows: i32 2045
+// CHECK-native-windows: i32 4093
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwug" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwup" to i8*)
// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s20enum_value_semantics23SinglePayloadNontrivialOwui" to i8*)
@@ -155,7 +151,7 @@
// CHECK-LABEL: @"$s20enum_value_semantics23SinglePayloadNontrivialOMf" =
// CHECK-SAME: internal constant <{ {{.*}} }> <{
-// CHECK-SAME: i8** getelementptr inbounds ([17 x i8*], [17 x i8*]* @"$s20enum_value_semantics23SinglePayloadNontrivialOWV", i32 0, i32 0),
+// CHECK-SAME: i8** getelementptr inbounds (%swift.enum_vwtable, %swift.enum_vwtable* @"$s20enum_value_semantics23SinglePayloadNontrivialOWV", i32 0, i32 0),
// CHECK-SAME: i64 513,
// CHECK-SAME: {{.*}}* @"$s20enum_value_semantics23SinglePayloadNontrivialOMn"
// CHECK-SAME: }>
@@ -173,7 +169,7 @@
// Pattern flags. 0x4020_0000 == (MetadataKind::Enum << 21).
// CHECK-SAME: i32 1075838976,
// Value witness table.
-// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([17 x i8*]* @"$s20enum_value_semantics18GenericFixedLayoutOWV" to i64), i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32, i32, i32 }>, <{ i32, i32, i32, i32 }>* @"$s20enum_value_semantics18GenericFixedLayoutOMP", i32 0, i32 3) to i64)) to i32)
+// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (%swift.enum_vwtable* @"$s20enum_value_semantics18GenericFixedLayoutOWV" to i64), i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32, i32, i32 }>, <{ i32, i32, i32, i32 }>* @"$s20enum_value_semantics18GenericFixedLayoutOMP", i32 0, i32 3) to i64)) to i32)
// CHECK-SAME: }>
sil @single_payload_nontrivial_copy_destroy : $(@owned SinglePayloadNontrivial) -> () {
@@ -197,16 +193,6 @@
//
-// -- NoPayload getExtraInhabitants
-// CHECK-LABEL: define internal i32 @"$s20enum_value_semantics9NoPayloadOwxg"
-// CHECK: [[VALUE:%.*]] = load i8, i8* {{%.*}}, align 1
-// CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[VALUE]] to i32
-// CHECK-NEXT: [[SUB:%.*]] = sub i32 [[ZEXT]], 3
-// CHECK-NEXT: [[EXTRA:%.*]] = icmp slt i32 [[SUB]], 0
-// CHECK-NEXT: [[RES:%.*]] = select i1 [[EXTRA]], i32 -1, i32 [[SUB]]
-// CHECK-NEXT: ret i32 [[RES]]
-
-
// -- NoPayload getEnumTag
// CHECK-LABEL: define internal i32 @"$s20enum_value_semantics9NoPayloadOwug"
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics9NoPayloadO*
diff --git a/test/IRGen/existentials.sil b/test/IRGen/existentials.sil
index 3f48965..5298898 100644
--- a/test/IRGen/existentials.sil
+++ b/test/IRGen/existentials.sil
@@ -8,8 +8,8 @@
protocol P {}
// NonBitwiseTakableBit = 0x00100000. This struct is bitwise takable because
-// 0x70007 = 458759
-// CHECK: @"$s12existentials14BitwiseTakableVWV" = internal constant [14 x i8*] {{.*}} i8* inttoptr (i64 458759 to i8*)
+// 0x30007 = 196615
+// CHECK: @"$s12existentials14BitwiseTakableVWV" = internal constant %swift.vwtable {{.*}} i32 196615
struct BitwiseTakable {
var p: P
}
diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil
index 378ec3c..1d7f2c8 100644
--- a/test/IRGen/existentials_opaque_boxed.sil
+++ b/test/IRGen/existentials_opaque_boxed.sil
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-%target-ptrsize
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
sil_stage canonical
@@ -41,11 +41,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METATYPE]]
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[FLAG_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[FLAG_WITNESS:%.*]] = load i8*, i8** [[FLAG_WITNESS_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAG_WITNESS]]
-// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: [[EXISTENTIAL_BUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[EXISTENTIAL_BUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[EXISTENTIAL_BUFFER]] to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %allocateBox
@@ -115,11 +115,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** %3, {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
-// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[MASKED]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %done, label %deallocateBox
// CHECK: done:
@@ -132,10 +132,14 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
-// CHECK: [[VW_ADDR2:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 8
-// CHECK: [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
-// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 255
+// CHECK: [[VWT2_CAST:%.*]] = bitcast i8** [[VWT2]] to %swift.vwtable*
+// CHECK: [[SIZE2_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT2_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE2_ADDR]]
+// CHECK-64:[[T0:%.*]] = zext i32 [[FLAGS]] to i64
+// CHECK-64:[[ALIGNMASK:%.*]] = and i64 [[T0]], 255
+// CHECK-32:[[ALIGNMASK:%.*]] = and i32 [[FLAGS]], 255
+// CHECK-16:[[T0:%.*]] = trunc i32 [[FLAGS]] to i16
+// CHECK-16:[[ALIGNMASK:%.*]] = and i16 [[T0]], 255
// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
@@ -164,11 +168,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
-// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: [[VALUEADDRINLINE:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %boxed
//
@@ -178,7 +182,11 @@
// CHECK: boxed:
// CHECK: [[REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.refcounted**
// CHECK: [[REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFADDR]]
-// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 255
+// CHECK-64:[[T0:%.*]] = zext i32 [[FLAGS]] to i64
+// CHECK-64:[[ALIGNMASK:%.*]] = and i64 [[T0]], 255
+// CHECK-32:[[ALIGNMASK:%.*]] = and i32 [[FLAGS]], 255
+// CHECK-16:[[T0:%.*]] = trunc i32 [[FLAGS]] to i16
+// CHECK-16:[[ALIGNMASK:%.*]] = and i16 [[T0]], 255
// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
@@ -207,11 +215,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
-// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: [[VALUEADDRINLINE:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %boxed
//
@@ -219,7 +227,11 @@
// CHECK: ret %swift.opaque* [[VALUEADDRINLINE]]
// CHECK: boxed:
-// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 255
+// CHECK-64:[[T0:%.*]] = zext i32 [[FLAGS]] to i64
+// CHECK-64:[[ALIGNMASK:%.*]] = and i64 [[T0]], 255
+// CHECK-32:[[ALIGNMASK:%.*]] = and i32 [[FLAGS]], 255
+// CHECK-16:[[T0:%.*]] = trunc i32 [[FLAGS]] to i16
+// CHECK-16:[[ALIGNMASK:%.*]] = and i16 [[T0]], 255
// CHECK: [[OPAQUE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: [[REFANDADDR:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
// CHECK: [[REF:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 0
@@ -244,11 +256,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
-// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %inline, label %outline
//
// CHECK: inline:
@@ -301,11 +313,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
-// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
-// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[MASKED]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %match-inline, label %match-outline
//
// CHECK: match-inline:
@@ -339,19 +351,19 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[DEST_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[DEST_VWT:%.*]] = load i8**, i8*** [[DEST_VWT_ADDR]]
-// CHECK: [[DEST_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[DEST_VWT]], i32 9
-// CHECK: [[DEST_VW:%.*]] = load i8*, i8** [[DEST_VW_ADDR]]
-// CHECK: [[DEST_FLAGS:%.*]] = ptrtoint i8* [[DEST_VW]] to {{(i64|i32)}}
-// CHECK: [[DEST_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[DEST_FLAGS]], 131072
-// CHECK: [[DEST_ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[DEST_ISNOTINLINE]], 0
+// CHECK: [[DEST_VWT_CAST:%.*]] = bitcast i8** [[DEST_VWT]] to %swift.vwtable*
+// CHECK: [[DEST_FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[DEST_VWT_CAST]], i32 0, i32 10
+// CHECK: [[DEST_FLAGS:%.*]] = load i32, i32* [[DEST_FLAGS_ADDR]]
+// CHECK: [[DEST_ISNOTINLINE:%.*]] = and i32 [[DEST_FLAGS]], 131072
+// CHECK: [[DEST_ISINLINE:%.*]] = icmp eq i32 [[DEST_ISNOTINLINE]], 0
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[SRC_TYPE]] to i8***
// CHECK: [[SRC_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[SRC_VWT:%.*]] = load i8**, i8*** [[SRC_VWT_ADDR]]
-// CHECK: [[SRC_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SRC_VWT]], i32 9
-// CHECK: [[SRC_VW:%.*]] = load i8*, i8** [[SRC_VW_ADDR]]
-// CHECK: [[SRC_FLAGS:%.*]] = ptrtoint i8* [[SRC_VW]] to {{(i64|i32)}}
-// CHECK: [[SRC_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[SRC_FLAGS]], 131072
-// CHECK: [[SRC_ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[SRC_ISNOTINLINE]], 0
+// CHECK: [[SRC_VWT_CAST:%.*]] = bitcast i8** [[SRC_VWT]] to %swift.vwtable*
+// CHECK: [[SRC_FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[SRC_VWT_CAST]], i32 0, i32 10
+// CHECK: [[SRC_FLAGS:%.*]] = load i32, i32* [[SRC_FLAGS_ADDR]]
+// CHECK: [[SRC_ISNOTINLINE:%.*]] = and i32 [[SRC_FLAGS]], 131072
+// CHECK: [[SRC_ISINLINE:%.*]] = icmp eq i32 [[SRC_ISNOTINLINE]], 0
// CHECK: br i1 [[DEST_ISINLINE]], label %dest-inline, label %dest-outline
//
// CHECK: dest-inline:
diff --git a/test/IRGen/generic_casts.swift b/test/IRGen/generic_casts.swift
index cafedc0..ed100e7 100644
--- a/test/IRGen/generic_casts.swift
+++ b/test/IRGen/generic_casts.swift
@@ -38,9 +38,9 @@
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], i64 -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
- // CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
- // CHECK: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
- // CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
+ // CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+ // CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+ // CHECK: [[SIZE:%.*]] = load i64, i64* [[SIZE_ADDR]]
// CHECK: [[T_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
// CHECK: [[T_TMP:%.*]] = bitcast i8* [[T_ALLOCA]] to %swift.opaque*
// CHECK: [[TEMP:%.*]] = call %swift.opaque* {{.*}}(%swift.opaque* noalias [[T_TMP]], %swift.opaque* noalias %0, %swift.type* %T)
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 1ce6ed2..602dc61 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -28,12 +28,11 @@
// CHECK: @"$s15generic_structs13SingleDynamicVWV" = internal constant
// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$s15generic_structs13SingleDynamicVwCP" to i8*),
// -- ...
-// -- placeholder for size, flags, stride
-// CHECK-SAME: i8* null, i8* inttoptr (i64 4194304 to i8*), i8* null
-// -- extra inhabitants
-// CHECK-SAME: i8* null,
-// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$s15generic_structs13SingleDynamicVwxs" to i8*),
-// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$s15generic_structs13SingleDynamicVwxg" to i8*)]
+// -- placeholder for size, stride, flags
+// CHECK-SAME: i64 0,
+// CHECK-SAME: i64 0,
+// CHECK-SAME: i32 4194304,
+// CHECK-SAME: i32 0 }
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00"
diff --git a/test/IRGen/generic_tuples.swift b/test/IRGen/generic_tuples.swift
index f001ed8..b00c140 100644
--- a/test/IRGen/generic_tuples.swift
+++ b/test/IRGen/generic_tuples.swift
@@ -18,9 +18,9 @@
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], i64 -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load i64, i64* [[SIZE_ADDR]]
// CHECK: [[X_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
// CHECK: [[X_TMP:%.*]] = bitcast i8* [[X_ALLOCA]] to %swift.opaque*
// Debug info shadow copy.
diff --git a/test/IRGen/global_resilience.sil b/test/IRGen/global_resilience.sil
index 800c56f..c73f154 100644
--- a/test/IRGen/global_resilience.sil
+++ b/test/IRGen/global_resilience.sil
@@ -128,21 +128,21 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 9
-// CHECK: [[FLAGSWITNESS:%.*]] = load i8*, i8** [[FLAGS_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAGSWITNESS]] to i{{.*}}
-// CHECK: [[ISNOTINLINE:%.*]] = and {{.*}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{.*}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %done, label %outline.allocateValueInBuffer
//
// CHECK: outline.allocateValueInBuffer:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[SIZEWITNESS:%.*]] = load i8*, i8** [[SIZE_ADDR]]
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZEWITNESS]]
-// CHECK: [[ALIGN:%.*]] = and {{.*}} [[FLAGS]], 255
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
+// CHECK: [[ALIGN:%.*]] = and {{.*}}, 255
// CHECK: [[PTR:%.*]] = call noalias i8* @swift_slowAlloc({{.*}} [[SIZE]], {{.*}} [[ALIGN]])
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* %1 to i8**
// CHECK: store i8* [[PTR]], i8** [[ADDR]]
@@ -158,11 +158,11 @@
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 9
-// CHECK: [[FLAGSWITNESS:%.*]] = load i8*, i8** [[FLAGS_ADDR]]
-// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAGSWITNESS]] to i{{.*}}
-// CHECK: [[ISNOTINLINE:%.*]] = and {{.*}} [[FLAGS]], 131072
-// CHECK: [[ISINLINE:%.*]] = icmp eq {{.*}} [[ISNOTINLINE]], 0
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 10
+// CHECK: [[FLAGS:%.*]] = load i32, i32* [[FLAGS_ADDR]]
+// CHECK: [[ISNOTINLINE:%.*]] = and i32 [[FLAGS]], 131072
+// CHECK: [[ISINLINE:%.*]] = icmp eq i32 [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %done, label %outline.projectValueInBuffer
//
// CHECK: outline.projectValueInBuffer:
diff --git a/test/IRGen/indexing.sil b/test/IRGen/indexing.sil
index d8153fe..add599e 100644
--- a/test/IRGen/indexing.sil
+++ b/test/IRGen/indexing.sil
@@ -42,14 +42,14 @@
}
// CHECK: define{{( protected)?}} {{.*}}void @dynamic_size(%swift.opaque* noalias nocapture, i64, %swift.type* %T) {{.*}} {
-// CHECK: %3 = bitcast %swift.type* %T to i8***
-// CHECK-NEXT: %4 = getelementptr inbounds i8**, i8*** %3, i64 -1
-// CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** %4, align 8
-// CHECK-NEXT: %5 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 10
-// CHECK-NEXT: %6 = load i8*, i8** %5, align 8
-// CHECK-NEXT: %stride = ptrtoint i8* %6 to i64
-// CHECK-NEXT: %7 = mul nsw i64 %1, %stride
-// CHECK-NEXT: %8 = getelementptr inbounds i8, i8* %2, i64 %7
+// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8***
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1
+// CHECK-NEXT: [[VWT:%T.valueWitnesses]] = load i8**, i8*** [[T1]], align 8
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[STRIDE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 9
+// CHECK: [[STRIDE:%.*]] = load i64, i64* [[STRIDE_ADDR]]
+// CHECK-NEXT: [[T0:%.*]] = mul nsw i64 %1, [[STRIDE]]
+// CHECK-NEXT: getelementptr inbounds i8, i8* %2, i64 [[T0]]
sil @dynamic_size : $@convention(thin) <T> (@in T, Builtin.Word) -> () {
entry(%p : $*T, %i: $Builtin.Word):
diff --git a/test/IRGen/indirect_enum.sil b/test/IRGen/indirect_enum.sil
index 9ecc1cf..401bb3b 100644
--- a/test/IRGen/indirect_enum.sil
+++ b/test/IRGen/indirect_enum.sil
@@ -2,8 +2,8 @@
import Swift
-// CHECK-64: @"$s13indirect_enum5TreeAOWV" = internal constant {{.*}} i8* inttoptr ([[WORD:i64]] 8 to i8*), i8* inttoptr (i64 2424839 to i8*), i8* inttoptr (i64 8 to i8*)
-// CHECK-32: @"$s13indirect_enum5TreeAOWV" = internal constant {{.*}} i8* inttoptr ([[WORD:i32]] 4 to i8*), i8* inttoptr (i32 2424835 to i8*), i8* inttoptr (i32 4 to i8*)
+// CHECK-64: @"$s13indirect_enum5TreeAOWV" = internal constant %swift.enum_vwtable { {{.*}}, i64 8, i64 8, i32 2162695,
+// CHECK-32: @"$s13indirect_enum5TreeAOWV" = internal constant %swift.enum_vwtable { {{.*}}, i32 4, i32 4, i32 2162691,
// CHECK-NOT: define{{( protected)?}} private %swift.type** @get_field_types_TreeA
indirect enum TreeA<T> {
diff --git a/test/IRGen/lifetime.sil b/test/IRGen/lifetime.sil
index 365302c..db8b5a2 100644
--- a/test/IRGen/lifetime.sil
+++ b/test/IRGen/lifetime.sil
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -gnone -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -gnone -emit-ir %s | %FileCheck %s -DINT=i%target-ptrsize
// CHECK: [[OPAQUE:%swift.opaque]] = type opaque
// CHECK: [[TYPE:%swift.type]] = type
@@ -22,9 +22,9 @@
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], {{(i32|i64)}} -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK-NEXT: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
-// CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
+// CHECK-NEXT: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK-NEXT: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
// CHECK-NEXT: [[Y_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8({{(i32|i64)}} -1, i8* [[Y_ALLOCA]])
// CHECK-NEXT: [[Y_TMP:%.*]] = bitcast i8* [[Y_ALLOCA]] to %swift.opaque*
@@ -61,9 +61,9 @@
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], {{(i32|i64)}} -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK-NEXT: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
-// CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
+// CHECK-NEXT: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK-NEXT: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
// CHECK-NEXT: [[Y_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8({{(i32|i64)}} -1, i8* [[Y_ALLOCA]])
// CHECK-NEXT: [[Y_TMP:%.*]] = bitcast i8* [[Y_ALLOCA]] to %swift.opaque*
diff --git a/test/IRGen/multi_file_resilience.swift b/test/IRGen/multi_file_resilience.swift
index dd0ee00..2b64442 100644
--- a/test/IRGen/multi_file_resilience.swift
+++ b/test/IRGen/multi_file_resilience.swift
@@ -16,9 +16,9 @@
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
-// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],
// CHECK: [[COPY:%.*]] = bitcast i8* [[ALLOCA]] to [[FOO:%T4main3FooV]]*
// Perform 'initializeWithCopy' via the VWT instead of trying to inline it.
diff --git a/test/IRGen/multi_module_resilience.swift b/test/IRGen/multi_module_resilience.swift
index 30328ce..3e1df12 100644
--- a/test/IRGen/multi_module_resilience.swift
+++ b/test/IRGen/multi_module_resilience.swift
@@ -20,9 +20,9 @@
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
-// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],
// CHECK: [[COPY:%.*]] = bitcast i8* [[ALLOCA]] to [[FOO:%T11OtherModule3FooV]]*
// Perform 'initializeWithCopy' via the VWT instead of trying to inline it.
@@ -49,9 +49,9 @@
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
-// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
-// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
+// CHECK: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[SIZE:%.*]] = load [[INT]], [[INT]]* [[SIZE_ADDR]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],
// CHECK: [[COPY:%.*]] = bitcast i8* [[ALLOCA]] to [[BAR:%T11OtherModule3BarV]]*
// Perform 'initializeWithCopy' via the VWT instead of trying to inline it.
diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil
index a060d06..6880591 100644
--- a/test/IRGen/partial_apply.sil
+++ b/test/IRGen/partial_apply.sil
@@ -233,10 +233,14 @@
// CHECK: [[T_METADATA_BASE:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[T_VWTABLE_ADDR:%.*]] = getelementptr {{.*}} [[T_METADATA_BASE]], [[WORD:i[0-9]+]] -1
// CHECK: [[T_VWTABLE:%.*]] = load {{.*}} [[T_VWTABLE_ADDR]]
-// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 9
-// CHECK: [[T_FLAGS_PTR:%.*]] = load {{.*}} [[T_FLAGS_ADDR]]
-// CHECK: [[T_FLAGS:%.*]] = ptrtoint {{.*}} [[T_FLAGS_PTR]] to [[WORD]]
-// CHECK: [[T_ALIGN_MASK:%.*]] = and [[WORD]] [[T_FLAGS]], 255
+// CHECK: [[T_VWTABLE_CAST:%.*]] = bitcast i8** [[T_VWTABLE]] to %swift.vwtable*
+// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T_VWTABLE_CAST]], i32 0, i32 10
+// CHECK: [[T_FLAGS:%.*]] = load i32, i32* [[T_FLAGS_ADDR]]
+// CHECK-64: [[T0:%.*]] = zext i32 [[T_FLAGS]] to i64
+// CHECK-64: [[T_ALIGN_MASK:%.*]] = and i64 [[T0]], 255
+// CHECK-32: [[T_ALIGN_MASK:%.*]] = and i32 [[T_FLAGS]], 255
+// CHECK-16: [[T0:%.*]] = trunc i32 [[T_FLAGS]] to i16
+// CHECK-16: [[T_ALIGN_MASK:%.*]] = and i16 [[T0]], 255
// CHECK: [[T_ALIGN_MASK_NOT:%.*]] = xor [[WORD]] [[T_ALIGN_MASK]], -1
// -- 32 is 64-bit offset of 'T' field, 16 for obj header + 8 for T metadata + 8 for SwiftClass field
// CHECK-64: [[T_UP_TO_ALIGN_1:%.*]] = add i64 32, [[T_ALIGN_MASK]]
@@ -245,9 +249,9 @@
// CHECK: [[T_OFFSET:%.*]] = and [[WORD]] [[T_UP_TO_ALIGN_1]], [[T_ALIGN_MASK_NOT]]
// -- Add the size of T to start the Int field.
-// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 8
-// CHECK: [[T_SIZE_PTR:%.*]] = load {{.*}} [[T_SIZE_ADDR]]
-// CHECK: [[T_SIZE:%.*]] = ptrtoint {{.*}} [[T_SIZE_PTR]] to [[WORD]]
+// CHECK: [[T_VWTABLE_CAST:%.*]] = bitcast i8** [[T_VWTABLE]] to %swift.vwtable*
+// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T_VWTABLE_CAST]], i32 0, i32 8
+// CHECK: [[T_SIZE:%.*]] = load [[WORD]], [[WORD]]* [[T_SIZE_ADDR]]
// CHECK: [[T_END:%.*]] = add [[WORD]] [[T_OFFSET]], [[T_SIZE]]
// -- Accumulate total alignment.
diff --git a/test/IRGen/struct_layout.sil b/test/IRGen/struct_layout.sil
index 9f08ccc..b76758c 100644
--- a/test/IRGen/struct_layout.sil
+++ b/test/IRGen/struct_layout.sil
@@ -9,9 +9,9 @@
// 64: %T4main14Rdar15410780_CV = type <{ %TSSSg }>
// 64: %TSSSg = type <{ [16 x i8] }>
-// 64: @"$s4main14Rdar15410780_AVWV" = internal constant {{.*}} (i64 257
-// 64: @"$s4main14Rdar15410780_BVWV" = internal constant {{.*}} (i64 258
-// 64: @"$s4main14Rdar15410780_CVWV" = internal constant {{.*}} (i64 16
+// 64: @"$s4main14Rdar15410780_AVWV" = internal constant {{.*}} i64 257
+// 64: @"$s4main14Rdar15410780_BVWV" = internal constant {{.*}} i64 258
+// 64: @"$s4main14Rdar15410780_CVWV" = internal constant {{.*}} i64 16
// 32: %T4main14Rdar15410780_AV = type <{ i2048, %Ts4Int8V }>
@@ -20,9 +20,9 @@
// 32: %T4main14Rdar15410780_CV = type <{ %TSSSg }>
// 32: %TSSSg = type <{ [12 x i8] }>
-// 32: @"$s4main14Rdar15410780_AVWV" = internal constant {{.*}} (i32 257
-// 32: @"$s4main14Rdar15410780_BVWV" = internal constant {{.*}} (i32 258
-// 32: @"$s4main14Rdar15410780_CVWV" = internal constant {{.*}} (i32 12
+// 32: @"$s4main14Rdar15410780_AVWV" = internal constant {{.*}} i32 257
+// 32: @"$s4main14Rdar15410780_BVWV" = internal constant {{.*}} i32 258
+// 32: @"$s4main14Rdar15410780_CVWV" = internal constant {{.*}} i32 12
// <rdar://problem/15410780>
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 8ff8aa2..d6d61fd 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -25,9 +25,9 @@
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
-// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
-// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
-// CHECK: [[WITNESS_FOR_SIZE:%.*]] = ptrtoint i8* [[WITNESS]]
+// CHECK-NEXT: [[VWT_CAST:%.*]] = bitcast i8** [[VWT]] to %swift.vwtable*
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[VWT_CAST]], i32 0, i32 8
+// CHECK: [[WITNESS_FOR_SIZE:%.*]] = load [[INT]], [[INT]]* [[WITNESS_ADDR]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
// CHECK: [[STRUCT_ADDR:%.*]] = bitcast i8* [[ALLOCA]] to %swift.opaque*
diff --git a/test/IRGen/struct_with_resilient_type.swift b/test/IRGen/struct_with_resilient_type.swift
index 0c2c8ba..8312df7 100644
--- a/test/IRGen/struct_with_resilient_type.swift
+++ b/test/IRGen/struct_with_resilient_type.swift
@@ -28,7 +28,8 @@
fooImp.foo(ptr: bar)
}
// CHECK-LABEL: define{{.*}} @"$s26struct_with_resilient_type18ProtAndResilStructV3baryyFTc"(%T26struct_with_resilient_type18ProtAndResilStructV* noalias nocapture)
-// CHECK: %flags.alignmentMask = and i64 %flags, 255
+// CHECK: [[T0:%.*]] = zext i32 %flags to i64
+// CHECK: %flags.alignmentMask = and i64 [[T0]], 255
// CHECK: [[XOR_ALIGN:%.*]] = xor i64 %flags.alignmentMask, -1
// CHECK: [[INIT_OFFSET:%.*]] = add i64 16, %flags.alignmentMask
// CHECK: [[T0:%.*]] = and i64 [[INIT_OFFSET]], [[XOR_ALIGN]]
diff --git a/test/IRGen/type_layout.swift b/test/IRGen/type_layout.swift
index c0e4535..d500096 100644
--- a/test/IRGen/type_layout.swift
+++ b/test/IRGen/type_layout.swift
@@ -48,19 +48,19 @@
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$sBi64_WV", i32 8)
var c: SSing
// -- Multi-element structs use open-coded layouts
- // CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_16_8_0_pod, i32 0, i32 0)
+ // CHECK: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_0_pod to i8**)
var d: SMult
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI:[0-9a-f]+]]_bt, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI:[0-9a-f]+]]_bt, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_[[REF_XI:[0-9a-f]+]]_bt to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_[[REF_XI:[0-9a-f]+]]_bt to i8**)
var e: SMult2
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_bt, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_[[REF_XI]]_bt to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_[[REF_XI]]_bt to i8**)
var f: SMult3
// -- Single-case enum, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$sBi64_WV", i32 8)
var g: ESing
// -- Multi-case enum, open-coded layout
- // CHECK: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_9_8_fe_pod, i32 0, i32 0)
+ // CHECK: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_9_8_fe_pod to i8**)
var h: EMult
// -- Single-element generic struct, shares layout of its field (T)
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
diff --git a/test/IRGen/type_layout_objc.swift b/test/IRGen/type_layout_objc.swift
index 636a4d6..175aa22 100644
--- a/test/IRGen/type_layout_objc.swift
+++ b/test/IRGen/type_layout_objc.swift
@@ -46,19 +46,19 @@
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$sBi64_WV", i32 8)
var c: SSing
// -- Multi-element structs use open-coded layouts
- // CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_16_8_0_pod, i32 0, i32 0)
+ // CHECK: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_0_pod to i8**)
var d: SMult
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff_bt, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_1000_bt, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_7fffffff_bt to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_1000_bt to i8**)
var e: SMult2
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff_bt, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_1000_bt, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_7fffffff_bt to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_1000_bt to i8**)
var f: SMult3
// -- Single-case enum, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$sBi64_WV", i32 8)
var g: ESing
// -- Multi-case enum, open-coded layout
- // CHECK: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_9_8_fe_pod, i32 0, i32 0)
+ // CHECK: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_9_8_fe_pod to i8**)
var h: EMult
// -- Single-element generic struct, shares layout of its field (T)
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
diff --git a/test/IRGen/type_layout_reference_storage.swift b/test/IRGen/type_layout_reference_storage.swift
index 27fd9e9..b2361b5 100644
--- a/test/IRGen/type_layout_reference_storage.swift
+++ b/test/IRGen/type_layout_reference_storage.swift
@@ -11,35 +11,35 @@
var z: T
// -- Known-Swift-refcounted type
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod to i8**)
unowned(unsafe) var cu: C
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1_bt, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1_bt, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_1_bt to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_1_bt to i8**)
unowned(safe) var cs: C
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var cwo: C?
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var cwi: C!
// -- Known-Swift-refcounted archetype
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var nu: Native
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1_bt, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1_bt, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_1_bt to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_1_bt to i8**)
unowned(safe) var nc: Native
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var nwo: Native?
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var nwi: Native!
// -- Open-code layout for protocol types with witness tables. Note:
@@ -47,81 +47,81 @@
// when ObjC interop is disabled.
// 2) 0x7fffffff is the max extra inhabitant count, but not all types in
// all scenarios.
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var pu: P
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_7fffffff to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_7fffffff to i8**)
unowned(safe) var ps: P
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_7fffffff to i8**)
weak var pwo: P?
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_16_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_4_7fffffff to i8**)
weak var pwi: P!
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff to i8**)
unowned(safe) var pqs: P & Q
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var pqu: P & Q
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff to i8**)
weak var pqwo: (P & Q)?
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff to i8**)
weak var pqwi: (P & Q)!
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff_bt, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff_bt, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff_bt to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff_bt to i8**)
unowned(safe) var pqcs: P & Q & C
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var pqcu: P & Q & C
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff to i8**)
weak var pqcwo: (P & Q & C)?
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_24_8_7fffffff to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_12_4_7fffffff to i8**)
weak var pqcwi: (P & Q & C)!
// -- Unknown-refcounted existential without witness tables.
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var aou: AnyObject
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_1 to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_1 to i8**)
unowned(safe) var aos: AnyObject
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var aowo: AnyObject?
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var aowi: AnyObject!
// -- Unknown-refcounted archetype
- // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_pod to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_pod to i8**)
unowned(unsafe) var uu: Unknown
- // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1, i32 0, i32 0)
- // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
- // CHECK-objc-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1, i32 0, i32 0)
+ // CHECK-native-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_1 to i8**)
+ // CHECK-native-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_[[REF_XI]]_bt to i8**)
+ // CHECK-objc-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_1 to i8**)
unowned(safe) var us: Unknown
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var uwo: Unknown?
- // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
- // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
+ // CHECK-64: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_8_8_0 to i8**)
+ // CHECK-32: store i8** bitcast ({ [[INT]], [[INT]], i32, i32 }* @type_layout_4_4_0 to i8**)
weak var uwi: Unknown!
}
diff --git a/test/IRGen/weak.sil b/test/IRGen/weak.sil
index a8a21c9..e946601 100644
--- a/test/IRGen/weak.sil
+++ b/test/IRGen/weak.sil
@@ -28,9 +28,9 @@
}
// size 8
-// flags 0x130007 == 1245191 (non-POD, non-inline, non-bitwise-takable)
// stride 8
-// CHECK: @"$s4weak1AVWV" = {{.*}} i8* inttoptr (i64 8 to i8*), i8* inttoptr (i64 1245191 to i8*), i8* inttoptr (i64 8 to i8*)]
+// flags 0x130007 == 1245191 (non-POD, non-inline, non-bitwise-takable)
+// CHECK: @"$s4weak1AVWV" = {{.*}} i64 8, i64 8, i32 1245191,
sil @test_weak_load_store : $@convention(thin) (@inout A, Optional<C>) -> () {
bb0(%0 : $*A, %1 : $Optional<C>):
diff --git a/unittests/runtime/Enum.cpp b/unittests/runtime/Enum.cpp
index a8cb4c7..50ac951 100644
--- a/unittests/runtime/Enum.cpp
+++ b/unittests/runtime/Enum.cpp
@@ -16,33 +16,60 @@
using namespace swift;
+SWIFT_CC(swift)
+static unsigned byte_getExtraInhabitantTag(const OpaqueValue *src,
+ unsigned numXI,
+ const Metadata *self) {
+ assert(numXI == 2);
+ uint8_t byte = *reinterpret_cast<const uint8_t*>(src);
+ if (byte > 253)
+ return byte - 253;
+ return 0;
+}
+
+static unsigned byte_getEnumTagSinglePayload(const OpaqueValue *value,
+ unsigned numEmptyCases,
+ const Metadata *self) {
+ return swift_getEnumTagSinglePayloadGeneric(value, numEmptyCases, self,
+ byte_getExtraInhabitantTag);
+}
+
+SWIFT_CC(swift)
+static void byte_storeExtraInhabitantTag(OpaqueValue *dest, unsigned tag,
+ unsigned numXI, const Metadata *self) {
+ assert(numXI == 2);
+ assert(tag > 0 && tag <= 2);
+ *reinterpret_cast<uint8_t*>(dest) = 253 + tag;
+}
+
+static void byte_storeEnumTagSinglePayload(OpaqueValue *value,
+ unsigned tag,
+ unsigned numEmptyCases,
+ const Metadata *self) {
+ swift_storeEnumTagSinglePayloadGeneric(value, tag, numEmptyCases, self,
+ byte_storeExtraInhabitantTag);
+}
+
+// Just use the normal operations for copying i8.
+#define byte_initializeBufferWithCopyOfBuffer \
+ VALUE_WITNESS_SYM(Bi8_).initializeBufferWithCopyOfBuffer
+#define byte_destroy VALUE_WITNESS_SYM(Bi8_).destroy
+#define byte_initializeWithCopy VALUE_WITNESS_SYM(Bi8_).initializeWithCopy
+#define byte_assignWithCopy VALUE_WITNESS_SYM(Bi8_).assignWithCopy
+#define byte_initializeWithTake VALUE_WITNESS_SYM(Bi8_).initializeWithTake
+#define byte_assignWithTake VALUE_WITNESS_SYM(Bi8_).assignWithTake
+
// Mock up a value witness table for Builtin.Int8 will 254 and 255 as extra
// inhabitants.
-ExtraInhabitantsValueWitnessTable Int8WithExtraInhabitantValueWitness
-= {
- // ValueWitnessTable
- ValueWitnessTable{
+ValueWitnessTable Int8WithExtraInhabitantValueWitness = {
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
-#define VALUE_WITNESS(LOWER_ID, UPPER_ID) VALUE_WITNESS_SYM(Bi8_).LOWER_ID,
+#define VALUE_WITNESS(LOWER_ID, UPPER_ID) byte_##LOWER_ID,
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
#include "swift/ABI/ValueWitness.def"
- VALUE_WITNESS_SYM(Bi8_).size,
- VALUE_WITNESS_SYM(Bi8_).flags.withExtraInhabitants(true),
- VALUE_WITNESS_SYM(Bi8_).stride
- },
- // extraInhabitantFlags
- ExtraInhabitantFlags().withNumExtraInhabitants(2),
- // storeExtraInhabitant
- [](OpaqueValue *dest, int index, const Metadata *self) {
- *reinterpret_cast<uint8_t*>(dest) = 254 + index;
- },
- // getExtraInhabitantIndex
- [](const OpaqueValue *src, const Metadata *self) -> int {
- uint8_t byte = *reinterpret_cast<const uint8_t*>(src);
- if (byte >= 254)
- return byte - 254;
- return -1;
- }
+ VALUE_WITNESS_SYM(Bi8_).size,
+ VALUE_WITNESS_SYM(Bi8_).stride,
+ VALUE_WITNESS_SYM(Bi8_).flags,
+ /*extraInhabitantCount*/ 2
};
FullMetadata<OpaqueMetadata> XI_TMBi8_ = {
@@ -58,10 +85,10 @@
}
int test_getEnumCaseSinglePayload(std::initializer_list<uint8_t> repr,
- const FullOpaqueMetadata &metadata,
- unsigned numEmptyCases) {
- return swift_getEnumCaseSinglePayload(asOpaque(repr.begin()),
- &metadata.base, numEmptyCases);
+ const FullOpaqueMetadata &metadata,
+ unsigned numEmptyCases) {
+ return metadata.base.vw_getEnumTagSinglePayload(asOpaque(repr.begin()),
+ numEmptyCases);
}
TEST(EnumTest, getEnumCaseSinglePayload) {
@@ -110,10 +137,9 @@
buf.resize(before.size());
memcpy(buf.data(), before.begin(), before.size());
- swift_storeEnumTagSinglePayload(asOpaque(buf.data()),
- &metadata.base,
- whichCase,
- numEmptyCases);
+ metadata.base.vw_storeEnumTagSinglePayload(asOpaque(buf.data()),
+ whichCase,
+ numEmptyCases);
return memcmp(buf.data(), after.begin(), after.size()) == 0;
}
diff --git a/validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c b/validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c
index a617edc..e2bc223 100644
--- a/validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c
+++ b/validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c
@@ -6,14 +6,14 @@
int $sBi32_WV;
int $sBi64_WV;
int $sBi8_WV;
-void swift_getEnumCaseSinglePayload(void) {}
void swift_getGenericMetadata(void) {}
void swift_checkMetadataState(void) {}
void swift_slowAlloc(void) {}
void swift_slowDealloc(void) {}
-void swift_storeEnumTagSinglePayload(void) {}
void swift_allocateGenericValueMetadata(void) {}
void swift_initEnumMetadataSinglePayload(void) {}
+void swift_getEnumTagSinglePayloadGeneric(void) {}
+void swift_storeEnumTagSinglePayloadGeneric(void) {}
void swift_retain(){}
void swift_allocBox(){}
void swift_getWitnessTable(void) {}