Files
swift-mirror/test/IRGen/conditional-dead-strip-exec.swift
Augusto Noronha 529845056b Fix functions not being kept for debugger
At Onone, many types of functions (anything user written, compiler
generated setters and getters, etc), should be kept in the final
binary so they're accessible by the debugger.

rdar://126763340
2024-05-14 10:31:44 -07:00

107 lines
2.9 KiB
Swift

// Tests that with -conditional-runtime-records, LLVM GlobalDCE is able to
// remove unused classes, protocols and protocol conformances.
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -Xfrontend -conditional-runtime-records %s -emit-ir -o %t/main.ll
// RUN: %target-clang %t/main.ll -isysroot %sdk -L%swift-lib-dir/swift/%target-sdk-name -flto -o %t/main
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %s
// RUN: %llvm-nm --defined-only %t/main | %FileCheck %s --check-prefix=NM
// REQUIRES: executable_test
// FIXME(mracek): More work needed to get this to work on non-Apple platforms.
// REQUIRES: VENDOR=apple
// For LTO, the linker dlopen()'s the libLTO library, which is a scenario that
// ASan cannot work in ("Interceptors are not working, AddressSanitizer is
// loaded too late").
// REQUIRES: no_asan
// (1) used
@inline(never) func func1_used() { print("func1_used") }
// (2) unused
@_semantics("no.preserve.debugger")
@inline(never) func func2_dead() { print("func2_dead") }
// (3) completely unused
protocol CompletelyUnusedProtocol { }
// (4) implemented only by an unused class (4), thus unused
protocol TheProtocol { }
// (5) unused class
class MyClass: TheProtocol {
@_semantics("no.preserve.debugger")
func unused_method() {}
}
// (6) implemented by a used class (8), but unused, thus unused
protocol UnusedProto { }
// (7) implemented and used (8)
protocol ActuallyUsedProto {
func bark()
}
// (8) used class, but the UnusedProto conformance is unused because the UnusedProto protocol itself is unused
class UsedClass : UnusedProto, ActuallyUsedProto {
public func bark() { print("UsedClass.bark") }
}
// (9) unused protocol with associated type
protocol ProtoWithAssocType { associatedtype T }
struct Implementor : ProtoWithAssocType { typealias T = Int }
print("Hello!")
func1_used()
let o = UsedClass()
o.bark()
let p: ActuallyUsedProto = UsedClass()
p.bark()
// CHECK: Hello!
// CHECK: func1_used
// CHECK: UsedClass.bark
// CHECK: UsedClass.bark
// In summary, only the following should be kept alive in the binary result:
// func func1_used() { ... }
// protocol ActuallyUsedProto { ... }
// class UsedClass : ActuallyUsedProto /* UnusedProto conformance removed */ { ... }
// (1)
// NM: $s4main10func1_usedyyF
// (2)
// NM-NOT: $s4main10func2_deadyyF
// (9)
// NM-NOT: $s4main11ImplementorVAA18ProtoWithAssocTypeAAMA
// NM-NOT: $s4main11ImplementorVMf
// NM-NOT: $s4main11ImplementorVMn
// (4)
// NM-NOT: $s4main11TheProtocolMp
// (6)
// NM-NOT: $s4main11UnusedProtoMp
// (3)
// NM-NOT: $s4main24CompletelyUnusedProtocolMp
// (5)
// NM-NOT: $s4main7MyClassC13unused_methodyyF
// NM-NOT: $s4main7MyClassCAA11TheProtocolAAMc
// NM-NOT: $s4main7MyClassCAA11TheProtocolAAWP
// NM-NOT: $s4main7MyClassCMf
// NM-NOT: $s4main7MyClassCMn
// (8)
// NM-NOT: $s4main9UsedClassCAA11UnusedProtoAAMc
// NM-NOT: $s4main9UsedClassCAA11UnusedProtoAAWP