Skip to content

Commit c0c25be

Browse files
committed
IRGen: Ensure that default witness thunks are emitted in the same thread as the protocol descriptor
Protocol descriptors for resilient protocols relatively-reference default witness thunks, so when using -num-threads N with N > 1, we must ensure the default witness thunk is emitted in the same LLVM module.
1 parent 13e5c50 commit c0c25be

File tree

6 files changed

+52
-15
lines changed

6 files changed

+52
-15
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ static bool hasCodeCoverageInstrumentation(SILFunction &f, SILModule &m) {
985985
return f.getProfiler() && m.getOptions().EmitProfileCoverageMapping;
986986
}
987987

988-
void IRGenerator::emitGlobalTopLevel(bool emitForParallelEmission) {
988+
void IRGenerator::emitGlobalTopLevel() {
989989
// Generate order numbers for the functions in the SIL module that
990990
// correspond to definitions in the LLVM module.
991991
unsigned nextOrderNumber = 0;
@@ -996,10 +996,14 @@ void IRGenerator::emitGlobalTopLevel(bool emitForParallelEmission) {
996996
}
997997

998998
// Ensure that relative symbols are collocated in the same LLVM module.
999-
for (SILWitnessTable &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
999+
for (auto &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
10001000
CurrentIGMPtr IGM = getGenModule(wt.getDeclContext());
1001-
if (emitForParallelEmission)
1002-
IGM->ensureRelativeSymbolCollocation(wt);
1001+
ensureRelativeSymbolCollocation(wt);
1002+
}
1003+
1004+
for (auto &wt : PrimaryIGM->getSILModule().getDefaultWitnessTableList()) {
1005+
CurrentIGMPtr IGM = getGenModule(wt.getProtocol()->getDeclContext());
1006+
ensureRelativeSymbolCollocation(wt);
10031007
}
10041008

10051009
for (SILGlobalVariable &v : PrimaryIGM->getSILModule().getSILGlobals()) {

lib/IRGen/GenProto.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
#include "swift/ClangImporter/ClangModule.h"
3939
#include "swift/IRGen/Linking.h"
4040
#include "swift/SIL/SILDeclRef.h"
41+
#include "swift/SIL/SILDefaultWitnessTable.h"
4142
#include "swift/SIL/SILModule.h"
4243
#include "swift/SIL/SILValue.h"
44+
#include "swift/SIL/SILWitnessTable.h"
4345
#include "swift/SIL/SILWitnessVisitor.h"
4446
#include "swift/SIL/TypeLowering.h"
4547
#include "llvm/ADT/SmallString.h"
@@ -2091,7 +2093,10 @@ void IRGenModule::emitProtocolConformance(
20912093
setTrueConstGlobal(var);
20922094
}
20932095

2094-
void IRGenModule::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
2096+
void IRGenerator::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
2097+
if (!CurrentIGM)
2098+
return;
2099+
20952100
// Only resilient conformances use relative pointers for witness methods.
20962101
if (wt.isDeclaration() || isAvailableExternally(wt.getLinkage()) ||
20972102
!isResilientConformance(wt.getConformance()))
@@ -2102,7 +2107,20 @@ void IRGenModule::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
21022107
continue;
21032108
auto *witness = entry.getMethodWitness().Witness;
21042109
if (witness)
2105-
IRGen.forceLocalEmitOfLazyFunction(witness);
2110+
forceLocalEmitOfLazyFunction(witness);
2111+
}
2112+
}
2113+
2114+
void IRGenerator::ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt) {
2115+
if (!CurrentIGM)
2116+
return;
2117+
2118+
for (auto &entry : wt.getEntries()) {
2119+
if (entry.getKind() != SILWitnessTable::Method)
2120+
continue;
2121+
auto *witness = entry.getMethodWitness().Witness;
2122+
if (witness)
2123+
forceLocalEmitOfLazyFunction(witness);
21062124
}
21072125
}
21082126

@@ -2246,6 +2264,10 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
22462264
if (isAvailableExternally(wt->getLinkage()))
22472265
return;
22482266

2267+
// Ensure that relatively-referenced symbols for witness thunks are collocated
2268+
// in the same LLVM module.
2269+
IRGen.ensureRelativeSymbolCollocation(*wt);
2270+
22492271
auto conf = wt->getConformance();
22502272
PrettyStackTraceConformance _st(Context, "emitting witness table for", conf);
22512273

lib/IRGen/IRGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,11 @@ static void performParallelIRGeneration(
964964
}
965965

966966
// Emit the module contents.
967-
irgen.emitGlobalTopLevel(true /*emitForParallelEmission*/);
967+
irgen.emitGlobalTopLevel();
968968

969969
for (auto *File : M->getFiles()) {
970970
if (auto *SF = dyn_cast<SourceFile>(File)) {
971-
IRGenModule *IGM = irgen.getGenModule(SF);
971+
CurrentIGMPtr IGM = irgen.getGenModule(SF);
972972
IGM->emitSourceFile(*SF);
973973
} else {
974974
File->collectLinkLibraries([&](LinkLibrary LinkLib) {

lib/IRGen/IRGenModule.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ namespace swift {
9393
class ProtocolCompositionType;
9494
class RootProtocolConformance;
9595
struct SILDeclRef;
96+
class SILDefaultWitnessTable;
9697
class SILGlobalVariable;
9798
class SILModule;
9899
class SILProperty;
@@ -311,11 +312,7 @@ class IRGenerator {
311312

312313
/// Emit functions, variables and tables which are needed anyway, e.g. because
313314
/// they are externally visible.
314-
/// If \p emitForParallelEmission is true ensures that symbols that are
315-
/// expressed as relative pointers are collocated in the same output module
316-
/// with their base symbol. For example, witness methods need to be collocated
317-
/// with the witness table in the same LLVM module.
318-
void emitGlobalTopLevel(bool emitForParallelEmission = false);
315+
void emitGlobalTopLevel();
319316

320317
/// Emit references to each of the protocol descriptors defined in this
321318
/// IR module.
@@ -355,6 +352,10 @@ class IRGenerator {
355352
DefaultIGMForFunction[f] = CurrentIGM;
356353
}
357354

355+
void ensureRelativeSymbolCollocation(SILWitnessTable &wt);
356+
357+
void ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt);
358+
358359
void noteUseOfTypeMetadata(NominalTypeDecl *type) {
359360
noteUseOfTypeGlobals(type, true, RequireMetadata);
360361
}
@@ -1385,8 +1386,6 @@ private: \
13851386

13861387
void emitSharedContextDescriptor(DeclContext *dc);
13871388

1388-
void ensureRelativeSymbolCollocation(SILWitnessTable &wt);
1389-
13901389
llvm::GlobalVariable *
13911390
getGlobalForDynamicallyReplaceableThunk(LinkEntity &entity, llvm::Type *type,
13921391
ForDefinition_t forDefinition);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extension Defaultable {
2+
public func defaulted() {}
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience
3+
// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-testing
4+
// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-resilience
5+
// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-testing -enable-resilience
6+
7+
public protocol Defaultable {
8+
func defaulted()
9+
}

0 commit comments

Comments
 (0)