Skip to content

Commit d082bb7

Browse files
authored
[IRGen] Fix layout string generation for pre-specialized metadata (#65162) (#65327)
* [IRGen] Fix layout string generation for pre-specialized metadata rdar://108012057 Pre-specialized metadata has to be specifically handled by using the bound generic type instead of the unbound one. All the necessary information is already being passed down as BoundGenericTypeCharacteristics, we just need to apply them when present. * Add tests and a few fixes * Fixes after rebase * Attempt to fix Windows linker issue in test
1 parent 0fa8d99 commit d082bb7

File tree

7 files changed

+181
-32
lines changed

7 files changed

+181
-32
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4464,6 +4464,7 @@ namespace {
44644464

44654465
protected:
44664466
using super::asImpl;
4467+
using super::B;
44674468
using super::getLoweredType;
44684469
using super::IGM;
44694470
using super::Target;
@@ -4487,6 +4488,41 @@ namespace {
44874488

44884489
SILType getLoweredType() { return SILType::getPrimitiveObjectType(type); }
44894490

4491+
llvm::Constant *emitLayoutString() {
4492+
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses))
4493+
return nullptr;
4494+
auto lowered = getLoweredType();
4495+
auto &ti = IGM.getTypeInfo(lowered);
4496+
auto *typeLayoutEntry =
4497+
ti.buildTypeLayoutEntry(IGM, lowered, /*useStructLayouts*/ true);
4498+
auto genericSig =
4499+
lowered.getNominalOrBoundGenericNominal()->getGenericSignature();
4500+
4501+
return typeLayoutEntry->layoutString(IGM, genericSig);
4502+
}
4503+
4504+
llvm::Constant *getLayoutString() {
4505+
return emitLayoutString();
4506+
}
4507+
4508+
void addLayoutStringPointer() {
4509+
if (auto *layoutString = getLayoutString()) {
4510+
B.addSignedPointer(layoutString,
4511+
IGM.getOptions().PointerAuth.TypeLayoutString,
4512+
PointerAuthEntity::Special::TypeLayoutString);
4513+
} else {
4514+
B.addNullPointer(IGM.Int8PtrTy);
4515+
}
4516+
}
4517+
4518+
bool hasLayoutString() {
4519+
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses)) {
4520+
return false;
4521+
}
4522+
4523+
return !!getLayoutString();
4524+
}
4525+
44904526
ConstantReference emitValueWitnessTable(bool relativeReference) {
44914527
return irgen::emitValueWitnessTable(IGM, type, false, relativeReference);
44924528
}
@@ -5342,6 +5378,13 @@ namespace {
53425378
StructDecl &decl,
53435379
ConstantStructBuilder &B)
53445380
: super(IGM, type, decl, B) {}
5381+
5382+
llvm::Constant *emitNominalTypeDescriptor() {
5383+
auto descriptor =
5384+
StructContextDescriptorBuilder(IGM, Target, RequireMetadata,
5385+
hasLayoutString()).emit();
5386+
return descriptor;
5387+
}
53455388
};
53465389

53475390
} // end anonymous namespace

lib/IRGen/GenValueWitness.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -989,9 +989,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
989989
return addFunction(getDestroyStrongFunction(IGM));
990990
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
991991
IGM.getOptions().EnableLayoutStringValueWitnesses) {
992+
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
993+
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
992994
if (auto *typeLayoutEntry =
993-
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
994-
/*useStructLayouts*/true)) {
995+
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
995996
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
996997
->getGenericSignature();
997998
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
@@ -1017,9 +1018,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
10171018
return addFunction(getMemCpyFunction(IGM, concreteTI));
10181019
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
10191020
IGM.getOptions().EnableLayoutStringValueWitnesses) {
1021+
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
1022+
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
10201023
if (auto *typeLayoutEntry =
1021-
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
1022-
/*useStructLayouts*/true)) {
1024+
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
10231025
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
10241026
->getGenericSignature();
10251027
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
@@ -1037,9 +1039,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
10371039
return addFunction(getAssignWithCopyStrongFunction(IGM));
10381040
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
10391041
IGM.getOptions().EnableLayoutStringValueWitnesses) {
1042+
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
1043+
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
10401044
if (auto *typeLayoutEntry =
1041-
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
1042-
/*useStructLayouts*/true)) {
1045+
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
10431046
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
10441047
->getGenericSignature();
10451048
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
@@ -1057,9 +1060,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
10571060
return addFunction(getAssignWithTakeStrongFunction(IGM));
10581061
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
10591062
IGM.getOptions().EnableLayoutStringValueWitnesses) {
1063+
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
1064+
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
10601065
if (auto *typeLayoutEntry =
1061-
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
1062-
/*useStructLayouts*/true)) {
1066+
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
10631067
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
10641068
->getGenericSignature();
10651069
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
@@ -1077,9 +1081,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
10771081
return addFunction(getInitWithCopyStrongFunction(IGM));
10781082
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
10791083
IGM.getOptions().EnableLayoutStringValueWitnesses) {
1084+
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
1085+
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
10801086
if (auto *typeLayoutEntry =
1081-
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
1082-
/*useStructLayouts*/true)) {
1087+
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
10831088
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
10841089
->getGenericSignature();
10851090
if (typeLayoutEntry->layoutString(IGM, genericSig) ||

stdlib/public/runtime/Metadata.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2833,7 +2833,10 @@ void swift::swift_initStructMetadataWithLayoutString(
28332833
previousFieldOffset = fieldType->vw_size();
28342834
fullOffset += previousFieldOffset;
28352835
} else if (fieldType->isAnyExistentialType()) {
2836-
auto tag = RefCountingKind::Existential;
2836+
auto *existential = dyn_cast<ExistentialTypeMetadata>(fieldType);
2837+
assert(existential);
2838+
auto tag = existential->isClassBounded() ? RefCountingKind::Unknown
2839+
: RefCountingKind::Existential;
28372840
*(uint64_t*)(layoutStr + layoutStrOffset) =
28382841
((uint64_t)tag << 56) | offset;
28392842
layoutStrOffset += sizeof(uint64_t);

test/IRGen/layout_string_union_types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-type-layout -emit-ir -import-objc-header %S/Inputs/union_type.h %s
1+
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-type-layout -emit-ir -import-objc-header %S/Inputs/union_type.h %s
22

33
struct UnionWrapper {
44
let x: TestUnion

test/Interpreter/Inputs/layout_string_witnesses_types.swift

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -365,20 +365,40 @@ public struct ComplexNesting<A, B, C, D> {
365365
}
366366

367367
internal enum InternalEnum {
368-
case a(Int, AnyObject)
369-
case b(Int)
370-
case c(String)
368+
case a(Int, AnyObject)
369+
case b(Int)
370+
case c(String)
371371
}
372372

373373
public struct InternalEnumWrapper {
374-
internal let x: InternalEnum
375-
internal let y: Int = 32
374+
internal let x: InternalEnum
375+
internal let y: Int = 32
376376

377-
public init(x: AnyObject) {
378-
self.x = .a(23, x)
377+
public init(x: AnyObject) {
378+
self.x = .a(23, x)
379+
}
380+
}
381+
382+
public struct PrespecializedStruct<T> {
383+
let y: Int = 0
384+
let x: T
385+
let z: T
386+
387+
public init(x: T) {
388+
self.x = x
389+
self.z = x
379390
}
380391
}
381392

393+
@inline(never)
394+
public func consume<T>(_ x: T.Type) {
395+
withExtendedLifetime(x) {}
396+
}
397+
public func preSpec() {
398+
consume(PrespecializedStruct<AnyObject>.self)
399+
consume(PrespecializedStruct<SimpleClass>.self)
400+
consume(PrespecializedStruct<Int>.self)
401+
}
382402

383403
@inline(never)
384404
public func testAssign<T>(_ ptr: UnsafeMutablePointer<T>, from x: T) {

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
2-
31
// RUN: %empty-directory(%t)
4-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-type-layout -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
5-
// RUN: %target-build-swift -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-type-layout -Xfrontend -enable-autolinking-runtime-compatibility-bytecode-layouts -c -parse-as-library -o %t/layout_string_witnesses_types.o %S/Inputs/layout_string_witnesses_types.swift
6-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-library-evolution -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
7-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
8-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-type-layout -Xfrontend -enable-autolinking-runtime-compatibility-bytecode-layouts -module-name layout_string_witnesses_dynamic %t/layout_string_witnesses_types.o %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s
2+
// RUN: %target-swift-frontend -prespecialize-generic-metadata -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-type-layout -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
3+
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
4+
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
5+
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-library-evolution -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
6+
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
7+
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-type-layout -Xfrontend -enable-autolinking-runtime-compatibility-bytecode-layouts -module-name layout_string_witnesses_dynamic -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
98
// RUN: %target-codesign %t/main
10-
// RUN: %target-run %t/main | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
9+
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
1110

1211
// REQUIRES: executable_test
1312

@@ -52,6 +51,85 @@ func testGeneric() {
5251

5352
testGeneric()
5453

54+
func testPrespecializedAnyObject() {
55+
let ptr = UnsafeMutablePointer<PrespecializedStruct<AnyObject>>.allocate(capacity: 1)
56+
57+
do {
58+
let x = PrespecializedStruct<AnyObject>(x: SimpleClass(x: 23))
59+
testInit(ptr, to: x)
60+
}
61+
62+
do {
63+
let y = PrespecializedStruct<AnyObject>(x: SimpleClass(x: 32))
64+
65+
// CHECK-NEXT: Before deinit
66+
print("Before deinit")
67+
68+
// CHECK-NEXT: SimpleClass deinitialized!
69+
testAssign(ptr, from: y)
70+
}
71+
72+
// CHECK-NEXT: Before deinit
73+
print("Before deinit")
74+
75+
76+
// CHECK-NEXT: SimpleClass deinitialized!
77+
testDestroy(ptr)
78+
79+
ptr.deallocate()
80+
}
81+
82+
testPrespecializedAnyObject()
83+
84+
func testPrespecializedSimpleClass() {
85+
let ptr = UnsafeMutablePointer<PrespecializedStruct<SimpleClass>>.allocate(capacity: 1)
86+
87+
do {
88+
let x = PrespecializedStruct<SimpleClass>(x: SimpleClass(x: 23))
89+
testInit(ptr, to: x)
90+
}
91+
92+
do {
93+
let y = PrespecializedStruct<SimpleClass>(x: SimpleClass(x: 32))
94+
95+
// CHECK-NEXT: Before deinit
96+
print("Before deinit")
97+
98+
// CHECK-NEXT: SimpleClass deinitialized!
99+
testAssign(ptr, from: y)
100+
}
101+
102+
// CHECK-NEXT: Before deinit
103+
print("Before deinit")
104+
105+
106+
// CHECK-NEXT: SimpleClass deinitialized!
107+
testDestroy(ptr)
108+
109+
ptr.deallocate()
110+
}
111+
112+
testPrespecializedSimpleClass()
113+
114+
115+
func testPrespecializedInt() {
116+
let ptr = UnsafeMutablePointer<PrespecializedStruct<Int>>.allocate(capacity: 1)
117+
118+
do {
119+
let x = PrespecializedStruct<Int>(x: 23)
120+
testInit(ptr, to: x)
121+
}
122+
123+
do {
124+
let y = PrespecializedStruct<Int>(x: 32)
125+
testAssign(ptr, from: y)
126+
}
127+
128+
ptr.deallocate()
129+
}
130+
131+
testPrespecializedInt()
132+
55133
func testGenericTuple() {
56134
let ptr = allocateInternalGenericPtr(of: GenericTupleWrapper<TestClass>.self)
57135

test/Interpreter/layout_string_witnesses_static.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-type-layout -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
2+
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-type-layout -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
33

44
// NOTE: We have to build this as dylib to turn private external symbols into local symbols, so we can observe potential issues with linkage
5-
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
5+
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
66
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
7-
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-library-evolution -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
8-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
9-
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -module-name layout_string_witnesses_static -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
7+
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-library-evolution -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
8+
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
9+
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -module-name layout_string_witnesses_static -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
1010
// RUN: %target-codesign %t/main
1111
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
1212

0 commit comments

Comments
 (0)