Skip to content

Commit b049319

Browse files
committed
[embedded] Remove unspecialized functions before running IRGen
1 parent 8577c6b commit b049319

File tree

6 files changed

+70
-7
lines changed

6 files changed

+70
-7
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,11 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
12611261
return true;
12621262
}
12631263

1264+
static bool loweredFunctionHasGenericArguments(SILFunction *f) {
1265+
auto s = f->getLoweredFunctionType()->getInvocationGenericSignature();
1266+
return s && !s->areAllParamsConcrete();
1267+
}
1268+
12641269
void IRGenerator::emitGlobalTopLevel(
12651270
const std::vector<std::string> &linkerDirectives) {
12661271
// Generate order numbers for the functions in the SIL module that
@@ -1294,6 +1299,19 @@ void IRGenerator::emitGlobalTopLevel(
12941299
// Emit SIL functions.
12951300
auto &m = PrimaryIGM->getSILModule();
12961301
for (SILFunction &f : m) {
1302+
// Generic functions should not be present in embedded Swift.
1303+
//
1304+
// TODO: Cannot enable this check yet because we first need removal of
1305+
// unspecialized classes and class vtables in SIL.
1306+
//
1307+
// if (SIL.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
1308+
// bool isGeneric = loweredFunctionHasGenericArguments(&f);
1309+
// if (isGeneric) {
1310+
// llvm::errs() << "Unspecialized function: \n" << f << "\n";
1311+
// assert(0 && "unspecialized function present in embedded Swift");
1312+
// }
1313+
// }
1314+
12971315
if (isLazilyEmittedFunction(f, m))
12981316
continue;
12991317

@@ -1407,11 +1425,6 @@ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRec
14071425
emitLazyTypeContextDescriptor(IGM, &decl, RequireMetadata);
14081426
}
14091427

1410-
static bool loweredFunctionHasGenericArguments(SILFunction *f) {
1411-
auto s = f->getLoweredFunctionType()->getInvocationGenericSignature();
1412-
return s && !s->areAllParamsConcrete();
1413-
}
1414-
14151428
/// Emit any lazy definitions (of globals or functions or whatever
14161429
/// else) that we require.
14171430
void IRGenerator::emitLazyDefinitions() {

lib/SIL/IR/SILFunction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,11 @@ bool SILFunction::hasValidLinkageForFragileRef() const {
842842
return hasPublicVisibility(getLinkage());
843843
}
844844

845+
static bool loweredFunctionHasGenericArguments(const SILFunction *f) {
846+
auto s = f->getLoweredFunctionType()->getInvocationGenericSignature();
847+
return s && !s->areAllParamsConcrete();
848+
}
849+
845850
bool
846851
SILFunction::isPossiblyUsedExternally() const {
847852
auto linkage = getLinkage();
@@ -869,6 +874,13 @@ SILFunction::isPossiblyUsedExternally() const {
869874
hasOpaqueResultTypeWithAvailabilityConditions())
870875
return true;
871876

877+
// In embedded Swift, generic functions, even public ones cannot be used
878+
// externally.
879+
bool embedded = getASTContext().LangOpts.hasFeature(Feature::Embedded);
880+
bool generic = loweredFunctionHasGenericArguments(this);
881+
if (embedded && generic)
882+
return false;
883+
872884
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
873885
}
874886

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class DeadFunctionAndGlobalElimination {
148148

149149
/// Marks a function as alive.
150150
void makeAlive(SILFunction *F) {
151+
LLVM_DEBUG(llvm::dbgs() << " makeAlive " << F->getName() << '\n');
151152
AliveFunctionsAndTables.insert(F);
152153
assert(F && "function does not exist");
153154
Worklist.insert(F);
@@ -431,7 +432,11 @@ class DeadFunctionAndGlobalElimination {
431432
F.forEachSpecializeAttrTargetFunction(
432433
[this](SILFunction *targetFun) { ensureAlive(targetFun); });
433434

434-
if (!F.shouldOptimize()) {
435+
bool retainBecauseFunctionIsNoOpt = !F.shouldOptimize();
436+
if (Module->getASTContext().LangOpts.hasFeature(Feature::Embedded))
437+
retainBecauseFunctionIsNoOpt = false;
438+
439+
if (retainBecauseFunctionIsNoOpt) {
435440
LLVM_DEBUG(llvm::dbgs() << " anchor a no optimization function: "
436441
<< F.getName() << "\n");
437442
ensureAlive(&F);
@@ -526,6 +531,8 @@ class DeadFunctionAndGlobalElimination {
526531

527532
// Check vtable methods.
528533
for (auto &vTable : Module->getVTables()) {
534+
LLVM_DEBUG(llvm::dbgs() << " processing vtable "
535+
<< vTable->getClass()->getName() << '\n');
529536
for (const SILVTable::Entry &entry : vTable->getEntries()) {
530537
if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator ||
531538
entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) {

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,9 @@ SILPassPipelinePlan::getIRGenPreparePassPipeline(const SILOptions &Options) {
891891
// boundaries as required by the ABI.
892892
P.addLoadableByAddress();
893893

894+
// For embedded Swift: Remove all unspecialized functions.
895+
P.addLateDeadFunctionAndGlobalElimination();
896+
894897
if (Options.EnablePackMetadataStackPromotion) {
895898
// Insert marker instructions indicating where on-stack pack metadata
896899
// deallocation must occur.

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)