Skip to content

[IRGen] Fix layout string generation for pre-specialized metadata #65162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4465,6 +4465,7 @@ namespace {

protected:
using super::asImpl;
using super::B;
using super::getLoweredType;
using super::IGM;
using super::Target;
Expand All @@ -4488,6 +4489,41 @@ namespace {

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

llvm::Constant *emitLayoutString() {
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses))
return nullptr;
auto lowered = getLoweredType();
auto &ti = IGM.getTypeInfo(lowered);
auto *typeLayoutEntry =
ti.buildTypeLayoutEntry(IGM, lowered, /*useStructLayouts*/ true);
auto genericSig =
lowered.getNominalOrBoundGenericNominal()->getGenericSignature();

return typeLayoutEntry->layoutString(IGM, genericSig);
}

llvm::Constant *getLayoutString() {
return emitLayoutString();
}

void addLayoutStringPointer() {
if (auto *layoutString = getLayoutString()) {
B.addSignedPointer(layoutString,
IGM.getOptions().PointerAuth.TypeLayoutString,
PointerAuthEntity::Special::TypeLayoutString);
} else {
B.addNullPointer(IGM.Int8PtrTy);
}
}

bool hasLayoutString() {
if (!IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses)) {
return false;
}

return !!getLayoutString();
}

ConstantReference emitValueWitnessTable(bool relativeReference) {
return irgen::emitValueWitnessTable(IGM, type, false, relativeReference);
}
Expand Down Expand Up @@ -5343,6 +5379,13 @@ namespace {
StructDecl &decl,
ConstantStructBuilder &B)
: super(IGM, type, decl, B) {}

llvm::Constant *emitNominalTypeDescriptor() {
auto descriptor =
StructContextDescriptorBuilder(IGM, Target, RequireMetadata,
hasLayoutString()).emit();
return descriptor;
}
};

} // end anonymous namespace
Expand Down
25 changes: 15 additions & 10 deletions lib/IRGen/GenValueWitness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,9 +989,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
return addFunction(getDestroyStrongFunction(IGM));
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.getOptions().EnableLayoutStringValueWitnesses) {
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
if (auto *typeLayoutEntry =
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
/*useStructLayouts*/true)) {
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
->getGenericSignature();
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
Expand All @@ -1017,9 +1018,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
return addFunction(getMemCpyFunction(IGM, concreteTI));
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.getOptions().EnableLayoutStringValueWitnesses) {
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
if (auto *typeLayoutEntry =
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
/*useStructLayouts*/true)) {
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
->getGenericSignature();
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
Expand All @@ -1037,9 +1039,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
return addFunction(getAssignWithCopyStrongFunction(IGM));
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.getOptions().EnableLayoutStringValueWitnesses) {
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
if (auto *typeLayoutEntry =
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
/*useStructLayouts*/true)) {
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
->getGenericSignature();
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
Expand All @@ -1057,9 +1060,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
return addFunction(getAssignWithTakeStrongFunction(IGM));
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.getOptions().EnableLayoutStringValueWitnesses) {
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
if (auto *typeLayoutEntry =
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
/*useStructLayouts*/true)) {
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
->getGenericSignature();
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
Expand All @@ -1077,9 +1081,10 @@ static void addValueWitness(IRGenModule &IGM, ConstantStructBuilder &B,
return addFunction(getInitWithCopyStrongFunction(IGM));
} else if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.getOptions().EnableLayoutStringValueWitnesses) {
auto ty = boundGenericCharacteristics ? boundGenericCharacteristics->concreteType : concreteType;
auto &typeInfo = boundGenericCharacteristics ? *boundGenericCharacteristics->TI : concreteTI;
if (auto *typeLayoutEntry =
concreteTI.buildTypeLayoutEntry(IGM, concreteType,
/*useStructLayouts*/true)) {
typeInfo.buildTypeLayoutEntry(IGM, ty, /*useStructLayouts*/true)) {
auto genericSig = concreteType.getNominalOrBoundGenericNominal()
->getGenericSignature();
if (typeLayoutEntry->layoutString(IGM, genericSig) ||
Expand Down
5 changes: 4 additions & 1 deletion stdlib/public/runtime/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2833,7 +2833,10 @@ void swift::swift_initStructMetadataWithLayoutString(
previousFieldOffset = fieldType->vw_size();
fullOffset += previousFieldOffset;
} else if (fieldType->isAnyExistentialType()) {
auto tag = RefCountingKind::Existential;
auto *existential = dyn_cast<ExistentialTypeMetadata>(fieldType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

assert(existential);
auto tag = existential->isClassBounded() ? RefCountingKind::Unknown
: RefCountingKind::Existential;
*(uint64_t*)(layoutStr + layoutStrOffset) =
((uint64_t)tag << 56) | offset;
layoutStrOffset += sizeof(uint64_t);
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/layout_string_union_types.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-type-layout -emit-ir -import-objc-header %S/Inputs/union_type.h %s
// 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

struct UnionWrapper {
let x: TestUnion
Expand Down
34 changes: 27 additions & 7 deletions test/Interpreter/Inputs/layout_string_witnesses_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -365,20 +365,40 @@ public struct ComplexNesting<A, B, C, D> {
}

internal enum InternalEnum {
case a(Int, AnyObject)
case b(Int)
case c(String)
case a(Int, AnyObject)
case b(Int)
case c(String)
}

public struct InternalEnumWrapper {
internal let x: InternalEnum
internal let y: Int = 32
internal let x: InternalEnum
internal let y: Int = 32

public init(x: AnyObject) {
self.x = .a(23, x)
public init(x: AnyObject) {
self.x = .a(23, x)
}
}

public struct PrespecializedStruct<T> {
let y: Int = 0
let x: T
let z: T

public init(x: T) {
self.x = x
self.z = x
}
}

@inline(never)
public func consume<T>(_ x: T.Type) {
withExtendedLifetime(x) {}
}
public func preSpec() {
consume(PrespecializedStruct<AnyObject>.self)
consume(PrespecializedStruct<SimpleClass>.self)
consume(PrespecializedStruct<Int>.self)
}

@inline(never)
public func testAssign<T>(_ ptr: UnsafeMutablePointer<T>, from x: T) {
Expand Down
94 changes: 86 additions & 8 deletions test/Interpreter/layout_string_witnesses_dynamic.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@


// RUN: %empty-directory(%t)
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
// 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
// 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
// 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)
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os

// REQUIRES: executable_test

Expand Down Expand Up @@ -52,6 +51,85 @@ func testGeneric() {

testGeneric()

func testPrespecializedAnyObject() {
let ptr = UnsafeMutablePointer<PrespecializedStruct<AnyObject>>.allocate(capacity: 1)

do {
let x = PrespecializedStruct<AnyObject>(x: SimpleClass(x: 23))
testInit(ptr, to: x)
}

do {
let y = PrespecializedStruct<AnyObject>(x: SimpleClass(x: 32))

// CHECK-NEXT: Before deinit
print("Before deinit")

// CHECK-NEXT: SimpleClass deinitialized!
testAssign(ptr, from: y)
}

// CHECK-NEXT: Before deinit
print("Before deinit")


// CHECK-NEXT: SimpleClass deinitialized!
testDestroy(ptr)

ptr.deallocate()
}

testPrespecializedAnyObject()

func testPrespecializedSimpleClass() {
let ptr = UnsafeMutablePointer<PrespecializedStruct<SimpleClass>>.allocate(capacity: 1)

do {
let x = PrespecializedStruct<SimpleClass>(x: SimpleClass(x: 23))
testInit(ptr, to: x)
}

do {
let y = PrespecializedStruct<SimpleClass>(x: SimpleClass(x: 32))

// CHECK-NEXT: Before deinit
print("Before deinit")

// CHECK-NEXT: SimpleClass deinitialized!
testAssign(ptr, from: y)
}

// CHECK-NEXT: Before deinit
print("Before deinit")


// CHECK-NEXT: SimpleClass deinitialized!
testDestroy(ptr)

ptr.deallocate()
}

testPrespecializedSimpleClass()


func testPrespecializedInt() {
let ptr = UnsafeMutablePointer<PrespecializedStruct<Int>>.allocate(capacity: 1)

do {
let x = PrespecializedStruct<Int>(x: 23)
testInit(ptr, to: x)
}

do {
let y = PrespecializedStruct<Int>(x: 32)
testAssign(ptr, from: y)
}

ptr.deallocate()
}

testPrespecializedInt()

func testGenericTuple() {
let ptr = allocateInternalGenericPtr(of: GenericTupleWrapper<TestClass>.self)

Expand Down
10 changes: 5 additions & 5 deletions test/Interpreter/layout_string_witnesses_static.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// RUN: %empty-directory(%t)
// 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
// 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

// NOTE: We have to build this as dylib to turn private external symbols into local symbols, so we can observe potential issues with linkage
// 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
// 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
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
// 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
// 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
// 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)
// 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
// 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
// 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)
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os

Expand Down