diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 395047a03d2..46b26a49826 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -587,10 +587,10 @@ protected: SWIFT_INLINE_BITFIELD_EMPTY(TypeDecl, ValueDecl); - SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, TypeDecl, 16+16+8+1, + SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, TypeDecl, 16+16+3+1, Depth : 16, Index : 16, - ParamKind : 8, + ParamKind : 3, /// Whether this generic parameter represents an opaque type. IsOpaqueType : 1 diff --git a/include/swift/AST/FeatureAvailability.def b/include/swift/AST/FeatureAvailability.def index c9700579f73..16708183e35 100644 --- a/include/swift/AST/FeatureAvailability.def +++ b/include/swift/AST/FeatureAvailability.def @@ -79,6 +79,7 @@ FEATURE(Differentiation, FUTURE) FEATURE(ClearSensitive, FUTURE) FEATURE(UpdatePureObjCClassMetadata, FUTURE) FEATURE(ValueGenericType, FUTURE) +FEATURE(InitRawStructMetadata2, FUTURE) #undef FEATURE #undef FUTURE diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 80f8ca8cf76..e007273a355 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -1057,10 +1057,18 @@ void _swift_registerConcurrencyStandardTypeDescriptors( /// as the basis for the layout. SWIFT_RUNTIME_EXPORT void swift_initRawStructMetadata(StructMetadata *self, - StructLayoutFlags structLayoutFlags, + StructLayoutFlags flags, const TypeLayout *likeType, - intptr_t count, - RawLayoutFlags rawLayoutFlags); + ssize_t count); + +/// Initialize the value witness table for a struct using the provided like type +/// as the basis for the layout. +SWIFT_RUNTIME_EXPORT +void swift_initRawStructMetadata2(StructMetadata *self, + StructLayoutFlags structLayoutFlags, + const TypeLayout *likeType, + intptr_t count, + RawLayoutFlags rawLayoutFlags); /// Check if the given generic arguments are valid inputs for the generic type /// context and if so call the metadata access function and return the metadata. diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index 6e04138d00f..84ac37cfef5 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -2823,13 +2823,26 @@ FUNCTION(GenericInstantiateLayoutString, UNKNOWN_MEMEFFECTS) // void swift_initRawStructMetadata(Metadata *structType, -// StructLayoutFlags structLayoutFlags, +// StructLayoutFlags flags, // const TypeLayout *likeType, -// intptr_t count, -// RawLayoutFlags rawLayoutFlags); +// int32_t count); FUNCTION(InitRawStructMetadata, swift_initRawStructMetadata, - C_CC, AlwaysAvailable, + C_CC, InitRawStructMetadataAvailability, + RETURNS(VoidTy), + ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy->getPointerTo(0), Int32Ty), + ATTRS(NoUnwind), + EFFECT(MetaData), + UNKNOWN_MEMEFFECTS) + +// void swift_initRawStructMetadata2(Metadata *structType, +// StructLayoutFlags structLayoutFlags, +// const TypeLayout *likeType, +// intptr_t count, +// RawLayoutFlags rawLayoutFlags); +FUNCTION(InitRawStructMetadata2, + swift_initRawStructMetadata2, + C_CC, InitRawStructMetadata2Availability, RETURNS(VoidTy), ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy->getPointerTo(0), SizeTy, SizeTy), diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index a361e256f20..2e049f56d36 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -3213,9 +3213,9 @@ static void emitInitializeFieldOffsetVectorWithLayoutString( IGM.getPointerSize() * numFields); } -static void emitInitializeRawLayoutOld(IRGenFunction &IGF, SILType likeType, - llvm::Value *count, SILType T, - llvm::Value *metadata, +static void emitInitializeRawLayoutOldOld(IRGenFunction &IGF, SILType likeType, + llvm::Value *count, SILType T, + llvm::Value *metadata, MetadataDependencyCollector *collector) { auto &IGM = IGF.IGM; @@ -3296,11 +3296,11 @@ static void emitInitializeRawLayoutOld(IRGenFunction &IGF, SILType likeType, IGF.Builder.CreateLifetimeEnd(fieldLayouts, IGM.getPointerSize()); } -static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType, - llvm::Value *count, SILType T, - llvm::Value *metadata, - MetadataDependencyCollector *collector) { - // If our deployment target doesn't contain the new swift_initRawStructMetadata, +static void emitInitializeRawLayoutOld(IRGenFunction &IGF, SILType likeType, + llvm::Value *count, SILType T, + llvm::Value *metadata, + MetadataDependencyCollector *collector) { + // If our deployment target doesn't contain the swift_initRawStructMetadata, // emit a call to the swift_initStructMetadata tricking it into thinking // we have a single field. auto deploymentAvailability = @@ -3310,6 +3310,39 @@ static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType, if (!IGF.IGM.Context.LangOpts.DisableAvailabilityChecking && !deploymentAvailability.isContainedIn(initRawAvail) && !IGF.IGM.getSwiftModule()->isStdlibModule()) { + emitInitializeRawLayoutOldOld(IGF, likeType, count, T, metadata, collector); + return; + } + + auto &IGM = IGF.IGM; + auto likeTypeLayout = emitTypeLayoutRef(IGF, likeType, collector); + StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm; + + // If we don't have a count, then we're the 'like:' variant and we need to + // pass '-1' to the runtime call. + if (!count) { + count = llvm::ConstantInt::get(IGF.IGM.Int32Ty, -1); + } + + // Call swift_initRawStructMetadata(). + IGF.Builder.CreateCall(IGM.getInitRawStructMetadataFunctionPointer(), + {metadata, IGM.getSize(Size(uintptr_t(flags))), + likeTypeLayout, count}); +} + +static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType, + llvm::Value *count, SILType T, + llvm::Value *metadata, + MetadataDependencyCollector *collector) { + // If our deployment target doesn't contain the swift_initRawStructMetadata2, + // emit a call to the older swift_initRawStructMetadata. + auto deploymentAvailability = + AvailabilityContext::forDeploymentTarget(IGF.IGM.Context); + auto initRaw2Avail = IGF.IGM.Context.getInitRawStructMetadata2Availability(); + + if (!IGF.IGM.Context.LangOpts.DisableAvailabilityChecking && + !deploymentAvailability.isContainedIn(initRaw2Avail) && + !IGF.IGM.getSwiftModule()->isStdlibModule()) { emitInitializeRawLayoutOld(IGF, likeType, count, T, metadata, collector); return; } @@ -3331,8 +3364,8 @@ static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType, rawLayoutFlags |= RawLayoutFlags::IsArray; } - // Call swift_initRawStructMetadata(). - IGF.Builder.CreateCall(IGM.getInitRawStructMetadataFunctionPointer(), + // Call swift_initRawStructMetadata2(). + IGF.Builder.CreateCall(IGM.getInitRawStructMetadata2FunctionPointer(), {metadata, IGM.getSize(Size(uintptr_t(structLayoutflags))), likeTypeLayout, diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index d82504a2c29..3e9bc15559b 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -986,6 +986,22 @@ namespace RuntimeConstants { return RuntimeAvailability::AlwaysAvailable; } + RuntimeAvailability InitRawStructMetadataAvailability(ASTContext &Context) { + auto featureAvailability = Context.getInitRawStructMetadataAvailability(); + if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) { + return RuntimeAvailability::ConditionallyAvailable; + } + return RuntimeAvailability::AlwaysAvailable; + } + + RuntimeAvailability InitRawStructMetadata2Availability(ASTContext &Context) { + auto featureAvailability = Context.getInitRawStructMetadata2Availability(); + if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) { + return RuntimeAvailability::ConditionallyAvailable; + } + return RuntimeAvailability::AlwaysAvailable; + } + } // namespace RuntimeConstants // We don't use enough attributes to justify generalizing the diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index dab4b8441b3..ca8bf891705 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -3028,10 +3028,39 @@ metadata: /// Initialize the value witness table for a @_rawLayout struct. SWIFT_RUNTIME_EXPORT void swift::swift_initRawStructMetadata(StructMetadata *structType, - StructLayoutFlags structLayoutFlags, + StructLayoutFlags layoutFlags, const TypeLayout *likeTypeLayout, - intptr_t count, - RawLayoutFlags rawLayoutFlags) { + ssize_t count) { + auto vwtable = getMutableVWTableForInit(structType, layoutFlags); + + // The existing vwt function entries are all fine to preserve, the only thing + // we need to initialize is the actual type layout. + auto size = likeTypeLayout->size; + auto stride = likeTypeLayout->stride; + auto alignMask = likeTypeLayout->flags.getAlignmentMask(); + auto extraInhabitantCount = likeTypeLayout->extraInhabitantCount; + + // If our count is not -1, we're dealing an array like layout. + if (count != -1) { + stride *= (size_t)count; + size = stride; + } + + vwtable->size = size; + vwtable->stride = stride; + vwtable->flags = ValueWitnessFlags() + .withAlignmentMask(alignMask) + .withCopyable(false); + vwtable->extraInhabitantCount = extraInhabitantCount; +} + +/// Initialize the value witness table for a @_rawLayout struct. +SWIFT_RUNTIME_EXPORT +void swift::swift_initRawStructMetadata2(StructMetadata *structType, + StructLayoutFlags structLayoutFlags, + const TypeLayout *likeTypeLayout, + intptr_t count, + RawLayoutFlags rawLayoutFlags) { auto vwtable = getMutableVWTableForInit(structType, structLayoutFlags); // The existing vwt function entries are all fine to preserve, the only thing