Skip to content

Commit e570e35

Browse files
authored
Merge pull request #75634 from benlangmuir/script-load-foundation-early-6
[6.0][immediate] Load Foundation early enough for bridging
2 parents 777dac5 + 21d2ae4 commit e570e35

File tree

5 files changed

+65
-0
lines changed

5 files changed

+65
-0
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ ERROR(error_immediate_mode_missing_library,none,
120120
(unsigned, StringRef))
121121
ERROR(error_immediate_mode_primary_file,none,
122122
"immediate mode is incompatible with -primary-file", ())
123+
WARNING(warning_immediate_mode_cannot_load_foundation,none,
124+
"immediate mode failed to load Foundation: %0", (StringRef))
123125
ERROR(error_missing_frontend_action,none,
124126
"no frontend action was selected", ())
125127
ERROR(error_unsupported_frontend_action, none,

include/swift/Immediate/Immediate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
namespace swift {
2626
class CompilerInstance;
27+
class DiagnosticEngine;
2728
class IRGenOptions;
2829
class SILOptions;
2930
class SILModule;
@@ -44,6 +45,9 @@ namespace swift {
4445

4546
int RunImmediatelyFromAST(CompilerInstance &CI);
4647

48+
/// On platforms that support ObjC bridging from the Foundation framework,
49+
/// ensure that Foundation is loaded early enough. Otherwise does nothing.
50+
void loadFoundationIfNeeded(DiagnosticEngine &Diags);
4751
} // end namespace swift
4852

4953
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H

lib/FrontendTool/FrontendTool.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
19421942
return finishDiagProcessing(1, /*verifierEnabled*/ false);
19431943
}
19441944

1945+
// Scripts that use the Foundation framework need it loaded early for bridging
1946+
// to work correctly on Darwin platforms. On other platforms this is a no-op.
1947+
if (Invocation.getFrontendOptions().RequestedAction ==
1948+
FrontendOptions::ActionType::Immediate) {
1949+
loadFoundationIfNeeded(Instance->getDiags());
1950+
}
1951+
19451952
// Don't ask clients to report bugs when running a script in immediate mode.
19461953
// When a script asserts the compiler reports the error with the same
19471954
// stacktrace as a compiler crash. From here we can't tell which is which,

lib/Immediate/Immediate.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,30 @@ int swift::RunImmediatelyFromAST(CompilerInstance &CI) {
431431

432432
return *Result;
433433
}
434+
435+
void swift::loadFoundationIfNeeded(DiagnosticEngine &Diags) {
436+
#if defined(__APPLE__)
437+
const char *FoundationPath =
438+
"/System/Library/Frameworks/Foundation.framework/Foundation";
439+
void *handle = dlopen(FoundationPath, RTLD_NOLOAD);
440+
if (handle) {
441+
// Foundation is already loaded. Use dlclose to release the ref-count that
442+
// was incremented by dlopen and return.
443+
dlclose(handle);
444+
return;
445+
} else {
446+
// Foundation is not yet loaded. Load it now and leak the handle.
447+
// FIXME: it is fragile to load here, as there is no guarantee the swift
448+
// runtime has not initialized already. As the compiler adds more swift code
449+
// we may need to move this or find another solution.
450+
handle = dlopen(FoundationPath, RTLD_LAZY | RTLD_GLOBAL);
451+
if (!handle)
452+
Diags.diagnose(SourceLoc(),
453+
diag::warning_immediate_mode_cannot_load_foundation,
454+
dlerror());
455+
}
456+
457+
#else
458+
// Nothing to do.
459+
#endif
460+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Check that we can access localizedDescription, which crashes in the runtime
2+
// if Foundation is loaded after the runtime is already initialized on Darwin.
3+
4+
// REQUIRES: executable_test
5+
// REQUIRES: objc_interop
6+
// REQUIRES: OS=macosx
7+
8+
// FIXME: There's a separate bridging error with the just-built stdlib on CI
9+
// nodes.
10+
// REQUIRES: use_os_stdlib
11+
12+
// RUN: %target-jit-run %s
13+
// RUN: DYLD_INSERT_LIBRARIES=/System/Library/Frameworks/Foundation.framework/Foundation %target-jit-run %s
14+
15+
import Foundation
16+
17+
print("Insert Libraries: \(ProcessInfo.processInfo.environment["DYLD_INSERT_LIBRARIES"] ?? "<nil>")")
18+
19+
enum SomeError: LocalizedError {
20+
case fail
21+
}
22+
23+
let err = SomeError.fail
24+
let path = (#file as NSString).lastPathComponent
25+
let desc = err.localizedDescription

0 commit comments

Comments
 (0)