Merge pull request #18343 from rudkx/function-types
[PrintAsObjC] Replace a couple uses of getInput() with getParams().
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index ad7ea28..6500f54 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -272,6 +272,7 @@
message("-- CLANG_EXEC = ${CLANG_EXEC}")
message("-- SWIFT_OPTIMIZATION_LEVELS = ${SWIFT_OPTIMIZATION_LEVELS}")
message("-- ONLY_PLATFORMS = ${ONLY_PLATFORMS}")
+message("-- PAGE_ALIGNMENT_OPTION = ${PAGE_ALIGNMENT_OPTION}")
message("-- found platforms: ${platforms}")
message("-- found sdks:")
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 7e1e8da..54d0952 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -40,6 +40,19 @@
message(FATAL_ERROR "Unsupported platform?!")
endif()
+ set(PAGE_ALIGNMENT_OPTION "-Xllvm" "-align-module-to-page-size")
+ execute_process(
+ COMMAND "touch" "empty.swift"
+ RESULT_VARIABLE result
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(
+ COMMAND "${SWIFT_EXEC}" ${PAGE_ALIGNMENT_OPTION} "empty.swift"
+ RESULT_VARIABLE result
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT "${result}" MATCHES "0")
+ set(PAGE_ALIGNMENT_OPTION "")
+ endif()
+
# We always infer the SWIFT_LIBRARY_PATH from SWIFT_EXEC unless
# SWIFT_LIBRARY_PATH is specified explicitly.
if(NOT SWIFT_LIBRARY_PATH)
@@ -293,7 +306,7 @@
set(common_options
"-c"
"-target" "${target}"
- "-${BENCH_COMPILE_ARCHOPTS_OPT}")
+ "-${BENCH_COMPILE_ARCHOPTS_OPT}" ${PAGE_ALIGNMENT_OPTION})
if (is_darwin)
list(APPEND common_options
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index 6823a33..f3d2bf8 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -1188,144 +1188,6 @@
/// us to use.
template <typename Runtime>
struct TargetForeignTypeMetadata : public TargetMetadata<Runtime> {
- using StoredPointer = typename Runtime::StoredPointer;
- using StoredSize = typename Runtime::StoredSize;
- using InitializationFunction_t =
- void (TargetForeignTypeMetadata<Runtime> *selectedMetadata);
- using RuntimeMetadataPointer =
- ConstTargetMetadataPointer<Runtime, swift::TargetForeignTypeMetadata>;
-
- /// An invasive cache for the runtime-uniqued lookup structure that is stored
- /// in the header prefix of foreign metadata records.
- ///
- /// Prior to initialization, as emitted by the compiler, this contains the
- /// initialization flags.
- /// After initialization, it holds a pointer to the actual, runtime-uniqued
- /// metadata for this type.
- struct CacheValue {
- StoredSize Value;
-
- /// Work around a bug in libstdc++'s std::atomic that requires the type to
- /// be default-constructible.
- CacheValue() = default;
-
- explicit CacheValue(RuntimeMetadataPointer p)
- : Value(reinterpret_cast<StoredSize>(p))
- {}
-
- /// Various flags. The largest flag bit should be less than 4096 so that
- /// a flag set is distinguishable from a valid pointer.
- enum : StoredSize {
- /// This metadata has an initialization callback function. If
- /// this flag is not set, the metadata object needn't actually
- /// have a InitializationFunction field, and that field will be
- /// undefined.
- HasInitializationFunction = 0x1,
-
- LargestFlagMask = 0xFFF,
- };
-
- /// True if the metadata record associated with this cache has not been
- /// initialized, so contains a flag set describing parameters to the
- /// initialization operation. isFlags() == !isInitialized()
- bool isFlags() const {
- return Value <= LargestFlagMask;
- }
- /// True if the metadata record associated with this cache has an
- /// initialization function which must be run if it is picked as the
- /// canonical metadata record for its key.
- ///
- /// Undefined if !isFlags().
- bool hasInitializationFunction() const {
- assert(isFlags());
- return Value & HasInitializationFunction;
- }
-
- /// True if the metadata record associated with this cache has been
- /// initialized, so the cache contains an absolute pointer to the
- /// canonical metadata record for its key. isInitialized() == !isFlags()
- bool isInitialized() const {
- return !isFlags();
- }
-
- /// Gets the cached pointer to the unique canonical metadata record for
- /// this metadata record's key.
- ///
- /// Undefined if !isInitialized().
- RuntimeMetadataPointer getCachedUniqueMetadata() const {
- assert(isInitialized());
- return RuntimeMetadataPointer(Value);
- }
- };
-
-
- /// Foreign type metadata may have extra header fields depending on
- /// the flags.
- struct HeaderPrefix {
- /// An optional callback performed when a particular metadata object
- /// is chosen as the unique structure.
- ///
- /// If there is no initialization function, this metadata record can be
- /// assumed to be immutable (except for the \c Unique invasive cache
- /// field). The field is not present unless the HasInitializationFunction
- /// flag is set.
- RelativeDirectPointer<InitializationFunction_t> InitializationFunction;
-
- mutable std::atomic<CacheValue> Cache;
- };
-
- struct HeaderType : HeaderPrefix, TargetTypeMetadataHeader<Runtime> {};
-
- CacheValue getCacheValue() const {
- /// NB: This can be a relaxed-order load if there is no initialization
- /// function. On platforms Swift currently targets, consume is no more
- /// expensive than relaxed, so there's no reason to branch here (and LLVM
- /// isn't smart enough to eliminate it when it's not needed).
- ///
- /// A port to a platform where relaxed is significantly less expensive than
- /// consume (historically, Alpha) would probably want to preserve the
- /// 'hasInitializationFunction' bit in its own word to be able to avoid
- /// the consuming load when not needed.
- return asFullMetadata(this)->Cache
- .load(SWIFT_MEMORY_ORDER_CONSUME);
- }
-
- void setCachedUniqueMetadata(RuntimeMetadataPointer unique) const {
- auto cache = getCacheValue();
-
- // If the cache was already set to a pointer, we're done. We ought to
- // converge on a single unique pointer.
- if (cache.isInitialized()) {
- assert(cache.getCachedUniqueMetadata() == unique
- && "already set unique metadata to something else");
- return;
- }
-
- auto newCache = CacheValue(unique);
-
- // If there is no initialization function, this can be a relaxed store.
- if (cache.hasInitializationFunction())
- asFullMetadata(this)->Cache.store(newCache, std::memory_order_relaxed);
-
- // Otherwise, we need a release store to publish the result of
- // initialization.
- else
- asFullMetadata(this)->Cache.store(newCache, std::memory_order_release);
- }
-
- /// Return the initialization function for this metadata record.
- ///
- /// As a prerequisite, the metadata record must not have been initialized yet,
- /// and must have an initialization function to begin with, otherwise the
- /// result is undefined.
- InitializationFunction_t *getInitializationFunction() const {
-#ifndef NDEBUG
- auto cache = getCacheValue();
- assert(cache.hasInitializationFunction());
-#endif
-
- return asFullMetadata(this)->InitializationFunction;
- }
};
using ForeignTypeMetadata = TargetForeignTypeMetadata<InProcess>;
@@ -1337,8 +1199,7 @@
/// We assume for now that foreign classes are entirely opaque
/// to Swift introspection.
template <typename Runtime>
-struct TargetForeignClassMetadata
- : public TargetForeignTypeMetadata<Runtime> {
+struct TargetForeignClassMetadata : public TargetForeignTypeMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
/// An out-of-line description of the type.
@@ -1348,8 +1209,15 @@
ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
Superclass;
- /// Reserved space. For now, these should be zero-initialized.
- StoredPointer Reserved[3];
+ /// Reserved space. For now, this should be zero-initialized.
+ /// If this is used for anything in the future, at least some of these
+ /// first bits should be flags.
+ StoredPointer Reserved[1];
+
+ ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
+ getDescription() const {
+ return Description;
+ }
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::ForeignClass;
@@ -2150,32 +2018,37 @@
union {
/// A direct reference to a nominal type descriptor.
RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime>,
- TypeMetadataRecordKind>
+ TypeReferenceKind>
DirectNominalTypeDescriptor;
/// An indirect reference to a nominal type descriptor.
RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime> * const,
- TypeMetadataRecordKind>
+ TypeReferenceKind>
IndirectNominalTypeDescriptor;
+
+ // We only allow a subset of the TypeReferenceKinds here.
+ // Should we just acknowledge that this is a different enum?
};
public:
- TypeMetadataRecordKind getTypeKind() const {
+ TypeReferenceKind getTypeKind() const {
return DirectNominalTypeDescriptor.getInt();
}
const TargetTypeContextDescriptor<Runtime> *
getTypeContextDescriptor() const {
switch (getTypeKind()) {
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
+ case TypeReferenceKind::DirectNominalTypeDescriptor:
return DirectNominalTypeDescriptor.getPointer();
- case TypeMetadataRecordKind::Reserved:
- case TypeMetadataRecordKind::IndirectObjCClass:
- return nullptr;
-
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
+ case TypeReferenceKind::IndirectNominalTypeDescriptor:
return *IndirectNominalTypeDescriptor.getPointer();
+
+ // These types (and any others we might add to TypeReferenceKind
+ // in the future) are just never used in these lists.
+ case TypeReferenceKind::DirectObjCClassName:
+ case TypeReferenceKind::IndirectObjCClass:
+ return nullptr;
}
return nullptr;
@@ -2250,6 +2123,66 @@
}
};
+/// A reference to a type.
+template <typename Runtime>
+struct TargetTypeReference {
+ union {
+ /// A direct reference to a nominal type descriptor.
+ RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
+ DirectNominalTypeDescriptor;
+
+ /// An indirect reference to a nominal type descriptor.
+ RelativeDirectPointer<
+ ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
+ IndirectNominalTypeDescriptor;
+
+ /// An indirect reference to an Objective-C class.
+ RelativeDirectPointer<
+ ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
+ IndirectObjCClass;
+
+ /// A direct reference to an Objective-C class name.
+ RelativeDirectPointer<const char>
+ DirectObjCClassName;
+ };
+
+ const TargetTypeContextDescriptor<Runtime> *
+ getTypeContextDescriptor(TypeReferenceKind kind) const {
+ switch (kind) {
+ case TypeReferenceKind::DirectNominalTypeDescriptor:
+ return DirectNominalTypeDescriptor;
+
+ case TypeReferenceKind::IndirectNominalTypeDescriptor:
+ return *IndirectNominalTypeDescriptor;
+
+ case TypeReferenceKind::DirectObjCClassName:
+ case TypeReferenceKind::IndirectObjCClass:
+ return nullptr;
+ }
+
+ return nullptr;
+ }
+
+#if SWIFT_OBJC_INTEROP
+ /// If this type reference is one of the kinds that supports ObjC
+ /// references,
+ const TargetClassMetadata<Runtime> *
+ getObjCClass(TypeReferenceKind kind) const;
+#endif
+
+ const TargetClassMetadata<Runtime> * const *
+ getIndirectObjCClass(TypeReferenceKind kind) const {
+ assert(kind == TypeReferenceKind::IndirectObjCClass);
+ return IndirectObjCClass.get();
+ }
+
+ const char *getDirectObjCClassName(TypeReferenceKind kind) const {
+ assert(kind == TypeReferenceKind::DirectObjCClassName);
+ return DirectObjCClassName.get();
+ }
+};
+using TypeReference = TargetTypeReference<InProcess>;
+
/// The structure of a protocol conformance.
///
/// This contains enough static information to recover the witness table for a
@@ -2284,21 +2217,7 @@
RelativeIndirectablePointer<ProtocolDescriptor> Protocol;
// Some description of the type that conforms to the protocol.
- union {
- /// A direct reference to a nominal type descriptor.
- RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
- DirectNominalTypeDescriptor;
-
- /// An indirect reference to a nominal type descriptor.
- RelativeDirectPointer<
- ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
- IndirectNominalTypeDescriptor;
-
- /// An indirect reference to the metadata.
- RelativeDirectPointer<
- ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
- IndirectObjCClass;
- };
+ TargetTypeReference<Runtime> TypeRef;
// The conformance, or a generator function for the conformance.
union {
@@ -2318,45 +2237,24 @@
return Protocol;
}
- TypeMetadataRecordKind getTypeKind() const {
+ TypeReferenceKind getTypeKind() const {
return Flags.getTypeReferenceKind();
}
typename ConformanceFlags::ConformanceKind getConformanceKind() const {
return Flags.getConformanceKind();
}
-
+
+ const char *getDirectObjCClassName() const {
+ return TypeRef.getDirectObjCClassName(getTypeKind());
+ }
+
const TargetClassMetadata<Runtime> * const *getIndirectObjCClass() const {
- switch (getTypeKind()) {
- case TypeMetadataRecordKind::IndirectObjCClass:
- break;
-
- case TypeMetadataRecordKind::Reserved:
- return nullptr;
-
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
- assert(false && "not indirect class object");
- }
-
- return IndirectObjCClass.get();
+ return TypeRef.getIndirectObjCClass(getTypeKind());
}
- const TargetTypeContextDescriptor<Runtime> *
- getTypeContextDescriptor() const {
- switch (getTypeKind()) {
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
- return DirectNominalTypeDescriptor;
-
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
- return *IndirectNominalTypeDescriptor;
-
- case TypeMetadataRecordKind::Reserved:
- case TypeMetadataRecordKind::IndirectObjCClass:
- return nullptr;
- }
-
- return nullptr;
+ const TargetTypeContextDescriptor<Runtime> *getTypeContextDescriptor() const {
+ return TypeRef.getTypeContextDescriptor(getTypeKind());
}
/// Retrieve the context of a retroactive conformance.
@@ -2418,7 +2316,7 @@
///
/// We currently check that the descriptor:
///
- /// 1. Has a valid TypeMetadataRecordKind.
+ /// 1. Has a valid TypeReferenceKind.
/// 2. Has a valid conformance kind.
void verify() const LLVM_ATTRIBUTE_USED;
#endif
@@ -3354,6 +3252,15 @@
}
};
+/// The control structure for performing non-trivial initialization of
+/// singleton foreign metadata.
+template <typename Runtime>
+struct TargetForeignMetadataInitialization {
+ /// The completion function. The pattern will always be null.
+ TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
+ CompletionFunction;
+};
+
template <typename Runtime>
class TargetTypeContextDescriptor
: public TargetContextDescriptor<Runtime> {
@@ -3377,6 +3284,13 @@
return TypeContextDescriptorFlags(this->Flags.getKindSpecificFlags());
}
+ /// Return the kind of metadata initialization required by this type.
+ /// Note that this is only meaningful for non-generic types.
+ TypeContextDescriptorFlags::MetadataInitializationKind
+ getMetadataInitialization() const {
+ return getTypeContextDescriptorFlags().getMetadataInitialization();
+ }
+
/// Does this type have non-trivial "in place" metadata initialization?
///
/// The type of the initialization-control structure differs by subclass,
@@ -3385,6 +3299,16 @@
return getTypeContextDescriptorFlags().hasInPlaceMetadataInitialization();
}
+ /// Does this type have "foreign" metadata initialiation?
+ bool hasForeignMetadataInitialization() const {
+ return getTypeContextDescriptorFlags().hasForeignMetadataInitialization();
+ }
+
+ /// Given that this type has foreign metadata initialization, return the
+ /// control structure for it.
+ const TargetForeignMetadataInitialization<Runtime> &
+ getForeignMetadataInitialization() const;
+
const TargetTypeGenericContextDescriptorHeader<Runtime> &
getFullGenericContextHeader() const;
@@ -3523,12 +3447,14 @@
public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
/*additional trailing objects:*/
+ TargetForeignMetadataInitialization<Runtime>,
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>> {
private:
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
+ TargetForeignMetadataInitialization<Runtime>,
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>>;
@@ -3539,6 +3465,8 @@
public:
using MethodDescriptor = TargetMethodDescriptor<Runtime>;
using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
+ using ForeignMetadataInitialization =
+ TargetForeignMetadataInitialization<Runtime>;
using StoredPointer = typename Runtime::StoredPointer;
using StoredPointerDifference = typename Runtime::StoredPointerDifference;
@@ -3563,7 +3491,7 @@
return !Superclass.isNull();
}
- TypeMetadataRecordKind getSuperclassReferenceKind() const {
+ TypeReferenceKind getSuperclassReferenceKind() const {
return getTypeContextDescriptorFlags().class_getSuperclassReferenceKind();
}
@@ -3626,6 +3554,10 @@
using TrailingGenericContextObjects::numTrailingObjects;
+ size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+ return this->hasForeignMetadataInitialization() ? 1 : 0;
+ }
+
size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
return hasVTable() ? 1 : 0;
}
@@ -3638,6 +3570,11 @@
}
public:
+ const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+ assert(this->hasForeignMetadataInitialization());
+ return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+ }
+
/// True if metadata records for this type have a field offset vector for
/// its stored properties.
bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
@@ -3785,8 +3722,12 @@
: public TargetValueTypeDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
+ /*additional trailing objects*/
+ TargetForeignMetadataInitialization<Runtime>,
TargetInPlaceValueMetadataInitialization<Runtime>> {
public:
+ using ForeignMetadataInitialization =
+ TargetForeignMetadataInitialization<Runtime>;
using InPlaceMetadataInitialization =
TargetInPlaceValueMetadataInitialization<Runtime>;
@@ -3794,6 +3735,7 @@
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
+ ForeignMetadataInitialization,
InPlaceMetadataInitialization>;
using TrailingObjects =
@@ -3802,8 +3744,12 @@
template<typename T>
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
-
using TrailingGenericContextObjects::numTrailingObjects;
+
+ size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+ return this->hasForeignMetadataInitialization() ? 1 : 0;
+ }
+
size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
return this->hasInPlaceMetadataInitialization() ? 1 : 0;
}
@@ -3826,6 +3772,11 @@
/// its stored properties.
bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
+ const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+ assert(this->hasForeignMetadataInitialization());
+ return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+ }
+
const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
assert(this->hasInPlaceMetadataInitialization());
return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
@@ -3847,15 +3798,20 @@
: public TargetValueTypeDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
+ /*additional trailing objects*/
+ TargetForeignMetadataInitialization<Runtime>,
TargetInPlaceValueMetadataInitialization<Runtime>> {
public:
using InPlaceMetadataInitialization =
TargetInPlaceValueMetadataInitialization<Runtime>;
+ using ForeignMetadataInitialization =
+ TargetForeignMetadataInitialization<Runtime>;
private:
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
+ ForeignMetadataInitialization,
InPlaceMetadataInitialization>;
using TrailingObjects =
@@ -3864,8 +3820,12 @@
template<typename T>
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
-
using TrailingGenericContextObjects::numTrailingObjects;
+
+ size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+ return this->hasForeignMetadataInitialization() ? 1 : 0;
+ }
+
size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
return this->hasInPlaceMetadataInitialization() ? 1 : 0;
}
@@ -3906,6 +3866,11 @@
return TargetEnumMetadata<Runtime>::getGenericArgumentOffset();
}
+ const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+ assert(this->hasForeignMetadataInitialization());
+ return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+ }
+
const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
assert(this->hasInPlaceMetadataInitialization());
return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
@@ -3999,6 +3964,24 @@
}
}
+template <typename Runtime>
+const TargetForeignMetadataInitialization<Runtime> &
+TargetTypeContextDescriptor<Runtime>::getForeignMetadataInitialization() const {
+ switch (this->getKind()) {
+ case ContextDescriptorKind::Class:
+ return llvm::cast<TargetClassDescriptor<Runtime>>(this)
+ ->getForeignMetadataInitialization();
+ case ContextDescriptorKind::Enum:
+ return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
+ ->getForeignMetadataInitialization();
+ case ContextDescriptorKind::Struct:
+ return llvm::cast<TargetStructDescriptor<Runtime>>(this)
+ ->getForeignMetadataInitialization();
+ default:
+ swift_runtime_unreachable("Not a type context descriptor.");
+ }
+}
+
template<typename Runtime>
inline const TargetInPlaceValueMetadataInitialization<Runtime> &
TargetValueTypeDescriptor<Runtime>::getInPlaceMetadataInitialization() const {
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0e48429..d6d560a 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -350,7 +350,7 @@
};
/// Kinds of type metadata/protocol conformance records.
-enum class TypeMetadataRecordKind : unsigned {
+enum class TypeReferenceKind : unsigned {
/// The conformance is for a nominal type referenced directly;
/// getNominalTypeDescriptor() points to the nominal type descriptor.
DirectNominalTypeDescriptor = 0x00,
@@ -359,9 +359,10 @@
/// getNominalTypeDescriptor() points to the nominal type descriptor.
IndirectNominalTypeDescriptor = 0x01,
- /// Reserved for future use.
- Reserved = 0x02,
-
+ /// The conformance is for an Objective-C class that should be looked up
+ /// by class name.
+ DirectObjCClassName = 0x02,
+
/// The conformance is for an Objective-C class that has no nominal type
/// descriptor.
/// getIndirectObjCClass() points to a variable that contains the pointer to
@@ -371,6 +372,8 @@
/// unused.
IndirectObjCClass = 0x03,
+ // We only reserve three bits for this in the various places we store it.
+
First_Kind = DirectNominalTypeDescriptor,
Last_Kind = IndirectObjCClass,
};
@@ -593,7 +596,7 @@
return ConformanceFlags((Value & ~ConformanceKindMask) | int_type(kind));
}
- ConformanceFlags withTypeReferenceKind(TypeMetadataRecordKind kind) const {
+ ConformanceFlags withTypeReferenceKind(TypeReferenceKind kind) const {
return ConformanceFlags((Value & ~TypeMetadataKindMask)
| (int_type(kind) << TypeMetadataKindShift));
}
@@ -621,8 +624,8 @@
}
/// Retrieve the type reference kind kind.
- TypeMetadataRecordKind getTypeReferenceKind() const {
- return TypeMetadataRecordKind(
+ TypeReferenceKind getTypeReferenceKind() const {
+ return TypeReferenceKind(
(Value & TypeMetadataKindMask) >> TypeMetadataKindShift);
}
@@ -1237,16 +1240,16 @@
/// Only meaningful for class descriptors.
Class_HasResilientSuperclass = 14,
- /// The kind of reference that this class makes to its superclass
- /// descriptor. A TypeMetadataRecordKind.
- ///
- /// Only meaningful for class descriptors.
- Class_SuperclassReferenceKind = 12,
- Class_SuperclassReferenceKind_width = 2,
-
/// Whether the immediate class members in this metadata are allocated
/// at negative offsets. For now, we don't use this.
- Class_AreImmediateMembersNegative = 11,
+ Class_AreImmediateMembersNegative = 13,
+
+ /// The kind of reference that this class makes to its superclass
+ /// descriptor. A TypeReferenceKind.
+ ///
+ /// Only meaningful for class descriptors.
+ Class_SuperclassReferenceKind = 10,
+ Class_SuperclassReferenceKind_width = 3,
};
public:
@@ -1265,6 +1268,10 @@
/// "in-place" code pattern.
InPlaceMetadataInitialization = 1,
+ /// The type requires non-trivial singleton initialization using the
+ /// "foreign" code pattern.
+ ForeignMetadataInitialization = 2,
+
// We only have two bits here, so if you add a third special kind,
// include more flag bits in its out-of-line storage.
};
@@ -1279,6 +1286,10 @@
return getMetadataInitialization() == InPlaceMetadataInitialization;
}
+ bool hasForeignMetadataInitialization() const {
+ return getMetadataInitialization() == ForeignMetadataInitialization;
+ }
+
enum ImportNamespaceKind {
/// The type comes the default namespace for its language.
DefaultNamespace = 0,
@@ -1333,7 +1344,7 @@
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
Class_SuperclassReferenceKind_width,
- TypeMetadataRecordKind,
+ TypeReferenceKind,
class_getSuperclassReferenceKind,
class_setSuperclassReferenceKind)
};
diff --git a/include/swift/Demangling/ManglingMacros.h b/include/swift/Demangling/ManglingMacros.h
index 9c35415..d537b02 100644
--- a/include/swift/Demangling/ManglingMacros.h
+++ b/include/swift/Demangling/ManglingMacros.h
@@ -66,12 +66,6 @@
#define VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT2(Ty, WV))
-#define UNOWNED_VALUE_WITNESS_SYM(Ty) \
- MANGLE_SYM(MANGLING_CONCAT3(Ty, Xo, WV))
-
-#define WEAK_VALUE_WITNESS_SYM(Ty) \
- MANGLE_SYM(MANGLING_CONCAT3(OPTIONAL_MANGLING(Ty), Xw, WV))
-
#define METATYPE_VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, METATYPE_MANGLING, WV))
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index cbbce7e..63db68b 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -740,16 +740,23 @@
return llvm::None;
return cls->getClassBoundsAsSwiftSuperclass();
+ },
+ [](StoredPointer objcClassName) -> llvm::Optional<ClassMetadataBounds> {
+ // We have no ability to look up an ObjC class by name.
+ // FIXME: add a query for this; clients may have a way to do it.
+ return llvm::None;
});
}
- template <class Result, class DescriptorFn, class MetadataFn>
+ template <class Result, class DescriptorFn, class MetadataFn,
+ class ClassNameFn>
llvm::Optional<Result>
- forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
+ forTypeReference(TypeReferenceKind refKind, StoredPointer ref,
const DescriptorFn &descriptorFn,
- const MetadataFn &metadataFn) {
+ const MetadataFn &metadataFn,
+ const ClassNameFn &classNameFn) {
switch (refKind) {
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+ case TypeReferenceKind::IndirectNominalTypeDescriptor: {
StoredPointer descriptorAddress = 0;
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
return llvm::None;
@@ -758,7 +765,7 @@
LLVM_FALLTHROUGH;
}
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+ case TypeReferenceKind::DirectNominalTypeDescriptor: {
auto descriptor = readContextDescriptor(ref);
if (!descriptor)
return llvm::None;
@@ -766,7 +773,10 @@
return descriptorFn(descriptor);
}
- case TypeMetadataRecordKind::IndirectObjCClass: {
+ case TypeReferenceKind::DirectObjCClassName:
+ return classNameFn(ref);
+
+ case TypeReferenceKind::IndirectObjCClass: {
StoredPointer classRef = 0;
if (!Reader->readInteger(RemoteAddress(ref), &classRef))
return llvm::None;
@@ -777,10 +787,9 @@
return metadataFn(metadata);
}
-
- default:
- return llvm::None;
}
+
+ return llvm::None;
}
/// Read a single generic type argument from a bound generic type
@@ -1179,8 +1188,22 @@
TypeContextDescriptorFlags typeFlags(flags.getKindSpecificFlags());
unsigned baseSize = 0;
unsigned genericHeaderSize = sizeof(GenericContextDescriptorHeader);
- unsigned inPlaceInitSize = 0;
+ unsigned metadataInitSize = 0;
bool hasVTable = false;
+
+ auto readMetadataInitSize = [&]() -> unsigned {
+ switch (typeFlags.getMetadataInitialization()) {
+ case TypeContextDescriptorFlags::NoMetadataInitialization:
+ return 0;
+ case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
+ // FIXME: classes
+ return sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
+ case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+ return sizeof(TargetForeignMetadataInitialization<Runtime>);
+ }
+ return 0;
+ };
+
switch (auto kind = flags.getKind()) {
case ContextDescriptorKind::Module:
baseSize = sizeof(TargetModuleContextDescriptor<Runtime>);
@@ -1196,22 +1219,17 @@
baseSize = sizeof(TargetClassDescriptor<Runtime>);
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
hasVTable = typeFlags.class_hasVTable();
+ metadataInitSize = readMetadataInitSize();
break;
case ContextDescriptorKind::Enum:
baseSize = sizeof(TargetEnumDescriptor<Runtime>);
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
- if (typeFlags.hasInPlaceMetadataInitialization()) {
- inPlaceInitSize =
- sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
- }
+ metadataInitSize = readMetadataInitSize();
break;
case ContextDescriptorKind::Struct:
baseSize = sizeof(TargetStructDescriptor<Runtime>);
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
- if (typeFlags.hasInPlaceMetadataInitialization()) {
- inPlaceInitSize =
- sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
- }
+ metadataInitSize = readMetadataInitSize();
break;
case ContextDescriptorKind::Protocol:
baseSize = sizeof(TargetProtocolDescriptorRef<Runtime>);
@@ -1220,7 +1238,7 @@
// We don't know about this kind of context.
return nullptr;
}
-
+
// Determine the full size of the descriptor. This is reimplementing a fair
// bit of TrailingObjects but for out-of-process; maybe there's a way to
// factor the layout stuff out...
@@ -1247,7 +1265,8 @@
TargetVTableDescriptorHeader<Runtime> header;
auto headerAddr = address
+ baseSize
- + genericsSize;
+ + genericsSize
+ + metadataInitSize;
if (!Reader->readBytes(RemoteAddress(headerAddr),
(uint8_t*)&header, sizeof(header)))
@@ -1257,7 +1276,7 @@
+ header.VTableSize * sizeof(TargetMethodDescriptor<Runtime>);
}
- unsigned size = baseSize + genericsSize + vtableSize + inPlaceInitSize;
+ unsigned size = baseSize + genericsSize + metadataInitSize + vtableSize;
auto buffer = (uint8_t *)malloc(size);
if (!Reader->readBytes(RemoteAddress(address), buffer, size)) {
free(buffer);
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 61b4e44..e741041 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -239,10 +239,6 @@
// pointer types.
SWIFT_RUNTIME_EXPORT
const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(Bo); // Builtin.NativeObject
-SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable UNOWNED_VALUE_WITNESS_SYM(Bo); // unowned Builtin.NativeObject
-SWIFT_RUNTIME_EXPORT
-const ValueWitnessTable WEAK_VALUE_WITNESS_SYM(Bo); // weak Builtin.NativeObject?
SWIFT_RUNTIME_EXPORT
const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(Bb); // Builtin.BridgeObject
@@ -254,10 +250,6 @@
// The ObjC-pointer table can be used for arbitrary ObjC pointer types.
SWIFT_RUNTIME_EXPORT
const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(BO); // Builtin.UnknownObject
-SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable UNOWNED_VALUE_WITNESS_SYM(BO); // unowned Builtin.UnknownObject
-SWIFT_RUNTIME_EXPORT
-const ValueWitnessTable WEAK_VALUE_WITNESS_SYM(BO); // weak Builtin.UnknownObject?
#endif
// The () -> () table can be used for arbitrary function types.
@@ -477,9 +469,10 @@
#endif
/// \brief Fetch a unique type metadata object for a foreign type.
-SWIFT_RUNTIME_EXPORT
-const ForeignTypeMetadata *
-swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique);
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+MetadataResponse
+swift_getForeignTypeMetadata(MetadataRequest request,
+ ForeignTypeMetadata *nonUnique);
/// \brief Fetch a unique witness table for a foreign witness table.
SWIFT_RUNTIME_EXPORT
@@ -532,6 +525,46 @@
const Metadata *elt2, const char *labels,
const ValueWitnessTable *proposedWitnesses);
+/// Perform layout as if for a tuple whose elements have the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+/// Must be non-null.
+/// \param elementOffsets - An array into which to write the offsets of
+/// the elements. May be null. Must have space for all elements,
+/// including element 0 (which will always have offset 0).
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+void swift_getTupleTypeLayout(TypeLayout *tupleLayout,
+ uint32_t *elementOffsets,
+ TupleTypeFlags flags,
+ const TypeLayout * const *elements);
+
+/// Perform layout as if for a two-element tuple whose elements have
+/// the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+/// Must be non-null.
+/// \returns The offset of the second element.
+/// The first element always has offset 0.
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+size_t swift_getTupleTypeLayout2(TypeLayout *tupleLayout,
+ const TypeLayout *elt0,
+ const TypeLayout *elt1);
+
+struct OffsetPair { size_t First; size_t Second; };
+
+/// Perform layout as if for a three-element tuple whose elements have
+/// the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+/// Must be non-null.
+/// \returns The offsets of the second and third elements.
+/// The first element always has offset 0.
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+OffsetPair swift_getTupleTypeLayout3(TypeLayout *tupleLayout,
+ const TypeLayout *elt0Layout,
+ const TypeLayout *elt1Layout,
+ const TypeLayout *elt2Layout);
+
/// Initialize the value witness table and struct field offset vector for a
/// struct, using the "Universal" layout strategy.
SWIFT_RUNTIME_EXPORT
@@ -715,11 +748,11 @@
/// Return the superclass, if any. The result is nullptr for root
/// classes and class protocol types.
SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const Metadata *_swift_class_getSuperclass(const Metadata *theClass);
SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void swift_getFieldAt(
const Metadata *base, unsigned index,
void (*callback)(const char *name, const Metadata *type, void *ctx), void *callbackCtx);
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 1a7ba9e..df4b82d 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -638,9 +638,9 @@
ATTRS(NoUnwind, ReadNone))
// Metadata *swift_getForeignTypeMetadata(Metadata *nonUnique);
-FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, C_CC,
- RETURNS(TypeMetadataPtrTy),
- ARGS(TypeMetadataPtrTy),
+FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, SwiftCC,
+ RETURNS(TypeMetadataResponseTy),
+ ARGS(SizeTy, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields
// WitnessTable *swift_getForeignWitnessTable(
@@ -766,6 +766,34 @@
Int8PtrTy, WitnessTablePtrTy),
ATTRS(NoUnwind, ReadOnly))
+// void swift_getTupleTypeLayout(TypeLayout *result,
+// uint32_t offsets,
+// TupleTypeFlags flags,
+// const TypeLayout * const *elts);
+FUNCTION(GetTupleLayout, swift_getTupleTypeLayout, SwiftCC,
+ RETURNS(VoidTy),
+ ARGS(FullTypeLayoutTy->getPointerTo(0), Int32Ty->getPointerTo(0),
+ SizeTy, Int8PtrPtrTy->getPointerTo(0)),
+ ATTRS(NoUnwind))
+
+// size_t swift_getTupleTypeLayout2(TypeLayout *layout,
+// const TypeLayout *elt0,
+// const TypeLayout *elt1);
+FUNCTION(GetTupleLayout2, swift_getTupleTypeLayout2, SwiftCC,
+ RETURNS(SizeTy),
+ ARGS(FullTypeLayoutTy->getPointerTo(0), Int8PtrPtrTy, Int8PtrPtrTy),
+ ATTRS(NoUnwind))
+
+// OffsetPair swift_getTupleTypeLayout3(TypeLayout *layout,
+// const TypeLayout *elt0,
+// const TypeLayout *elt1,
+// const TypeLayout *elt2);
+FUNCTION(GetTupleLayout3, swift_getTupleTypeLayout3, SwiftCC,
+ RETURNS(OffsetPairTy),
+ ARGS(FullTypeLayoutTy->getPointerTo(0),
+ Int8PtrPtrTy, Int8PtrPtrTy, Int8PtrPtrTy),
+ ATTRS(NoUnwind))
+
// Metadata *swift_getExistentialTypeMetadata(
// ProtocolClassConstraint classConstraint,
// const Metadata *superclassConstraint,
diff --git a/lib/IRGen/ForeignClassMetadataVisitor.h b/lib/IRGen/ForeignClassMetadataVisitor.h
index cce48b0..6452fc0 100644
--- a/lib/IRGen/ForeignClassMetadataVisitor.h
+++ b/lib/IRGen/ForeignClassMetadataVisitor.h
@@ -37,16 +37,8 @@
void layout() {
super::layout();
asImpl().addNominalTypeDescriptor();
- asImpl().noteStartOfSuperClass();
asImpl().addSuperclass();
asImpl().addReservedWord();
- asImpl().addReservedWord();
- asImpl().addReservedWord();
- }
-
- bool requiresInitializationFunction() {
- return Target->getSuperclassDecl() &&
- Target->getSuperclassDecl()->isForeign();
}
CanType getTargetType() const {
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 354e240..5331d3e 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -1488,8 +1488,7 @@
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
// Imported types.
- if (getTypeMetadataAccessStrategy(type) ==
- MetadataAccessStrategy::NonUniqueAccessor)
+ if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
return SILLinkage::Shared;
// Everything else is only referenced inside its module.
@@ -1507,8 +1506,7 @@
auto type = getType();
// Imported types, non-primitive structural types.
- if (getTypeMetadataAccessStrategy(type) ==
- MetadataAccessStrategy::NonUniqueAccessor)
+ if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
return SILLinkage::Shared;
// Everything else is only referenced inside its module.
@@ -1548,6 +1546,7 @@
return getSILLinkage(FormalLinkage::HiddenUnique, forDefinition);
case MetadataAccessStrategy::PrivateAccessor:
return getSILLinkage(FormalLinkage::Private, forDefinition);
+ case MetadataAccessStrategy::ForeignAccessor:
case MetadataAccessStrategy::NonUniqueAccessor:
return SILLinkage::Shared;
}
@@ -2680,42 +2679,79 @@
return {gotEquivalent, ConstantReference::Indirect};
}
-TypeEntityReference
-IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
- TypeMetadataRecordKind kind;
- Optional<LinkEntity> entity;
- llvm::Type *defaultTy;
+static TypeEntityReference
+getTypeContextDescriptorEntityReference(IRGenModule &IGM,
+ NominalTypeDecl *decl) {
+ // A reference to a concrete type.
+ // TODO: consider using a symbolic reference (i.e. a symbol string
+ // to be looked up dynamically) for types defined outside the module.
+ auto kind = TypeReferenceKind::DirectNominalTypeDescriptor;
+ auto entity = LinkEntity::forNominalTypeDescriptor(decl);
+ auto defaultTy = IGM.TypeContextDescriptorTy;
- auto clas = dyn_cast<ClassDecl>(decl);
- if (clas && !clas->isForeign() && !hasKnownSwiftMetadata(*this, clas)) {
- // A reference to an Objective-C class object.
- assert(clas->isObjC() && "Must have an Objective-C class here");
+ auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
+ entity, IGM.getPointerAlignment(), defaultTy);
- kind = TypeMetadataRecordKind::IndirectObjCClass;
- defaultTy = TypeMetadataPtrTy;
- entity = LinkEntity::forObjCClassRef(clas);
- } else {
- // A reference to a concrete type.
- // TODO: consider using a symbolic reference (i.e. a symbol string
- // to be looked up dynamically) for types defined outside the module.
- kind = TypeMetadataRecordKind::DirectNominalTypeDescriptor;
- entity = LinkEntity::forNominalTypeDescriptor(decl);
- defaultTy = TypeContextDescriptorTy;
- }
-
- auto ref = getAddrOfLLVMVariableOrGOTEquivalent(
- *entity, getPointerAlignment(), defaultTy);
-
- // Adjust the flags now that we know whether the reference to this
- // entity will be indirect.
if (ref.isIndirect()) {
- assert(kind == TypeMetadataRecordKind::DirectNominalTypeDescriptor);
- kind = TypeMetadataRecordKind::IndirectNominalTypeDescriptor;
+ kind = TypeReferenceKind::IndirectNominalTypeDescriptor;
}
return TypeEntityReference(kind, ref.getValue());
}
+static TypeEntityReference
+getObjCClassRefEntityReference(IRGenModule &IGM, ClassDecl *cls) {
+ // A reference to an Objective-C class object.
+ assert(cls->isObjC() && "Must have an Objective-C class here");
+
+ auto kind = TypeReferenceKind::IndirectObjCClass;
+ auto entity = LinkEntity::forObjCClassRef(cls);
+ auto defaultTy = IGM.TypeMetadataPtrTy;
+
+ auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
+ entity, IGM.getPointerAlignment(), defaultTy);
+ assert(!ref.isIndirect());
+
+ return TypeEntityReference(kind, ref.getValue());
+}
+
+static TypeEntityReference
+getRuntimeOnlyClassEntityReference(IRGenModule &IGM, ClassDecl *cls) {
+ assert(cls->getForeignClassKind() == ClassDecl::ForeignKind::RuntimeOnly);
+
+ auto namedClangDecl = Mangle::ASTMangler::getClangDeclForMangling(cls);
+ assert(namedClangDecl);
+
+ auto kind = TypeReferenceKind::DirectObjCClassName;
+ auto ref = IGM.getAddrOfGlobalString(namedClangDecl->getName());
+
+ return TypeEntityReference(kind, ref);
+}
+
+TypeEntityReference
+IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
+ auto clas = dyn_cast<ClassDecl>(decl);
+ if (!clas) {
+ return getTypeContextDescriptorEntityReference(*this, decl);
+ }
+
+ switch (clas->getForeignClassKind()) {
+ case ClassDecl::ForeignKind::RuntimeOnly:
+ return getRuntimeOnlyClassEntityReference(*this, clas);
+
+ case ClassDecl::ForeignKind::CFType:
+ return getTypeContextDescriptorEntityReference(*this, clas);
+
+ case ClassDecl::ForeignKind::Normal:
+ if (hasKnownSwiftMetadata(*this, clas)) {
+ return getTypeContextDescriptorEntityReference(*this, clas);
+ } else {
+ return getObjCClassRefEntityReference(*this, clas);
+ }
+ }
+ llvm_unreachable("bad foreign type kind");
+}
+
/// Form an LLVM constant for the relative distance between a reference
/// (appearing at gep (0, indices) of `base`) and `target`.
llvm::Constant *
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 0b37c5e..cf2cb23d 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -247,9 +247,9 @@
using super::asDerived;
using super::emitCopyOfTables;
- using super::getNumStoredProtocols;
protected:
+ using super::getNumStoredProtocols;
const ReferenceCounting Refcounting;
template <class... As>
@@ -618,13 +618,13 @@
};
/// A type implementation for existential types.
-#define LOADABLE_REF_STORAGE_HELPER(Name) \
+#define REF_STORAGE_HELPER(Name, Super) \
private: \
bool shouldStoreExtraInhabitantsInRef(IRGenModule &IGM) const { \
- if (getNumStoredProtocols() == 0) \
+ if (IGM.getReferenceStorageExtraInhabitantCount( \
+ ReferenceOwnership::Name, Refcounting) > 1) \
return true; \
- return IGM.getReferenceStorageExtraInhabitantCount( \
- ReferenceOwnership::Name, Refcounting) > 1; \
+ return getNumStoredProtocols() == 0; \
} \
public: \
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override { \
@@ -635,7 +635,7 @@
return IGM.getReferenceStorageExtraInhabitantCount( \
ReferenceOwnership::Name, Refcounting) - IsOptional; \
} else { \
- return LoadableTypeInfo::getFixedExtraInhabitantCount(IGM); \
+ return Super::getFixedExtraInhabitantCount(IGM); \
} \
} \
APInt getFixedExtraInhabitantValue(IRGenModule &IGM, \
@@ -647,8 +647,7 @@
ReferenceOwnership::Name, \
Refcounting); \
} else { \
- return LoadableTypeInfo::getFixedExtraInhabitantValue(IGM, \
- bits, index); \
+ return Super::getFixedExtraInhabitantValue(IGM, bits, index); \
} \
} \
llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF, Address src, \
@@ -658,7 +657,7 @@
return IGF.getReferenceStorageExtraInhabitantIndex(valueSrc, \
ReferenceOwnership::Name, Refcounting); \
} else { \
- return LoadableTypeInfo::getExtraInhabitantIndex(IGF, src, T); \
+ return Super::getExtraInhabitantIndex(IGF, src, T); \
} \
} \
void storeExtraInhabitant(IRGenFunction &IGF, llvm::Value *index, \
@@ -668,7 +667,7 @@
return IGF.storeReferenceStorageExtraInhabitant(index, valueDest, \
ReferenceOwnership::Name, Refcounting); \
} else { \
- return LoadableTypeInfo::storeExtraInhabitant(IGF, index, dest, T); \
+ return Super::storeExtraInhabitant(IGF, index, dest, T); \
} \
} \
APInt getFixedExtraInhabitantMask(IRGenModule &IGM) const override { \
@@ -680,7 +679,7 @@
bits = bits.zextOrTrunc(getFixedSize().getValueInBits()); \
return bits; \
} else { \
- return LoadableTypeInfo::getFixedExtraInhabitantMask(IGM); \
+ return Super::getFixedExtraInhabitantMask(IGM); \
} \
}
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
@@ -688,6 +687,7 @@
public AddressOnlyClassExistentialTypeInfoBase< \
AddressOnly##Name##ClassExistentialTypeInfo, \
FixedTypeInfo> { \
+ bool IsOptional; \
public: \
AddressOnly##Name##ClassExistentialTypeInfo( \
ArrayRef<ProtocolEntry> protocols, \
@@ -700,7 +700,8 @@
ty, size, std::move(spareBits), \
align, IsNotPOD, \
IsNotBitwiseTakable, \
- IsFixedSize) {} \
+ IsFixedSize), \
+ IsOptional(isOptional) {} \
void emitValueAssignWithCopy(IRGenFunction &IGF, \
Address dest, Address src) const { \
IGF.emit##Name##CopyAssign(dest, src, Refcounting); \
@@ -721,6 +722,7 @@
IGF.emit##Name##Destroy(addr, Refcounting); \
} \
StringRef getStructNameSuffix() const { return "." #name "ref"; } \
+ REF_STORAGE_HELPER(Name, FixedTypeInfo) \
};
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
class Loadable##Name##ClassExistentialTypeInfo final \
@@ -767,7 +769,7 @@
getValueTypeInfoForExtraInhabitants(IRGenModule &IGM) const { \
llvm_unreachable("should have overridden all actual uses of this"); \
} \
- LOADABLE_REF_STORAGE_HELPER(Name) \
+ REF_STORAGE_HELPER(Name, LoadableTypeInfo) \
};
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \
@@ -794,8 +796,8 @@
else \
return IGM.getUnknownObjectTypeInfo(); \
} \
- /* FIXME -- Use LOADABLE_REF_STORAGE_HELPER and make */ \
- /* getValueTypeInfoForExtraInhabitantsThis call llvm_unreachable() */ \
+ /* FIXME -- Use REF_STORAGE_HELPER and make */ \
+ /* getValueTypeInfoForExtraInhabitants call llvm_unreachable() */ \
void emitValueRetain(IRGenFunction &IGF, llvm::Value *value, \
Atomicity atomicity) const {} \
void emitValueRelease(IRGenFunction &IGF, llvm::Value *value, \
@@ -803,7 +805,7 @@
void emitValueFixLifetime(IRGenFunction &IGF, llvm::Value *value) const {} \
};
#include "swift/AST/ReferenceStorage.def"
-#undef LOADABLE_REF_STORAGE_HELPER
+#undef REF_STORAGE_HELPER
} // end anonymous namespace
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 84c8b9b..a94ff70 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -188,6 +188,20 @@
IGF.Builder.CreateRet(returnValue);
}
+static bool needsForeignMetadataCompletionFunction(StructDecl *decl) {
+ // Currently, foreign structs never need a completion function.
+ return false;
+}
+
+static bool needsForeignMetadataCompletionFunction(EnumDecl *decl) {
+ // Currently, foreign enums never need a completion function.
+ return false;
+}
+
+static bool needsForeignMetadataCompletionFunction(ClassDecl *decl) {
+ return decl->hasSuperclass();
+}
+
/*****************************************************************************/
/** Nominal Type Descriptor Emission *****************************************/
/*****************************************************************************/
@@ -695,16 +709,17 @@
}
};
- template<class Impl>
+ template<class Impl, class DeclType>
class TypeContextDescriptorBuilderBase
: public ContextDescriptorBuilderBase<Impl> {
using super = ContextDescriptorBuilderBase<Impl>;
protected:
- NominalTypeDecl *Type;
+ DeclType *Type;
RequireMetadata_t HasMetadata;
- bool HasInPlaceMetadataInitialization;
+ TypeContextDescriptorFlags::MetadataInitializationKind
+ MetadataInitialization;
using super::IGM;
using super::B;
@@ -713,12 +728,11 @@
public:
using super::addGenericSignature;
- TypeContextDescriptorBuilderBase(IRGenModule &IGM, NominalTypeDecl *Type,
+ TypeContextDescriptorBuilderBase(IRGenModule &IGM, DeclType *Type,
RequireMetadata_t requireMetadata)
: super(IGM), Type(Type),
HasMetadata(requireMetadata),
- HasInPlaceMetadataInitialization(
- computeHasInPlaceMetadataInitialization()) {
+ MetadataInitialization(computeMetadataInitialization()) {
}
void layout() {
@@ -728,7 +742,7 @@
// ABI TODO: layout info should be superseded by remote mirror metadata
asImpl().addLayoutInfo();
asImpl().addGenericSignature();
- asImpl().maybeAddInPlaceMetadataInitialization();
+ asImpl().maybeAddMetadataInitialization();
}
void addName() {
@@ -738,7 +752,8 @@
// Use the original name with tag for synthesized decls. The tag comes
// after the null terminator for the name.
if (auto *synthesizedTypeAttr =
- Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+ Type->getAttrs()
+ .template getAttribute<ClangImporterSynthesizedTypeAttr>()) {
nameBuf.append(synthesizedTypeAttr->originalTypeName);
nameBuf.push_back('\0');
nameBuf.append(synthesizedTypeAttr->getManglingName());
@@ -758,16 +773,28 @@
}
void addAccessFunction() {
- // Don't emit the access function if we're only lazily emitting the
- // context descriptor.
+ llvm::Constant *accessor;
+
+ // Don't include an access function if we're emitting the context
+ // descriptor without metadata.
if (!HasMetadata) {
- B.addInt32(0);
- return;
+ accessor = nullptr;
+
+ // If it's a generic type, use the generic access function.
+ // This has a different prototype from an ordinary function, but
+ // the runtime knows to check for that.
+ } else if (Type->isGenericContext()) {
+ accessor = getGenericTypeMetadataAccessFunction(IGM, Type,
+ NotForDefinition);
+
+ // Otherwise, use the ordinary access function, which we'll define
+ // when we emit the metadata.
+ } else {
+ CanType type = Type->getDeclaredType()->getCanonicalType();
+ accessor = getOtherwiseDefinedTypeMetadataAccessFunction(IGM, type);
}
- llvm::Constant *accessFn =
- getRequiredTypeMetadataAccessFunction(IGM, Type, NotForDefinition);
- B.addRelativeAddressOrNull(accessFn);
+ B.addRelativeAddressOrNull(accessor);
}
ConstantReference getParent() {
@@ -831,7 +858,8 @@
/// Flags to indicate Clang-imported declarations so we mangle them
/// consistently at runtime.
void setClangImportedFlags(TypeContextDescriptorFlags &flags) {
- if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+ if (Type->getAttrs()
+ .template getAttribute<ClangImporterSynthesizedTypeAttr>()) {
flags.setIsSynthesizedRelatedEntity(true);
}
@@ -845,36 +873,56 @@
}
}
- bool computeHasInPlaceMetadataInitialization() {
+ TypeContextDescriptorFlags::MetadataInitializationKind
+ computeMetadataInitialization() {
// Not if we don't have metadata.
if (!HasMetadata)
- return false;
+ return TypeContextDescriptorFlags::NoMetadataInitialization;
+
+ // Generic types use their own system.
+ if (Type->isGenericContext())
+ return TypeContextDescriptorFlags::NoMetadataInitialization;
+
+ // Check for foreign metadata.
+ if (requiresForeignTypeMetadata(Type))
+ return TypeContextDescriptorFlags::ForeignMetadataInitialization;
+
+ // The only other option is in-place initialization.
// Only struct and enums for now. Classes currently use an eager
// mechanism that doesn't properly support recursive dependencies, so
// their equivalent of in-place initialization does not yet use this
// infrastructure.
if (!isa<StructDecl>(Type) && !isa<EnumDecl>(Type))
- return false;
+ return TypeContextDescriptorFlags::NoMetadataInitialization;
- return needsInPlaceMetadataInitialization(IGM, Type);
- }
+ if (needsInPlaceMetadataInitialization(IGM, Type))
+ return TypeContextDescriptorFlags::InPlaceMetadataInitialization;
- bool hasInPlaceMetadataInitialization() {
- return HasInPlaceMetadataInitialization;
+ return TypeContextDescriptorFlags::NoMetadataInitialization;
}
void setMetadataInitializationKind(TypeContextDescriptorFlags &flags) {
- if (HasInPlaceMetadataInitialization) {
- flags.setMetadataInitialization(
- TypeContextDescriptorFlags::InPlaceMetadataInitialization);
- }
+ flags.setMetadataInitialization(MetadataInitialization);
}
- void maybeAddInPlaceMetadataInitialization() {
- if (!HasInPlaceMetadataInitialization)
+ void maybeAddMetadataInitialization() {
+ switch (MetadataInitialization) {
+ case TypeContextDescriptorFlags::NoMetadataInitialization:
return;
+ case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+ asImpl().addForeignMetadataInitialization();
+ return;
+
+ case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
+ asImpl().addInPlaceMetadataInitialization();
+ return;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ void addInPlaceMetadataInitialization() {
if (isa<StructDecl>(Type) || isa<EnumDecl>(Type)) {
asImpl().addInPlaceValueMetadataInitialization();
} else {
@@ -882,6 +930,20 @@
}
}
+ /// Add a ForeignMetadataInitialization structure to the descriptor.
+ void addForeignMetadataInitialization() {
+ llvm::Constant *completionFunction = nullptr;
+ if (asImpl().needsForeignMetadataCompletionFunction()) {
+ completionFunction =
+ IGM.getAddrOfTypeMetadataCompletionFunction(Type, NotForDefinition);
+ }
+ B.addRelativeAddressOrNull(completionFunction);
+ }
+
+ bool needsForeignMetadataCompletionFunction() {
+ return ::needsForeignMetadataCompletionFunction(Type);
+ }
+
/// Add an InPlaceValueMetadataInitialization structure to the descriptor.
void addInPlaceValueMetadataInitialization() {
// Relative pointer to the initialization cache.
@@ -975,7 +1037,8 @@
class StructContextDescriptorBuilder
- : public TypeContextDescriptorBuilderBase<StructContextDescriptorBuilder>
+ : public TypeContextDescriptorBuilderBase<StructContextDescriptorBuilder,
+ StructDecl>
{
using super = TypeContextDescriptorBuilderBase;
@@ -1024,7 +1087,8 @@
};
class EnumContextDescriptorBuilder
- : public TypeContextDescriptorBuilderBase<EnumContextDescriptorBuilder>
+ : public TypeContextDescriptorBuilderBase<EnumContextDescriptorBuilder,
+ EnumDecl>
{
using super = TypeContextDescriptorBuilderBase;
@@ -1082,7 +1146,8 @@
};
class ClassContextDescriptorBuilder
- : public TypeContextDescriptorBuilderBase<ClassContextDescriptorBuilder>,
+ : public TypeContextDescriptorBuilderBase<ClassContextDescriptorBuilder,
+ ClassDecl>,
public SILVTableVisitor<ClassContextDescriptorBuilder>
{
using super = TypeContextDescriptorBuilderBase;
@@ -2365,8 +2430,7 @@
assert(!Target->isGenericContext());
auto type =cast<ClassType>(Target->getDeclaredType()->getCanonicalType());
- (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
- CacheStrategy::Lazy,
+ (void) createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
[&](IRGenFunction &IGF, DynamicMetadataRequest request,
llvm::Constant *cacheVar) -> MetadataResponse {
// There's an interesting special case where we can do the
@@ -2842,32 +2906,6 @@
};
}
-static llvm::Value *
-emitOnceValueTypeMetadataInitialization(IRGenFunction &IGF,
- CanNominalType type,
- llvm::Value *metadata,
- MetadataDependencyCollector *collector) {
- // All the value types are basically similar, as are foreign types.
- assert(isa<StructType>(type) || isa<EnumType>(type) ||
- IGF.IGM.requiresForeignTypeMetadata(type));
-
- // Set up the value witness table if it's dependent.
- SILType loweredType = IGF.IGM.getLoweredType(AbstractionPattern(type), type);
- auto &ti = IGF.IGM.getTypeInfo(loweredType);
- if (!ti.isFixedSize()) {
- loweredType = loweredType.getAddressType();
- if (isa<StructType>(type)) {
- emitInitializeFieldOffsetVector(IGF, loweredType, metadata, true,
- collector);
- } else if (isa<EnumType>(type)) {
- auto &strategy = getEnumImplStrategy(IGF.IGM, loweredType);
- strategy.initializeMetadata(IGF, metadata, true, loweredType, collector);
- }
- }
-
- return metadata;
-}
-
/// Create an access function for the given type which triggers the
/// in-place initialization path.
static void
@@ -2876,11 +2914,11 @@
CanType type) {
assert(!typeDecl->isGenericContext());
- (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
- CacheStrategy::InPlaceInitialization,
- [&](IRGenFunction &IGF,
- DynamicMetadataRequest request,
- llvm::Constant *cacheVariable) {
+ (void) createTypeMetadataAccessFunction(IGM, type,
+ CacheStrategy::InPlaceInitialization,
+ [&](IRGenFunction &IGF,
+ DynamicMetadataRequest request,
+ llvm::Constant *cacheVariable) {
llvm::Value *descriptor =
IGF.IGM.getAddrOfTypeContextDescriptor(typeDecl, RequireMetadata);
auto responsePair =
@@ -2904,7 +2942,7 @@
// Otherwise, use the lazy pattern, which should be emitted using a
// direct reference to the metadata.
- (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition);
+ createDirectTypeMetadataAccessFunction(IGM, type, /*allow existing*/ false);
}
@@ -3423,6 +3461,7 @@
protected:
using super::IGM;
+ using super::Target;
using super::asImpl;
using super::B;
@@ -3430,90 +3469,53 @@
ForeignMetadataBuilderBase(T &&...args) : super(std::forward<T>(args)...) {}
Size AddressPoint = Size::invalid();
+ bool CanBeConstant = true;
public:
- void layout() {
- if (asImpl().requiresInitializationFunction())
- asImpl().addInitializationFunction();
- asImpl().addForeignFlags();
- super::layout();
- }
-
- void addForeignFlags() {
- int64_t flags = 0;
- if (asImpl().requiresInitializationFunction()) flags |= 1;
- B.addInt(IGM.IntPtrTy, flags);
- }
-
- void addForeignName() {
- CanType targetType = asImpl().getTargetType();
- IRGenMangler mangler;
- std::string Name =
- mangler.mangleTypeForForeignMetadataUniquing(targetType);
- llvm::Constant *nameStr = IGM.getAddrOfGlobalString(Name,
- /*relatively addressed*/ true);
- B.addRelativeAddress(nameStr);
- }
-
- void addInitializationFunction() {
- auto type = cast<NominalType>(asImpl().getTargetType());
-
- auto fnTy = llvm::FunctionType::get(IGM.VoidTy, {IGM.TypeMetadataPtrTy},
- /*variadic*/ false);
- llvm::Function *fn = llvm::Function::Create(fnTy,
- llvm::GlobalValue::PrivateLinkage,
- Twine("initialize_metadata_")
- + type->getDecl()->getName().str(),
- &IGM.Module);
- fn->setAttributes(IGM.constructInitialAttributes());
-
- // Set up the function.
- IRGenFunction IGF(IGM, fn);
- if (IGM.DebugInfo)
- IGM.DebugInfo->emitArtificialFunction(IGF, fn);
-
- // Emit the initialization.
- llvm::Value *metadata = IGF.collectParameters().claimNext();
- asImpl().emitInitialization(IGF, metadata);
-
- IGF.Builder.CreateRetVoid();
-
- B.addRelativeAddress(fn);
-
- // Keep pointer alignment on 64-bit platforms for further fields.
- switch (IGM.getPointerSize().getValue()) {
- case 4:
- break;
- case 8:
- B.addInt32(0);
- break;
- default:
- llvm_unreachable("unsupported word size");
- }
- }
-
void noteAddressPoint() {
AddressPoint = B.getNextOffsetFromGlobal();
}
+ bool canBeConstant() {
+ return CanBeConstant;
+ }
+
Size getOffsetOfAddressPoint() const { return AddressPoint; }
void createMetadataAccessFunction() {
+ if (asImpl().needsMetadataCompletionFunction())
+ asImpl().createMetadataCompletionFunction();
+
auto type = cast<NominalType>(asImpl().getTargetType());
- (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
- CacheStrategy::Lazy,
- [&](IRGenFunction &IGF,
- DynamicMetadataRequest request,
- llvm::Constant *cacheVariable) {
- return emitOnceTypeMetadataAccessFunctionBody(IGF, type, cacheVariable,
- [&](IRGenFunction &IGF, llvm::Value *candidate) {
- MetadataDependencyCollector *collector = nullptr;
- auto metadata = uniqueForeignTypeMetadataRef(IGF, candidate);
- return emitOnceValueTypeMetadataInitialization(IGF, type,
- metadata,
- collector);
- });
+ (void) createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
+ [&](IRGenFunction &IGF,
+ DynamicMetadataRequest request,
+ llvm::Constant *cacheVariable) {
+ auto candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type);
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
+ {request.get(IGF), candidate});
+ call->addAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+ call->addAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::ReadNone);
+
+ return MetadataResponse::handle(IGF, request, call);
+ });
+ }
+
+ bool needsMetadataCompletionFunction() {
+ return needsForeignMetadataCompletionFunction(Target);
+ }
+
+ void createMetadataCompletionFunction() {
+ // Note that we can't call this until we've finished laying out the
+ // metadata because otherwise we'll try to reenter when we ask for
+ // the metadata candidate.
+ emitMetadataCompletionFunction(IGM, Target,
+ [&](IRGenFunction &IGF, llvm::Value *metadata,
+ MetadataDependencyCollector *collector) {
+ asImpl().emitInitializeMetadata(IGF, metadata, collector);
});
}
};
@@ -3538,24 +3540,20 @@
ConstantStructBuilder &B)
: ForeignMetadataBuilderBase(IGM, target, B) {}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
- // Dig out the address of the superclass field.
- auto &layout = IGF.IGM.getForeignMetadataLayout(Target);
- Address metadataWords(IGF.Builder.CreateBitCast(metadata,
- IGM.Int8PtrPtrTy),
- IGM.getPointerAlignment());
- auto superclassField =
- createPointerSizedGEP(IGF, metadataWords,
- layout.getSuperClassOffset().getStaticOffset());
- superclassField =
- IGF.Builder.CreateBitCast(
- superclassField,
- llvm::PointerType::get(IGM.TypeMetadataPtrTy, 0));
+ void emitInitializeMetadata(IRGenFunction &IGF, llvm::Value *metadata,
+ MetadataDependencyCollector *collector) {
+ // Emit a reference to the superclass.
+ auto superclass = IGF.emitAbstractTypeMetadataRef(
+ Target->getSuperclass()->getCanonicalType());
- // Unique the superclass field and write it back.
- auto superclass = IGF.Builder.CreateLoad(superclassField);
- auto uniquedSuperclass = uniqueForeignTypeMetadataRef(IGF, superclass);
- IGF.Builder.CreateStore(uniquedSuperclass, superclassField);
+ // Dig out the address of the superclass field and store.
+ auto &layout = IGF.IGM.getForeignMetadataLayout(Target);
+ Address addr(metadata, IGM.getPointerAlignment());
+ addr = IGF.Builder.CreateElementBitCast(addr, IGM.TypeMetadataPtrTy);
+ auto superclassField =
+ createPointerSizedGEP(IGF, addr,
+ layout.getSuperClassOffset().getStaticOffset());
+ IGF.Builder.CreateStore(superclass, superclassField);
}
// Visitor methods.
@@ -3580,21 +3578,15 @@
B.add(descriptor);
}
- void noteStartOfSuperClass() { }
-
void addSuperclass() {
- auto superclassDecl = Target->getSuperclassDecl();
- if (!superclassDecl || !superclassDecl->isForeign()) {
- B.addNullPointer(IGM.TypeMetadataPtrTy);
- return;
- }
+ // Always leave the superclass pointer unfilled. We'll have to
+ // unique it during initialization anyway, so we might as well spare
+ // ourselves the load-time work.
+ B.addNullPointer(IGM.TypeMetadataPtrTy);
- auto superclassType =
- superclassDecl->swift::TypeDecl::getDeclaredInterfaceType()
- ->getCanonicalType();
- auto superclass =
- IGM.getAddrOfForeignTypeMetadataCandidate(superclassType);
- B.add(superclass);
+ // But remember if we might need to change it.
+ if (Target->hasSuperclass())
+ CanBeConstant = false;
}
void addReservedWord() {
@@ -3616,10 +3608,9 @@
return Target->getDeclaredType()->getCanonicalType();
}
- bool requiresInitializationFunction() const {
- return false;
+ void createMetadataCompletionFunction() {
+ llvm_unreachable("foreign structs never require completion");
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
B.add(emitValueWitnessTable());
@@ -3644,10 +3635,9 @@
return Target->getDeclaredType()->getCanonicalType();
}
- bool requiresInitializationFunction() const {
- return false;
+ void createMetadataCompletionFunction() {
+ llvm_unreachable("foreign enums never require completion");
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
B.add(emitValueWitnessTable());
@@ -3659,18 +3649,29 @@
};
} // end anonymous namespace
-bool IRGenModule::requiresForeignTypeMetadata(CanType type) {
+bool irgen::requiresForeignTypeMetadata(CanType type) {
if (NominalTypeDecl *nominal = type->getAnyNominal()) {
- if (auto *clas = dyn_cast<ClassDecl>(nominal)) {
- return clas->isForeign();
- }
-
- return isa<ClangModuleUnit>(nominal->getModuleScopeContext());
+ return requiresForeignTypeMetadata(nominal);
}
return false;
}
+bool irgen::requiresForeignTypeMetadata(NominalTypeDecl *decl) {
+ if (auto *clas = dyn_cast<ClassDecl>(decl)) {
+ switch (clas->getForeignClassKind()) {
+ case ClassDecl::ForeignKind::Normal:
+ case ClassDecl::ForeignKind::RuntimeOnly:
+ return false;
+ case ClassDecl::ForeignKind::CFType:
+ return true;
+ }
+ llvm_unreachable("bad foreign class kind");
+ }
+
+ return isa<ClangModuleUnit>(decl->getModuleScopeContext());
+}
+
llvm::Constant *
IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
// What we save in GlobalVars is actually the offsetted value.
@@ -3685,6 +3686,7 @@
// Local function to create the global variable for the foreign type
// metadata candidate.
+ bool canBeConstant;
Size addressPoint;
llvm::Constant *result = nullptr;
auto createCandidateVariable = [&] {
@@ -3696,6 +3698,7 @@
createVariable(*this, link, definition.getType(),
getPointerAlignment());
definition.installInGlobal(var);
+ var->setConstant(canBeConstant);
// Apply the offset.
result = llvm::ConstantExpr::getBitCast(var, Int8PtrTy);
@@ -3717,6 +3720,7 @@
ForeignClassMetadataBuilder builder(*this, classDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
+ canBeConstant = builder.canBeConstant();
createCandidateVariable();
builder.createMetadataAccessFunction();
@@ -3729,6 +3733,7 @@
ForeignStructMetadataBuilder builder(*this, structDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
+ canBeConstant = builder.canBeConstant();
createCandidateVariable();
builder.createMetadataAccessFunction();
@@ -3739,6 +3744,7 @@
ForeignEnumMetadataBuilder builder(*this, enumDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
+ canBeConstant = builder.canBeConstant();
createCandidateVariable();
builder.createMetadataAccessFunction();
@@ -3753,8 +3759,7 @@
if (auto enclosing = type->getNominalParent()) {
auto canonicalEnclosing = enclosing->getCanonicalType();
if (requiresForeignTypeMetadata(canonicalEnclosing)) {
- (void)getTypeMetadataAccessFunction(*this, canonicalEnclosing,
- ForDefinition);
+ (void)getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing);
}
}
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index f0f9e55..cf3975d 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -47,6 +47,9 @@
class StructLayout;
struct ClassLayout;
+ bool requiresForeignTypeMetadata(CanType type);
+ bool requiresForeignTypeMetadata(NominalTypeDecl *decl);
+
/// Emit the metadata associated with the given class declaration.
void emitClassMetadata(IRGenModule &IGM, ClassDecl *theClass,
const StructLayout &layout,
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index de5a049..e1d3aeb 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2226,19 +2226,7 @@
// Trigger the lazy emission of the foreign type metadata.
CanType conformingType = conf->getType()->getCanonicalType();
if (requiresForeignTypeMetadata(conformingType)) {
- // Make sure we emit the metadata access function.
- (void)getTypeMetadataAccessFunction(*this, conformingType,
- ForDefinition);
-
- // Make sure we emit the nominal type descriptor.
- auto *nominal = conformingType->getAnyNominal();
- auto entity = LinkEntity::forNominalTypeDescriptor(nominal);
- if (auto entry = GlobalVars[entity]) {
- if (!cast<llvm::GlobalValue>(entry)->isDeclaration())
- return;
- }
-
- emitLazyTypeContextDescriptor(*this, nominal, RequireMetadata);
+ (void)getAddrOfForeignTypeMetadataCandidate(conformingType);
}
}
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 35dc688..228bee1 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -74,6 +74,10 @@
#include <thread>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
using namespace swift;
using namespace irgen;
using namespace llvm;
@@ -82,6 +86,14 @@
"disable-objc-arc-contract", cl::Hidden,
cl::desc("Disable running objc arc contract for testing purposes"));
+// This option is for performance benchmarking: to ensure a consistent
+// performance data, modules are aligned to the page size.
+// Warning: this blows up the text segment size. So use this option only for
+// performance benchmarking.
+static cl::opt<bool> AlignModuleToPageSize(
+ "align-module-to-page-size", cl::Hidden,
+ cl::desc("Align the text section of all LLVM modules to the page size"));
+
namespace {
// We need this to access IRGenOptions from extension functions
class PassManagerBuilderWrapper : public PassManagerBuilder {
@@ -274,6 +286,23 @@
// Do it.
ModulePasses.run(*Module);
+
+ if (AlignModuleToPageSize) {
+ // For performance benchmarking: Align the module to the page size by
+ // aligning the first function of the module.
+ unsigned pageSize =
+#if HAVE_UNISTD_H
+ sysconf(_SC_PAGESIZE));
+#else
+ 4096; // Use a default value
+#endif
+ for (auto I = Module->begin(), E = Module->end(); I != E; ++I) {
+ if (!I->isDeclaration()) {
+ I->setAlignment(pageSize);
+ break;
+ }
+ }
+ }
}
namespace {
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 7c70497..4654572 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -199,6 +199,16 @@
SizeTy
});
+ OffsetPairTy = llvm::StructType::get(getLLVMContext(), { SizeTy, SizeTy });
+
+ // The TypeLayout structure, including all possible trailing components.
+ FullTypeLayoutTy = createStructType(*this, "swift.full_type_layout", {
+ SizeTy, // size
+ SizeTy, // flags
+ SizeTy, // alignment
+ SizeTy // extra inhabitant flags (optional)
+ });
+
// A protocol descriptor describes a protocol. It is not type metadata in
// and of itself, but is referenced in the structure of existential type
// metadata records.
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 5030cc7..469910c 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -98,7 +98,7 @@
class SourceLoc;
class SourceFile;
class Type;
- enum class TypeMetadataRecordKind : unsigned;
+ enum class TypeReferenceKind : unsigned;
namespace Lowering {
class TypeConverter;
@@ -424,13 +424,13 @@
/// A reference to a declared type entity.
class TypeEntityReference {
- TypeMetadataRecordKind Kind;
+ TypeReferenceKind Kind;
llvm::Constant *Value;
public:
- TypeEntityReference(TypeMetadataRecordKind kind, llvm::Constant *value)
+ TypeEntityReference(TypeReferenceKind kind, llvm::Constant *value)
: Kind(kind), Value(value) {}
- TypeMetadataRecordKind getKind() const { return Kind; }
+ TypeReferenceKind getKind() const { return Kind; }
llvm::Constant *getValue() const { return Value; }
};
@@ -531,6 +531,8 @@
llvm::StructType *TypeMetadataResponseTy; /// { %swift.type*, iSize }
llvm::StructType *TypeMetadataDependencyTy; /// { %swift.type*, iSize }
};
+ llvm::StructType *OffsetPairTy; /// { iSize, iSize }
+ llvm::StructType *FullTypeLayoutTy; /// %swift.full_type_layout = { ... }
llvm::PointerType *TupleTypeMetadataPtrTy; /// %swift.tuple_type*
llvm::StructType *FullHeapMetadataStructTy; /// %swift.full_heapmetadata = type { ... }
llvm::PointerType *FullHeapMetadataPtrTy;/// %swift.full_heapmetadata*
@@ -1170,9 +1172,6 @@
ForDefinition_t forDefinition);
llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
- /// Determine whether the given type requires foreign type metadata.
- bool requiresForeignTypeMetadata(CanType type);
-
llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
ForDefinition_t forDefinition);
llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index bb8eeb8..4c4fc21 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -613,8 +613,9 @@
ForeignClassMetadataLayout &layout)
: super(IGM, decl), Layout(layout) {}
- void noteStartOfSuperClass() {
+ void addSuperclass() {
Layout.SuperClassOffset = getNextOffset();
+ super::addSuperclass();
}
void layout() {
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index a266a35..e2d9d42 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -469,25 +469,6 @@
classObject);
}
-/// Emit a reference to the type metadata for a foreign type.
-llvm::Value *irgen::uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
- llvm::Value *candidate) {
- auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
- candidate);
- call->addAttribute(llvm::AttributeList::FunctionIndex,
- llvm::Attribute::NoUnwind);
- call->addAttribute(llvm::AttributeList::FunctionIndex,
- llvm::Attribute::ReadNone);
- return call;
-}
-
-/// Emit a reference to the type metadata for a foreign type.
-static llvm::Value *emitForeignTypeMetadataRef(IRGenFunction &IGF,
- CanType type) {
- llvm::Value *candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type);
- return uniqueForeignTypeMetadataRef(IGF, candidate);
-}
-
/// Returns a metadata reference for a nominal type.
///
/// This is only valid in a couple of special cases:
@@ -634,6 +615,9 @@
assert(type->hasUnboundGenericType());
}
+ if (requiresForeignTypeMetadata(nominal))
+ return MetadataAccessStrategy::ForeignAccessor;
+
// If the type doesn't guarantee that it has an access function,
// we might have to use a non-unique accessor.
@@ -1632,10 +1616,8 @@
CanNominalType type,
llvm::Constant *cacheVariable,
OnceMetadataInitializer initializer) {
- llvm::Constant *metadata =
- IGF.IGM.requiresForeignTypeMetadata(type)
- ? IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type)
- : IGF.IGM.getAddrOfTypeMetadata(type);
+ assert(!requiresForeignTypeMetadata(type));
+ llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
// We might not have interesting initialization to do.
assert((cacheVariable == nullptr) ==
@@ -1688,9 +1670,9 @@
/// metadata-construction functions. It is not used for the in-place
/// initialization of non-generic nominal type metadata.
static MetadataResponse
-emitTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
- DynamicMetadataRequest request,
- CanType type) {
+emitDirectTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
+ DynamicMetadataRequest request,
+ CanType type) {
assert(!type->hasArchetype() &&
"cannot emit metadata accessor for context-dependent type");
@@ -1718,54 +1700,61 @@
// metadata for it.)
assert(!IGF.IGM.isResilient(typeDecl, ResilienceExpansion::Maximal));
- // Non-native types are just wrapped in various ways.
- if (auto classDecl = dyn_cast<ClassDecl>(typeDecl)) {
- // We emit a completely different pattern for foreign classes.
- if (classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
- return MetadataResponse::forComplete(
- emitForeignTypeMetadataRef(IGF, type));
- }
+ // We should never be emitting a metadata accessor for foreign type
+ // metadata using this function.
+ assert(!requiresForeignTypeMetadata(typeDecl));
- // Classes that might not have Swift metadata use a different
- // symbol name.
+ // Classes that might not have Swift metadata use a different
+ // access pattern.
+ if (auto classDecl = dyn_cast<ClassDecl>(typeDecl)) {
if (!hasKnownSwiftMetadata(IGF.IGM, classDecl)) {
return MetadataResponse::forComplete(emitObjCMetadataRef(IGF, classDecl));
}
-
- // Imported value types require foreign metadata uniquing.
- } else if (isa<ClangModuleUnit>(typeDecl->getModuleScopeContext())) {
- return MetadataResponse::forComplete(emitForeignTypeMetadataRef(IGF, type));
}
- // Okay, everything else is built from a Swift metadata object.
- llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
-
// We should not be doing more serious work along this path.
assert(isTypeMetadataAccessTrivial(IGF.IGM, type));
+ // Okay, everything else is built from a Swift metadata object.
+ llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
+
return MetadataResponse::forComplete(metadata);
}
-/// Get or create an accessor function to the given non-dependent type.
-llvm::Function *
-irgen::getTypeMetadataAccessFunction(IRGenModule &IGM,
- CanType type,
- ForDefinition_t shouldDefine,
- CacheStrategy cacheStrategy,
- MetadataAccessGenerator generator) {
+static llvm::Function *getAccessFunctionPrototype(IRGenModule &IGM,
+ CanType type,
+ ForDefinition_t forDefinition) {
assert(!type->hasArchetype());
// Type should be bound unless it's type erased.
assert(isTypeErasedGenericClassType(type)
? !isa<BoundGenericType>(type)
: !isa<UnboundGenericType>(type));
- llvm::Function *accessor =
- IGM.getAddrOfTypeMetadataAccessFunction(type, shouldDefine);
+ return IGM.getAddrOfTypeMetadataAccessFunction(type, forDefinition);
+}
+
+llvm::Function *
+irgen::getOtherwiseDefinedTypeMetadataAccessFunction(IRGenModule &IGM,
+ CanType type) {
+ return getAccessFunctionPrototype(IGM, type, NotForDefinition);
+}
+
+/// Get or create an accessor function to the given non-dependent type.
+llvm::Function *
+irgen::createTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+ CacheStrategy cacheStrategy,
+ MetadataAccessGenerator generator,
+ bool allowExistingDefinition) {
+ // Get the prototype.
+ auto accessor = getAccessFunctionPrototype(IGM, type, ForDefinition);
// If we're not supposed to define the accessor, or if we already
// have defined it, just return the pointer.
- if (!shouldDefine || !accessor->empty())
+ if (!accessor->empty()) {
+ assert(allowExistingDefinition &&
+ "repeat definition of access function!");
return accessor;
+ }
// Okay, define the accessor.
llvm::Constant *cacheVariable = nullptr;
@@ -1806,19 +1795,18 @@
return accessor;
}
-/// Get or create an accessor function to the given non-dependent type.
-llvm::Function *irgen::getTypeMetadataAccessFunction(IRGenModule &IGM,
- CanType type,
- ForDefinition_t shouldDefine) {
- return getTypeMetadataAccessFunction(IGM, type, shouldDefine,
- CacheStrategy::Lazy,
- [&](IRGenFunction &IGF,
- DynamicMetadataRequest request,
- llvm::Constant *cacheVariable) {
+/// Emit a standard accessor function to the given non-dependent type.
+llvm::Function *
+irgen::createDirectTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+ bool allowExistingDefinition) {
+ return createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
+ [&](IRGenFunction &IGF,
+ DynamicMetadataRequest request,
+ llvm::Constant *cacheVariable) {
// We should not be called with ForDefinition for nominal types
// that require in-place initialization.
- return emitTypeMetadataAccessFunctionBody(IGF, request, type);
- });
+ return emitDirectTypeMetadataAccessFunctionBody(IGF, request, type);
+ }, allowExistingDefinition);
}
/// Get or create an accessor function to the given generic type.
@@ -1857,32 +1845,16 @@
return accessor;
}
-/// Return the type metadata access function for the given type, if it
-/// is guaranteed to exist.
-llvm::Constant *
-irgen::getRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
- NominalTypeDecl *theDecl,
- ForDefinition_t shouldDefine) {
- if (theDecl->isGenericContext()) {
- return getGenericTypeMetadataAccessFunction(IGM, theDecl, shouldDefine);
- }
-
- CanType declaredType = theDecl->getDeclaredType()->getCanonicalType();
- return getTypeMetadataAccessFunction(IGM, declaredType, shouldDefine);
-}
-
/// Emit a call to the type metadata accessor for the given function.
static MetadataResponse
-emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF,
- CanType type,
- DynamicMetadataRequest request,
- ForDefinition_t shouldDefine) {
+emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF, CanType type,
+ DynamicMetadataRequest request) {
// If we already cached the metadata, use it.
if (auto local = IGF.tryGetLocalTypeMetadata(type, request))
return local;
llvm::Constant *accessor =
- getTypeMetadataAccessFunction(IGF.IGM, type, shouldDefine);
+ getOrCreateTypeMetadataAccessFunction(IGF.IGM, type);
llvm::CallInst *call = IGF.Builder.CreateCall(accessor, { request.get(IGF) });
call->setCallingConv(IGF.IGM.SwiftCC);
call->setDoesNotAccessMemory();
@@ -1917,17 +1889,7 @@
return emitDirectTypeMetadataRef(*this, type, request);
}
- switch (getTypeMetadataAccessStrategy(type)) {
- case MetadataAccessStrategy::PublicUniqueAccessor:
- case MetadataAccessStrategy::HiddenUniqueAccessor:
- case MetadataAccessStrategy::PrivateAccessor:
- return emitCallToTypeMetadataAccessFunction(*this, type, request,
- NotForDefinition);
- case MetadataAccessStrategy::NonUniqueAccessor:
- return emitCallToTypeMetadataAccessFunction(*this, type, request,
- ForDefinition);
- }
- llvm_unreachable("bad type metadata access strategy");
+ return emitCallToTypeMetadataAccessFunction(*this, type, request);
}
/// Return the address of a function that will return type metadata
@@ -1940,12 +1902,17 @@
"cannot create global function to return dependent type metadata");
switch (getTypeMetadataAccessStrategy(type)) {
+ case MetadataAccessStrategy::ForeignAccessor:
+ // Force the foreign candidate to exist.
+ (void) IGM.getAddrOfForeignTypeMetadataCandidate(type);
+ LLVM_FALLTHROUGH;
case MetadataAccessStrategy::PublicUniqueAccessor:
case MetadataAccessStrategy::HiddenUniqueAccessor:
case MetadataAccessStrategy::PrivateAccessor:
- return getTypeMetadataAccessFunction(IGM, type, NotForDefinition);
+ return getOtherwiseDefinedTypeMetadataAccessFunction(IGM, type);
case MetadataAccessStrategy::NonUniqueAccessor:
- return getTypeMetadataAccessFunction(IGM, type, ForDefinition);
+ return createDirectTypeMetadataAccessFunction(IGM, type,
+ /*allow existing*/true);
}
llvm_unreachable("bad type metadata access strategy");
}
@@ -2160,6 +2127,23 @@
return emitFromValueWitnessTablePointer(vwtable);
}
+ /// Given that the type is fixed-layout, emit the type layout by
+ /// emitting a global layout for it.
+ llvm::Value *emitFromFixedLayout(CanType t) {
+ auto layout = tryEmitFromFixedLayout(t);
+ assert(layout && "type must be fixed-size to call emitFromFixedLayout");
+ return layout;
+ }
+
+ /// If the type is fixed-layout, emit the type layout by
+ /// emitting a global layout for it.
+ llvm::Value *tryEmitFromFixedLayout(CanType t) {
+ auto &ti = IGF.getTypeInfo(SILType::getPrimitiveObjectType(t));
+ if (auto fixedTI = dyn_cast<FixedTypeInfo>(&ti))
+ return IGF.IGM.emitFixedTypeLayout(t, *fixedTI);
+ return nullptr;
+ }
+
bool hasVisibleValueWitnessTable(CanType t) const {
// Some builtin and structural types have value witnesses exported from
// the runtime.
@@ -2267,7 +2251,7 @@
}
case MetatypeRepresentation::Thick:
if (isa<ExistentialMetatypeType>(type)) {
- return emitFromTypeMetadata(type, request);
+ return emitFromFixedLayout(type);
}
// Otherwise, this is a metatype that looks like a pointer.
LLVM_FALLTHROUGH;
@@ -2311,68 +2295,101 @@
return visitAnyClassType(type->getClassOrBoundGenericClass(), request);
}
- llvm::Value *visitReferenceStorageType(CanReferenceStorageType type,
- DynamicMetadataRequest request) {
- // Other reference storage types all have the same layout for their
- // storage qualification and the reference counting of their underlying
- // object.
+ llvm::Value *visitTupleType(CanTupleType type,
+ DynamicMetadataRequest request) {
+ // Single-element tuples have exactly the same layout as their elements.
+ if (type->getNumElements() == 1) {
+ return visit(type.getElementType(0), request);
+ }
- auto &C = IGF.IGM.Context;
- CanType referent = type.getReferentType();
- CanType underlyingTy = referent;
- if (auto Ty = referent.getOptionalObjectType())
- underlyingTy = Ty;
+ // If the type is fixed-layout, use a global layout.
+ if (auto layout = tryEmitFromFixedLayout(type))
+ return layout;
- // Reference storage types with witness tables need open-coded layouts.
- // TODO: Maybe we could provide prefabs for 1 witness table.
- if (underlyingTy.isExistentialType()) {
- auto layout = underlyingTy.getExistentialLayout();
- for (auto *protoTy : layout.getProtocols()) {
- auto *protoDecl = protoTy->getDecl();
- if (IGF.getSILTypes().protocolRequiresWitnessTable(protoDecl))
- return visitType(type, request);
+ // TODO: check for cached VWT / metadata for the type.
+
+ // Use swift_getTupleTypeLayout to compute a layout.
+
+ // Create a buffer to hold the result. We don't have any reasonable
+ // way to scope the lifetime of this.
+ auto resultPtr = IGF.createAlloca(IGF.IGM.FullTypeLayoutTy,
+ IGF.IGM.getPointerAlignment())
+ .getAddress();
+
+ switch (type->getNumElements()) {
+ case 0:
+ case 1:
+ llvm_unreachable("filtered out above");
+
+ case 2: {
+ auto elt0 = visit(type.getElementType(0), request);
+ auto elt1 = visit(type.getElementType(1), request);
+
+ // Ignore the offset.
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayout2Fn(),
+ {resultPtr, elt0, elt1});
+ call->setDoesNotThrow();
+
+ break;
+ }
+
+ case 3: {
+ auto elt0 = visit(type.getElementType(0), request);
+ auto elt1 = visit(type.getElementType(1), request);
+ auto elt2 = visit(type.getElementType(2), request);
+
+ // Ignore the offsets.
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayout3Fn(),
+ {resultPtr, elt0, elt1, elt2});
+ call->setDoesNotThrow();
+
+ break;
+ }
+
+ default: {
+ // Allocate a temporary array for the element layouts.
+ auto eltLayoutsArraySize =
+ IGF.IGM.getPointerSize() * type->getNumElements();
+ auto eltLayoutsArray =
+ IGF.createAlloca(IGF.IGM.Int8PtrPtrTy,
+ IGF.IGM.getSize(Size(type->getNumElements())),
+ IGF.IGM.getPointerAlignment());
+ IGF.Builder.CreateLifetimeStart(eltLayoutsArray, eltLayoutsArraySize);
+
+ // Emit layouts for all the elements and store them into the array.
+ for (auto i : indices(type.getElementTypes())) {
+ auto eltLayout = visit(type.getElementType(i), request);
+ auto eltLayoutSlot =
+ i == 0 ? eltLayoutsArray
+ : IGF.Builder.CreateConstArrayGEP(eltLayoutsArray, i,
+ IGF.IGM.getPointerSize());
+ IGF.Builder.CreateStore(eltLayout, eltLayoutSlot);
}
+
+ // Ignore the offsets.
+ auto offsetsPtr =
+ llvm::ConstantPointerNull::get(IGF.IGM.Int32Ty->getPointerTo());
+
+ // Flags.
+ auto flags = TupleTypeFlags().withNumElements(type->getNumElements());
+ auto flagsValue = IGF.IGM.getSize(Size(flags.getIntValue()));
+
+ // Compute the layout.
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayoutFn(),
+ {resultPtr, offsetsPtr, flagsValue,
+ eltLayoutsArray.getAddress()});
+ call->setDoesNotThrow();
+
+ // We're done with the buffer.
+ IGF.Builder.CreateLifetimeEnd(eltLayoutsArray, eltLayoutsArraySize);
+
+ break;
+ }
}
- // Unmanaged references are plain pointers with extra inhabitants,
- // which look like thick metatypes.
- //
- // FIXME: This sounds wrong, an Objective-C tagged pointer could be
- // stored in an unmanaged reference for instance.
- if (type->getOwnership() == ReferenceOwnership::Unmanaged) {
- auto metatype = CanMetatypeType::get(C.TheNativeObjectType);
- return emitFromValueWitnessTable(metatype);
- }
-
- CanType valueWitnessReferent;
- switch (getReferenceCountingForType(IGF.IGM, underlyingTy)) {
- case ReferenceCounting::Unknown:
- case ReferenceCounting::Block:
- case ReferenceCounting::ObjC:
- valueWitnessReferent = C.TheUnknownObjectType;
- break;
-
- case ReferenceCounting::Native:
- valueWitnessReferent = C.TheNativeObjectType;
- break;
-
- case ReferenceCounting::Bridge:
- valueWitnessReferent = C.TheBridgeObjectType;
- break;
-
- case ReferenceCounting::Error:
- llvm_unreachable("shouldn't be possible");
- }
-
- // Get the reference storage type of the builtin object whose value
- // witness we can borrow.
- if (referent->getOptionalObjectType())
- valueWitnessReferent = OptionalType::get(valueWitnessReferent)
- ->getCanonicalType();
-
- auto valueWitnessType = CanReferenceStorageType::get(valueWitnessReferent,
- type->getOwnership());
- return emitFromValueWitnessTable(valueWitnessType);
+ // Cast resultPtr to i8**, our general currency type for type layouts.
+ resultPtr = IGF.Builder.CreateBitCast(resultPtr, IGF.IGM.Int8PtrPtrTy);
+ return resultPtr;
}
};
diff --git a/lib/IRGen/MetadataRequest.h b/lib/IRGen/MetadataRequest.h
index ec5d1a8..8b3dc07 100644
--- a/lib/IRGen/MetadataRequest.h
+++ b/lib/IRGen/MetadataRequest.h
@@ -450,11 +450,30 @@
/// There is a unique private accessor function for the given type metadata.
PrivateAccessor,
+ /// The given type metadata is for a foreign type; its accessor function
+ /// is built as a side-effect of emitting a metadata candidate.
+ ForeignAccessor,
+
/// There is no unique accessor function for the given type metadata, but
/// one should be made automatically.
NonUniqueAccessor
};
+/// Does the given access strategy rely on an accessor that's generated
+/// on-demand and thus may be shared across object files?
+static inline bool isAccessorLazilyGenerated(MetadataAccessStrategy strategy) {
+ switch (strategy) {
+ case MetadataAccessStrategy::PublicUniqueAccessor:
+ case MetadataAccessStrategy::HiddenUniqueAccessor:
+ case MetadataAccessStrategy::PrivateAccessor:
+ return false;
+ case MetadataAccessStrategy::ForeignAccessor:
+ case MetadataAccessStrategy::NonUniqueAccessor:
+ return true;
+ }
+ llvm_unreachable("bad kind");
+}
+
/// Is it basically trivial to access the given metadata? If so, we don't
/// need a cache variable in its accessor.
bool isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type);
@@ -467,9 +486,16 @@
llvm::Function *getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM,
CanType type);
-llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
- CanType type,
- ForDefinition_t shouldDefine);
+/// Return the type metadata access function for the given type, given that
+/// some other code will be defining it.
+llvm::Function *
+getOtherwiseDefinedTypeMetadataAccessFunction(IRGenModule &IGM, CanType type);
+
+/// Emit a type metadata access function that just directly accesses
+/// the metadata.
+llvm::Function *
+createDirectTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+ bool allowExistingDefinition);
using MetadataAccessGenerator =
llvm::function_ref<MetadataResponse(IRGenFunction &IGF,
@@ -487,22 +513,41 @@
InPlaceInitialization,
};
-llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
- CanType type,
- ForDefinition_t shouldDefine,
- CacheStrategy cacheStrategy,
- MetadataAccessGenerator generator);
+/// Emit a type metadata access function using the given generator function.
+llvm::Function *
+createTypeMetadataAccessFunction(IRGenModule &IGM,
+ CanType type,
+ CacheStrategy cacheStrategy,
+ MetadataAccessGenerator generator,
+ bool allowExistingDefinition = false);
+/// Either create or return a reference to a generic type metadata
+/// access function.
+///
+/// Note that a generic type metadata access function is a somewhat
+/// different kind of thing from an ordinary type metadata access function:
+///
+/// - A generic type metadata access function is associated with a type
+/// object of kind `(...) -> type` --- typically, an unapplied
+/// generic type (like `Dictionary`, without any type arguments).
+/// It takes the concrete witnesses to the generic signature as
+/// parameters and builds an appropriately instantiated type for those
+/// arguments.
+///
+/// - An ordinary type metadata access function is associated with
+/// a type object of kind `type` --- which is to say, an ordinary type
+/// like `Float` or `Dictionary<String, Int>`. There may be ordinary
+/// access functions for various specializations of generic types;
+/// these will be created on demand.
+///
+/// The definitions of generic type metadata access functions currently
+/// always follow the same pattern, so we don't need to take a closure to
+/// define the body.
llvm::Function *
getGenericTypeMetadataAccessFunction(IRGenModule &IGM,
NominalTypeDecl *nominal,
ForDefinition_t shouldDefine);
-llvm::Constant *
-getRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
- NominalTypeDecl *theDecl,
- ForDefinition_t shouldDefine);
-
using OnceMetadataInitializer =
llvm::function_ref<llvm::Value*(IRGenFunction &IGF, llvm::Value *metadata)>;
@@ -512,9 +557,6 @@
llvm::Constant *cacheVariable,
OnceMetadataInitializer initializer);
-llvm::Value *uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
- llvm::Value *candidate);
-
using CacheEmitter =
llvm::function_ref<MetadataResponse(IRGenFunction &IGF, Explosion ¶ms)>;
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 8c8eac0..a2753d2 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -363,6 +363,7 @@
std::vector<ConversionFunctionInfo> HelperFuncInfo;
SourceLoc FileEndLoc;
+ llvm::StringSet<> OverridingRemoveNames;
/// For a given expression, check whether the type of this expression is
/// name alias type, and the name alias type is known to change to raw
@@ -385,7 +386,8 @@
APIDiffMigratorPass(EditorAdapter &Editor, SourceFile *SF,
const MigratorOptions &Opts):
ASTMigratorPass(Editor, SF, Opts), DiffStore(Diags),
- FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
+ FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()),
+ OverridingRemoveNames(funcNamesForOverrideRemoval()) {}
~APIDiffMigratorPass() {
Editor.disableCache();
@@ -1290,6 +1292,92 @@
}
}
+ llvm::StringSet<> funcNamesForOverrideRemoval() {
+ llvm::StringSet<> Results;
+ Results.insert("c:objc(cs)NSObject(im)application:delegateHandlesKey:");
+ Results.insert("c:objc(cs)NSObject(im)changeColor:");
+ Results.insert("c:objc(cs)NSObject(im)controlTextDidBeginEditing:");
+ Results.insert("c:objc(cs)NSObject(im)controlTextDidEndEditing:");
+ Results.insert("c:objc(cs)NSObject(im)controlTextDidChange:");
+ Results.insert("c:objc(cs)NSObject(im)changeFont:");
+ Results.insert("c:objc(cs)NSObject(im)validModesForFontPanel:");
+ Results.insert("c:objc(cs)NSObject(im)discardEditing");
+ Results.insert("c:objc(cs)NSObject(im)commitEditing");
+ Results.insert("c:objc(cs)NSObject(im)commitEditingWithDelegate:didCommitSelector:contextInfo:");
+ Results.insert("c:objc(cs)NSObject(im)commitEditingAndReturnError:");
+ Results.insert("c:objc(cs)NSObject(im)objectDidBeginEditing:");
+ Results.insert("c:objc(cs)NSObject(im)objectDidEndEditing:");
+ Results.insert("c:objc(cs)NSObject(im)validateMenuItem:");
+ Results.insert("c:objc(cs)NSObject(im)pasteboard:provideDataForType:");
+ Results.insert("c:objc(cs)NSObject(im)pasteboardChangedOwner:");
+ Results.insert("c:objc(cs)NSObject(im)validateToolbarItem:");
+ Results.insert("c:objc(cs)NSObject(im)layer:shouldInheritContentsScale:fromWindow:");
+ Results.insert("c:objc(cs)NSObject(im)view:stringForToolTip:point:userData:");
+ return Results;
+ }
+
+ SourceLoc shouldRemoveOverride(AbstractFunctionDecl *AFD) {
+ if (AFD->getKind() != DeclKind::Func)
+ return SourceLoc();
+ SourceLoc OverrideLoc;
+
+ // Get the location of override keyword.
+ if (auto *Override = AFD->getAttrs().getAttribute<OverrideAttr>()) {
+ if (Override->getRange().isValid()) {
+ OverrideLoc = Override->getLocation();
+ }
+ }
+ if (OverrideLoc.isInvalid())
+ return SourceLoc();
+ auto *OD = AFD->getOverriddenDecl();
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ if (swift::ide::printDeclUSR(OD, OS))
+ return SourceLoc();
+ return OverridingRemoveNames.find(OS.str()) == OverridingRemoveNames.end() ?
+ SourceLoc() : OverrideLoc;
+ }
+
+ struct SuperRemoval: public ASTWalker {
+ EditorAdapter &Editor;
+ llvm::StringSet<> &USRs;
+ SuperRemoval(EditorAdapter &Editor, llvm::StringSet<> &USRs):
+ Editor(Editor), USRs(USRs) {}
+ bool isSuperExpr(Expr *E) {
+ if (E->isImplicit())
+ return false;
+ // Check if the expression is super.foo().
+ if (auto *CE = dyn_cast<CallExpr>(E)) {
+ if (auto *DSC = dyn_cast<DotSyntaxCallExpr>(CE->getFn())) {
+ if (DSC->getBase()->getKind() != ExprKind::SuperRef)
+ return false;
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ auto *RD = DSC->getFn()->getReferencedDecl().getDecl();
+ if (swift::ide::printDeclUSR(RD, OS))
+ return false;
+ return USRs.find(OS.str()) != USRs.end();
+ }
+ }
+ // We should handle try super.foo() too.
+ if (auto *TE = dyn_cast<AnyTryExpr>(E)) {
+ return isSuperExpr(TE->getSubExpr());
+ }
+ return false;
+ }
+ std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override {
+ if (auto *BS = dyn_cast<BraceStmt>(S)) {
+ for(auto Ele: BS->getElements()) {
+ if (Ele.is<Expr*>() && isSuperExpr(Ele.get<Expr*>())) {
+ Editor.remove(Ele.getSourceRange());
+ }
+ }
+ }
+ // We only handle top-level expressions, so avoid visiting further.
+ return {false, S};
+ }
+ };
+
bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
if (D->isImplicit())
return true;
@@ -1305,6 +1393,14 @@
handleLocalParameterBridge(AFD, DiffItem);
}
}
+ auto OverrideLoc = shouldRemoveOverride(AFD);
+ if (OverrideLoc.isValid()) {
+ // Remove override keyword.
+ Editor.remove(OverrideLoc);
+ // Remove super-dot call.
+ SuperRemoval Removal(Editor, OverridingRemoveNames);
+ D->walk(Removal);
+ }
}
return true;
}
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 98baf07..1bdd5af 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -313,6 +313,11 @@
}
}
break;
+
+ case ConstraintLocator::ContextualType:
+ // This was just for identifying purposes, strip it off.
+ path = path.slice(1);
+ continue;
default:
// FIXME: Lots of other cases to handle.
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 41c1b06..4ae9e88 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -318,6 +318,13 @@
return { false, expr };
}
+ // Don't walk into unresolved member expressions - we avoid merging type
+ // variables inside UnresolvedMemberExpr and those outside, since they
+ // should be allowed to behave independently in CS.
+ if (isa<UnresolvedMemberExpr>(expr)) {
+ return {false, expr };
+ }
+
return { true, expr };
}
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index bac7d4e..cf40dbe 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1417,16 +1417,19 @@
if (getContextualTypePurpose() == CTP_YieldByReference)
constraintKind = ConstraintKind::Bind;
+ auto *convertTypeLocator = getConstraintLocator(
+ getConstraintLocator(expr), ConstraintLocator::ContextualType);
+
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
convertType = convertType.transform([&](Type type) -> Type {
if (type->is<UnresolvedType>())
- return createTypeVariable(getConstraintLocator(expr));
+ return createTypeVariable(convertTypeLocator);
return type;
});
}
addConstraint(constraintKind, getType(expr), convertType,
- getConstraintLocator(expr), /*isFavored*/ true);
+ convertTypeLocator, /*isFavored*/ true);
}
// Notify the listener that we've built the constraint system.
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index 2417886..2f6a966 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -80,6 +80,7 @@
case TypeParameterRequirement:
case ImplicitlyUnwrappedDisjunctionChoice:
case DynamicLookupResult:
+ case ContextualType:
if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
id.AddInteger(elt.getValue());
if (numValues > 1)
@@ -258,6 +259,10 @@
case DynamicLookupResult:
out << "dynamic lookup result";
break;
+
+ case ContextualType:
+ out << "contextual type";
+ break;
}
}
diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h
index 05cdcb5..8fbaf44 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -131,8 +131,10 @@
TypeParameterRequirement,
/// \brief Locator for a binding from an IUO disjunction choice.
ImplicitlyUnwrappedDisjunctionChoice,
- /// \brief A result of an expressoin involving dynamic lookup.
+ /// \brief A result of an expression involving dynamic lookup.
DynamicLookupResult,
+ /// \brief The desired contextual type passed in to the constraint system.
+ ContextualType,
};
/// \brief Determine the number of numeric values used for the given path
@@ -167,6 +169,7 @@
case OpenedGeneric:
case ImplicitlyUnwrappedDisjunctionChoice:
case DynamicLookupResult:
+ case ContextualType:
return 0;
case GenericArgument:
@@ -231,6 +234,7 @@
case TypeParameterRequirement:
case ImplicitlyUnwrappedDisjunctionChoice:
case DynamicLookupResult:
+ case ContextualType:
return 0;
case FunctionArgument:
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 123033a..04a2785 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -700,24 +700,34 @@
return false;
}
+static Type withParens(ConstraintSystem &cs, Type type, ParenType *parenType) {
+ auto flags = parenType->getParameterFlags().withInOut(type->is<InOutType>());
+ return ParenType::get(cs.getASTContext(), type->getInOutObjectType(), flags);
+}
+
Type ConstraintSystem::getFixedTypeRecursive(Type type,
TypeMatchOptions &flags,
bool wantRValue,
bool retainParens) {
- if (wantRValue)
- type = type->getRValueType();
+ // FIXME: This function doesn't strictly honor retainParens
+ // everywhere.
if (retainParens) {
- if (auto parenTy = dyn_cast<ParenType>(type.getPointer())) {
- type = getFixedTypeRecursive(parenTy->getUnderlyingType(), flags,
- wantRValue, retainParens);
- auto flags = parenTy->getParameterFlags().withInOut(type->is<InOutType>());
- return ParenType::get(getASTContext(), type->getInOutObjectType(), flags);
+ if (wantRValue)
+ type = type->getRValueType();
+
+ if (auto *parenTy = dyn_cast<ParenType>(type.getPointer())) {
+ auto fixed = getFixedTypeRecursive(parenTy->getUnderlyingType(), flags,
+ wantRValue, retainParens);
+ return withParens(*this, fixed, parenTy);
}
}
while (true) {
+ if (wantRValue)
+ type = type->getRValueType();
+
if (auto depMemType = type->getAs<DependentMemberType>()) {
if (!depMemType->getBase()->isTypeVariableOrMember()) return type;
@@ -725,9 +735,6 @@
Type newType = simplifyType(type);
if (newType.getPointer() == type.getPointer()) return type;
- if (wantRValue)
- newType = newType->getRValueType();
-
type = newType;
// Once we've simplified a dependent member type, we need to generate a
@@ -736,35 +743,21 @@
continue;
}
- if (auto typeVar = type->getAs<TypeVariableType>()) {
- bool hasRepresentative = false;
- if (auto *repr = getRepresentative(typeVar)) {
- if (typeVar != repr) {
- hasRepresentative = true;
- typeVar = repr;
- }
- }
+ auto typeVar = type->getAs<TypeVariableType>();
+ if (!typeVar)
+ return type;
- if (auto fixed = getFixedType(typeVar)) {
- if (wantRValue)
- fixed = fixed->getRValueType();
-
- type = fixed;
- continue;
- }
-
- // If type variable has a representative but
- // no fixed type, reflect that in the type itself.
- if (hasRepresentative)
- type = typeVar;
-
- break;
+ if (auto fixed = getFixedType(typeVar)) {
+ type = fixed;
+ continue;
}
- break;
- }
+ if (retainParens)
+ if (auto *parenType = dyn_cast<ParenType>(type.getPointer()))
+ return withParens(*this, getRepresentative(typeVar), parenType);
- return type;
+ return getRepresentative(typeVar);
+ }
}
/// Does a var or subscript produce an l-value?
@@ -2022,12 +2015,10 @@
return simplifyTypeImpl(
*this, type,
[&](TypeVariableType *tvt) -> Type {
- tvt = getRepresentative(tvt);
- if (auto fixed = getFixedType(tvt)) {
+ if (auto fixed = getFixedType(tvt))
return simplifyType(fixed);
- }
- return tvt;
+ return getRepresentative(tvt);
});
}
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index dcf81ed..5f5af86 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -365,11 +365,8 @@
auto rep = getRepresentative(record);
Implementation &repImpl = rep->getImpl();
- // Check whether it has a fixed type.
- if (auto type = repImpl.ParentOrFixed.dyn_cast<TypeBase *>())
- return type;
-
- return Type();
+ // Return the bound type if there is one, otherwise, null.
+ return repImpl.ParentOrFixed.dyn_cast<TypeBase *>();
}
/// \brief Assign a fixed type to this equivalence class.
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 604d6db..67fd66f 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2040,9 +2040,18 @@
if (options.contains(TypeCheckExprFlags::AllowUnresolvedTypeVariables))
allowFreeTypeVariables = FreeTypeVariableBinding::UnresolvedType;
+ Type convertTo = convertType.getType();
+ if (options.contains(TypeCheckExprFlags::ExpressionTypeMustBeOptional)) {
+ assert(!convertTo && "convertType and type check options conflict");
+ auto *convertTypeLocator = cs.getConstraintLocator(
+ cs.getConstraintLocator(expr), ConstraintLocator::ContextualType);
+ Type var = cs.createTypeVariable(convertTypeLocator);
+ convertTo = getOptionalType(expr->getLoc(), var);
+ }
+
// Attempt to solve the constraint system.
SmallVector<Solution, 4> viable;
- if (cs.solve(expr, convertType.getType(), listener, viable,
+ if (cs.solve(expr, convertTo, listener, viable,
allowFreeTypeVariables))
return Type();
@@ -2439,6 +2448,8 @@
TypeLoc contextualType;
auto contextualPurpose = CTP_Unused;
+ TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
+
if (pattern->hasType()) {
contextualType = TypeLoc::withoutLoc(pattern->getType());
contextualPurpose = CTP_Initialization;
@@ -2453,10 +2464,11 @@
if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner))
contextualType = typedPattern->getTypeLoc();
}
+ } else if (isa<OptionalSomePattern>(pattern)) {
+ flags |= TypeCheckExprFlags::ExpressionTypeMustBeOptional;
}
// Type-check the initializer.
- TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
if (skipApplyingSolution)
flags |= TypeCheckExprFlags::SkipApplyingSolution;
diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp
index 71597f4..4b9c38a 100644
--- a/lib/Sema/TypeCheckProtocolInference.cpp
+++ b/lib/Sema/TypeCheckProtocolInference.cpp
@@ -176,6 +176,13 @@
InferredAssociatedTypesByWitnesses result;
auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
+
+ // The extension where the conformance being checked is declared.
+ auto conformanceExtension = checker.Conformance->
+ getDeclContext()->getAsDeclOrDeclExtensionContext();
+ if (extension == conformanceExtension)
+ return true;
+
// Assume unconstrained concrete extensions we found witnesses in are
// always viable.
if (!extension->getExtendedType()->isAnyExistentialType()) {
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 60580dc..b2c4b6b 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -261,6 +261,10 @@
/// This is an inout yield.
IsInOutYield = 0x200,
+
+ /// If set, a conversion constraint should be specfied so that the result of
+ /// the expression is an optional type.
+ ExpressionTypeMustBeOptional = 0x400,
};
using TypeCheckExprOptions = OptionSet<TypeCheckExprFlags>;
diff --git a/stdlib/public/SwiftShims/AssertionReporting.h b/stdlib/public/SwiftShims/AssertionReporting.h
index d8a628b..9c55a62 100644
--- a/stdlib/public/SwiftShims/AssertionReporting.h
+++ b/stdlib/public/SwiftShims/AssertionReporting.h
@@ -29,7 +29,7 @@
/// <prefix>: <message>: file <file>, line <line>\n
///
/// The message may be omitted by passing messageLength=0.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_reportFatalErrorInFile(
const unsigned char *prefix, int prefixLength,
const unsigned char *message, int messageLength,
@@ -40,7 +40,7 @@
/// Report a fatal error to system console, stderr, and crash logs.
///
/// <prefix>: <message>\n
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_reportFatalError(
const unsigned char *prefix, int prefixLength,
const unsigned char *message, int messageLength,
@@ -50,7 +50,7 @@
///
/// <file>: <line>: <column>: fatal error: use of unimplemented
/// initializer '<initName>' for class '<className>'
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_reportUnimplementedInitializerInFile(
const unsigned char *className, int classNameLength,
const unsigned char *initName, int initNameLength,
@@ -62,7 +62,7 @@
///
/// fatal error: use of unimplemented initializer '<initName>'
/// for class 'className'
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_reportUnimplementedInitializer(
const unsigned char *className, int classNameLength,
const unsigned char *initName, int initNameLength,
diff --git a/stdlib/public/SwiftShims/CoreFoundationShims.h b/stdlib/public/SwiftShims/CoreFoundationShims.h
index 6928bdc..bf3c574 100644
--- a/stdlib/public/SwiftShims/CoreFoundationShims.h
+++ b/stdlib/public/SwiftShims/CoreFoundationShims.h
@@ -56,12 +56,12 @@
typedef __swift_uint8_t _swift_shims_UInt8;
// Buffer is nullable in case the string is zero-length.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_CFStringGetCharacters(
_swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFRange range,
_swift_shims_UniChar *_Nullable buffer);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
_swift_shims_CFIndex _swift_stdlib_CFStringGetBytes(
_swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFRange range,
_swift_shims_CFStringEncoding encoding, _swift_shims_UInt8 lossByte,
@@ -69,31 +69,31 @@
_swift_shims_UInt8 *_Nonnull buffer, _swift_shims_CFIndex maxBufLen,
_swift_shims_CFIndex *_Nullable usedBufLen);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const _swift_shims_UniChar *_Nullable _swift_stdlib_CFStringGetCharactersPtr(
_swift_shims_CFStringRef _Nonnull theString);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
_swift_shims_CFIndex _swift_stdlib_CFStringGetLength(
_swift_shims_CFStringRef _Nonnull theString);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__attribute__((ns_returns_retained))
_swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateWithSubstring(
_swift_shims_CFAllocatorRef _Nullable alloc,
_swift_shims_CFStringRef _Nonnull str, _swift_shims_CFRange range);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
_swift_shims_UniChar _swift_stdlib_CFStringGetCharacterAtIndex(
_swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFIndex idx);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__attribute__((ns_returns_retained))
_swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateCopy(
_swift_shims_CFAllocatorRef _Nullable alloc,
_swift_shims_CFStringRef _Nonnull theString);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__attribute__((ns_returns_retained))
_swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateWithBytes(
_swift_shims_CFAllocatorRef _Nullable alloc,
@@ -101,13 +101,13 @@
_swift_shims_CFStringEncoding encoding,
_swift_shims_Boolean isExternalRepresentation);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const char *_Nullable _swift_stdlib_CFStringGetCStringPtr(
_swift_shims_CFStringRef _Nonnull theString,
_swift_shims_CFStringEncoding encoding);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
_swift_shims_CFStringRef _Nonnull _swift_stdlib_objcDebugDescription(
id _Nonnull nsObject);
#endif // __OBJC2__
diff --git a/stdlib/public/SwiftShims/FoundationShims.h b/stdlib/public/SwiftShims/FoundationShims.h
index 684abb6..85013b7 100644
--- a/stdlib/public/SwiftShims/FoundationShims.h
+++ b/stdlib/public/SwiftShims/FoundationShims.h
@@ -54,7 +54,7 @@
__swift_intptr_t patchVersion;
} _SwiftNSOperatingSystemVersion;
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
_SwiftNSOperatingSystemVersion _swift_stdlib_operatingSystemVersion();
#ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/GlobalObjects.h b/stdlib/public/SwiftShims/GlobalObjects.h
index 75be561..51aef54 100644
--- a/stdlib/public/SwiftShims/GlobalObjects.h
+++ b/stdlib/public/SwiftShims/GlobalObjects.h
@@ -37,7 +37,7 @@
struct _SwiftArrayBodyStorage body;
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
struct _SwiftEmptyArrayStorage _swiftEmptyArrayStorage;
struct _SwiftUnsafeBitMap {
@@ -72,10 +72,10 @@
__swift_uintptr_t entries;
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
struct _SwiftEmptyDictionaryStorage _swiftEmptyDictionaryStorage;
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
struct _SwiftEmptySetStorage _swiftEmptySetStorage;
struct _SwiftHashingParameters {
@@ -84,7 +84,7 @@
__swift_bool deterministic;
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
struct _SwiftHashingParameters _swift_stdlib_Hashing_parameters;
#ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index b4ccbf0..cbc1309 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -67,17 +67,17 @@
extern "C" {
#endif
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_instantiateInertHeapObject(void *address,
const HeapMetadata *metadata);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift_retainCount(HeapObject *obj);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift_unownedRetainCount(HeapObject *obj);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift_weakRetainCount(HeapObject *obj);
#ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/RuntimeShims.h b/stdlib/public/SwiftShims/RuntimeShims.h
index bc8793e..e108947 100644
--- a/stdlib/public/SwiftShims/RuntimeShims.h
+++ b/stdlib/public/SwiftShims/RuntimeShims.h
@@ -27,33 +27,33 @@
#endif
/// Return an NSString to be used as the Mirror summary of the object
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void *_swift_objCMirrorSummary(const void * nsObject);
/// Call strtold_l with the C locale, swapping argument and return
/// types so we can operate on Float80. Return NULL on overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const char *_swift_stdlib_strtold_clocale(const char *nptr, void *outResult);
/// Call strtod_l with the C locale, swapping argument and return
/// types so we can operate consistently on Float80. Return NULL on
/// overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const char *_swift_stdlib_strtod_clocale(const char *nptr, double *outResult);
/// Call strtof_l with the C locale, swapping argument and return
/// types so we can operate consistently on Float80. Return NULL on
/// overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_flockfile_stdout(void);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_funlockfile_stdout(void);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int _swift_stdlib_putc_stderr(int C);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t _swift_stdlib_getHardwareConcurrency();
#ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/RuntimeStubs.h b/stdlib/public/SwiftShims/RuntimeStubs.h
index 412b31a..78c821a 100644
--- a/stdlib/public/SwiftShims/RuntimeStubs.h
+++ b/stdlib/public/SwiftShims/RuntimeStubs.h
@@ -27,15 +27,15 @@
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_ssize_t
swift_stdlib_readLine_stdin(unsigned char * _Nullable * _Nonnull LinePtr);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char * _Nullable * _Nonnull
_swift_stdlib_getUnsafeArgvArgc(int * _Nonnull outArgLen);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void
_swift_stdlib_overrideUnsafeArgvArgc(char * _Nullable * _Nonnull argv, int argc);
diff --git a/stdlib/public/SwiftShims/UnicodeShims.h b/stdlib/public/SwiftShims/UnicodeShims.h
index f36f571..ea52a82 100644
--- a/stdlib/public/SwiftShims/UnicodeShims.h
+++ b/stdlib/public/SwiftShims/UnicodeShims.h
@@ -29,7 +29,7 @@
namespace swift { extern "C" {
#endif
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const __swift_uint8_t *_swift_stdlib_GraphemeClusterBreakPropertyTrie;
struct _swift_stdlib_GraphemeClusterBreakPropertyTrieMetadataTy {
@@ -54,20 +54,20 @@
unsigned SuppDataBytesOffset;
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const struct _swift_stdlib_GraphemeClusterBreakPropertyTrieMetadataTy
_swift_stdlib_GraphemeClusterBreakPropertyTrieMetadata;
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const __swift_uint16_t *
_swift_stdlib_ExtendedGraphemeClusterNoBoundaryRulesMatrix;
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t _swift_stdlib_unicode_strToUpper(
__swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
const __swift_uint16_t *Source, __swift_int32_t SourceLength);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t _swift_stdlib_unicode_strToLower(
__swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
const __swift_uint16_t *Source, __swift_int32_t SourceLength);
@@ -448,10 +448,10 @@
typedef __swift_uint8_t
__swift_stdlib_UVersionInfo[__SWIFT_STDLIB_U_MAX_VERSION_LENGTH];
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void __swift_stdlib_ubrk_close(__swift_stdlib_UBreakIterator *bi);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_stdlib_UBreakIterator *
__swift_stdlib_ubrk_open(__swift_stdlib_UBreakIteratorType type,
const char *_Nullable locale,
@@ -459,97 +459,97 @@
__swift_int32_t textLength,
__swift_stdlib_UErrorCode *status);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void __swift_stdlib_ubrk_setUText(__swift_stdlib_UBreakIterator *bi,
__swift_stdlib_UText *text,
__swift_stdlib_UErrorCode *status);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void __swift_stdlib_ubrk_setText(__swift_stdlib_UBreakIterator *bi,
const __swift_stdlib_UChar *text,
__swift_int32_t textLength,
__swift_stdlib_UErrorCode *status);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_stdlib_UText *
__swift_stdlib_utext_openUTF8(__swift_stdlib_UText *_Nullable, const char *,
__swift_int64_t, __swift_stdlib_UErrorCode *);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_stdlib_UText *
__swift_stdlib_utext_openUChars(__swift_stdlib_UText *_Nullable,
const __swift_stdlib_UChar *, __swift_int64_t,
__swift_stdlib_UErrorCode *);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_ubrk_preceding(__swift_stdlib_UBreakIterator *bi,
__swift_int32_t offset);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_ubrk_following(__swift_stdlib_UBreakIterator *bi,
__swift_int32_t offset);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_stdlib_UBool
__swift_stdlib_unorm2_hasBoundaryBefore(const __swift_stdlib_UNormalizer2 *,
__swift_stdlib_UChar32);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
const __swift_stdlib_UNormalizer2 *
__swift_stdlib_unorm2_getNFCInstance(__swift_stdlib_UErrorCode *);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t
__swift_stdlib_unorm2_normalize(const __swift_stdlib_UNormalizer2 *,
const __swift_stdlib_UChar *, __swift_int32_t,
__swift_stdlib_UChar *, __swift_int32_t,
__swift_stdlib_UErrorCode *);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_unorm2_spanQuickCheckYes(
const __swift_stdlib_UNormalizer2 *, const __swift_stdlib_UChar *,
__swift_int32_t, __swift_stdlib_UErrorCode *);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_stdlib_UBool
__swift_stdlib_u_hasBinaryProperty(__swift_stdlib_UChar32,
__swift_stdlib_UProperty);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void __swift_stdlib_u_charAge(
__swift_stdlib_UChar32, __swift_stdlib_UVersionInfo _Nonnull);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t
__swift_stdlib_u_getIntPropertyValue(__swift_stdlib_UChar32,
__swift_stdlib_UProperty);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_u_charName(
__swift_stdlib_UChar32 code, __swift_stdlib_UCharNameChoice nameChoice,
char *_Nullable buffer, __swift_int32_t bufferLength,
__swift_stdlib_UErrorCode *pErrorCode);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_u_strToLower(
__swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_u_strToTitle(
__swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
__swift_stdlib_UBreakIterator *_Nullable titleIter,
const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_int32_t __swift_stdlib_u_strToUpper(
__swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
double __swift_stdlib_u_getNumericValue(__swift_stdlib_UChar32 c);
diff --git a/stdlib/public/SwiftShims/Visibility.h b/stdlib/public/SwiftShims/Visibility.h
index 0c3dfbb..023c30c 100644
--- a/stdlib/public/SwiftShims/Visibility.h
+++ b/stdlib/public/SwiftShims/Visibility.h
@@ -136,8 +136,5 @@
#define SWIFT_RUNTIME_STDLIB_SPI SWIFT_RUNTIME_EXPORT
#define SWIFT_RUNTIME_STDLIB_INTERNAL SWIFT_RUNTIME_EXPORT
-/// Old marker for runtime-stdlib interfaces. This marker will go away soon.
-#define SWIFT_RUNTIME_STDLIB_INTERFACE SWIFT_RUNTIME_STDLIB_API
-
// SWIFT_STDLIB_SHIMS_VISIBILITY_H
#endif
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 35fae48..f1def9a 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -3059,7 +3059,7 @@
}
// func _isClassOrObjCExistential<T>(x: T.Type) -> Bool
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
bool _swift_isClassOrObjCExistentialType(const Metadata *value,
const Metadata *T) {
return swift_isClassOrObjCExistentialTypeImpl(T);
diff --git a/stdlib/public/runtime/KnownMetadata.cpp b/stdlib/public/runtime/KnownMetadata.cpp
index 7b88495..edaa299 100644
--- a/stdlib/public/runtime/KnownMetadata.cpp
+++ b/stdlib/public/runtime/KnownMetadata.cpp
@@ -67,14 +67,6 @@
const ExtraInhabitantsValueWitnessTable swift::VALUE_WITNESS_SYM(Bo) =
ValueWitnessTableForBox<SwiftRetainableBox>::table;
-/// The basic value-witness table for Swift unowned pointers.
-const ExtraInhabitantsValueWitnessTable swift::UNOWNED_VALUE_WITNESS_SYM(Bo) =
- ValueWitnessTableForBox<SwiftUnownedRetainableBox>::table;
-
-/// The basic value-witness table for Swift weak pointers.
-const ValueWitnessTable swift::WEAK_VALUE_WITNESS_SYM(Bo) =
- ValueWitnessTableForBox<SwiftWeakRetainableBox>::table;
-
/// The value-witness table for pointer-aligned unmanaged pointer types.
const ExtraInhabitantsValueWitnessTable swift::METATYPE_VALUE_WITNESS_SYM(Bo) =
ValueWitnessTableForBox<PointerPointerBox>::table;
@@ -103,14 +95,6 @@
const ExtraInhabitantsValueWitnessTable swift::VALUE_WITNESS_SYM(BO) =
ValueWitnessTableForBox<ObjCRetainableBox>::table;
-/// The basic value-witness table for ObjC unowned pointers.
-const ExtraInhabitantsValueWitnessTable swift::UNOWNED_VALUE_WITNESS_SYM(BO) =
- ValueWitnessTableForBox<ObjCUnownedRetainableBox>::table;
-
-/// The basic value-witness table for ObjC weak pointers.
-const ValueWitnessTable swift::WEAK_VALUE_WITNESS_SYM(BO) =
- ValueWitnessTableForBox<ObjCWeakRetainableBox>::table;
-
#endif
/*** Functions ***************************************************************/
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 463d638..d79078a1 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -83,11 +83,19 @@
generics.Base.getNumArguments() * sizeof(void*));
}
+#if SWIFT_OBJC_INTEROP
+static ClassMetadataBounds computeMetadataBoundsForObjCClass(Class cls) {
+ cls = swift_getInitializedObjCClass(cls);
+ auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
+ return metadata->getClassBoundsAsSwiftSuperclass();
+}
+#endif
+
static ClassMetadataBounds
computeMetadataBoundsForSuperclass(const void *ref,
- TypeMetadataRecordKind refKind) {
+ TypeReferenceKind refKind) {
switch (refKind) {
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+ case TypeReferenceKind::IndirectNominalTypeDescriptor: {
auto description = *reinterpret_cast<const ClassDescriptor * const *>(ref);
if (!description) {
swift::fatalError(0, "instantiating class metadata for class with "
@@ -96,25 +104,28 @@
return description->getMetadataBounds();
}
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+ case TypeReferenceKind::DirectNominalTypeDescriptor: {
auto description = reinterpret_cast<const ClassDescriptor *>(ref);
return description->getMetadataBounds();
}
- case TypeMetadataRecordKind::IndirectObjCClass:
+ case TypeReferenceKind::DirectObjCClassName: {
#if SWIFT_OBJC_INTEROP
- {
- auto cls = *reinterpret_cast<const Class *>(ref);
- cls = swift_getInitializedObjCClass(cls);
- auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
- return metadata->getClassBoundsAsSwiftSuperclass();
- }
+ auto cls = objc_lookUpClass(reinterpret_cast<const char *>(ref));
+ return computeMetadataBoundsForObjCClass(cls);
#else
- // fallthrough
-#endif
-
- case TypeMetadataRecordKind::Reserved:
break;
+#endif
+ }
+
+ case TypeReferenceKind::IndirectObjCClass: {
+#if SWIFT_OBJC_INTEROP
+ auto cls = *reinterpret_cast<const Class *>(ref);
+ return computeMetadataBoundsForObjCClass(cls);
+#else
+ break;
+#endif
+ }
}
swift_runtime_unreachable("unsupported superclass reference kind");
}
@@ -220,13 +231,6 @@
return { metadata, state };
}
- static const TypeContextDescriptor *getDescription(Metadata *type) {
- if (auto classType = dyn_cast<ClassMetadata>(type))
- return classType->getDescription();
- else
- return cast<ValueMetadata>(type)->getDescription();
- }
-
TryInitializeResult tryInitialize(Metadata *metadata,
PrivateMetadataState state,
PrivateMetadataCompletionContext *context) {
@@ -235,7 +239,8 @@
// Finish the completion function.
if (state < PrivateMetadataState::NonTransitiveComplete) {
// Find a pattern. Currently we always use the default pattern.
- auto &generics = getDescription(metadata)->getFullGenericContextHeader();
+ auto &generics = metadata->getTypeContextDescriptor()
+ ->getFullGenericContextHeader();
auto pattern = generics.DefaultInstantiationPattern.get();
// Complete the metadata's instantiation.
@@ -571,10 +576,6 @@
return { metadata, state };
}
- static const TypeContextDescriptor *getDescription(Metadata *type) {
- return cast<ValueMetadata>(type)->getDescription();
- }
-
TryInitializeResult tryInitialize(Metadata *metadata,
PrivateMetadataState state,
PrivateMetadataCompletionContext *context) {
@@ -1377,6 +1378,43 @@
layout.stride = std::max(size_t(1), roundUpToAlignMask(size, alignMask));
}
+
+size_t swift::swift_getTupleTypeLayout2(TypeLayout *result,
+ const TypeLayout *elt0,
+ const TypeLayout *elt1) {
+ const TypeLayout *elts[] = { elt0, elt1 };
+ uint32_t offsets[2];
+ swift_getTupleTypeLayout(result, offsets,
+ TupleTypeFlags().withNumElements(2), elts);
+ assert(offsets[0] == 0);
+ return offsets[1];
+}
+
+OffsetPair swift::swift_getTupleTypeLayout3(TypeLayout *result,
+ const TypeLayout *elt0,
+ const TypeLayout *elt1,
+ const TypeLayout *elt2) {
+ const TypeLayout *elts[] = { elt0, elt1, elt2 };
+ uint32_t offsets[3];
+ swift_getTupleTypeLayout(result, offsets,
+ TupleTypeFlags().withNumElements(3), elts);
+ assert(offsets[0] == 0);
+ return {offsets[1], offsets[2]};
+}
+
+void swift::swift_getTupleTypeLayout(TypeLayout *result,
+ uint32_t *elementOffsets,
+ TupleTypeFlags flags,
+ const TypeLayout * const *elements) {
+ *result = TypeLayout();
+ performBasicLayout(*result, elements, flags.getNumElements(),
+ [](const TypeLayout *elt) { return elt; },
+ [elementOffsets](size_t i, const TypeLayout *elt, size_t offset) {
+ if (elementOffsets)
+ elementOffsets[i] = uint32_t(offset);
+ });
+}
+
MetadataResponse
swift::swift_getTupleTypeMetadata(MetadataRequest request,
TupleTypeFlags flags,
@@ -1600,6 +1638,37 @@
/***************************************************************************/
/*** Nominal type descriptors **********************************************/
/***************************************************************************/
+
+namespace {
+ /// A class encapsulating everything interesting about the identity of
+ /// a type context *except* the identity of the parent context.
+ class TypeContextIdentity {
+ StringRef Name;
+ public:
+ explicit TypeContextIdentity(const TypeContextDescriptor *type) {
+ // Use the name of the type context.
+ Name = type->Name.get();
+
+ // If this is a synthesized entity, include the related entity tag.
+ if (type->isSynthesizedRelatedEntity()) {
+ auto tag = type->getSynthesizedDeclRelatedEntityTag();
+ assert(Name.end() + 1 == tag.begin());
+
+ // The length computation needs to include the \0 at the
+ // end of the name.
+ Name = StringRef(Name.begin(), Name.size() + tag.size() + 1);
+ }
+ }
+
+ bool operator==(const TypeContextIdentity &other) const {
+ return Name == other.Name;
+ }
+ int compare(const TypeContextIdentity &other) const {
+ return Name.compare(other.Name);
+ }
+ };
+}
+
bool swift::equalContexts(const ContextDescriptor *a,
const ContextDescriptor *b)
{
@@ -1640,20 +1709,7 @@
&& kind <= ContextDescriptorKind::Type_Last) {
auto typeA = cast<TypeContextDescriptor>(a);
auto typeB = cast<TypeContextDescriptor>(b);
- if (strcmp(typeA->Name.get(), typeB->Name.get()) != 0)
- return false;
-
- // A synthesized entity has to match the related entity tag too.
- if (typeA->isSynthesizedRelatedEntity()) {
- if (!typeB->isSynthesizedRelatedEntity())
- return false;
-
- if (typeA->getSynthesizedDeclRelatedEntityTag()
- != typeB->getSynthesizedDeclRelatedEntityTag())
- return false;
- }
-
- return true;
+ return TypeContextIdentity(typeA) == TypeContextIdentity(typeB);
}
// Otherwise, this runtime doesn't know anything about this context kind.
@@ -3097,147 +3153,122 @@
/*** Foreign types *********************************************************/
/***************************************************************************/
-namespace {
- /// A reference to a context descriptor, used as a uniquing key.
- struct ContextDescriptorKey {
- const TypeContextDescriptor *Data;
- };
-} // end anonymous namespace
-
-template <>
-struct llvm::DenseMapInfo<ContextDescriptorKey> {
- static ContextDescriptorKey getEmptyKey() {
- return ContextDescriptorKey{(const TypeContextDescriptor*) 0};
- }
- static ContextDescriptorKey getTombstoneKey() {
- return ContextDescriptorKey{(const TypeContextDescriptor*) 1};
- }
- static unsigned getHashValue(ContextDescriptorKey val) {
- if ((uintptr_t)val.Data <= 1) {
- return llvm::hash_value(val.Data);
- }
-
- // Hash by name.
- // In full generality, we'd get a better hash by walking up the entire
- // descriptor tree and hashing names all along the way, and we'd be faster
- // if we special cased unique keys by hashing pointers. In practice, this
- // is only used to unique foreign metadata records, which only ever appear
- // in the "C" or "ObjC" special context, and are never unique.
-
- // llvm::hash_value(StringRef) is, unfortunately, defined out of
- // line in a library we otherwise would not need to link against.
- StringRef name(val.Data->Name.get());
- return llvm::hash_combine_range(name.begin(), name.end());
- }
- static bool isEqual(ContextDescriptorKey lhs, ContextDescriptorKey rhs) {
- if ((uintptr_t)lhs.Data <= 1 || (uintptr_t)rhs.Data <= 1) {
- return lhs.Data == rhs.Data;
- }
- return equalContexts(lhs.Data, rhs.Data);
- }
-};
-
// We use a DenseMap over what are essentially StringRefs instead of a
// StringMap because we don't need to actually copy the string.
namespace {
-struct ForeignTypeState {
- Mutex Lock;
- ConditionVariable InitializationWaiters;
- llvm::DenseMap<ContextDescriptorKey, const ForeignTypeMetadata *> Types;
-};
-} // end anonymous namespace
-static Lazy<ForeignTypeState> ForeignTypes;
+static const TypeContextDescriptor *
+getForeignTypeDescription(Metadata *metadata) {
+ if (auto foreignClass = dyn_cast<ForeignClassMetadata>(metadata))
+ return foreignClass->getDescription();
+ return cast<ValueMetadata>(metadata)->getDescription();
+}
-const ForeignTypeMetadata *
-swift::swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique) {
- // Fast path: check the invasive cache.
- auto cache = nonUnique->getCacheValue();
- if (cache.isInitialized()) {
- return cache.getCachedUniqueMetadata();
+class ForeignMetadataCacheEntry
+ : public MetadataCacheEntryBase<ForeignMetadataCacheEntry, /*spurious*/ int> {
+
+ Metadata *Value;
+
+ friend MetadataCacheEntryBase;
+ ValueType getValue() {
+ return Value;
+ }
+ void setValue(ValueType value) {
+ swift_runtime_unreachable("should never be called");
}
- // Okay, check the global map.
- auto &foreignTypes = ForeignTypes.get();
- ContextDescriptorKey key{nonUnique->getTypeContextDescriptor()};
- assert(key.Data
- && "all foreign metadata should have a type context descriptor");
- bool hasInit = cache.hasInitializationFunction();
+public:
+ static const char *getName() { return "ForeignMetadataCache"; }
- const ForeignTypeMetadata *uniqueMetadata;
- bool inserted;
+ template <class... Args>
+ ForeignMetadataCacheEntry(const TypeContextDescriptor *description,
+ MetadataRequest request, Metadata *candidate)
+ : Value(candidate) {
+ // Remember that the metadata is still just a candidate until this
+ // is actually successfully installed in the concurrent map.
- // A helper function to find the current entry for the key using the
- // saved iterator if it's still valid. This should only be called
- // while the lock is held.
- decltype(foreignTypes.Types.begin()) savedIterator;
- size_t savedSize = 0;
- auto getCurrentEntry = [&]() -> const ForeignTypeMetadata *& {
- // The iterator may have been invalidated if the size of the map
- // has changed since the last lookup.
- if (foreignTypes.Types.size() != savedSize) {
- savedSize = foreignTypes.Types.size();
- savedIterator = foreignTypes.Types.find(key);
- assert(savedIterator != foreignTypes.Types.end() &&
- "entries cannot be removed from foreign types metadata map");
- }
- return savedIterator->second;
- };
+ auto &init = description->getForeignMetadataInitialization();
- {
- ScopedLock guard(foreignTypes.Lock);
-
- // Try to create an entry in the map. The initial value of the entry
- // is our copy of the metadata unless it has an initialization function,
- // in which case we have to insert null as a placeholder to tell others
- // to wait while we call the initializer.
- auto valueToInsert = (hasInit ? nullptr : nonUnique);
- auto insertResult = foreignTypes.Types.insert({key, valueToInsert});
- inserted = insertResult.second;
- savedIterator = insertResult.first;
- savedSize = foreignTypes.Types.size();
- uniqueMetadata = savedIterator->second;
-
- // If we created the entry, then the unique metadata is our copy.
- if (inserted) {
- uniqueMetadata = nonUnique;
-
- // If we didn't create the entry, but it's null, then we have to wait
- // until it becomes non-null.
+ PrivateMetadataState state;
+ if (!init.CompletionFunction) {
+ if (areAllTransitiveMetadataComplete_cheap(candidate)) {
+ state = PrivateMetadataState::Complete;
+ } else {
+ state = PrivateMetadataState::NonTransitiveComplete;
+ }
} else {
- while (uniqueMetadata == nullptr) {
- foreignTypes.Lock.wait(foreignTypes.InitializationWaiters);
- uniqueMetadata = getCurrentEntry();
+ state = inferStateForMetadata(candidate);
+ }
+
+ flagAllocatedDuringConstruction(state);
+ }
+
+ enum : bool { MayFlagAllocatedDuringConstruction = true };
+
+ const TypeContextDescriptor *getDescription() const {
+ return getForeignTypeDescription(Value);
+ }
+
+ template <class... Args>
+ static size_t numTrailingObjects(OverloadToken<int>, Args &&...) {
+ return 0;
+ }
+
+ intptr_t getKeyIntValueForDump() const {
+ return reinterpret_cast<intptr_t>(getDescription()->Name.get());
+ }
+
+ int compareWithKey(const TypeContextDescriptor *key) const {
+ // We can just compare unparented type-context identities because
+ // we assume that foreign types don't have interesting parenting
+ // structure.
+ return TypeContextIdentity(key)
+ .compare(TypeContextIdentity(getDescription()));
+ }
+
+ AllocationResult allocate(Metadata *candidate) {
+ swift_runtime_unreachable(
+ "always flags allocation complete during construction");
+ }
+
+ TryInitializeResult tryInitialize(Metadata *metadata,
+ PrivateMetadataState state,
+ PrivateMetadataCompletionContext *ctxt) {
+ assert(state != PrivateMetadataState::Complete);
+
+ // Finish the completion function.
+ auto &init = getDescription()->getForeignMetadataInitialization();
+ if (init.CompletionFunction) {
+ // Try to complete the metadata's instantiation.
+ auto dependency =
+ init.CompletionFunction(metadata, &ctxt->Public, nullptr);
+
+ // If this failed with a dependency, infer the current metadata state
+ // and return.
+ if (dependency) {
+ return { inferStateForMetadata(metadata), dependency };
}
}
+
+ // Check for transitive completeness.
+ if (auto dependency = checkTransitiveCompleteness(metadata)) {
+ return { PrivateMetadataState::NonTransitiveComplete, dependency };
+ }
+
+ // We're done.
+ return { PrivateMetadataState::Complete, MetadataDependency() };
}
+};
- // If we inserted the entry and there's an initialization function,
- // call it. This has to be done with the lock dropped.
- if (inserted && hasInit) {
- nonUnique->getInitializationFunction()(nonUnique);
+} // end anonymous namespace
- // Update the cache entry:
+static Lazy<MetadataCache<ForeignMetadataCacheEntry, false>> ForeignMetadata;
- // - Reacquire the lock.
- ScopedLock guard(foreignTypes.Lock);
-
- // - Change the entry.
- auto &entry = getCurrentEntry();
- assert(entry == nullptr);
- entry = nonUnique;
-
- // - Notify waiters.
- foreignTypes.InitializationWaiters.notifyAll();
- }
-
- // Remember the unique result in the invasive cache. We don't want
- // to do this until after the initialization completes; otherwise,
- // it will be possible for code to fast-path through this function
- // too soon.
- nonUnique->setCachedUniqueMetadata(uniqueMetadata);
-
- return uniqueMetadata;
+MetadataResponse
+swift::swift_getForeignTypeMetadata(MetadataRequest request,
+ ForeignTypeMetadata *candidate) {
+ auto description = getForeignTypeDescription(candidate);
+ return ForeignMetadata->getOrInsert(description, request, candidate).second;
}
/// Unique-ing of foreign types' witness tables.
@@ -3628,16 +3659,25 @@
if (tupleMetadata->NumElements == 0)
return std::move(callbacks).forOtherMetadata(tupleMetadata);
return std::move(callbacks).forTupleMetadata(tupleMetadata);
+ } else if (auto foreignClass = dyn_cast<ForeignClassMetadata>(metadata)) {
+ return std::move(callbacks).forForeignMetadata(foreignClass,
+ foreignClass->getDescription());
} else {
return std::move(callbacks).forOtherMetadata(metadata);
}
if (!description->isGeneric()) {
- if (description->hasInPlaceMetadataInitialization()) {
+ switch (description->getMetadataInitialization()) {
+ case TypeContextDescriptorFlags::NoMetadataInitialization:
+ return std::move(callbacks).forOtherMetadata(metadata);
+
+ case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+ return std::move(callbacks).forForeignMetadata(metadata, description);
+
+ case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
return std::move(callbacks).forInPlaceMetadata(description);
}
-
- return std::move(callbacks).forOtherMetadata(metadata);
+ swift_runtime_unreachable("bad metadata initialization kind");
}
auto &generics = description->getFullGenericContextHeader();
@@ -3665,6 +3705,11 @@
return cache.enqueue(key, QueueEntry, Dependency);
}
+ bool forForeignMetadata(const Metadata *metadata,
+ const TypeContextDescriptor *description) {
+ return ForeignMetadata.get().enqueue(description, QueueEntry, Dependency);
+ }
+
bool forInPlaceMetadata(const TypeContextDescriptor *description) && {
return InPlaceMetadata.get().enqueue(description, QueueEntry, Dependency);
}
@@ -3692,6 +3737,11 @@
cache.resumeInitialization(key, QueueEntry);
}
+ void forForeignMetadata(const Metadata *metadata,
+ const TypeContextDescriptor *description) {
+ ForeignMetadata.get().resumeInitialization(description, QueueEntry);
+ }
+
void forInPlaceMetadata(const TypeContextDescriptor *description) && {
InPlaceMetadata.get().resumeInitialization(description, QueueEntry);
}
@@ -3722,6 +3772,11 @@
return cache.await(key, Request);
}
+ MetadataResponse forForeignMetadata(const Metadata *metadata,
+ const TypeContextDescriptor *description) {
+ return ForeignMetadata.get().await(description, Request);
+ }
+
MetadataResponse forInPlaceMetadata(
const TypeContextDescriptor *description) && {
return InPlaceMetadata.get().await(description, Request);
@@ -3767,6 +3822,14 @@
return false;
+ // Foreign classes require their superclass to be transitively complete.
+ } else if (auto foreignClassType = dyn_cast<ForeignClassMetadata>(type)) {
+ if (auto super = foreignClassType->Superclass) {
+ if (predicate(super))
+ return true;
+ }
+ return false;
+
// Other types do not have transitive completeness requirements.
} else {
return false;
@@ -3798,7 +3861,7 @@
/// Do a quick check to see if all the transitive type metadata are complete.
static bool
areAllTransitiveMetadataComplete_cheap(const Metadata *type) {
- // Look for any transitive metadata that's incomplete.
+ // Look for any transitive metadata that's *incomplete*.
return !findAnyTransitiveMetadata(type, [](const Metadata *type) {
struct IsIncompleteCallbacks {
bool forGenericMetadata(const Metadata *type,
@@ -3810,6 +3873,17 @@
return true;
}
+ bool forForeignMetadata(const Metadata *metadata,
+ const TypeContextDescriptor *description) {
+ // If the type doesn't have a completion function, we can assume
+ // it's transitively complete by construction.
+ if (!description->getForeignMetadataInitialization().CompletionFunction)
+ return false;
+
+ // TODO: it might be worth doing a quick check against the cache here.
+ return false;
+ }
+
bool forInPlaceMetadata(const TypeContextDescriptor *description) && {
// TODO: this could be cheap enough.
return true;
@@ -3972,6 +4046,11 @@
return cache.checkDependency(key, Requirement);
}
+ MetadataDependency forForeignMetadata(const Metadata *metadata,
+ const TypeContextDescriptor *description) {
+ return ForeignMetadata.get().checkDependency(description, Requirement);
+ }
+
MetadataDependency forInPlaceMetadata(
const TypeContextDescriptor *description) && {
return InPlaceMetadata.get().checkDependency(description, Requirement);
diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h
index fad75ec..e87d4d9 100644
--- a/stdlib/public/runtime/MetadataCache.h
+++ b/stdlib/public/runtime/MetadataCache.h
@@ -787,6 +787,31 @@
Optional<Status>
beginAllocation(ConcurrencyControl &concurrency, MetadataRequest request,
Args &&...args) {
+ // Returning a non-None value here will preempt initialization, so we
+ // should only do it if we're reached PrivateMetadataState::Complete.
+
+ // Fast-track out if flagAllocatedDuringConstruction was called.
+ if (Impl::MayFlagAllocatedDuringConstruction) {
+ // This can be a relaxed load because beginAllocation is called on the
+ // same thread that called the constructor.
+ auto trackingInfo =
+ PrivateMetadataTrackingInfo(
+ TrackingInfo.load(std::memory_order_relaxed));
+
+ // If we've already allocated metadata, we can skip the rest of
+ // allocation.
+ if (trackingInfo.hasAllocatedMetadata()) {
+ // Skip initialization, too, if we're fully complete.
+ if (trackingInfo.isComplete()) {
+ return Status{asImpl().getValue(), MetadataState::Complete};
+
+ // Otherwise go directly to the initialization phase.
+ } else {
+ return None;
+ }
+ }
+ }
+
// Allocate the metadata.
AllocationResult allocationResult =
asImpl().allocate(std::forward<Args>(args)...);
@@ -804,6 +829,23 @@
return None;
}
+ enum : bool { MayFlagAllocatedDuringConstruction = false };
+
+ /// As an alternative to allocate(), flag that allocation was
+ /// completed within the entry's constructor. This should only be
+ /// called from within the constructor.
+ ///
+ /// If this is called, allocate() will not be called.
+ ///
+ /// If this is called, the subclass must define
+ /// enum { MayFlagAllocatedDuringConstruction = true };
+ void flagAllocatedDuringConstruction(PrivateMetadataState state) {
+ assert(Impl::MayFlagAllocatedDuringConstruction);
+ assert(state != PrivateMetadataState::Allocating);
+ TrackingInfo.store(PrivateMetadataTrackingInfo(state).getRawValue(),
+ std::memory_order_relaxed);
+ }
+
/// Begin initialization immediately after allocation.
template <class... Args>
Status beginInitialization(ConcurrencyControl &concurrency,
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index f18dfd5..2c29082 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -71,19 +71,19 @@
};
switch (auto kind = getTypeKind()) {
- case TypeMetadataRecordKind::Reserved:
- printf("unknown (reserved)");
- break;
+ case TypeReferenceKind::DirectObjCClassName:
+ printf("direct Objective-C class name %s", getDirectObjCClassName());
+ break;
- case TypeMetadataRecordKind::IndirectObjCClass:
- printf("indirect Objective-C class %s",
- class_getName(*getIndirectObjCClass()));
- break;
-
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
- printf("unique nominal type descriptor %s", symbolName(getTypeContextDescriptor()));
- break;
+ case TypeReferenceKind::IndirectObjCClass:
+ printf("indirect Objective-C class %s",
+ class_getName(*getIndirectObjCClass()));
+ break;
+
+ case TypeReferenceKind::DirectNominalTypeDescriptor:
+ case TypeReferenceKind::IndirectNominalTypeDescriptor:
+ printf("unique nominal type descriptor %s", symbolName(getTypeContextDescriptor()));
+ break;
}
printf(" => ");
@@ -107,8 +107,8 @@
#ifndef NDEBUG
template<> void ProtocolConformanceDescriptor::verify() const {
auto typeKind = unsigned(getTypeKind());
- assert(((unsigned(TypeMetadataRecordKind::First_Kind) <= typeKind) &&
- (unsigned(TypeMetadataRecordKind::Last_Kind) >= typeKind)) &&
+ assert(((unsigned(TypeReferenceKind::First_Kind) <= typeKind) &&
+ (unsigned(TypeReferenceKind::Last_Kind) >= typeKind)) &&
"Corrupted type metadata record kind");
auto confKind = unsigned(getConformanceKind());
@@ -119,6 +119,26 @@
}
#endif
+#if SWIFT_OBJC_INTEROP
+template <>
+const ClassMetadata *TypeReference::getObjCClass(TypeReferenceKind kind) const {
+ switch (kind) {
+ case TypeReferenceKind::IndirectObjCClass:
+ return *getIndirectObjCClass(kind);
+
+ case TypeReferenceKind::DirectObjCClassName:
+ return reinterpret_cast<const ClassMetadata *>(
+ objc_lookUpClass(getDirectObjCClassName(kind)));
+
+ case TypeReferenceKind::DirectNominalTypeDescriptor:
+ case TypeReferenceKind::IndirectNominalTypeDescriptor:
+ return nullptr;
+ }
+
+ swift_runtime_unreachable("Unhandled TypeReferenceKind in switch.");
+}
+#endif
+
/// Take the type reference inside a protocol conformance record and fetch the
/// canonical metadata pointer for the type it refers to.
/// Returns nil for universal or generic type references.
@@ -126,22 +146,23 @@
const Metadata *
ProtocolConformanceDescriptor::getCanonicalTypeMetadata() const {
switch (getTypeKind()) {
- case TypeMetadataRecordKind::Reserved:
- return nullptr;
- case TypeMetadataRecordKind::IndirectObjCClass:
+ case TypeReferenceKind::IndirectObjCClass:
+ case TypeReferenceKind::DirectObjCClassName:
+#if SWIFT_OBJC_INTEROP
// The class may be ObjC, in which case we need to instantiate its Swift
// metadata. The class additionally may be weak-linked, so we have to check
// for null.
- if (auto *ClassMetadata = *getIndirectObjCClass())
- return getMetadataForClass(ClassMetadata);
+ if (auto cls = TypeRef.getObjCClass(getTypeKind()))
+ return getMetadataForClass(cls);
+#endif
return nullptr;
-
- case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
- case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
+
+ case TypeReferenceKind::DirectNominalTypeDescriptor:
+ case TypeReferenceKind::IndirectNominalTypeDescriptor:
return nullptr;
}
- swift_runtime_unreachable("Unhandled TypeMetadataRecordKind in switch.");
+ swift_runtime_unreachable("Unhandled TypeReferenceKind in switch.");
}
template<>
@@ -601,9 +622,9 @@
// An accessor function might still be necessary even if the witness table
// can be shared.
} else if (descriptor.getTypeKind()
- == TypeMetadataRecordKind::DirectNominalTypeDescriptor ||
+ == TypeReferenceKind::DirectNominalTypeDescriptor ||
descriptor.getTypeKind()
- == TypeMetadataRecordKind::IndirectNominalTypeDescriptor) {
+ == TypeReferenceKind::IndirectNominalTypeDescriptor) {
auto R = descriptor.getTypeContextDescriptor();
auto P = descriptor.getProtocol();
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
index ec62bb1..402608c 100644
--- a/stdlib/public/runtime/ReflectionMirror.mm
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -660,7 +660,7 @@
// func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
@@ -668,7 +668,7 @@
}
// func _getChildCount<T>(_: T, type: Any.Type) -> Int
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
intptr_t swift_reflectionMirror_count(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
@@ -688,7 +688,7 @@
// outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
// outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
// ) -> Any
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
AnyReturn swift_reflectionMirror_subscript(OpaqueValue *value, const Metadata *type,
intptr_t index,
const char **outName,
@@ -701,19 +701,19 @@
#pragma clang diagnostic pop
// func _getDisplayStyle<T>(_: T) -> CChar
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
char swift_reflectionMirror_displayStyle(OpaqueValue *value, const Metadata *T) {
return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->displayStyle(); });
}
// func _getEnumCaseName<T>(_ value: T) -> UnsafePointer<CChar>?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const char *swift_EnumCaseName(OpaqueValue *value, const Metadata *T) {
return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->enumCaseName(); });
}
// func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const char *swift_OpaqueSummary(const Metadata *T) {
switch (T->getKind()) {
case MetadataKind::Class:
@@ -749,7 +749,7 @@
#if SWIFT_OBJC_INTEROP
// func _getQuickLookObject<T>(_: T) -> AnyObject?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
id swift_reflectionMirror_quickLookObject(OpaqueValue *value, const Metadata *T) {
return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->quickLookObject(); });
}
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index 04ea4ba..41d37f4 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -177,7 +177,7 @@
class_getInstanceSize(cls), mask));
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
NSString *swift_stdlib_getDescription(OpaqueValue *value,
const Metadata *type);
diff --git a/stdlib/public/stubs/CommandLine.cpp b/stdlib/public/stubs/CommandLine.cpp
index 654d619..f206c50 100644
--- a/stdlib/public/stubs/CommandLine.cpp
+++ b/stdlib/public/stubs/CommandLine.cpp
@@ -33,7 +33,7 @@
static char **_swift_stdlib_ProcessOverrideUnsafeArgv = nullptr;
static int _swift_stdlib_ProcessOverrideUnsafeArgc = 0;
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void _swift_stdlib_overrideUnsafeArgvArgc(char **argv, int argc) {
_swift_stdlib_ProcessOverrideUnsafeArgv = argv;
_swift_stdlib_ProcessOverrideUnsafeArgc = argc;
@@ -45,7 +45,7 @@
extern "C" char ***_NSGetArgv(void);
extern "C" int *_NSGetArgc(void);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
assert(outArgLen != nullptr);
@@ -58,7 +58,7 @@
return *_NSGetArgv();
}
#elif defined(__linux__) || defined(__CYGWIN__)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
assert(outArgLen != nullptr);
@@ -92,7 +92,7 @@
#elif defined (_WIN32)
#include <stdlib.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
assert(outArgLen != nullptr);
@@ -111,7 +111,7 @@
#include <sys/param.h>
#include <sys/sysctl.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
assert(outArgLen != nullptr);
@@ -156,7 +156,7 @@
return outBuf;
}
#else // __ANDROID__; Add your favorite arch's command line arg grabber here.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
*outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
diff --git a/stdlib/public/stubs/GlobalObjects.cpp b/stdlib/public/stubs/GlobalObjects.cpp
index 323ff9a..2c2836c 100644
--- a/stdlib/public/stubs/GlobalObjects.cpp
+++ b/stdlib/public/stubs/GlobalObjects.cpp
@@ -23,21 +23,21 @@
#include <stdlib.h>
namespace swift {
-// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_INTERFACE?
+// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_API?
// _direct type metadata for Swift._EmptyArrayStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ClassMetadata CLASS_METADATA_SYM(s18_EmptyArrayStorage);
// _direct type metadata for Swift._RawNativeDictionaryStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ClassMetadata CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage);
// _direct type metadata for Swift._RawNativeSetStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ClassMetadata CLASS_METADATA_SYM(s20_RawNativeSetStorage);
} // namespace swift
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
// HeapObject header;
{
@@ -51,7 +51,7 @@
}
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
swift::_SwiftEmptyDictionaryStorage swift::_swiftEmptyDictionaryStorage = {
// HeapObject header;
{
@@ -79,7 +79,7 @@
0 // int entries; (zero'd bits)
};
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
swift::_SwiftEmptySetStorage swift::_swiftEmptySetStorage = {
// HeapObject header;
{
@@ -128,7 +128,7 @@
SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void swift::_swift_instantiateInertHeapObject(void *address,
const HeapMetadata *metadata) {
::new (address) HeapObject{metadata};
diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp
index d0892da..5f95397 100644
--- a/stdlib/public/stubs/LibcShims.cpp
+++ b/stdlib/public/stubs/LibcShims.cpp
@@ -59,12 +59,12 @@
"__swift_mode_t must be defined as equivalent to mode_t in LibcShims.h");
#endif
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void swift::_stdlib_free(void *ptr) {
free(ptr);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int swift::_stdlib_putchar_unlocked(int c) {
#if defined(_WIN32)
return _putc_nolock(c, stdout);
@@ -73,30 +73,30 @@
#endif
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift::_stdlib_fwrite_stdout(const void *ptr,
__swift_size_t size,
__swift_size_t nitems) {
return fwrite(ptr, size, nitems, stdout);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift::_stdlib_strlen(const char *s) {
return strlen(s);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_size_t swift::_stdlib_strlen_unsigned(const unsigned char *s) {
return strlen(reinterpret_cast<const char *>(s));
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int swift::_stdlib_memcmp(const void *s1, const void *s2,
__swift_size_t n) {
return memcmp(s1, s2, n);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_ssize_t
swift::_stdlib_read(int fd, void *buf, __swift_size_t nbyte) {
#if defined(_WIN32)
@@ -106,7 +106,7 @@
#endif
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_ssize_t
swift::_stdlib_write(int fd, const void *buf, __swift_size_t nbyte) {
#if defined(_WIN32)
@@ -116,7 +116,7 @@
#endif
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int swift::_stdlib_close(int fd) {
#if defined(_WIN32)
return _close(fd);
@@ -210,7 +210,7 @@
static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
"__swift_thread_key_t is not a DWORD");
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
void _stdlib_destroyTLS(void *);
static void
@@ -221,7 +221,7 @@
_stdlib_destroyTLS(ptr);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int
swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
void (* _Nullable destructor)(void *)) {
@@ -229,13 +229,13 @@
return *key != FLS_OUT_OF_INDEXES;
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void * _Nullable
swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
return FlsGetValue(key);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
const void * _Nullable value) {
return FlsSetValue(key, const_cast<void *>(value)) == TRUE;
@@ -248,20 +248,20 @@
"fix __swift_pthread_key_t's typedef in LibcShims.h by adding an "
"#if guard and definition for your platform");
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int
swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
void (* _Nullable destructor)(void *)) {
return pthread_key_create(key, destructor);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
void * _Nullable
swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
return pthread_getspecific(key);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
const void * _Nullable value) {
return pthread_setspecific(key, value);
@@ -270,7 +270,7 @@
#if defined(__APPLE__)
#include <malloc/malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
size_t swift::_stdlib_malloc_size(const void *ptr) {
return malloc_size(ptr);
}
@@ -279,19 +279,19 @@
#define _GNU_SOURCE
#endif
#include <malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
size_t swift::_stdlib_malloc_size(const void *ptr) {
return malloc_usable_size(const_cast<void *>(ptr));
}
#elif defined(_WIN32)
#include <malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
size_t swift::_stdlib_malloc_size(const void *ptr) {
return _msize(const_cast<void *>(ptr));
}
#elif defined(__FreeBSD__)
#include <malloc_np.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
size_t swift::_stdlib_malloc_size(const void *ptr) {
return malloc_usable_size(const_cast<void *>(ptr));
}
@@ -305,12 +305,12 @@
return theGlobalMT19937.get();
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_uint32_t swift::_stdlib_cxx11_mt19937() {
return getGlobalMT19937()();
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
__swift_uint32_t
swift::_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
if (upper_bound > 0)
diff --git a/stdlib/public/stubs/MathStubs.cpp b/stdlib/public/stubs/MathStubs.cpp
index 9f8de55..39ac393 100644
--- a/stdlib/public/stubs/MathStubs.cpp
+++ b/stdlib/public/stubs/MathStubs.cpp
@@ -66,7 +66,7 @@
(defined(__linux__) && defined(__s390x__)) || \
(defined(__ANDROID__) && defined(__arm64__))
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ti_int
__muloti4(ti_int a, ti_int b, int* overflow)
{
@@ -120,7 +120,7 @@
// missing. Perhaps relevant bug report:
// FIXME: https://llvm.org/bugs/show_bug.cgi?id=14469
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
di_int
__mulodi4(di_int a, di_int b, int* overflow)
{
@@ -377,14 +377,14 @@
return q.all;
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
tu_int
__udivti3(tu_int a, tu_int b)
{
return __udivmodti4(a, b, NULL);
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
tu_int
__umodti3(tu_int a, tu_int b)
{
@@ -393,7 +393,7 @@
return r;
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ti_int
__divti3(ti_int a, ti_int b)
{
@@ -406,7 +406,7 @@
return (__udivmodti4(a, b, (tu_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
}
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
ti_int
__modti3(ti_int a, ti_int b)
{
diff --git a/stdlib/public/stubs/OptionalBridgingHelper.mm b/stdlib/public/stubs/OptionalBridgingHelper.mm
index 26a81e5..0b019ad 100644
--- a/stdlib/public/stubs/OptionalBridgingHelper.mm
+++ b/stdlib/public/stubs/OptionalBridgingHelper.mm
@@ -88,7 +88,7 @@
/// Return the sentinel object to use to represent `nil` for a given Optional
/// type.
-SWIFT_RUNTIME_STDLIB_INTERFACE SWIFT_CC(swift)
+SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift)
id _swift_Foundation_getOptionalNilSentinelObject(const Metadata *Wrapped) {
// Figure out the depth of optionality we're working with.
unsigned depth = 1;
diff --git a/stdlib/public/stubs/Reflection.mm b/stdlib/public/stubs/Reflection.mm
index 9d46fae..4b88783 100644
--- a/stdlib/public/stubs/Reflection.mm
+++ b/stdlib/public/stubs/Reflection.mm
@@ -16,7 +16,7 @@
#import <Foundation/Foundation.h>
SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
bool _swift_stdlib_NSObject_isKindOfClass(
id _Nonnull object,
NSString * _Nonnull className) {
diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 2624098..009c926 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -111,7 +111,7 @@
return size_t(P - Buffer);
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
uint64_t swift_int64ToString(char *Buffer, size_t BufferLength,
int64_t Value, int64_t Radix,
bool Uppercase) {
@@ -135,7 +135,7 @@
Negative);
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
uint64_t swift_uint64ToString(char *Buffer, intptr_t BufferLength,
uint64_t Value, int64_t Radix,
bool Uppercase) {
@@ -249,19 +249,19 @@
}
#endif
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
uint64_t swift_float32ToString(char *Buffer, size_t BufferLength,
float Value, bool Debug) {
return swift_format_float(Value, Buffer, BufferLength);
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
uint64_t swift_float64ToString(char *Buffer, size_t BufferLength,
double Value, bool Debug) {
return swift_format_double(Value, Buffer, BufferLength);
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
uint64_t swift_float80ToString(char *Buffer, size_t BufferLength,
long double Value, bool Debug) {
#if SWIFT_DTOA_FLOAT80_SUPPORT
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
index 09bee1a..392b0dd 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
@@ -50,7 +50,7 @@
using namespace swift;
% for Class in ('Array', 'Dictionary', 'Set', 'String', 'Enumerator', 'Data', 'IndexSet'):
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
@interface _SwiftNativeNS${Class}Base : NS${Class}
{
@private
@@ -109,7 +109,7 @@
return (lhs == rhs) || [lhs isEqual:rhs];
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
int32_t swift_stdlib_compareNSStringDeterministicUnicodeCollation(
NSString *lhs, NSString *rhs) {
// 'kCFCompareNonliteral' actually means "normalize to NFD".
@@ -117,7 +117,7 @@
(__bridge CFStringRef)rhs, kCFCompareNonliteral);
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
int32_t
swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr(void *Lhs,
void *Rhs) {
@@ -130,7 +130,7 @@
return Result;
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
size_t
swift_stdlib_CFStringHashCString(const uint8_t *bytes, CFIndex len) {
CFHashCode Result = CFStringHashCString(bytes, len);
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m b/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
index 6dc6b45..e84e8c9 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
@@ -48,7 +48,7 @@
#define AUTORELEASEPOOL
#endif
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
size_t swift_stdlib_NSStringHashValue(NSString *str,
bool isASCII) {
AUTORELEASEPOOL {
@@ -56,7 +56,7 @@
}
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
size_t
swift_stdlib_NSStringHashValuePointer(void *opaque, bool isASCII) {
NSString __unsafe_unretained *str =
@@ -66,7 +66,7 @@
}
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
NS_RETURNS_RETAINED NSString *
swift_stdlib_NSStringLowercaseString(NSString *str) {
AUTORELEASEPOOL {
@@ -74,7 +74,7 @@
}
}
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
NS_RETURNS_RETAINED NSString *
swift_stdlib_NSStringUppercaseString(NSString *str) {
AUTORELEASEPOOL {
diff --git a/stdlib/public/stubs/UnicodeNormalization.cpp b/stdlib/public/stubs/UnicodeNormalization.cpp
index a3a29ee..896f318 100644
--- a/stdlib/public/stubs/UnicodeNormalization.cpp
+++ b/stdlib/public/stubs/UnicodeNormalization.cpp
@@ -191,7 +191,7 @@
ptr_cast<UErrorCode>(status));
}
-SWIFT_RUNTIME_STDLIB_INTERFACE swift::__swift_stdlib_UText *
+SWIFT_RUNTIME_STDLIB_API swift::__swift_stdlib_UText *
swift::__swift_stdlib_utext_openUTF8(__swift_stdlib_UText *ut,
const char *s, int64_t len,
__swift_stdlib_UErrorCode *status) {
@@ -200,7 +200,7 @@
ptr_cast<UErrorCode>(status)));
}
-SWIFT_RUNTIME_STDLIB_INTERFACE swift::__swift_stdlib_UText *
+SWIFT_RUNTIME_STDLIB_API swift::__swift_stdlib_UText *
swift::__swift_stdlib_utext_openUChars(__swift_stdlib_UText *ut,
const __swift_stdlib_UChar *s,
int64_t len,
diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift
index a23fb0a..7422423 100644
--- a/test/Constraints/array_literal.swift
+++ b/test/Constraints/array_literal.swift
@@ -340,3 +340,19 @@
let _: PArray<Int> = [i, i, i]
let _: PArray<String> = [s, s, s] // expected-error{{cannot convert value of type '[String]' to specified type 'PArray<String>'}}
}
+
+
+// SR-8385
+enum SR8385: ExpressibleByStringLiteral {
+ case text(String)
+ init(stringLiteral value: String) {
+ self = .text(value)
+ }
+}
+
+func testSR8385() {
+ let _: [SR8385] = [SR8385("hello")]
+ let _: [SR8385] = [.text("hello")]
+ let _: [SR8385] = ["hello", SR8385.text("world")]
+ let _: [SR8385] = ["hello", .text("world")]
+}
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 734d5bb..17e7623 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -351,3 +351,57 @@
if case One.E.SomeError = error {} // expected-error{{generic enum type 'One.E' is ambiguous without explicit generic parameters when matching value of type 'Error'}}
}
}
+
+// SR-8347
+// constrain initializer expressions of optional some pattern bindings to be optional
+func test8347() -> String {
+ struct C {
+ subscript (s: String) -> String? {
+ return ""
+ }
+ subscript (s: String) -> [String] {
+ return [""]
+ }
+
+ func f() -> String? {
+ return ""
+ }
+ func f() -> Int {
+ return 3
+ }
+
+ func g() -> String {
+ return ""
+ }
+
+ func h() -> String {
+ return ""
+ }
+ func h() -> Double {
+ return 3.0
+ }
+ func h() -> Int? { //expected-note{{found this candidate}}
+ return 2
+ }
+ func h() -> Float? { //expected-note{{found this candidate}}
+ return nil
+ }
+
+ }
+
+ let c = C()
+ if let s = c[""] {
+ return s
+ }
+ if let s = c.f() {
+ return s
+ }
+ if let s = c.g() { //expected-error{{initializer for conditional binding must have Optional type, not 'String'}}
+ return s
+ }
+ if let s = c.h() { //expected-error{{ambiguous use of 'h()'}}
+ return s
+ }
+}
+
+
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 74a4322..3ff3ec0 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -413,3 +413,15 @@
// with the typealias uncommented you do not get a crash.
// typealias BaseElement = Element.BaseElement
}
+
+// SR-8337
+struct Foo<Bar> {}
+
+protocol P {
+ associatedtype A
+ var foo: Foo<A> { get }
+}
+
+extension Foo: P where Bar: P {
+ var foo: Foo { return self }
+}
diff --git a/test/IRGen/cf.sil b/test/IRGen/cf.sil
index 3dedb89..7ad9c7f 100644
--- a/test/IRGen/cf.sil
+++ b/test/IRGen/cf.sil
@@ -9,26 +9,19 @@
// CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type
// CHECK: [[OBJC:%objc_object]] = type
-// CHECK-32: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-32-SAME: i32 0,
-// CHECK-32-SAME: i8** @"$SBOWV", i32 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null, i8* null, i8* null }>
-
-// CHECK-64: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-64-SAME: i64 0,
-// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null, i8* null, i8* null }>
+// CHECK: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden constant <{ {{.*}} }> <{ i8** @"$SBOWV", [[INT]] 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null }>
// CHECK: [[MUTABLE_REFRIGERATOR_NAME:@.*]] = private constant [25 x i8] c"CCMutableRefrigeratorRef\00"
// CHECK-64: @"$SSo24CCMutableRefrigeratorRefaMn" = linkonce_odr hidden constant
-// -- is imported C typedef, is class, is nonunique
-// CHECK-64-SAME: <i32 0x0011_0010>
+// -- is imported C typedef, foreign init, reflectable, is class, is nonunique
+// CHECK-64-SAME: <i32 0x0015_0010>
// CHECK-64-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
+// CHECK-64-SAME: @"$SSo24CCMutableRefrigeratorRefaMa"
+// CHECK-64-SAME: @"$SSo24CCMutableRefrigeratorRefaMr"
// CHECK-64: @"$SSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-64-SAME: @initialize_metadata_CCMutableRefrigerator
-// CHECK-64-SAME: i32 0,
-// CHECK-64-SAME: i64 1,
-// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo24CCMutableRefrigeratorRefaMn", [[TYPE]]* bitcast{{.*}}@"$SSo17CCRefrigeratorRefaN{{.*}} to %swift.type*), i8* null, i8* null, i8* null }>
+// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
sil_stage canonical
@@ -46,7 +39,8 @@
return %5 : $()
}
-// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @call_generic([[REFRIGERATOR]]*, [[MUTABLE_REFRIGERATOR]]*) {{.*}} {
+// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @call_generic
+// CHECK-SAME: ([[REFRIGERATOR]]*, [[MUTABLE_REFRIGERATOR]]*) {{.*}} {
// CHECK: [[T0:%.*]] = bitcast [[REFRIGERATOR]]* %0 to [[OBJC]]*
// CHECK-NEXT: [[T1:%.*]] = call swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"([[INT]] 0)
// CHECK-NEXT: [[T2:%.*]] = extractvalue %swift.metadata_response [[T1]], 0
@@ -57,14 +51,15 @@
// CHECK-NEXT: call swiftcc void @generic_function([[OBJC]]* [[T0]], [[TYPE]]* [[T2]])
// CHECK-NEXT: ret void
-// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"(
-// CHECK-32: call [[TYPE]]* @swift_getForeignTypeMetadata([[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), i32 8) to [[TYPE]]*))
-// CHECK-64: call [[TYPE]]* @swift_getForeignTypeMetadata([[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), i64 16) to [[TYPE]]*))
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"(
+// CHECK-32: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), [[INT]] 4) to [[TYPE]]*))
+// CHECK-64: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), [[INT]] 8) to [[TYPE]]*))
-// CHECK: define private void @initialize_metadata_CCMutableRefrigerator(%swift.type*)
-// CHECK-64: [[T0:%.*]] = bitcast %swift.type* %0 to i8**
-// CHECK-64: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[T0]], i32 2
-// CHECK-64: [[T2:%.*]] = bitcast i8** [[T1]] to %swift.type**
-// CHECK-64: [[T3:%.*]] = load %swift.type*, %swift.type** [[T2]]
-// CHECK-64: [[T4:%.*]] = call %swift.type* @swift_getForeignTypeMetadata(%swift.type* [[T3]])
-// CHECK-64: store %swift.type* [[T4]], %swift.type** [[T2]]
+// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$SSo24CCMutableRefrigeratorRefaMr"(%swift.type*, i8*, i8**)
+// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"([[INT]] 255)
+// CHECK-NEXT: [[T1:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
+// CHECK-NEXT: extractvalue %swift.metadata_response [[T0]], 1
+// CHECK-NEXT: [[T2:%.*]] = bitcast %swift.type* %0 to %swift.type**
+// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i32 2
+// CHECK-NEXT: store %swift.type* [[T1]], %swift.type** [[T3]], align
+// CHECK-NEXT: ret %swift.metadata_response zeroinitializer
diff --git a/test/IRGen/class_metadata.swift b/test/IRGen/class_metadata.swift
index f885543..e958903 100644
--- a/test/IRGen/class_metadata.swift
+++ b/test/IRGen/class_metadata.swift
@@ -104,8 +104,8 @@
// CHECK: [[D_NAME:@.*]] = private constant [2 x i8] c"D\00"
// CHECK-LABEL: @"$S14class_metadata1DCMn" =
-// Flags. 268501072 == 0x1001_0050 == Reflectable | IndirectSuperclass | Unique | Class
-// CHECK-SAME: i32 268501072,
+// Flags. 67174480 == 0x0401_0050 == Reflectable | IndirectSuperclass | Unique | Class
+// CHECK-SAME: i32 67174480,
// Parent.
// CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
// Name.
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e53779a..5939a06 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -32,7 +32,7 @@
// CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}{{(dllexport )?}}constant <{{.*}}> <{
// -- flags: class, unique, reflectable, has vtable, has resilient superclass
-// CHECK-SAME: <i32 0xD001_0050>
+// CHECK-SAME: <i32 0xC401_0050>
// -- name:
// CHECK-SAME: [15 x i8]* [[RESILIENTCHILD_NAME]]
// -- num fields
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index eeefa58..7fef35f 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -331,21 +331,27 @@
}
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$S15enum_resilience24EnumWithResilientPayloadOMr"(%swift.type*, i8*, i8**)
+// CHECK: [[TUPLE_LAYOUT:%.*]] = alloca %swift.full_type_layout
// CHECK: [[SIZE_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
// CHECK-NEXT: [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[SIZE_RESPONSE]], 0
// CHECK-NEXT: [[SIZE_STATE:%.*]] = extractvalue %swift.metadata_response [[SIZE_RESPONSE]], 1
// CHECK-NEXT: [[T0:%.*]] = icmp ule [[INT]] [[SIZE_STATE]], 63
// CHECK-NEXT: br i1 [[T0]], label %[[SATISFIED1:.*]], label
// CHECK: [[SATISFIED1]]:
-// CHECK: [[TUPLE_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @swift_getTupleTypeMetadata2([[INT]] 319, %swift.type* [[SIZE_METADATA]], %swift.type* [[SIZE_METADATA]], i8* null, i8** null)
-// CHECK-NEXT: [[TUPLE_METADATA:%.*]] = extractvalue %swift.metadata_response [[TUPLE_RESPONSE]], 0
-// CHECK-NEXT: [[TUPLE_STATE:%.*]] = extractvalue %swift.metadata_response [[TUPLE_RESPONSE]], 1
-// CHECK-NEXT: [[T0:%.*]] = icmp ule [[INT]] [[TUPLE_STATE]], 63
-// CHECK-NEXT: br i1 [[T0]], label %[[SATISFIED2:.*]], label
-// CHECK: [[SATISFIED2]]:
+// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* [[SIZE_METADATA]] to i8***
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
+// CHECK-NEXT: [[SIZE_VWT:%.*]] = load i8**, i8*** [[T1]],
+// CHECK-NEXT: [[SIZE_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT: store i8** [[SIZE_LAYOUT_1]],
+// CHECK-NEXT: getelementptr
+// CHECK-NEXT: [[SIZE_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT: [[SIZE_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT: call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT]], i8** [[SIZE_LAYOUT_2]], i8** [[SIZE_LAYOUT_3]])
+// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT]] to i8**
+// CHECK-NEXT: store i8** [[T0]],
// CHECK: call void @swift_initEnumMetadataMultiPayload
-// CHECK: phi %swift.type* [ [[SIZE_METADATA]], %entry ], [ [[TUPLE_METADATA]], %[[SATISFIED1]] ], [ null, %[[SATISFIED2]] ]
-// CHECK: phi [[INT]] [ 63, %entry ], [ 63, %[[SATISFIED1]] ], [ 0, %[[SATISFIED2]] ]
+// CHECK: phi %swift.type* [ [[SIZE_METADATA]], %entry ], [ null, %[[SATISFIED1]] ]
+// CHECK: phi [[INT]] [ 63, %entry ], [ 0, %[[SATISFIED1]] ]
public protocol Prot {
diff --git a/test/IRGen/foreign_types.sil b/test/IRGen/foreign_types.sil
index c413015..58159d9 100644
--- a/test/IRGen/foreign_types.sil
+++ b/test/IRGen/foreign_types.sil
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -I %S/Inputs/abi %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -I %S/Inputs/abi %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
sil_stage canonical
import c_layout
@@ -15,8 +15,7 @@
// CHECK-SAME: [[AMAZING_COLOR_NAME]]
// CHECK-SAME: @"$SSo12AmazingColorVMa"
-// CHECK-LABEL: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVN" = linkonce_odr hidden global
-// CHECK-SAME: [[INT:i[0-9]+]] 0,
+// CHECK-LABEL: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVN" = linkonce_odr hidden constant
// CHECK-SAME: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVWV"
// CHECK-SAME: [[INT]] 1,
// CHECK-SAME: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVMn"
@@ -38,7 +37,7 @@
}
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo14HasNestedUnionVMa"(
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata{{.*}}$SSo14HasNestedUnionVN
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}$SSo14HasNestedUnionVN
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo12AmazingColorVMa"(
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata{{.*}}@"$SSo12AmazingColorVN"
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}@"$SSo12AmazingColorVN"
diff --git a/test/IRGen/objc.swift b/test/IRGen/objc.swift
index ef0d59f..934270a 100644
--- a/test/IRGen/objc.swift
+++ b/test/IRGen/objc.swift
@@ -23,7 +23,7 @@
// CHECK: @"\01L_selector(bar)" = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
// CHECK: @"$SSo4RectVMn" = linkonce_odr hidden constant
-// CHECK: @"$SSo4RectVN" = linkonce_odr hidden global
+// CHECK: @"$SSo4RectVN" = linkonce_odr hidden constant
// CHECK: @"\01L_selector_data(acquiesce)"
// CHECK-NOT: @"\01L_selector_data(disharmonize)"
@@ -130,7 +130,7 @@
func test11_helper<T>(_ t: T) {}
// NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata.
// CHECK-LABEL: define hidden swiftcc void @"$S4objc6test11yySo4RectVF"
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata({{.*}} @"$SSo4RectVN"
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata(i64 %0, {{.*}} @"$SSo4RectVN"
func test11(_ r: Rect) { test11_helper(r) }
class WeakObjC {
diff --git a/test/IRGen/objc_ns_enum.swift b/test/IRGen/objc_ns_enum.swift
index 786a45f..e9ad416 100644
--- a/test/IRGen/objc_ns_enum.swift
+++ b/test/IRGen/objc_ns_enum.swift
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %build-irgen-test-overlays
-// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
// REQUIRES: CPU=x86_64
// REQUIRES: objc_interop
@@ -10,7 +10,7 @@
// CHECK: @"$SSo16NSRuncingOptionsVWV" = linkonce_odr hidden constant
// CHECK: @"$SSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant
-// CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden global
+// CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden constant
// CHECK: @"$SSo16NSRuncingOptionsVSQSCMc" = linkonce_odr hidden constant %swift.protocol_conformance_descriptor { {{.*}}@"$SSo16NSRuncingOptionsVSQSCWa
// CHECK: @"$SSo28NeverActuallyMentionedByNameVSQSCWp" = linkonce_odr hidden constant
@@ -87,11 +87,11 @@
use_metadata(NSRuncingOptions.mince)
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo16NSRuncingOptionsVMa"(i64)
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata({{.*}} @"$SSo16NSRuncingOptionsVN" {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}} @"$SSo16NSRuncingOptionsVN" {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
// CHECK-LABEL: define linkonce_odr hidden i8** @"$SSo16NSRuncingOptionsVSQSCWa"()
// CHECK: [[NONUNIQUE:%.*]] = call i8** @swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @"$SSo16NSRuncingOptionsVSQSCWG", %swift.type* null, i8*** null)
-// CHECK: [[UNIQUE:%.*]] = call i8** @swift_getForeignWitnessTable(i8** [[NONUNIQUE]], %swift.type_descriptor* bitcast (<{ i32, i32, i32, i32, i32, i32 }>* @"$SSo16NSRuncingOptionsVMn" to %swift.type_descriptor*), %swift.protocol* @"$SSQMp")
+// CHECK: [[UNIQUE:%.*]] = call i8** @swift_getForeignWitnessTable(i8** [[NONUNIQUE]], %swift.type_descriptor* bitcast (<{ i32, i32, i32, i32, i32, i32, i32 }>* @"$SSo16NSRuncingOptionsVMn" to %swift.type_descriptor*), %swift.protocol* @"$SSQMp")
// CHECK: ret i8** [[UNIQUE]]
@objc enum ExportedToObjC: Int {
diff --git a/test/IRGen/objc_runtime_visible_conformance.swift b/test/IRGen/objc_runtime_visible_conformance.swift
index 530a9a2..dbe2124 100644
--- a/test/IRGen/objc_runtime_visible_conformance.swift
+++ b/test/IRGen/objc_runtime_visible_conformance.swift
@@ -8,9 +8,10 @@
extension A : MyProtocol {}
extension A : YourProtocol {}
-// CHECK-LABEL: @"$SSo1ACMn" = linkonce_odr hidden constant <{ {{.*}} }>
-
-// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo1ACMa"({{i32|i64}}) {{.*}} {
-// CHECK: call %objc_class* @objc_lookUpClass
-// CHECK: call %swift.type* @swift_getObjCClassMetadata
-// CHECK: ret
+// CHECK-LABEL: @"$SSo1AC32objc_runtime_visible_conformance10MyProtocolACMc"
+// CHECK-SAME: @"$S32objc_runtime_visible_conformance10MyProtocolMp"
+// CHECK-SAME: [2 x i8]* [[STRING_A:@[0-9]+]]
+// CHECK-SAME: @"$SSo1AC32objc_runtime_visible_conformance10MyProtocolACWP"
+// DirectObjCClassName
+// CHECK-SAME: i32 16
+// CHECK: [[STRING_A]] = private unnamed_addr constant [2 x i8] c"A\00"
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 61f5841..20c8e85 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -198,20 +198,29 @@
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$S17struct_resilience26StructWithResilientStorageVMr"(%swift.type*, i8*, i8**)
// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
+// CHECK: [[TUPLE_LAYOUT:%.*]] = alloca %swift.full_type_layout,
// CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
// public let s: Size
-// CHECK: call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
+// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
+// CHECK: [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
+// CHECK: [[T0:%.*]] = bitcast %swift.type* [[SIZE_METADATA]] to i8***
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
+// CHECK: [[SIZE_VWT:%.*]] = load i8**, i8*** [[T1]],
+// CHECK: [[SIZE_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
// CHECK: [[FIELD_1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
-// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_1]]
+// CHECK: store i8** [[SIZE_LAYOUT_1:%.*]], i8*** [[FIELD_1]]
// public let ss: (Size, Size)
-// CHECK: call swiftcc %swift.metadata_response @swift_getTupleTypeMetadata2([[INT]] 319,
+// CHECK: [[SIZE_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK: [[SIZE_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK: call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT]], i8** [[SIZE_LAYOUT_2]], i8** [[SIZE_LAYOUT_3]])
+// CHECK: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT]] to i8**
// CHECK: [[FIELD_2:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 1
-// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_2]]
+// CHECK: store i8** [[T0]], i8*** [[FIELD_2]]
// Fixed-layout aggregate -- we can reference a static value witness table
// public let n: Int
diff --git a/test/IRGen/type_layout.swift b/test/IRGen/type_layout.swift
index b9fd828..f850c03 100644
--- a/test/IRGen/type_layout.swift
+++ b/test/IRGen/type_layout.swift
@@ -25,6 +25,10 @@
// CHECK: define internal %swift.type* @"$S11type_layout14TypeLayoutTestVMi"
// CHECK: define internal swiftcc %swift.metadata_response @"$S11type_layout14TypeLayoutTestVMr"
struct TypeLayoutTest<T> {
+ // CHECK: [[TUPLE_LAYOUT_M:%.*]] = alloca %swift.full_type_layout,
+ // CHECK: [[TUPLE_LAYOUT_N:%.*]] = alloca %swift.full_type_layout,
+ // CHECK: [[TUPLE_LAYOUT_O:%.*]] = alloca %swift.full_type_layout,
+ // CHECK: [[TUPLE_ELT_LAYOUTS_O:%.*]] = alloca i8**, [[INT]] 4,
// -- dynamic layout, projected from metadata
// CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[INT]] 319, %swift.type* %T)
// CHECK: [[T_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
@@ -80,4 +84,35 @@
// -- Single-field aggregate with alignment
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi128_WV", i32 8)
var l: AlignedFourInts
+ // -- Tuple with two elements
+ // CHECK: [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT_M]], i8** [[T_LAYOUT_1]], i8** [[T_LAYOUT_2]])
+ // CHECK: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_M]] to i8**
+ // CHECK: store i8** [[T0]]
+ var m: (T, T)
+ // -- Tuple with three elements
+ // CHECK: [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: call swiftcc { [[INT]], [[INT]] } @swift_getTupleTypeLayout3(%swift.full_type_layout* [[TUPLE_LAYOUT_N]], i8** [[T_LAYOUT_1]], i8** [[T_LAYOUT_2]], i8** [[T_LAYOUT_3]])
+ // CHECK: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_N]] to i8**
+ // CHECK: store i8** [[T0]]
+ var n: (T, T, T)
+ // -- Tuple with four elements
+ // CHECK: [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: store i8** [[T_LAYOUT_1]], i8*** [[TUPLE_ELT_LAYOUTS_O]],
+ // CHECK: [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 1
+ // CHECK: store i8** [[T_LAYOUT_2]], i8*** [[T0]],
+ // CHECK: [[T_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 2
+ // CHECK: store i8** [[T_LAYOUT_3]], i8*** [[T0]],
+ // CHECK: [[T_LAYOUT_4:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 3
+ // CHECK: store i8** [[T_LAYOUT_4]], i8*** [[T0]],
+ // CHECK: call swiftcc void @swift_getTupleTypeLayout(%swift.full_type_layout* [[TUPLE_LAYOUT_O]], i32* null, [[INT]] 4, i8*** [[TUPLE_ELT_LAYOUTS_O]])
+ // CHECK: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_O]] to i8**
+ // CHECK: store i8** [[T0]]
+ var o: (T, T, T, T)
}
diff --git a/test/IRGen/type_layout_reference_storage.swift b/test/IRGen/type_layout_reference_storage.swift
index 2305cdf..2160315 100644
--- a/test/IRGen/type_layout_reference_storage.swift
+++ b/test/IRGen/type_layout_reference_storage.swift
@@ -11,23 +11,35 @@
var z: T
// -- Known-Swift-refcounted type
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
- unowned(safe) var cs: C
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+ // 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)
unowned(unsafe) var cu: C
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+ // 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)
+ 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)
weak var cwo: C?
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+ // 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)
weak var cwi: C!
// -- Known-Swift-refcounted archetype
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
- unowned(safe) var nc: Native
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+ // 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)
unowned(unsafe) var nu: Native
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+ // 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)
+ 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)
weak var nwo: Native?
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+ // 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)
weak var nwi: Native!
// -- Open-code layout for protocol types with witness tables. Note:
@@ -35,8 +47,8 @@
// 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:[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_8_4_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
+ // 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)
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)
@@ -81,23 +93,35 @@
weak var pqcwi: (P & Q & C)!
// -- Unknown-refcounted existential without witness tables.
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
- unowned(safe) var aos: AnyObject
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+ // 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)
unowned(unsafe) var aou: AnyObject
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+ // 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)
+ 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)
weak var aowo: AnyObject?
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+ // 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)
weak var aowi: AnyObject!
// -- Unknown-refcounted archetype
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
- unowned(safe) var us: Unknown
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+ // 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)
unowned(unsafe) var uu: Unknown
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+ // 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)
+ 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)
weak var uwo: Unknown?
- // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+ // 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)
weak var uwi: Unknown!
}
@@ -105,10 +129,12 @@
public class Base {
var a: UInt32 = 0
}
-// CHECK-LABEL: %swift.type* @{{.*}}7DerivedCMi"(%swift.type_descriptor*, i8**, i8**)
-// CHECK-NOT: store {{.*}}getelementptr{{.*}}SBomWV
-// CHECK: call swiftcc %swift.metadata_response @"$S29type_layout_reference_storage1P_pXmTMa"([[INT]] 0)
-// CHECK: store {{.*}}getelementptr{{.*}}SBoWV
+// CHECK-LABEL: %swift.metadata_response @{{.*}}7DerivedCMr"(
+// CHECK: call swiftcc %swift.metadata_response @"$S29type_layout_reference_storage4BaseCMa"
+// CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_{{.*}}_pod, i32 0, i32 0),
+// CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_{{.*}}_pod, i32 0, i32 0),
+// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 8),
+// CHECK: call void @swift_initClassMetadata
// CHECK: ret
public class Derived<T> : Base {
var type : P.Type
diff --git a/test/Interpreter/objc_runtime_visible.swift b/test/Interpreter/objc_runtime_visible.swift
index af79a34..7698760 100644
--- a/test/Interpreter/objc_runtime_visible.swift
+++ b/test/Interpreter/objc_runtime_visible.swift
@@ -62,7 +62,6 @@
}
ObjCRuntimeVisibleTestSuite.test("protocols/downcast")
- .xfail(.always("unimplemented"))
.code {
let obj = HiddenClass.create()
let opaque: AnyObject = obj
diff --git a/test/Migrator/remove_override.swift b/test/Migrator/remove_override.swift
new file mode 100644
index 0000000..397dedb
--- /dev/null
+++ b/test/Migrator/remove_override.swift
@@ -0,0 +1,127 @@
+// REQUIRES: OS=macosx
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -c -update-code -swift-version 4 -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/remove_override.result.swift -o %t/rename-func-decl.swift.remap
+// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.result.swift
+
+import AppKit
+
+class AppDelegate: NSObject {
+ override class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+ super.application(sender, delegateHandlesKey: key)
+ return false
+ }
+ override func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+ return super.application(sender, delegateHandlesKey: key)
+ }
+ override class func changeColor(_ sender: Any?) {
+ super.changeColor(sender)
+ }
+ override func changeColor(_ sender: Any?) {
+
+ }
+ override class func controlTextDidBeginEditing(_ obj: Notification) {
+
+ }
+ override func controlTextDidBeginEditing(_ obj: Notification) {
+
+ }
+ override class func controlTextDidEndEditing(_ obj: Notification) {
+
+ }
+ override func controlTextDidEndEditing(_ obj: Notification) {
+
+ }
+ override class func controlTextDidChange(_ obj: Notification) {
+
+ }
+ override func controlTextDidChange(_ obj: Notification) {
+
+ }
+ override class func changeFont(_ sender: Any?) {
+
+ }
+ override func changeFont(_ sender: Any?) {
+
+ }
+ override class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+ return []
+ }
+ override func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+ return []
+ }
+ override class func discardEditing() {
+
+ }
+ override func discardEditing() {
+
+ }
+ override class func commitEditing() -> Bool {
+ return false
+ }
+ override func commitEditing() -> Bool {
+ return false
+ }
+ override class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+
+ }
+ override func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+
+ }
+ override class func commitEditingAndReturnError() throws {
+
+ }
+ override func commitEditingAndReturnError() throws {
+
+ }
+ override class func objectDidBeginEditing(_ editor: Any) {
+
+ }
+ override func objectDidBeginEditing(_ editor: Any) {
+
+ }
+ override class func objectDidEndEditing(_ editor: Any) {
+
+ }
+ override func objectDidEndEditing(_ editor: Any) {
+
+ }
+ override class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+ return false
+ }
+ override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+ return false
+ }
+ override class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+
+ }
+ override func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+
+ }
+ override class func pasteboardChangedOwner(_ sender: NSPasteboard) {
+
+ }
+ override func pasteboardChangedOwner(_ sender: NSPasteboard) {
+
+ }
+ override class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+ return false
+ }
+ override func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+ return false
+ }
+ override class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+ return ""
+ }
+ override func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+ return ""
+ }
+}
+
+// We shouldn't migrate further sub-class.
+class MyAppDelegate: AppDelegate {
+ override func commitEditing() -> Bool {
+ super.commitEditing()
+ return false
+ }
+}
+
diff --git a/test/Migrator/remove_override.swift.expected b/test/Migrator/remove_override.swift.expected
new file mode 100644
index 0000000..db3f7ad
--- /dev/null
+++ b/test/Migrator/remove_override.swift.expected
@@ -0,0 +1,127 @@
+// REQUIRES: OS=macosx
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -c -update-code -swift-version 4 -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/remove_override.result.swift -o %t/rename-func-decl.swift.remap
+// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.result.swift
+
+import AppKit
+
+class AppDelegate: NSObject {
+ class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+
+ return false
+ }
+ func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+ return super.application(sender, delegateHandlesKey: key)
+ }
+ class func changeColor(_ sender: Any?) {
+
+ }
+ func changeColor(_ sender: Any?) {
+
+ }
+ class func controlTextDidBeginEditing(_ obj: Notification) {
+
+ }
+ func controlTextDidBeginEditing(_ obj: Notification) {
+
+ }
+ class func controlTextDidEndEditing(_ obj: Notification) {
+
+ }
+ func controlTextDidEndEditing(_ obj: Notification) {
+
+ }
+ class func controlTextDidChange(_ obj: Notification) {
+
+ }
+ func controlTextDidChange(_ obj: Notification) {
+
+ }
+ class func changeFont(_ sender: Any?) {
+
+ }
+ func changeFont(_ sender: Any?) {
+
+ }
+ class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+ return []
+ }
+ func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+ return []
+ }
+ class func discardEditing() {
+
+ }
+ func discardEditing() {
+
+ }
+ class func commitEditing() -> Bool {
+ return false
+ }
+ func commitEditing() -> Bool {
+ return false
+ }
+ class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+
+ }
+ func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+
+ }
+ class func commitEditingAndReturnError() throws {
+
+ }
+ func commitEditingAndReturnError() throws {
+
+ }
+ class func objectDidBeginEditing(_ editor: Any) {
+
+ }
+ func objectDidBeginEditing(_ editor: Any) {
+
+ }
+ class func objectDidEndEditing(_ editor: Any) {
+
+ }
+ func objectDidEndEditing(_ editor: Any) {
+
+ }
+ class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+ return false
+ }
+ func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+ return false
+ }
+ class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+
+ }
+ func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+
+ }
+ class func pasteboardChangedOwner(_ sender: NSPasteboard) {
+
+ }
+ func pasteboardChangedOwner(_ sender: NSPasteboard) {
+
+ }
+ class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+ return false
+ }
+ func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+ return false
+ }
+ class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+ return ""
+ }
+ func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+ return ""
+ }
+}
+
+// We shouldn't migrate further sub-class.
+class MyAppDelegate: AppDelegate {
+ override func commitEditing() -> Bool {
+ super.commitEditing()
+ return false
+ }
+}
+
diff --git a/test/lit.cfg b/test/lit.cfg
index b9454b5..c0e1f23 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -638,12 +638,15 @@
elif run_os == 'ios' or run_os == 'tvos' or run_os == 'watchos':
# iOS/tvOS/watchOS simulator
if run_os == 'ios':
+ config.available_features.add('DARWIN_SIMULATOR=ios')
lit_config.note("Testing iOS simulator " + config.variant_triple)
xcrun_sdk_name = "iphonesimulator"
elif run_os == 'watchos':
+ config.available_features.add('DARWIN_SIMULATOR=watchos')
lit_config.note("Testing watchOS simulator " + config.variant_triple)
xcrun_sdk_name = "watchsimulator"
else:
+ config.available_features.add('DARWIN_SIMULATOR=tvos')
lit_config.note("Testing AppleTV simulator " + config.variant_triple)
xcrun_sdk_name = "appletvsimulator"