From 9ab224212e12318cb3390f9893fe08e065e41442 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Wed, 1 Oct 2025 15:38:07 -0700 Subject: [PATCH 1/2] [VariadicGenerics] Fix memeffect of metadata accessor. The metadata accessor for a variadic generic type takes as arguments packs of metadata records and witness tables, and each such pack is passed in a buffer. So any such accessor is not correctly annotated `memory(none)`. rdar://161606892 --- include/swift/IRGen/GenericRequirement.h | 5 +++++ lib/IRGen/GenMeta.cpp | 5 +++-- lib/IRGen/GenericArguments.h | 4 +++- validation-test/IRGen/rdar161606892.swift | 8 ++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 validation-test/IRGen/rdar161606892.swift diff --git a/include/swift/IRGen/GenericRequirement.h b/include/swift/IRGen/GenericRequirement.h index 3722cb2252ede..5d8714fe661be 100644 --- a/include/swift/IRGen/GenericRequirement.h +++ b/include/swift/IRGen/GenericRequirement.h @@ -109,6 +109,11 @@ class GenericRequirement { bool isAnyWitnessTable() const { return kind == Kind::WitnessTable || kind == Kind::WitnessTablePack; } + + bool isAnyPack() const { + return kind == Kind::MetadataPack || kind == Kind::WitnessTablePack; + } + bool isValue() const { return kind == Kind::Value; } diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index ff645f54b4327..eb048eb1a76ce 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -2996,8 +2996,9 @@ void irgen::emitLazyMetadataAccessor(IRGenModule &IGM, if (IGM.getOptions().optimizeForSize()) accessor->addFnAttr(llvm::Attribute::NoInline); - bool isReadNone = (genericArgs.Types.size() <= - NumDirectGenericTypeMetadataAccessFunctionArgs); + bool isReadNone = + !genericArgs.hasPacks && (genericArgs.Types.size() <= + NumDirectGenericTypeMetadataAccessFunctionArgs); emitCacheAccessFunction( IGM, accessor, /*cache*/ nullptr, /*cache type*/ nullptr, diff --git a/lib/IRGen/GenericArguments.h b/lib/IRGen/GenericArguments.h index a2cf298e0b5a7..698dfd460bb13 100644 --- a/lib/IRGen/GenericArguments.h +++ b/lib/IRGen/GenericArguments.h @@ -50,8 +50,9 @@ struct GenericArguments { /// The values to use to initialize the arguments structure. SmallVector Values; SmallVector Types; + bool hasPacks = false; - void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) { + void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) { GenericTypeRequirements requirements(IGM, nominal); collectTypes(IGM, requirements); } @@ -59,6 +60,7 @@ struct GenericArguments { void collectTypes(IRGenModule &IGM, const GenericTypeRequirements &requirements) { for (auto &requirement : requirements.getRequirements()) { + hasPacks = hasPacks || requirement.isAnyPack(); Types.push_back(requirement.getType(IGM)); } } diff --git a/validation-test/IRGen/rdar161606892.swift b/validation-test/IRGen/rdar161606892.swift new file mode 100644 index 0000000000000..01e01c685f068 --- /dev/null +++ b/validation-test/IRGen/rdar161606892.swift @@ -0,0 +1,8 @@ +// RUN: %target-swift-frontend %s -target %target-swift-5.9-abi-triple -emit-irgen | %IRGenFileCheck %s + +// CHECK: Attrs: noinline nounwind{{$}} +// CHECK-NEXT: define {{.*}}@"$s13rdar1616068921PVMa" + +public struct P { + public var teas: (repeat each T) +} From dab39bbf9166927dde1ea036bd5e5f13df1715ba Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Fri, 3 Oct 2025 07:53:20 -0700 Subject: [PATCH 2/2] [VariadicGenerics] Fix memeffect of metadata accessor call. Follow up to https://github.com/swiftlang/swift/pull/84635/. The metadata accessor for a variadic generic type takes as arguments packs of metadata records and witness tables, and each such pack is passed in a buffer. So the call to any such accessor is not correctly annotated memory(none). rdar://161606892 --- lib/IRGen/IRGenFunction.h | 5 ++- lib/IRGen/MetadataRequest.cpp | 12 +++---- validation-test/IRGen/rdar161606892_2.swift | 40 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 validation-test/IRGen/rdar161606892_2.swift diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index 94e1cf65723bb..18a3975c10eb2 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -395,9 +395,8 @@ class IRGenFunction { // Emit a call to the given generic type metadata access function. MetadataResponse emitGenericTypeMetadataAccessFunctionCall( - llvm::Function *accessFunction, - ArrayRef args, - DynamicMetadataRequest request); + llvm::Function *accessFunction, ArrayRef args, + DynamicMetadataRequest request, bool hasPacks = false); // Emit a reference to the canonical type metadata record for the given AST // type. This can be used to identify the type at runtime. For types with diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 945996b7e00f6..541ac04dc2533 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -750,7 +750,7 @@ static MetadataResponse emitNominalMetadataRef(IRGenFunction &IGF, theDecl, genericArgs.Types, NotForDefinition); response = IGF.emitGenericTypeMetadataAccessFunctionCall( - accessor, genericArgs.Values, request); + accessor, genericArgs.Values, request, genericArgs.hasPacks); } IGF.setScopedLocalTypeMetadata(theType, response); @@ -2467,11 +2467,9 @@ void irgen::emitCacheAccessFunction(IRGenModule &IGM, llvm::Function *accessor, IGF.Builder.CreateRet(ret); } -MetadataResponse -IRGenFunction::emitGenericTypeMetadataAccessFunctionCall( - llvm::Function *accessFunction, - ArrayRef args, - DynamicMetadataRequest request) { +MetadataResponse IRGenFunction::emitGenericTypeMetadataAccessFunctionCall( + llvm::Function *accessFunction, ArrayRef args, + DynamicMetadataRequest request, bool hasPacks) { SmallVector callArgs; @@ -2495,7 +2493,7 @@ IRGenFunction::emitGenericTypeMetadataAccessFunctionCall( accessFunction, callArgs); call->setDoesNotThrow(); call->setCallingConv(IGM.SwiftCC); - call->setMemoryEffects(allocatedArgsBuffer + call->setMemoryEffects(hasPacks || allocatedArgsBuffer ? llvm::MemoryEffects::inaccessibleOrArgMemOnly() : llvm::MemoryEffects::none()); diff --git a/validation-test/IRGen/rdar161606892_2.swift b/validation-test/IRGen/rdar161606892_2.swift new file mode 100644 index 0000000000000..2651d0d7ef53f --- /dev/null +++ b/validation-test/IRGen/rdar161606892_2.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-build-swift \ +// RUN: -emit-module \ +// RUN: -target %target-swift-5.9-abi-triple \ +// RUN: %t/Library.swift \ +// RUN: -parse-as-library \ +// RUN: -module-name Library \ +// RUN: -emit-module-path %t/Library.swiftmodule + +// RUN: %target-swift-frontend \ +// RUN: %t/Downstream.swift \ +// RUN: -emit-irgen \ +// RUN: -target %target-swift-5.9-abi-triple \ +// RUN: -module-name main \ +// RUN: -lLibrary \ +// RUN: -I %t \ +// RUN: | %FileCheck %t/Downstream.swift --check-prefixes=CHECK,CHECK-OLD + +//--- Library.swift + +public struct Pack { + public init() {} +} + +public func sink(_ t: T) {} + +//--- Downstream.swift + +import Library + +// CHECK: doit +// CHECK: @"$s7Library4PackVMa"{{.*}} [[CALL:#[^,]+]] + +// CHECK: attributes [[CALL]] = { nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) } +@_silgen_name("doit") +func doit(ts: repeat each T, us: repeat each U) { + sink(Pack()) +}