Skip to content

Commit ea70aea

Browse files
committed
IRGen: Add code to support building fragile resilient protocol witnesses
We don't currently support building resilient relative protocol witness tables. One might want to build with relative witness tables but not need resilient protocols. Allow for that scenario. Add a test configuration to test library-evolution + fragile resilient protocols + relative protocol witness tables.
1 parent a79ee61 commit ea70aea

File tree

14 files changed

+138
-2
lines changed

14 files changed

+138
-2
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,8 @@ class IRGenOptions {
467467
/// Use relative (and constant) protocol witness tables.
468468
unsigned UseRelativeProtocolWitnessTables : 1;
469469

470+
unsigned UseFragileResilientProtocolWitnesses : 1;
471+
470472
/// The number of threads for multi-threaded code generation.
471473
unsigned NumThreads = 0;
472474

@@ -555,6 +557,7 @@ class IRGenOptions {
555557
EmitGenericRODatas(false), NoPreallocatedInstantiationCaches(false),
556558
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
557559
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
560+
UseFragileResilientProtocolWitnesses(false),
558561
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
559562
TypeInfoFilter(TypeInfoDumpFilter::All),
560563
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),

include/swift/Option/FrontendOptions.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,12 @@ def enable_relative_protocol_witness_tables :
12601260
def disable_relative_protocol_witness_tables :
12611261
Flag<["-"], "disable-relative-protocol-witness-tables">,
12621262
HelpText<"Disable relative protocol witness tables">;
1263+
def enable_fragile_resilient_protocol_witnesses :
1264+
Flag<["-"], "enable-fragile-relative-protocol-tables">,
1265+
HelpText<"Enable relative protocol witness tables">;
1266+
def disable_fragile_resilient_protocol_witnesses :
1267+
Flag<["-"], "disable-fragile-relative-protocol-tables">,
1268+
HelpText<"Disable relative protocol witness tables">;
12631269

12641270
def enable_new_llvm_pass_manager :
12651271
Flag<["-"], "enable-new-llvm-pass-manager">,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,6 +3042,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
30423042
Args.hasFlag(OPT_enable_relative_protocol_witness_tables,
30433043
OPT_disable_relative_protocol_witness_tables,
30443044
Opts.UseRelativeProtocolWitnessTables);
3045+
Opts.UseFragileResilientProtocolWitnesses =
3046+
Args.hasFlag(OPT_enable_fragile_resilient_protocol_witnesses,
3047+
OPT_disable_fragile_resilient_protocol_witnesses,
3048+
Opts.UseFragileResilientProtocolWitnesses);
30453049
Opts.EnableLargeLoadableTypesReg2Mem =
30463050
Args.hasFlag(OPT_enable_large_loadable_types_reg2mem,
30473051
OPT_disable_large_loadable_types_reg2mem,

lib/IRGen/GenDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6015,6 +6015,11 @@ bool IRGenModule::isResilient(NominalTypeDecl *D,
60156015
ClassDecl *asViewedFromRootClass) {
60166016
assert(!asViewedFromRootClass || isa<ClassDecl>(D));
60176017

6018+
// Ignore resilient protocols if requested.
6019+
if (isa<ProtocolDecl>(D) && IRGen.Opts.UseFragileResilientProtocolWitnesses) {
6020+
return false;
6021+
}
6022+
60186023
if (D->getModuleContext()->getBypassResilience())
60196024
return false;
60206025
if (expansion == ResilienceExpansion::Maximal &&

lib/IRGen/GenProto.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,10 @@ bool IRGenModule::isResilientConformance(
953953
const NormalProtocolConformance *conformance) {
954954
// If the protocol is not resilient, the conformance is not resilient
955955
// either.
956-
if (!conformance->getProtocol()->isResilient())
956+
bool shouldTreatProtocolNonResilient =
957+
IRGen.Opts.UseFragileResilientProtocolWitnesses;
958+
if (!conformance->getProtocol()->isResilient() ||
959+
shouldTreatProtocolNonResilient)
957960
return false;
958961

959962
auto *conformanceModule = conformance->getDeclContext()->getParentModule();
@@ -2156,6 +2159,7 @@ namespace {
21562159
void addResilientWitnesses() {
21572160
if (Description.resilientWitnesses.empty())
21582161
return;
2162+
assert(!IGM.IRGen.Opts.UseFragileResilientProtocolWitnesses);
21592163

21602164
Flags = Flags.withHasResilientWitnesses(true);
21612165

@@ -2528,6 +2532,16 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
25282532
bool isResilient = isResilientConformance(conf);
25292533
bool useRelativeProtocolWitnessTable =
25302534
IRGen.Opts.UseRelativeProtocolWitnessTables;
2535+
if (useRelativeProtocolWitnessTable &&
2536+
!conf->getConditionalRequirements().empty()) {
2537+
auto nominal = conf->getType()->getAnyNominal();
2538+
auto sig = nominal->getGenericSignatureOfContext();
2539+
sig->forEachParam([&](GenericTypeParamType *param, bool canonical) {
2540+
if (param->isParameterPack()) {
2541+
wt->dump();
2542+
llvm::report_fatal_error("use of relative protcol witness tables not supported");
2543+
}});
2544+
}
25312545
if (!isResilient) {
25322546
// Build the witness table.
25332547
ConstantInitBuilder builder(*this);

stdlib/cmake/modules/AddSwiftStdlib.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ function(_add_target_variant_c_compile_flags)
453453
list(APPEND result "-DSWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES")
454454
endif()
455455

456+
if(SWIFT_STDLIB_USE_FRAGILE_RESILIENT_PROTOCOL_WITNESS_TABLES)
457+
list(APPEND result "-DSWIFT_STDLIB_USE_FRAGILE_RESILIENT_PROTOCOL_WITNESS_TABLES")
458+
endif()
459+
456460
if(SWIFT_STDLIB_OVERRIDABLE_RETAIN_RELEASE)
457461
list(APPEND result "-DSWIFT_STDLIB_OVERRIDABLE_RETAIN_RELEASE")
458462
endif()

stdlib/cmake/modules/StdlibOptions.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,10 @@ option(SWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES
270270
"Use relative protocol witness tables"
271271
FALSE)
272272

273+
option(SWIFT_STDLIB_USE_FRAGILE_RESILIENT_PROTOCOL_WITNESS_TABLES
274+
"Use fragile protocol witness tables for resilient protocols"
275+
FALSE)
276+
273277
if("${SWIFT_HOST_VARIANT_SDK}" IN_LIST SWIFT_DARWIN_PLATFORMS)
274278
set(SWIFT_STDLIB_INSTALL_PARENT_MODULE_FOR_SHIMS_default TRUE)
275279
else()

stdlib/cmake/modules/SwiftSource.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,12 @@ function(_compile_swift_files
626626
list(APPEND swift_flags "-Xfrontend" "-swift-async-frame-pointer=never")
627627
endif()
628628

629+
if (SWIFT_STDLIB_USE_FRAGILE_RESILIENT_PROTOCOL_WITNESS_TABLES)
630+
list(APPEND swift_flags "-Xfrontend" "-validate-tbd-against-ir=none")
631+
list(APPEND swift_flags "-Xfrontend" "-enable-fragile-relative-protocol-tables")
632+
list(APPEND swift_flags "-enable-library-evolution")
633+
endif()
634+
629635
if(SWIFT_STDLIB_DISABLE_INSTANTIATION_CACHES)
630636
list(APPEND swift_flags "-Xfrontend" "-disable-preallocated-instantiation-caches")
631637
endif()

test/IRGen/relative_protocol_witness_table.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
// RUN: %target-swift-frontend -enable-relative-protocol-witness-tables -module-name A -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-cpu --check-prefix=CHECK
22

3+
// Test with resilience enabled.
4+
// In this mode we still assume protocols to be "fragile"/non changeable.
5+
// RUN: %target-swift-frontend -enable-resilience -enable-fragile-relative-protocol-tables -enable-relative-protocol-witness-tables -module-name A -primary-file %s -I %t -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-cpu --check-prefix=CHECK
6+
// RUN: %empty-directory(%t)
7+
// RUN: %target-swift-frontend -emit-module -enable-fragile-relative-protocol-tables -enable-library-evolution -enable-relative-protocol-witness-tables -emit-module-path=%t/resilient.swiftmodule -module-name=resilient %S/Inputs/relative_protocol_witness_tables2.swift
8+
// Inputs/relative_protocol_witness_tables2.swift
9+
// RUN: %target-swift-frontend -enable-fragile-relative-protocol-tables -enable-relative-protocol-witness-tables -module-name A -primary-file %s -I %t -emit-ir -DWITH_RESILIENCE | %FileCheck %s --check-prefix=CHECK-%target-cpu --check-prefix=CHECK
10+
// RUN: %target-swift-frontend -enable-fragile-relative-protocol-tables -enable-relative-protocol-witness-tables -module-name A -primary-file %s -I %t -emit-ir -DWITH_RESILIENCE | %FileCheck %s --check-prefix=EVO
11+
// RUN: not --crash %target-swift-frontend -enable-fragile-relative-protocol-tables -enable-relative-protocol-witness-tables -module-name A -primary-file %s -I %t -emit-ir -DWITH_RESILIENCE -DEXPECT_CRASH 2>&1 | %FileCheck %s --check-prefix=CRASH
12+
313
// REQUIRES: CPU=x86_64 || CPU=arm64 || CPU=arm64e
414

15+
#if WITH_RESILIENCE
16+
import resilient
17+
#endif
18+
519
func testVWT<T>(_ t: T) {
620
var local = t
721
}
@@ -323,3 +337,30 @@ func instantiate_conditional_conformance_2nd<T>(_ t : T) where T: Sub, T.S == T
323337
// CHECK: [[T26:%.*]] = call ptr @swift_getWitnessTableRelative({{.*}}@"$s1A1XVyxGAA4BaseA2aERzlMc{{.*}}, ptr {{.*}}, ptr [[T24]])
324338
// CHECK: [[T28:%.*]] = getelementptr inbounds ptr, ptr [[C0]], i32 1
325339
// CHECK: store ptr [[T26]], ptr [[T28]]
340+
341+
#if WITH_RESILIENCE
342+
public func requireFormallyResilientWitness<T: ResilientProto> (_ t: T) {
343+
t.impl()
344+
}
345+
346+
// EVO: define{{.*}} swiftcc void @"$s1A27useFormallyResilientWitnessyyF"()
347+
// EVO: call swiftcc void @"$s1A31requireFormallyResilientWitnessyyx9resilient0C5ProtoRzlF"(ptr noalias %4, ptr %1, ptr @"$s9resilient15ResilientStructVyxGAA0B5ProtoAAWP")
348+
public func useFormallyResilientWitness() {
349+
requireFormallyResilientWitness(ResilientStruct(1))
350+
}
351+
#endif
352+
353+
#if EXPECT_CRASH
354+
protocol P {
355+
func p()
356+
}
357+
358+
@available(SwiftStdlib 5.9, *)
359+
struct G<each T> {}
360+
361+
@available(SwiftStdlib 5.9, *)
362+
extension G: P where repeat each T: P {
363+
func p() {}
364+
}
365+
// CRASH: not supported
366+
#endif

test/lit.cfg

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ if run_vendor == 'apple':
11741174

11751175
# TODO: consider making the addition of these flags dependent on the CMake
11761176
# setting for hermetic seal at link
1177-
if not config.swift_freestanding_is_darwin:
1177+
if not config.swift_freestanding_is_darwin and not config.swift_stdlib_use_use_fragile_resilient_protocol_witness_tables:
11781178
swift_execution_tests_extra_flags += ' -experimental-hermetic-seal-at-link -lto=llvm-full'
11791179

11801180
if not config.swift_freestanding_is_darwin:
@@ -1186,6 +1186,9 @@ if run_vendor == 'apple':
11861186
if config.swift_stdlib_use_relative_protocol_witness_tables:
11871187
swift_execution_tests_extra_flags += ' -Xfrontend -enable-relative-protocol-witness-tables -Xfrontend -swift-async-frame-pointer=never'
11881188

1189+
if config.swift_stdlib_use_use_fragile_resilient_protocol_witness_tables:
1190+
swift_execution_tests_extra_flags += ' -Xfrontend -validate-tbd-against-ir=none -Xfrontend -enable-fragile-relative-protocol-tables'
1191+
11891192
# Build a resource dir for freestanding tests.
11901193
new_resource_dir = os.path.join(config.test_exec_root, "resource_dir")
11911194
if not os.path.exists(new_resource_dir): os.mkdir(new_resource_dir)

0 commit comments

Comments
 (0)