mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #75594 from benlangmuir/script-load-foundation-early
[immediate] Load Foundation early enough for bridging
This commit is contained in:
@@ -115,6 +115,8 @@ ERROR(error_immediate_mode_missing_library,none,
|
|||||||
(unsigned, StringRef))
|
(unsigned, StringRef))
|
||||||
ERROR(error_immediate_mode_primary_file,none,
|
ERROR(error_immediate_mode_primary_file,none,
|
||||||
"immediate mode is incompatible with -primary-file", ())
|
"immediate mode is incompatible with -primary-file", ())
|
||||||
|
WARNING(warning_immediate_mode_cannot_load_foundation,none,
|
||||||
|
"immediate mode failed to load Foundation: %0", (StringRef))
|
||||||
ERROR(error_missing_frontend_action,none,
|
ERROR(error_missing_frontend_action,none,
|
||||||
"no frontend action was selected", ())
|
"no frontend action was selected", ())
|
||||||
ERROR(error_invalid_source_location_str,none,
|
ERROR(error_invalid_source_location_str,none,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
class CompilerInstance;
|
class CompilerInstance;
|
||||||
|
class DiagnosticEngine;
|
||||||
class IRGenOptions;
|
class IRGenOptions;
|
||||||
class SILOptions;
|
class SILOptions;
|
||||||
class SILModule;
|
class SILModule;
|
||||||
@@ -44,6 +45,9 @@ namespace swift {
|
|||||||
|
|
||||||
int RunImmediatelyFromAST(CompilerInstance &CI);
|
int RunImmediatelyFromAST(CompilerInstance &CI);
|
||||||
|
|
||||||
|
/// On platforms that support ObjC bridging from the Foundation framework,
|
||||||
|
/// ensure that Foundation is loaded early enough. Otherwise does nothing.
|
||||||
|
void loadFoundationIfNeeded(DiagnosticEngine &Diags);
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|
||||||
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H
|
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H
|
||||||
|
|||||||
@@ -1955,6 +1955,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
|||||||
return finishDiagProcessing(1, /*verifierEnabled*/ false);
|
return finishDiagProcessing(1, /*verifierEnabled*/ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scripts that use the Foundation framework need it loaded early for bridging
|
||||||
|
// to work correctly on Darwin platforms. On other platforms this is a no-op.
|
||||||
|
if (Invocation.getFrontendOptions().RequestedAction ==
|
||||||
|
FrontendOptions::ActionType::Immediate) {
|
||||||
|
loadFoundationIfNeeded(Instance->getDiags());
|
||||||
|
}
|
||||||
|
|
||||||
// Don't ask clients to report bugs when running a script in immediate mode.
|
// Don't ask clients to report bugs when running a script in immediate mode.
|
||||||
// When a script asserts the compiler reports the error with the same
|
// When a script asserts the compiler reports the error with the same
|
||||||
// stacktrace as a compiler crash. From here we can't tell which is which,
|
// stacktrace as a compiler crash. From here we can't tell which is which,
|
||||||
|
|||||||
@@ -432,3 +432,30 @@ int swift::RunImmediatelyFromAST(CompilerInstance &CI) {
|
|||||||
|
|
||||||
return *Result;
|
return *Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void swift::loadFoundationIfNeeded(DiagnosticEngine &Diags) {
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
const char *FoundationPath =
|
||||||
|
"/System/Library/Frameworks/Foundation.framework/Foundation";
|
||||||
|
void *handle = dlopen(FoundationPath, RTLD_NOLOAD);
|
||||||
|
if (handle) {
|
||||||
|
// Foundation is already loaded. Use dlclose to release the ref-count that
|
||||||
|
// was incremented by dlopen and return.
|
||||||
|
dlclose(handle);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Foundation is not yet loaded. Load it now and leak the handle.
|
||||||
|
// FIXME: it is fragile to load here, as there is no guarantee the swift
|
||||||
|
// runtime has not initialized already. As the compiler adds more swift code
|
||||||
|
// we may need to move this or find another solution.
|
||||||
|
handle = dlopen(FoundationPath, RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if (!handle)
|
||||||
|
Diags.diagnose(SourceLoc(),
|
||||||
|
diag::warning_immediate_mode_cannot_load_foundation,
|
||||||
|
dlerror());
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Nothing to do.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
25
test/Interpreter/foundation-bridge-error.swift
Normal file
25
test/Interpreter/foundation-bridge-error.swift
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Check that we can access localizedDescription, which crashes in the runtime
|
||||||
|
// if Foundation is loaded after the runtime is already initialized on Darwin.
|
||||||
|
|
||||||
|
// REQUIRES: executable_test
|
||||||
|
// REQUIRES: objc_interop
|
||||||
|
// REQUIRES: OS=macosx
|
||||||
|
|
||||||
|
// FIXME: There's a separate bridging error with the just-built stdlib on CI
|
||||||
|
// nodes.
|
||||||
|
// REQUIRES: use_os_stdlib
|
||||||
|
|
||||||
|
// RUN: %target-jit-run %s
|
||||||
|
// RUN: DYLD_INSERT_LIBRARIES=/System/Library/Frameworks/Foundation.framework/Foundation %target-jit-run %s
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
print("Insert Libraries: \(ProcessInfo.processInfo.environment["DYLD_INSERT_LIBRARIES"] ?? "<nil>")")
|
||||||
|
|
||||||
|
enum SomeError: LocalizedError {
|
||||||
|
case fail
|
||||||
|
}
|
||||||
|
|
||||||
|
let err = SomeError.fail
|
||||||
|
let path = (#file as NSString).lastPathComponent
|
||||||
|
let desc = err.localizedDescription
|
||||||
Reference in New Issue
Block a user