Skip to content

Commit 439aa4b

Browse files
authored
Merge pull request #68781 from kubamracek/embedded-debuginfo
[embedded] Remove unspecialized functions before running IRGen
2 parents 8610b25 + ff1d177 commit 439aa4b

File tree

11 files changed

+83
-17
lines changed

11 files changed

+83
-17
lines changed

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ class SILOptions {
276276
/// is a single SILModule in a single thread.
277277
bool checkSILModuleLeaks = false;
278278

279+
/// Are we building in embedded Swift mode?
280+
bool EmbeddedSwift = false;
281+
279282
/// The name of the file to which the backend should save optimization
280283
/// records.
281284
std::string OptRecordFile;

include/swift/SIL/SILFunction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,12 @@ class SILFunction
781781
return getLoweredFunctionType()->hasIndirectFormalResults();
782782
}
783783

784+
// Returns true if the function has any generic arguments.
785+
bool isGeneric() const {
786+
auto s = getLoweredFunctionType()->getInvocationGenericSignature();
787+
return s && !s->areAllParamsConcrete();
788+
}
789+
784790
/// Returns true if this function ie either a class method, or a
785791
/// closure that captures the 'self' value or its metatype.
786792
///

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,6 +3118,7 @@ bool CompilerInvocation::parseArgs(
31183118
IRGenOpts.InternalizeAtLink = true;
31193119
IRGenOpts.DisableLegacyTypeInfo = true;
31203120
SILOpts.CMOMode = CrossModuleOptimizationMode::Everything;
3121+
SILOpts.EmbeddedSwift = true;
31213122
}
31223123

31233124
return false;

lib/IRGen/GenDecl.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,18 @@ void IRGenerator::emitGlobalTopLevel(
12941294
// Emit SIL functions.
12951295
auto &m = PrimaryIGM->getSILModule();
12961296
for (SILFunction &f : m) {
1297+
// Generic functions should not be present in embedded Swift.
1298+
//
1299+
// TODO: Cannot enable this check yet because we first need removal of
1300+
// unspecialized classes and class vtables in SIL.
1301+
//
1302+
// if (SIL.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
1303+
// if (f.isGeneric()) {
1304+
// llvm::errs() << "Unspecialized function: \n" << f << "\n";
1305+
// llvm_unreachable("unspecialized function present in embedded Swift");
1306+
// }
1307+
// }
1308+
12971309
if (isLazilyEmittedFunction(f, m))
12981310
continue;
12991311

@@ -1407,11 +1419,6 @@ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRec
14071419
emitLazyTypeContextDescriptor(IGM, &decl, RequireMetadata);
14081420
}
14091421

1410-
static bool loweredFunctionHasGenericArguments(SILFunction *f) {
1411-
auto s = f->getLoweredFunctionType()->getInvocationGenericSignature();
1412-
return s && !s->areAllParamsConcrete();
1413-
}
1414-
14151422
/// Emit any lazy definitions (of globals or functions or whatever
14161423
/// else) that we require.
14171424
void IRGenerator::emitLazyDefinitions() {
@@ -1424,7 +1431,7 @@ void IRGenerator::emitLazyDefinitions() {
14241431
assert(LazyFieldDescriptors.empty());
14251432
// LazyFunctionDefinitions are allowed, but they must not be generic
14261433
for (SILFunction *f : LazyFunctionDefinitions) {
1427-
assert(!loweredFunctionHasGenericArguments(f));
1434+
assert(!f->isGeneric());
14281435
}
14291436
assert(LazyWitnessTables.empty());
14301437
assert(LazyCanonicalSpecializedMetadataAccessors.empty());
@@ -1554,7 +1561,7 @@ void IRGenerator::addLazyFunction(SILFunction *f) {
15541561

15551562
// Embedded Swift doesn't expect any generic functions to be referenced.
15561563
if (SIL.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
1557-
assert(!loweredFunctionHasGenericArguments(f));
1564+
assert(!f->isGeneric());
15581565
}
15591566

15601567
assert(!FinishedEmittingLazyDefinitions);

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ class DeadFunctionAndGlobalElimination {
9292

9393
/// Checks is a function is alive, e.g. because it is visible externally.
9494
bool isAnchorFunction(SILFunction *F) {
95+
// In embedded Swift, (even public) generic functions *after serialization*
96+
// cannot be used externally and are not anchors.
97+
bool embedded = Module->getOptions().EmbeddedSwift;
98+
bool generic = F->isGeneric();
99+
bool isSerialized = Module->isSerialized();
100+
if (embedded && generic && isSerialized)
101+
return false;
95102

96103
// Functions that may be used externally cannot be removed.
97104
if (F->isPossiblyUsedExternally())
@@ -148,6 +155,7 @@ class DeadFunctionAndGlobalElimination {
148155

149156
/// Marks a function as alive.
150157
void makeAlive(SILFunction *F) {
158+
LLVM_DEBUG(llvm::dbgs() << " makeAlive " << F->getName() << '\n');
151159
AliveFunctionsAndTables.insert(F);
152160
assert(F && "function does not exist");
153161
Worklist.insert(F);
@@ -431,7 +439,11 @@ class DeadFunctionAndGlobalElimination {
431439
F.forEachSpecializeAttrTargetFunction(
432440
[this](SILFunction *targetFun) { ensureAlive(targetFun); });
433441

434-
if (!F.shouldOptimize()) {
442+
bool retainBecauseFunctionIsNoOpt = !F.shouldOptimize();
443+
if (Module->getOptions().EmbeddedSwift)
444+
retainBecauseFunctionIsNoOpt = false;
445+
446+
if (retainBecauseFunctionIsNoOpt) {
435447
LLVM_DEBUG(llvm::dbgs() << " anchor a no optimization function: "
436448
<< F.getName() << "\n");
437449
ensureAlive(&F);
@@ -526,6 +538,8 @@ class DeadFunctionAndGlobalElimination {
526538

527539
// Check vtable methods.
528540
for (auto &vTable : Module->getVTables()) {
541+
LLVM_DEBUG(llvm::dbgs() << " processing vtable "
542+
<< vTable->getClass()->getName() << '\n');
529543
for (const SILVTable::Entry &entry : vTable->getEntries()) {
530544
if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator ||
531545
entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) {

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
354354
RuntimeEffect impact = getRuntimeEffect(inst, impactType);
355355
LocWithParent loc(inst->getLoc().getSourceLoc(), parentLoc);
356356

357-
if (module.getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
357+
if (module.getOptions().EmbeddedSwift &&
358358
impact & RuntimeEffect::Existential) {
359359
PrettyStackTracePerformanceDiagnostics stackTrace("existential", inst);
360360
diagnose(loc, diag::performance_metadata, "existential");
@@ -507,7 +507,7 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
507507
void PerformanceDiagnostics::checkNonAnnotatedFunction(SILFunction *function) {
508508
for (SILBasicBlock &block : *function) {
509509
for (SILInstruction &inst : block) {
510-
if (function->getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
510+
if (function->getModule().getOptions().EmbeddedSwift) {
511511
auto loc = LocWithParent(inst.getLoc().getSourceLoc(), nullptr);
512512
visitInst(&inst, PerformanceConstraints::None, &loc);
513513
}
@@ -607,17 +607,17 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
607607
}
608608
}
609609

610-
if (!annotatedFunctionsFound &&
611-
!getModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded))
610+
if (!annotatedFunctionsFound && !getModule()->getOptions().EmbeddedSwift)
612611
return;
613612

614613
for (SILFunction &function : *module) {
615614
// Don't rerun diagnostics on deserialized functions.
616615
if (function.wasDeserializedCanonical())
617616
continue;
618617

619-
// Don't check generic functions, they're about to be removed anyway.
620-
if (getModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
618+
// Don't check generic functions in embedded Swift, they're about to be
619+
// removed anyway.
620+
if (getModule()->getOptions().EmbeddedSwift &&
621621
function.getLoweredFunctionType()->getSubstGenericSignature())
622622
continue;
623623

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,13 @@ SILPassPipelinePlan::getOnonePassPipeline(const SILOptions &Options) {
10441044
// constant folded before any generic specialization.
10451045
P.addLateOnoneSimplification();
10461046

1047+
if (Options.EmbeddedSwift) {
1048+
// For embedded Swift: Remove all unspecialized functions. This is important
1049+
// to avoid having debuginfo references to these functions that we don't
1050+
// want to emit in IRGen.
1051+
P.addLateDeadFunctionAndGlobalElimination();
1052+
}
1053+
10471054
P.addCleanupDebugSteps();
10481055

10491056
// Has only an effect if the -sil-based-debuginfo option is specified.

lib/SILOptimizer/Transforms/VTableSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class VTableSpecializer : public SILModuleTransform {
4343
void run() override {
4444
SILModule &module = *getModule();
4545

46-
if (!module.getASTContext().LangOpts.hasFeature(Feature::Embedded)) return;
46+
if (!module.getOptions().EmbeddedSwift) return;
4747

4848
LLVM_DEBUG(llvm::dbgs() << "***** VTableSpecializer\n");
4949

lib/SILOptimizer/UtilityPasses/Link.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class SILLinker : public SILModuleTransform {
3939

4040
// In embedded Swift, the stdlib contains all the runtime functions needed
4141
// (swift_retain, etc.). Link them in so they can be referenced in IRGen.
42-
if (M.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
42+
if (M.getOptions().EmbeddedSwift) {
4343
linkEmbeddedRuntimeFromStdlib();
4444
}
4545
}

test/embedded/classes-methods-no-stdlib.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class MySubClass: MyClass {
99
override func foo() { }
1010
}
1111

12-
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main7MyClassCACycfC" }>
12+
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @swift_deletedMethodError }>
1313
// CHECK: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr @"$s4main10MySubClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main10MySubClassCACycfC" }>
1414

1515
// CHECK: define {{.*}}void @"$s4main4test1xyAA7MyClassC_tF"(ptr %0)

test/embedded/debuginfo.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-frontend -g -emit-ir %s -enable-experimental-feature Embedded
2+
// RUN: %target-swift-frontend -g -O -emit-ir %s -enable-experimental-feature Embedded
3+
// RUN: %target-swift-frontend -g -Osize -emit-ir %s -enable-experimental-feature Embedded
4+
// RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature Embedded
5+
// RUN: %target-swift-frontend -O -emit-ir %s -enable-experimental-feature Embedded
6+
// RUN: %target-swift-frontend -Osize -emit-ir %s -enable-experimental-feature Embedded
7+
8+
// REQUIRES: swift_in_compiler
9+
// REQUIRES: VENDOR=apple
10+
// REQUIRES: OS=macosx
11+
12+
public func foo<T>(_ array: inout [T]) {
13+
array.withUnsafeMutableBytes {
14+
$0[0] = 0
15+
}
16+
}
17+
18+
func foo2<T>(_ array: inout [T]) {
19+
array.withUnsafeMutableBytes {
20+
$0[0] = 0
21+
}
22+
}
23+
24+
public func test() {
25+
var a: [UInt8] = [1, 2, 3]
26+
foo(&a)
27+
foo2(&a)
28+
}

0 commit comments

Comments
 (0)