Skip to content

Commit ee1f150

Browse files
committed
Merge pull request #2180 from jrose-apple/UIApplicationMain
[SILGen] Use the signature of the real UIApplicationMain.
2 parents b8f7254 + 1edaafa commit ee1f150

File tree

5 files changed

+105
-18
lines changed

5 files changed

+105
-18
lines changed

lib/SILGen/SILGenFunction.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,34 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
457457
CanType IUOptNSStringTy
458458
= ImplicitlyUnwrappedOptionalType::get(NSStringTy)->getCanonicalType();
459459

460+
// Look up UIApplicationMain.
461+
// FIXME: Doing an AST lookup here is gross and not entirely sound;
462+
// we're getting away with it because the types are guaranteed to already
463+
// be imported.
464+
ASTContext &ctx = getASTContext();
465+
Module *UIKit = ctx.getLoadedModule(ctx.getIdentifier("UIKit"));
466+
SmallVector<ValueDecl *, 1> results;
467+
UIKit->lookupQualified(UIKit->getDeclaredType(),
468+
ctx.getIdentifier("UIApplicationMain"),
469+
NL_QualifiedDefault,
470+
/*resolver*/nullptr,
471+
results);
472+
assert(!results.empty() && "couldn't find UIApplicationMain in UIKit");
473+
assert(results.size() == 1 && "more than one UIApplicationMain?");
474+
475+
SILDeclRef mainRef{results.front(), ResilienceExpansion::Minimal,
476+
SILDeclRef::ConstructAtNaturalUncurryLevel,
477+
/*isForeign*/true};
478+
auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, mainRef,
479+
NotForDefinition);
480+
auto fnTy = UIApplicationMainFn->getLoweredFunctionType();
481+
460482
// Get the class name as a string using NSStringFromClass.
461483
CanType mainClassTy = mainClass->getDeclaredTypeInContext()->getCanonicalType();
462484
CanType mainClassMetaty = CanMetatypeType::get(mainClassTy,
463485
MetatypeRepresentation::ObjC);
464486
ProtocolDecl *anyObjectProtocol =
465-
getASTContext().getProtocol(KnownProtocolKind::AnyObject);
487+
ctx.getProtocol(KnownProtocolKind::AnyObject);
466488
auto mainClassAnyObjectConformance = ProtocolConformanceRef(
467489
*SGM.M.getSwiftModule()->lookupConformance(mainClassTy, anyObjectProtocol,
468490
nullptr));
@@ -482,7 +504,7 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
482504
SILResultInfo(OptNSStringTy,
483505
ResultConvention::Autoreleased),
484506
/*error result*/ None,
485-
getASTContext());
507+
ctx);
486508
auto NSStringFromClassFn
487509
= SGM.M.getOrCreateFunction(mainClass, "NSStringFromClass",
488510
SILLinkage::PublicExternal,
@@ -493,22 +515,35 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
493515
SILType::getPrimitiveObjectType(mainClassMetaty));
494516
metaTy = B.createInitExistentialMetatype(mainClass, metaTy,
495517
SILType::getPrimitiveObjectType(anyObjectMetaTy),
496-
getASTContext().AllocateCopy(
518+
ctx.AllocateCopy(
497519
llvm::makeArrayRef(mainClassAnyObjectConformance)));
498520
SILValue optName = B.createApply(mainClass,
499521
NSStringFromClass,
500522
NSStringFromClass->getType(),
501523
SILType::getPrimitiveObjectType(OptNSStringTy),
502524
{}, metaTy);
503-
SILValue iuoptName = B.createUncheckedBitCast(mainClass, optName,
504-
SILType::getPrimitiveObjectType(IUOptNSStringTy));
505525

506-
// Call UIApplicationMain.
507-
auto UIApplicationMainFn = SGM.M.lookUpFunction("UIApplicationMain");
508-
assert(UIApplicationMainFn && "UIKit not imported?");
526+
// Fix up the string parameters to have the right type.
527+
SILType nameArgTy = fnTy->getSILArgumentType(3);
528+
assert(nameArgTy == fnTy->getSILArgumentType(2));
529+
auto managedName = ManagedValue::forUnmanaged(optName);
530+
SILValue nilValue;
531+
if (optName->getType() == nameArgTy) {
532+
nilValue = getOptionalNoneValue(mainClass,
533+
getTypeLowering(OptNSStringTy));
534+
} else {
535+
assert(nameArgTy.getSwiftRValueType() == IUOptNSStringTy);
536+
nilValue = getOptionalNoneValue(mainClass,
537+
getTypeLowering(IUOptNSStringTy));
538+
managedName = emitOptionalToOptional(
539+
mainClass, managedName,
540+
SILType::getPrimitiveObjectType(IUOptNSStringTy),
541+
[](SILGenFunction &, SILLocation, ManagedValue input, SILType) {
542+
return input;
543+
});
544+
}
509545

510546
// Fix up argv to have the right type.
511-
auto fnTy = UIApplicationMainFn->getLoweredFunctionType();
512547
auto argvTy = fnTy->getSILArgumentType(1);
513548

514549
SILType unwrappedTy = argvTy;
@@ -517,35 +552,36 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
517552
unwrappedTy = SILType::getPrimitiveObjectType(canInnerTy);
518553
}
519554

555+
auto managedArgv = ManagedValue::forUnmanaged(argv);
556+
520557
if (unwrappedTy != argv->getType()) {
521558
auto converted =
522-
emitPointerToPointer(mainClass, ManagedValue::forUnmanaged(argv),
559+
emitPointerToPointer(mainClass, managedArgv,
523560
argv->getType().getSwiftRValueType(),
524561
unwrappedTy.getSwiftRValueType());
525-
argv = converted.getUnmanagedSingleValue(*this, mainClass);
562+
managedArgv = std::move(converted).getAsSingleValue(*this, mainClass);
526563
}
527564

528565
if (unwrappedTy != argvTy) {
529-
argv = getOptionalSomeValue(mainClass, ManagedValue::forUnmanaged(argv),
530-
getTypeLowering(argvTy)).getUnmanagedValue();
566+
managedArgv = getOptionalSomeValue(mainClass, managedArgv,
567+
getTypeLowering(argvTy));
531568
}
532569

533570
auto UIApplicationMain = B.createFunctionRef(mainClass, UIApplicationMainFn);
534-
auto nil = B.createEnum(mainClass, SILValue(),
535-
getASTContext().getImplicitlyUnwrappedOptionalNoneDecl(),
536-
SILType::getPrimitiveObjectType(IUOptNSStringTy));
537571

538-
SILValue args[] = { argc, argv, nil, iuoptName };
572+
SILValue args[] = {argc, managedArgv.getValue(), nilValue,
573+
managedName.getValue()};
539574

540575
B.createApply(mainClass, UIApplicationMain,
541576
UIApplicationMain->getType(),
542577
argc->getType(), {}, args);
543578
SILValue r = B.createIntegerLiteral(mainClass,
544-
SILType::getBuiltinIntegerType(32, getASTContext()), 0);
579+
SILType::getBuiltinIntegerType(32, ctx), 0);
545580
auto rType = F.getLoweredFunctionType()->getSingleResult().getSILType();
546581
if (r->getType() != rType)
547582
r = B.createStruct(mainClass, rType, r);
548583

584+
Cleanups.emitCleanupsForReturn(mainClass);
549585
B.createReturn(mainClass, r);
550586
return;
551587
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
// RUN: %target-build-swift %s -o %t/main -parse-as-library
3+
4+
// We aren't yet able to run tests that require a UI context, so just try
5+
// building with the real SDK for now.
6+
// DISABLED: %target-run %t/main | FileCheck %s
7+
8+
// REQUIRES: OS=ios
9+
10+
import UIKit
11+
12+
@UIApplicationMain
13+
class MyDelegate : NSObject, UIApplicationDelegate {
14+
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
15+
// CHECK: launched
16+
print("launched")
17+
exit(EXIT_SUCCESS)
18+
}
19+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Foundation
2+
import UIKit
3+
4+
public func publicFoo(x: AnyObject.Type) -> String {
5+
return NSStringFromClass(x)
6+
}
7+
8+
public func publicBar() {
9+
UIApplicationMain(0, nil, nil, nil)
10+
}
11+
12+

test/SILGen/NSApplicationMain.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %target-swift-frontend -emit-silgen -parse-as-library -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | FileCheck %s
22
// RUN: %target-swift-frontend -emit-ir -parse-as-library -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | FileCheck %s -check-prefix=IR
33

4+
// RUN: %target-swift-frontend -emit-silgen -parse-as-library -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -D REFERENCE | FileCheck %s
5+
// RUN: %target-swift-frontend -emit-ir -parse-as-library -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -D REFERENCE | FileCheck %s -check-prefix=IR
6+
47
// REQUIRES: OS=macosx
58

69
import Foundation
@@ -14,8 +17,10 @@ class MyDelegate: NSApplicationDelegate {}
1417
// IR-LABEL: define{{( protected)?}} i32 @main
1518
// IR: call i32 @NSApplicationMain
1619

20+
#if REFERENCE
1721
// Ensure that we coexist with normal references to the functions we
1822
// implicitly reference in the synthesized main.
1923
func bar() {
2024
NSApplicationMain(Process.argc, Process.unsafeArgv)
2125
}
26+
#endif

test/SILGen/UIApplicationMain.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -parse-as-library %s | FileCheck %s
55
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-ir -parse-as-library %s | FileCheck %s -check-prefix=IR
66

7+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -parse-as-library %s -D REFERENCE | FileCheck %s
8+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-ir -parse-as-library %s -D REFERENCE | FileCheck %s -check-prefix=IR
9+
10+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -parse-as-library -primary-file %s %S/Inputs/UIApplicationMain-helper.swift -module-name test | FileCheck %s
11+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-ir -parse-as-library -primary-file %s %S/Inputs/UIApplicationMain-helper.swift -module-name test | FileCheck %s -check-prefix=IR
12+
13+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -parse-as-library %s %S/Inputs/UIApplicationMain-helper.swift -module-name test | FileCheck %s
14+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-ir -parse-as-library %s %S/Inputs/UIApplicationMain-helper.swift -module-name test | FileCheck %s -check-prefix=IR
15+
16+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -parse-as-library %S/Inputs/UIApplicationMain-helper.swift %s -module-name test | FileCheck %s
17+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-ir -parse-as-library %S/Inputs/UIApplicationMain-helper.swift %s -module-name test | FileCheck %s -check-prefix=IR
18+
719
// REQUIRES: OS=ios
820
// REQUIRES: objc_interop
921

@@ -20,9 +32,12 @@ class MyDelegate : UIApplicationDelegate {}
2032

2133
// Ensure that we coexist with normal references to the functions we
2234
// implicitly reference in the synthesized main.
35+
#if REFERENCE
2336
func foo(x: AnyObject.Type) -> String {
2437
return NSStringFromClass(x)
2538
}
39+
2640
func bar() {
2741
UIApplicationMain(0, nil, nil, nil)
2842
}
43+
#endif

0 commit comments

Comments
 (0)