mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Properly flag opaque existential types as not being
bitwise-takable. Swift SVN r20803
This commit is contained in:
@@ -495,11 +495,7 @@ namespace {
|
||||
OpaqueExistentialTypeInfo(llvm::Type *ty, Size size, Alignment align,
|
||||
ArrayRef<ProtocolEntry> protocols)
|
||||
: IndirectTypeInfo(ty, size, llvm::BitVector{}, align,
|
||||
IsNotPOD,
|
||||
// We ensure opaque existentials are always bitwise-
|
||||
// takable by storing non-bitwise-takable objects out
|
||||
// of line.
|
||||
IsBitwiseTakable),
|
||||
IsNotPOD, IsNotBitwiseTakable),
|
||||
NumProtocols(protocols.size()) {
|
||||
|
||||
for (unsigned i = 0; i != NumProtocols; ++i) {
|
||||
|
||||
@@ -184,6 +184,7 @@ struct LLVM_LIBRARY_VISIBILITY OpaqueExistentialBox
|
||||
static constexpr size_t alignment = alignof(Container);
|
||||
static constexpr size_t stride = sizeof(Container);
|
||||
static constexpr size_t isPOD = false;
|
||||
static constexpr bool isBitwiseTakable = false;
|
||||
static constexpr unsigned numExtraInhabitants = 0;
|
||||
};
|
||||
|
||||
@@ -321,6 +322,7 @@ struct LLVM_LIBRARY_VISIBILITY ClassExistentialBox
|
||||
static constexpr size_t alignment = alignof(Container);
|
||||
static constexpr size_t stride = sizeof(Container);
|
||||
static constexpr size_t isPOD = false;
|
||||
static constexpr size_t isBitwiseTakable = true;
|
||||
};
|
||||
|
||||
/// A non-fixed box implementation class for an class existential
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <cctype>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "ExistentialMetadataImpl.h"
|
||||
#include "Debug.h"
|
||||
@@ -1497,6 +1496,7 @@ getOpaqueExistentialValueWitnesses(unsigned numWitnessTables) {
|
||||
vwt->flags = ValueWitnessFlags()
|
||||
.withAlignment(Box::Container::getAlignment(numWitnessTables))
|
||||
.withPOD(false)
|
||||
.withBitwiseTakable(false)
|
||||
.withInlineStorage(false)
|
||||
.withExtraInhabitants(false);
|
||||
vwt->stride = Box::Container::getStride(numWitnessTables);
|
||||
@@ -1547,6 +1547,7 @@ getClassExistentialValueWitnesses(unsigned numWitnessTables) {
|
||||
vwt->flags = ValueWitnessFlags()
|
||||
.withAlignment(Box::Container::getAlignment(numWitnessTables))
|
||||
.withPOD(false)
|
||||
.withBitwiseTakable(true)
|
||||
.withInlineStorage(false)
|
||||
.withExtraInhabitants(true);
|
||||
vwt->stride = Box::Container::getStride(numWitnessTables);
|
||||
|
||||
@@ -103,6 +103,7 @@ struct NativeBox {
|
||||
static constexpr size_t alignment = Alignment;
|
||||
static constexpr size_t stride = Stride;
|
||||
static constexpr size_t isPOD = std::is_pod<T>::value;
|
||||
static constexpr bool isBitwiseTakable = isPOD;
|
||||
static constexpr unsigned numExtraInhabitants = 0;
|
||||
|
||||
static void destroy(T *value) {
|
||||
@@ -197,6 +198,7 @@ template <class Impl, class T> struct RetainableBoxBase {
|
||||
static constexpr size_t alignment = alignof(T);
|
||||
static constexpr size_t stride = sizeof(T);
|
||||
static constexpr bool isPOD = false;
|
||||
static constexpr bool isBitwiseTakable = true;
|
||||
|
||||
static void destroy(T *addr) {
|
||||
Impl::release(*addr);
|
||||
@@ -339,6 +341,7 @@ public:
|
||||
static constexpr size_t endOffset = StartOffset;
|
||||
static constexpr size_t alignment = 1;
|
||||
static constexpr bool isPOD = true;
|
||||
static constexpr bool isBitwiseTakable = true;
|
||||
|
||||
public:
|
||||
#define COPY_OP(OP) \
|
||||
@@ -370,6 +373,8 @@ public:
|
||||
(NextHelper::alignment > EltBox::alignment
|
||||
? NextHelper::alignment : EltBox::alignment);
|
||||
static constexpr bool isPOD = EltBox::isPOD && NextHelper::isPOD;
|
||||
static constexpr bool isBitwiseTakable =
|
||||
EltBox::isBitwiseTakable && NextHelper::isBitwiseTakable;
|
||||
|
||||
private:
|
||||
static constexpr size_t eltToNextOffset = (nextOffset - eltOffset);
|
||||
@@ -412,6 +417,7 @@ struct AggregateBox {
|
||||
static constexpr size_t alignment = Helper::alignment;
|
||||
static constexpr size_t stride = roundUpToAlignment(size, alignment);
|
||||
static constexpr bool isPOD = Helper::isPOD;
|
||||
static constexpr bool isBitwiseTakable = Helper::isBitwiseTakable;
|
||||
|
||||
/// Don't collect extra inhabitants from the members by default.
|
||||
static constexpr unsigned numExtraInhabitants = 0;
|
||||
@@ -659,12 +665,14 @@ struct ValueWitnesses : BufferValueWitnesses<ValueWitnesses<Box>,
|
||||
static constexpr size_t stride = Box::stride;
|
||||
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 ValueWitnessFlags flags =
|
||||
ValueWitnessFlags().withAlignmentMask(alignment - 1)
|
||||
.withInlineStorage(Base::isInline)
|
||||
.withPOD(isPOD)
|
||||
.withBitwiseTakable(isBitwiseTakable)
|
||||
.withExtraInhabitants(hasExtraInhabitants);
|
||||
static constexpr ExtraInhabitantFlags extraInhabitantFlags =
|
||||
ExtraInhabitantFlags().withNumExtraInhabitants(numExtraInhabitants);
|
||||
|
||||
@@ -328,3 +328,96 @@ TEST(MetadataTest, getGenericMetadata_SuperclassWithUnexpectedPrefix) {
|
||||
ASSERT_EQ(4 * sizeof(void*) + sizeof(HeapMetadataHeader),
|
||||
inst->getClassAddressPoint());
|
||||
}
|
||||
|
||||
static ProtocolDescriptor OpaqueProto1 = { "OpaqueProto1", nullptr,
|
||||
ProtocolDescriptorFlags().withSwift(true).withNeedsWitnessTable(true)
|
||||
.withClassConstraint(ProtocolClassConstraint::Any)
|
||||
};
|
||||
static ProtocolDescriptor OpaqueProto2 = { "OpaqueProto2", nullptr,
|
||||
ProtocolDescriptorFlags().withSwift(true).withNeedsWitnessTable(true)
|
||||
.withClassConstraint(ProtocolClassConstraint::Any)
|
||||
};
|
||||
static ProtocolDescriptor OpaqueProto3 = { "OpaqueProto3", nullptr,
|
||||
ProtocolDescriptorFlags().withSwift(true).withNeedsWitnessTable(true)
|
||||
.withClassConstraint(ProtocolClassConstraint::Any)
|
||||
};
|
||||
static ProtocolDescriptor ClassProto1 = { "ClassProto1", nullptr,
|
||||
ProtocolDescriptorFlags().withSwift(true).withNeedsWitnessTable(true)
|
||||
.withClassConstraint(ProtocolClassConstraint::Class)
|
||||
};
|
||||
|
||||
TEST(MetadataTest, getExistentialTypeMetadata_opaque) {
|
||||
const ProtocolDescriptor *protoList1[] = {
|
||||
&OpaqueProto1
|
||||
};
|
||||
auto ex1a = swift_getExistentialTypeMetadata(1, protoList1);
|
||||
auto ex1b = swift_getExistentialTypeMetadata(1, protoList1);
|
||||
ASSERT_EQ(ex1a, ex1b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex1a->getKind());
|
||||
ASSERT_EQ(5 * sizeof(void*), ex1a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex1a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex1a->getValueWitnesses()->isPOD());
|
||||
ASSERT_FALSE(ex1a->getValueWitnesses()->isBitwiseTakable());
|
||||
|
||||
const ProtocolDescriptor *protoList2[] = {
|
||||
&OpaqueProto1, &OpaqueProto2
|
||||
};
|
||||
auto ex2a = swift_getExistentialTypeMetadata(2, protoList2);
|
||||
auto ex2b = swift_getExistentialTypeMetadata(2, protoList2);
|
||||
ASSERT_EQ(ex2a, ex2b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex2a->getKind());
|
||||
ASSERT_EQ(6 * sizeof(void*), ex2a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex2a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex2a->getValueWitnesses()->isPOD());
|
||||
ASSERT_FALSE(ex2a->getValueWitnesses()->isBitwiseTakable());
|
||||
|
||||
const ProtocolDescriptor *protoList3[] = {
|
||||
&OpaqueProto1, &OpaqueProto2, &OpaqueProto3
|
||||
};
|
||||
auto ex3a = swift_getExistentialTypeMetadata(3, protoList3);
|
||||
auto ex3b = swift_getExistentialTypeMetadata(3, protoList3);
|
||||
ASSERT_EQ(ex3a, ex3b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex3a->getKind());
|
||||
ASSERT_EQ(7 * sizeof(void*), ex3a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex3a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex3a->getValueWitnesses()->isPOD());
|
||||
ASSERT_FALSE(ex3a->getValueWitnesses()->isBitwiseTakable());
|
||||
}
|
||||
|
||||
TEST(MetadataTest, getExistentialTypeMetadata_class) {
|
||||
const ProtocolDescriptor *protoList1[] = {
|
||||
&ClassProto1
|
||||
};
|
||||
auto ex1a = swift_getExistentialTypeMetadata(1, protoList1);
|
||||
auto ex1b = swift_getExistentialTypeMetadata(1, protoList1);
|
||||
ASSERT_EQ(ex1a, ex1b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex1a->getKind());
|
||||
ASSERT_EQ(2 * sizeof(void*), ex1a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex1a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex1a->getValueWitnesses()->isPOD());
|
||||
ASSERT_TRUE(ex1a->getValueWitnesses()->isBitwiseTakable());
|
||||
|
||||
const ProtocolDescriptor *protoList2[] = {
|
||||
&OpaqueProto1, &ClassProto1
|
||||
};
|
||||
auto ex2a = swift_getExistentialTypeMetadata(2, protoList2);
|
||||
auto ex2b = swift_getExistentialTypeMetadata(2, protoList2);
|
||||
ASSERT_EQ(ex2a, ex2b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex2a->getKind());
|
||||
ASSERT_EQ(3 * sizeof(void*), ex2a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex2a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex2a->getValueWitnesses()->isPOD());
|
||||
ASSERT_TRUE(ex2a->getValueWitnesses()->isBitwiseTakable());
|
||||
|
||||
const ProtocolDescriptor *protoList3[] = {
|
||||
&OpaqueProto1, &OpaqueProto2, &ClassProto1
|
||||
};
|
||||
auto ex3a = swift_getExistentialTypeMetadata(3, protoList3);
|
||||
auto ex3b = swift_getExistentialTypeMetadata(3, protoList3);
|
||||
ASSERT_EQ(ex3a, ex3b);
|
||||
ASSERT_EQ(MetadataKind::Existential, ex3a->getKind());
|
||||
ASSERT_EQ(4 * sizeof(void*), ex3a->getValueWitnesses()->getSize());
|
||||
ASSERT_EQ(alignof(void*), ex3a->getValueWitnesses()->getAlignment());
|
||||
ASSERT_FALSE(ex3a->getValueWitnesses()->isPOD());
|
||||
ASSERT_TRUE(ex3a->getValueWitnesses()->isBitwiseTakable());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user