mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -106,6 +106,8 @@ ERROR(error_mode_cannot_emit_dependencies,none,
|
|||||||
"this mode does not support emitting dependency files", ())
|
"this mode does not support emitting dependency files", ())
|
||||||
ERROR(error_mode_cannot_emit_header,none,
|
ERROR(error_mode_cannot_emit_header,none,
|
||||||
"this mode does not support emitting Objective-C headers", ())
|
"this mode does not support emitting Objective-C headers", ())
|
||||||
|
ERROR(error_mode_cannot_emit_loaded_module_trace,none,
|
||||||
|
"this mode does not support emitting the loaded module trace", ())
|
||||||
ERROR(error_mode_cannot_emit_module,none,
|
ERROR(error_mode_cannot_emit_module,none,
|
||||||
"this mode does not support emitting modules", ())
|
"this mode does not support emitting modules", ())
|
||||||
ERROR(error_mode_cannot_emit_module_doc,none,
|
ERROR(error_mode_cannot_emit_module_doc,none,
|
||||||
|
|||||||
@@ -473,8 +473,11 @@ public:
|
|||||||
/// Determine whether the witness for the given type requirement
|
/// Determine whether the witness for the given type requirement
|
||||||
/// is the default definition.
|
/// is the default definition.
|
||||||
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
|
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
|
||||||
return getTypeWitnessAndDecl(requirement, nullptr)
|
TypeDecl *witnessDecl = getTypeWitnessAndDecl(requirement, nullptr).second;
|
||||||
.second->isImplicit();
|
if (witnessDecl)
|
||||||
|
return witnessDecl->isImplicit();
|
||||||
|
// Conservatively assume it does not.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLazyLoader(LazyMemberLoader *resolver, uint64_t contextData);
|
void setLazyLoader(LazyMemberLoader *resolver, uint64_t contextData);
|
||||||
|
|||||||
@@ -445,6 +445,16 @@ private:
|
|||||||
void indent();
|
void indent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T> struct ArrayTraits<std::vector<T>> {
|
||||||
|
static size_t size(Output &out, std::vector<T> &seq) { return seq.size(); }
|
||||||
|
|
||||||
|
static T &element(Output &out, std::vector<T> &seq, size_t index) {
|
||||||
|
if (index >= seq.size())
|
||||||
|
seq.resize(index + 1);
|
||||||
|
return seq[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ScalarTraits<bool> {
|
struct ScalarTraits<bool> {
|
||||||
static void output(const bool &, llvm::raw_ostream &);
|
static void output(const bool &, llvm::raw_ostream &);
|
||||||
|
|||||||
@@ -146,6 +146,10 @@ private:
|
|||||||
/// detail than ShowIncrementalBuildDecisions.
|
/// detail than ShowIncrementalBuildDecisions.
|
||||||
bool ShowJobLifecycle = false;
|
bool ShowJobLifecycle = false;
|
||||||
|
|
||||||
|
/// When true, some frontend job has requested permission to pass
|
||||||
|
/// -emit-loaded-module-trace, so no other job needs to do it.
|
||||||
|
bool PassedEmitLoadedModuleTraceToFrontendJob = false;
|
||||||
|
|
||||||
static const Job *unwrap(const std::unique_ptr<const Job> &p) {
|
static const Job *unwrap(const std::unique_ptr<const Job> &p) {
|
||||||
return p.get();
|
return p.get();
|
||||||
}
|
}
|
||||||
@@ -232,6 +236,22 @@ public:
|
|||||||
/// -2 indicates that one of the Compilation's Jobs crashed during execution
|
/// -2 indicates that one of the Compilation's Jobs crashed during execution
|
||||||
int performJobs();
|
int performJobs();
|
||||||
|
|
||||||
|
/// Returns whether the callee is permitted to pass -emit-loaded-module-trace
|
||||||
|
/// to a frontend job.
|
||||||
|
///
|
||||||
|
/// This only returns true once, because only one job should pass that
|
||||||
|
/// argument.
|
||||||
|
bool requestPermissionForFrontendToEmitLoadedModuleTrace() {
|
||||||
|
if (PassedEmitLoadedModuleTraceToFrontendJob)
|
||||||
|
// Someone else has already done it!
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
// We're the first and only (to execute this path).
|
||||||
|
PassedEmitLoadedModuleTraceToFrontendJob = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// \brief Perform all jobs.
|
/// \brief Perform all jobs.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
|
|||||||
TYPE("remap", Remapping, "remap", "")
|
TYPE("remap", Remapping, "remap", "")
|
||||||
TYPE("imported-modules", ImportedModules, "importedmodules", "")
|
TYPE("imported-modules", ImportedModules, "importedmodules", "")
|
||||||
TYPE("tbd", TBD, "tbd", "")
|
TYPE("tbd", TBD, "tbd", "")
|
||||||
|
TYPE("module-trace", ModuleTrace, "trace.json", "")
|
||||||
|
|
||||||
// Misc types
|
// Misc types
|
||||||
TYPE("pcm", ClangModuleFile, "pcm", "")
|
TYPE("pcm", ClangModuleFile, "pcm", "")
|
||||||
|
|||||||
@@ -116,6 +116,9 @@ public:
|
|||||||
/// The path to which we should output fixits as source edits.
|
/// The path to which we should output fixits as source edits.
|
||||||
std::string FixitsOutputPath;
|
std::string FixitsOutputPath;
|
||||||
|
|
||||||
|
/// The path to which we should output a loaded module trace file.
|
||||||
|
std::string LoadedModuleTracePath;
|
||||||
|
|
||||||
/// Arguments which should be passed in immediate mode.
|
/// Arguments which should be passed in immediate mode.
|
||||||
std::vector<std::string> ImmediateArgv;
|
std::vector<std::string> ImmediateArgv;
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,16 @@ def emit_dependencies : Flag<["-"], "emit-dependencies">,
|
|||||||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
|
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
|
||||||
HelpText<"Emit basic Make-compatible dependencies files">;
|
HelpText<"Emit basic Make-compatible dependencies files">;
|
||||||
|
|
||||||
|
def emit_loaded_module_trace : Flag<["-"], "emit-loaded-module-trace">,
|
||||||
|
Flags<[FrontendOption, NoInteractiveOption]>,
|
||||||
|
HelpText<"Emit a JSON file containing information about what modules were loaded">;
|
||||||
|
def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">,
|
||||||
|
Flags<[FrontendOption, NoInteractiveOption]>,
|
||||||
|
HelpText<"Emit the loaded module trace JSON to <path>">,
|
||||||
|
MetaVarName<"<path>">;
|
||||||
|
def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">,
|
||||||
|
Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_loaded_module_trace_path>;
|
||||||
|
|
||||||
def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">,
|
def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">,
|
||||||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
|
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
|
||||||
HelpText<"Serialize diagnostics in a binary format">;
|
HelpText<"Serialize diagnostics in a binary format">;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
|
|||||||
/// in source control, you should also update the comment to briefly
|
/// in source control, you should also update the comment to briefly
|
||||||
/// describe what change you made. The content of this comment isn't important;
|
/// describe what change you made. The content of this comment isn't important;
|
||||||
/// it just ensures a conflict if two people change the module format.
|
/// it just ensures a conflict if two people change the module format.
|
||||||
const uint16_t VERSION_MINOR = 335; // Last change: no type in objc method table
|
const uint16_t VERSION_MINOR = 336; // Last change: typealias canonical type
|
||||||
|
|
||||||
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
||||||
using DeclIDField = BCFixed<31>;
|
using DeclIDField = BCFixed<31>;
|
||||||
@@ -571,7 +571,8 @@ namespace decls_block {
|
|||||||
|
|
||||||
using NameAliasTypeLayout = BCRecordLayout<
|
using NameAliasTypeLayout = BCRecordLayout<
|
||||||
NAME_ALIAS_TYPE,
|
NAME_ALIAS_TYPE,
|
||||||
DeclIDField // typealias decl
|
DeclIDField, // typealias decl
|
||||||
|
TypeIDField // canonical type (a fallback)
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using GenericTypeParamTypeLayout = BCRecordLayout<
|
using GenericTypeParamTypeLayout = BCRecordLayout<
|
||||||
|
|||||||
@@ -1420,6 +1420,7 @@ void Driver::buildActions(const ToolChain &TC,
|
|||||||
case types::TY_PCH:
|
case types::TY_PCH:
|
||||||
case types::TY_ImportedModules:
|
case types::TY_ImportedModules:
|
||||||
case types::TY_TBD:
|
case types::TY_TBD:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
// We could in theory handle assembly or LLVM input, but let's not.
|
// We could in theory handle assembly or LLVM input, but let's not.
|
||||||
// FIXME: What about LTO?
|
// FIXME: What about LTO?
|
||||||
Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
|
Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
|
||||||
@@ -1684,6 +1685,36 @@ void Driver::buildJobs(const ActionList &Actions, const OutputInfo &OI,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Optional<StringRef> getOutputFilenameFromPathArgOrAsTopLevel(
|
||||||
|
const OutputInfo &OI, const llvm::opt::DerivedArgList &Args,
|
||||||
|
llvm::opt::OptSpecifier PathArg, types::ID ExpectedOutputType,
|
||||||
|
bool TreatAsTopLevelOutput, StringRef ext, llvm::SmallString<128> &Buffer) {
|
||||||
|
if (const Arg *A = Args.getLastArg(PathArg))
|
||||||
|
return StringRef(A->getValue());
|
||||||
|
|
||||||
|
if (TreatAsTopLevelOutput) {
|
||||||
|
if (const Arg *A = Args.getLastArg(options::OPT_o)) {
|
||||||
|
if (OI.CompilerOutputType == ExpectedOutputType)
|
||||||
|
return StringRef(A->getValue());
|
||||||
|
|
||||||
|
// Otherwise, put the file next to the top-level output.
|
||||||
|
Buffer = A->getValue();
|
||||||
|
llvm::sys::path::remove_filename(Buffer);
|
||||||
|
llvm::sys::path::append(Buffer, OI.ModuleName);
|
||||||
|
llvm::sys::path::replace_extension(Buffer, ext);
|
||||||
|
return Buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// A top-level output wasn't specified, so just output to
|
||||||
|
// <ModuleName>.<ext>.
|
||||||
|
Buffer = OI.ModuleName;
|
||||||
|
llvm::sys::path::replace_extension(Buffer, ext);
|
||||||
|
return Buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
static StringRef getOutputFilename(Compilation &C,
|
static StringRef getOutputFilename(Compilation &C,
|
||||||
const JobAction *JA,
|
const JobAction *JA,
|
||||||
const OutputInfo &OI,
|
const OutputInfo &OI,
|
||||||
@@ -1706,29 +1737,14 @@ static StringRef getOutputFilename(Compilation &C,
|
|||||||
|
|
||||||
// Process Action-specific output-specifying options next,
|
// Process Action-specific output-specifying options next,
|
||||||
// since we didn't find anything applicable in the OutputMap.
|
// since we didn't find anything applicable in the OutputMap.
|
||||||
|
|
||||||
if (isa<MergeModuleJobAction>(JA)) {
|
if (isa<MergeModuleJobAction>(JA)) {
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_emit_module_path))
|
auto optFilename = getOutputFilenameFromPathArgOrAsTopLevel(
|
||||||
return A->getValue();
|
OI, Args, options::OPT_emit_module_path, types::TY_SwiftModuleFile,
|
||||||
|
OI.ShouldTreatModuleAsTopLevelOutput, SERIALIZED_MODULE_EXTENSION,
|
||||||
if (OI.ShouldTreatModuleAsTopLevelOutput) {
|
Buffer);
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_o)) {
|
if (optFilename)
|
||||||
if (OI.CompilerOutputType == types::TY_SwiftModuleFile)
|
return *optFilename;
|
||||||
return A->getValue();
|
|
||||||
|
|
||||||
// Otherwise, put the module next to the top-level output.
|
|
||||||
Buffer = A->getValue();
|
|
||||||
llvm::sys::path::remove_filename(Buffer);
|
|
||||||
llvm::sys::path::append(Buffer, OI.ModuleName);
|
|
||||||
llvm::sys::path::replace_extension(Buffer, SERIALIZED_MODULE_EXTENSION);
|
|
||||||
return Buffer.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// A top-level output wasn't specified, so just output to
|
|
||||||
// <ModuleName>.swiftmodule.
|
|
||||||
Buffer = OI.ModuleName;
|
|
||||||
llvm::sys::path::replace_extension(Buffer, SERIALIZED_MODULE_EXTENSION);
|
|
||||||
return Buffer.str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dSYM actions are never treated as top-level.
|
// dSYM actions are never treated as top-level.
|
||||||
@@ -2074,6 +2090,34 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
|
|||||||
if (C.getIncrementalBuildEnabled()) {
|
if (C.getIncrementalBuildEnabled()) {
|
||||||
addAuxiliaryOutput(C, *Output, types::TY_SwiftDeps, OI, OutputMap);
|
addAuxiliaryOutput(C, *Output, types::TY_SwiftDeps, OI, OutputMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The loaded-module-trace is the same for all compile jobs: all `import`
|
||||||
|
// statements are processed, even ones from non-primary files. Thus, only
|
||||||
|
// one of those jobs needs to emit the file, and we can get it to write
|
||||||
|
// straight to the desired final location.
|
||||||
|
auto tracePathEnvVar = getenv("SWIFT_LOADED_MODULE_TRACE_PATH");
|
||||||
|
auto shouldEmitTrace =
|
||||||
|
tracePathEnvVar ||
|
||||||
|
C.getArgs().hasArg(options::OPT_emit_loaded_module_trace,
|
||||||
|
options::OPT_emit_loaded_module_trace_path);
|
||||||
|
|
||||||
|
if (shouldEmitTrace &&
|
||||||
|
C.requestPermissionForFrontendToEmitLoadedModuleTrace()) {
|
||||||
|
StringRef filename;
|
||||||
|
// Prefer the environment variable.
|
||||||
|
if (tracePathEnvVar)
|
||||||
|
filename = StringRef(tracePathEnvVar);
|
||||||
|
else {
|
||||||
|
// By treating this as a top-level output, the return value always
|
||||||
|
// exists.
|
||||||
|
filename = *getOutputFilenameFromPathArgOrAsTopLevel(
|
||||||
|
OI, C.getArgs(), options::OPT_emit_loaded_module_trace_path,
|
||||||
|
types::TY_ModuleTrace,
|
||||||
|
/*TreatAsTopLevelOutput=*/true, "trace.json", Buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Output->setAdditionalOutputForType(types::TY_ModuleTrace, filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose the Objective-C header output path.
|
// Choose the Objective-C header output path.
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
|||||||
case types::TY_ObjCHeader:
|
case types::TY_ObjCHeader:
|
||||||
case types::TY_Image:
|
case types::TY_Image:
|
||||||
case types::TY_SwiftDeps:
|
case types::TY_SwiftDeps:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
llvm_unreachable("Output type can never be primary output.");
|
llvm_unreachable("Output type can never be primary output.");
|
||||||
case types::TY_INVALID:
|
case types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID");
|
llvm_unreachable("Invalid type ID");
|
||||||
@@ -388,6 +389,13 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
|||||||
Arguments.push_back(ReferenceDependenciesPath.c_str());
|
Arguments.push_back(ReferenceDependenciesPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &LoadedModuleTracePath =
|
||||||
|
context.Output.getAdditionalOutputForType(types::TY_ModuleTrace);
|
||||||
|
if (!LoadedModuleTracePath.empty()) {
|
||||||
|
Arguments.push_back("-emit-loaded-module-trace-path");
|
||||||
|
Arguments.push_back(LoadedModuleTracePath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &FixitsPath =
|
const std::string &FixitsPath =
|
||||||
context.Output.getAdditionalOutputForType(types::TY_Remapping);
|
context.Output.getAdditionalOutputForType(types::TY_Remapping);
|
||||||
if (!FixitsPath.empty()) {
|
if (!FixitsPath.empty()) {
|
||||||
@@ -518,6 +526,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
|
|||||||
case types::TY_Image:
|
case types::TY_Image:
|
||||||
case types::TY_SwiftDeps:
|
case types::TY_SwiftDeps:
|
||||||
case types::TY_Remapping:
|
case types::TY_Remapping:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
llvm_unreachable("Output type can never be primary output.");
|
llvm_unreachable("Output type can never be primary output.");
|
||||||
case types::TY_INVALID:
|
case types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID");
|
llvm_unreachable("Invalid type ID");
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ bool types::isTextual(ID Id) {
|
|||||||
case types::TY_AutolinkFile:
|
case types::TY_AutolinkFile:
|
||||||
case types::TY_ImportedModules:
|
case types::TY_ImportedModules:
|
||||||
case types::TY_TBD:
|
case types::TY_TBD:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
return true;
|
return true;
|
||||||
case types::TY_Image:
|
case types::TY_Image:
|
||||||
case types::TY_Object:
|
case types::TY_Object:
|
||||||
@@ -127,6 +128,7 @@ bool types::isAfterLLVM(ID Id) {
|
|||||||
case types::TY_SwiftDeps:
|
case types::TY_SwiftDeps:
|
||||||
case types::TY_Nothing:
|
case types::TY_Nothing:
|
||||||
case types::TY_Remapping:
|
case types::TY_Remapping:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
return false;
|
return false;
|
||||||
case types::TY_INVALID:
|
case types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID.");
|
llvm_unreachable("Invalid type ID.");
|
||||||
@@ -163,6 +165,7 @@ bool types::isPartOfSwiftCompilation(ID Id) {
|
|||||||
case types::TY_SwiftDeps:
|
case types::TY_SwiftDeps:
|
||||||
case types::TY_Nothing:
|
case types::TY_Nothing:
|
||||||
case types::TY_Remapping:
|
case types::TY_Remapping:
|
||||||
|
case types::TY_ModuleTrace:
|
||||||
return false;
|
return false;
|
||||||
case types::TY_INVALID:
|
case types::TY_INVALID:
|
||||||
llvm_unreachable("Invalid type ID.");
|
llvm_unreachable("Invalid type ID.");
|
||||||
|
|||||||
@@ -674,6 +674,10 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
OPT_emit_objc_header,
|
OPT_emit_objc_header,
|
||||||
OPT_emit_objc_header_path,
|
OPT_emit_objc_header_path,
|
||||||
"h", false);
|
"h", false);
|
||||||
|
determineOutputFilename(Opts.LoadedModuleTracePath,
|
||||||
|
OPT_emit_loaded_module_trace,
|
||||||
|
OPT_emit_loaded_module_trace_path,
|
||||||
|
"trace.json", false);
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(OPT_emit_fixits_path)) {
|
if (const Arg *A = Args.getLastArg(OPT_emit_fixits_path)) {
|
||||||
Opts.FixitsOutputPath = A->getValue();
|
Opts.FixitsOutputPath = A->getValue();
|
||||||
@@ -763,6 +767,39 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Opts.LoadedModuleTracePath.empty()) {
|
||||||
|
switch (Opts.RequestedAction) {
|
||||||
|
case FrontendOptions::NoneAction:
|
||||||
|
case FrontendOptions::Parse:
|
||||||
|
case FrontendOptions::DumpParse:
|
||||||
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::PrintAST:
|
||||||
|
case FrontendOptions::DumpScopeMaps:
|
||||||
|
case FrontendOptions::DumpTypeRefinementContexts:
|
||||||
|
case FrontendOptions::Immediate:
|
||||||
|
case FrontendOptions::REPL:
|
||||||
|
case FrontendOptions::UpdateCode:
|
||||||
|
Diags.diagnose(SourceLoc(),
|
||||||
|
diag::error_mode_cannot_emit_loaded_module_trace);
|
||||||
|
return true;
|
||||||
|
case FrontendOptions::Typecheck:
|
||||||
|
case FrontendOptions::EmitModuleOnly:
|
||||||
|
case FrontendOptions::EmitPCH:
|
||||||
|
case FrontendOptions::EmitSILGen:
|
||||||
|
case FrontendOptions::EmitSIL:
|
||||||
|
case FrontendOptions::EmitSIBGen:
|
||||||
|
case FrontendOptions::EmitSIB:
|
||||||
|
case FrontendOptions::EmitIR:
|
||||||
|
case FrontendOptions::EmitBC:
|
||||||
|
case FrontendOptions::EmitAssembly:
|
||||||
|
case FrontendOptions::EmitObject:
|
||||||
|
case FrontendOptions::EmitImportedModules:
|
||||||
|
case FrontendOptions::EmitTBD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Opts.ModuleOutputPath.empty() ||
|
if (!Opts.ModuleOutputPath.empty() ||
|
||||||
!Opts.ModuleDocOutputPath.empty()) {
|
!Opts.ModuleDocOutputPath.empty()) {
|
||||||
switch (Opts.RequestedAction) {
|
switch (Opts.RequestedAction) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "ReferenceDependencies.h"
|
#include "ReferenceDependencies.h"
|
||||||
#include "TBD.h"
|
#include "TBD.h"
|
||||||
|
|
||||||
|
#include "swift/Strings.h"
|
||||||
#include "swift/Subsystems.h"
|
#include "swift/Subsystems.h"
|
||||||
#include "swift/AST/ASTScope.h"
|
#include "swift/AST/ASTScope.h"
|
||||||
#include "swift/AST/DiagnosticsFrontend.h"
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
@@ -36,10 +37,12 @@
|
|||||||
#include "swift/Basic/Dwarf.h"
|
#include "swift/Basic/Dwarf.h"
|
||||||
#include "swift/Basic/Edit.h"
|
#include "swift/Basic/Edit.h"
|
||||||
#include "swift/Basic/FileSystem.h"
|
#include "swift/Basic/FileSystem.h"
|
||||||
|
#include "swift/Basic/JSONSerialization.h"
|
||||||
#include "swift/Basic/LLVMContext.h"
|
#include "swift/Basic/LLVMContext.h"
|
||||||
#include "swift/Basic/SourceManager.h"
|
#include "swift/Basic/SourceManager.h"
|
||||||
#include "swift/Basic/Statistic.h"
|
#include "swift/Basic/Statistic.h"
|
||||||
#include "swift/Basic/Timer.h"
|
#include "swift/Basic/Timer.h"
|
||||||
|
#include "swift/Basic/UUID.h"
|
||||||
#include "swift/Frontend/DiagnosticVerifier.h"
|
#include "swift/Frontend/DiagnosticVerifier.h"
|
||||||
#include "swift/Frontend/Frontend.h"
|
#include "swift/Frontend/Frontend.h"
|
||||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||||
@@ -55,6 +58,7 @@
|
|||||||
// FIXME: We're just using CompilerInstance::createOutputFile.
|
// FIXME: We're just using CompilerInstance::createOutputFile.
|
||||||
// This API should be sunk down to LLVM.
|
// This API should be sunk down to LLVM.
|
||||||
#include "clang/Frontend/CompilerInstance.h"
|
#include "clang/Frontend/CompilerInstance.h"
|
||||||
|
#include "clang/APINotes/Types.h"
|
||||||
|
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
@@ -72,6 +76,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) && !defined(__MINGW32__)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
static std::string displayName(StringRef MainExecutablePath) {
|
static std::string displayName(StringRef MainExecutablePath) {
|
||||||
@@ -133,6 +143,88 @@ static bool emitMakeDependencies(DiagnosticEngine &diags,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct LoadedModuleTraceFormat {
|
||||||
|
std::string Name;
|
||||||
|
std::string Arch;
|
||||||
|
std::vector<std::string> SwiftModules;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
namespace json {
|
||||||
|
template <> struct ObjectTraits<LoadedModuleTraceFormat> {
|
||||||
|
static void mapping(Output &out, LoadedModuleTraceFormat &contents) {
|
||||||
|
out.mapRequired("name", contents.Name);
|
||||||
|
out.mapRequired("arch", contents.Arch);
|
||||||
|
out.mapRequired("swiftmodules", contents.SwiftModules);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool emitLoadedModuleTrace(ASTContext &ctxt,
|
||||||
|
DependencyTracker &depTracker,
|
||||||
|
const FrontendOptions &opts) {
|
||||||
|
std::error_code EC;
|
||||||
|
llvm::raw_fd_ostream out(opts.LoadedModuleTracePath, EC,
|
||||||
|
llvm::sys::fs::F_Append);
|
||||||
|
|
||||||
|
if (out.has_error() || EC) {
|
||||||
|
ctxt.Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||||
|
opts.LoadedModuleTracePath, EC.message());
|
||||||
|
out.clear_error();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::SmallVector<std::string, 16> swiftModules;
|
||||||
|
|
||||||
|
// Canonicalise all the paths by opening them.
|
||||||
|
for (auto &dep : depTracker.getDependencies()) {
|
||||||
|
llvm::SmallString<256> buffer;
|
||||||
|
StringRef realPath;
|
||||||
|
int FD;
|
||||||
|
// FIXME: appropriate error handling
|
||||||
|
if (llvm::sys::fs::openFileForRead(dep, FD, &buffer)) {
|
||||||
|
// Couldn't open the file now, so let's just assume the old path was
|
||||||
|
// canonical (enough).
|
||||||
|
realPath = dep;
|
||||||
|
} else {
|
||||||
|
realPath = buffer.str();
|
||||||
|
// Not much we can do about failing to close.
|
||||||
|
(void)close(FD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide if this is a swiftmodule based on the extension of the raw
|
||||||
|
// dependency path, as the true file may have a different one.
|
||||||
|
auto ext = llvm::sys::path::extension(dep);
|
||||||
|
if (ext.startswith(".") &&
|
||||||
|
ext.drop_front() == SERIALIZED_MODULE_EXTENSION) {
|
||||||
|
swiftModules.push_back(realPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadedModuleTraceFormat trace = {
|
||||||
|
/*name=*/opts.ModuleName,
|
||||||
|
/*arch=*/ctxt.LangOpts.Target.getArchName(),
|
||||||
|
/*swiftmodules=*/reversePathSortedFilenames(swiftModules)};
|
||||||
|
|
||||||
|
// raw_fd_ostream is unbuffered, and we may have multiple processes writing,
|
||||||
|
// so first write the whole thing into memory and dump out that buffer to the
|
||||||
|
// file.
|
||||||
|
std::string stringBuffer;
|
||||||
|
{
|
||||||
|
llvm::raw_string_ostream memoryBuffer(stringBuffer);
|
||||||
|
json::Output jsonOutput(memoryBuffer, /*PrettyPrint=*/false);
|
||||||
|
json::jsonize(jsonOutput, trace, /*Required=*/true);
|
||||||
|
}
|
||||||
|
stringBuffer += "\n";
|
||||||
|
|
||||||
|
out << stringBuffer;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes SIL out to the given file.
|
/// Writes SIL out to the given file.
|
||||||
static bool writeSIL(SILModule &SM, ModuleDecl *M, bool EmitVerboseSIL,
|
static bool writeSIL(SILModule &SM, ModuleDecl *M, bool EmitVerboseSIL,
|
||||||
StringRef OutputFilename, bool SortSIL) {
|
StringRef OutputFilename, bool SortSIL) {
|
||||||
@@ -464,6 +556,10 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
|
|||||||
emitReferenceDependencies(Context.Diags, Instance->getPrimarySourceFile(),
|
emitReferenceDependencies(Context.Diags, Instance->getPrimarySourceFile(),
|
||||||
*Instance->getDependencyTracker(), opts);
|
*Instance->getDependencyTracker(), opts);
|
||||||
|
|
||||||
|
if (!opts.LoadedModuleTracePath.empty())
|
||||||
|
(void)emitLoadedModuleTrace(Context, *Instance->getDependencyTracker(),
|
||||||
|
opts);
|
||||||
|
|
||||||
if (Context.hadError())
|
if (Context.hadError())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -1006,7 +1102,8 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
|||||||
|
|
||||||
DependencyTracker depTracker;
|
DependencyTracker depTracker;
|
||||||
if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() ||
|
if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() ||
|
||||||
!Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty()) {
|
!Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty() ||
|
||||||
|
!Invocation.getFrontendOptions().LoadedModuleTracePath.empty()) {
|
||||||
Instance->setDependencyTracker(&depTracker);
|
Instance->setDependencyTracker(&depTracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3851,13 +3851,25 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
|
|||||||
switch (recordID) {
|
switch (recordID) {
|
||||||
case decls_block::NAME_ALIAS_TYPE: {
|
case decls_block::NAME_ALIAS_TYPE: {
|
||||||
DeclID underlyingID;
|
DeclID underlyingID;
|
||||||
decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID);
|
TypeID canonicalTypeID;
|
||||||
|
decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID,
|
||||||
|
canonicalTypeID);
|
||||||
auto alias = dyn_cast_or_null<TypeAliasDecl>(getDecl(underlyingID));
|
auto alias = dyn_cast_or_null<TypeAliasDecl>(getDecl(underlyingID));
|
||||||
if (!alias) {
|
if (!alias) {
|
||||||
error();
|
error();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx.LangOpts.EnableDeserializationRecovery) {
|
||||||
|
if (Type expectedType = getType(canonicalTypeID)) {
|
||||||
|
if (!alias->getDeclaredInterfaceType()->isEqual(expectedType)) {
|
||||||
|
// Fall back to the canonical type.
|
||||||
|
typeOrOffset = expectedType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typeOrOffset = alias->getDeclaredInterfaceType();
|
typeOrOffset = alias->getDeclaredInterfaceType();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4615,6 +4627,16 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
|
|||||||
auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
|
auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
|
||||||
auto second = getType(*rawIDIter++);
|
auto second = getType(*rawIDIter++);
|
||||||
auto third = cast_or_null<TypeDecl>(getDecl(*rawIDIter++));
|
auto third = cast_or_null<TypeDecl>(getDecl(*rawIDIter++));
|
||||||
|
if (isa<TypeAliasDecl>(third) &&
|
||||||
|
third->getModuleContext() != getAssociatedModule() &&
|
||||||
|
!third->getDeclaredInterfaceType()->isEqual(second)) {
|
||||||
|
// Conservatively drop references to typealiases in other modules
|
||||||
|
// that may have changed. This may also drop references to typealiases
|
||||||
|
// that /haven't/ changed but just happen to have generics in them, but
|
||||||
|
// in practice having a declaration here isn't actually required by the
|
||||||
|
// rest of the compiler.
|
||||||
|
third = nullptr;
|
||||||
|
}
|
||||||
typeWitnesses[first] = std::make_pair(second, third);
|
typeWitnesses[first] = std::make_pair(second, third);
|
||||||
}
|
}
|
||||||
assert(rawIDIter <= rawIDs.end() && "read too much");
|
assert(rawIDIter <= rawIDs.end() && "read too much");
|
||||||
|
|||||||
@@ -432,7 +432,8 @@ DeclContextID Serializer::addDeclContextRef(const DeclContext *DC) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclID Serializer::addDeclRef(const Decl *D, bool forceSerialization) {
|
DeclID Serializer::addDeclRef(const Decl *D, bool forceSerialization,
|
||||||
|
bool allowTypeAliasXRef) {
|
||||||
if (!D)
|
if (!D)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -447,6 +448,10 @@ DeclID Serializer::addDeclRef(const Decl *D, bool forceSerialization) {
|
|||||||
isa<PrecedenceGroupDecl>(D)) &&
|
isa<PrecedenceGroupDecl>(D)) &&
|
||||||
"cannot cross-reference this decl");
|
"cannot cross-reference this decl");
|
||||||
|
|
||||||
|
assert((allowTypeAliasXRef || !isa<TypeAliasDecl>(D) ||
|
||||||
|
D->getModuleContext() == M) &&
|
||||||
|
"cannot cross-reference typealiases directly (use the NameAliasType)");
|
||||||
|
|
||||||
id = { ++LastDeclID, forceSerialization };
|
id = { ++LastDeclID, forceSerialization };
|
||||||
DeclsAndTypesToWrite.push(D);
|
DeclsAndTypesToWrite.push(D);
|
||||||
return id.first;
|
return id.first;
|
||||||
@@ -1326,7 +1331,8 @@ void Serializer::writeNormalConformance(
|
|||||||
Type type, TypeDecl *typeDecl) {
|
Type type, TypeDecl *typeDecl) {
|
||||||
data.push_back(addDeclRef(assocType));
|
data.push_back(addDeclRef(assocType));
|
||||||
data.push_back(addTypeRef(type));
|
data.push_back(addTypeRef(type));
|
||||||
data.push_back(addDeclRef(typeDecl));
|
data.push_back(addDeclRef(typeDecl, /*forceSerialization*/false,
|
||||||
|
/*allowTypeAliasXRef*/true));
|
||||||
++numTypeWitnesses;
|
++numTypeWitnesses;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@@ -3118,7 +3124,10 @@ void Serializer::writeType(Type ty) {
|
|||||||
|
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
|
||||||
NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
addDeclRef(typeAlias));
|
addDeclRef(typeAlias,
|
||||||
|
/*forceSerialization*/false,
|
||||||
|
/*allowTypeAliasXRef*/true),
|
||||||
|
TypeID());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TypeKind::NameAlias: {
|
case TypeKind::NameAlias: {
|
||||||
@@ -3127,7 +3136,10 @@ void Serializer::writeType(Type ty) {
|
|||||||
|
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
|
||||||
NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
addDeclRef(typeAlias));
|
addDeclRef(typeAlias,
|
||||||
|
/*forceSerialization*/false,
|
||||||
|
/*allowTypeAliasXRef*/true),
|
||||||
|
addTypeRef(ty->getCanonicalType()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -405,7 +405,8 @@ public:
|
|||||||
/// The Decl will be scheduled for serialization if necessary.
|
/// The Decl will be scheduled for serialization if necessary.
|
||||||
///
|
///
|
||||||
/// \returns The ID for the given Decl in this module.
|
/// \returns The ID for the given Decl in this module.
|
||||||
DeclID addDeclRef(const Decl *D, bool forceSerialization = false);
|
DeclID addDeclRef(const Decl *D, bool forceSerialization = false,
|
||||||
|
bool allowTypeAliasXRef = false);
|
||||||
|
|
||||||
/// Records the use of the given DeclContext.
|
/// Records the use of the given DeclContext.
|
||||||
///
|
///
|
||||||
|
|||||||
1
test/Driver/Inputs/loaded_module_trace_empty.swift
Normal file
1
test/Driver/Inputs/loaded_module_trace_empty.swift
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// Don't need anything here, just for the module to exist.
|
||||||
1
test/Driver/Inputs/loaded_module_trace_header.h
Normal file
1
test/Driver/Inputs/loaded_module_trace_header.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "loaded_module_trace_header2.h"
|
||||||
1
test/Driver/Inputs/loaded_module_trace_header2.h
Normal file
1
test/Driver/Inputs/loaded_module_trace_header2.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import Foundation;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import Module
|
||||||
22
test/Driver/loaded_module_trace.swift
Normal file
22
test/Driver/loaded_module_trace.swift
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// RUN: rm -rf %t && mkdir -p %t
|
||||||
|
// RUN: %target-build-swift -emit-module -module-name Module %S/Inputs/loaded_module_trace_empty.swift -o %t/Module.swiftmodule
|
||||||
|
// RUN: %target-build-swift -emit-module -module-name Module2 %S/Inputs/loaded_module_trace_imports_module.swift -o %t/Module2.swiftmodule -I %t
|
||||||
|
// RUN: %target-build-swift %s -emit-loaded-module-trace -o %t/loaded_module_trace -I %t
|
||||||
|
// RUN: %FileCheck -check-prefix=CHECK %s < %t/loaded_module_trace.trace.json
|
||||||
|
// RUN: %FileCheck -check-prefix=CHECK-CONFIRM-ONELINE %s < %t/loaded_module_trace.trace.json
|
||||||
|
|
||||||
|
// CHECK: {
|
||||||
|
// CHECK: "name":"loaded_module_trace"
|
||||||
|
// CHECK: "arch":"{{[^"]*}}"
|
||||||
|
// CHECK: "swiftmodules":[
|
||||||
|
// CHECK: "{{[^"]*}}/Module2.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Swift.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/SwiftOnoneSupport.swiftmodule"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
|
// Make sure it's all on a single line.
|
||||||
|
// CHECK-CONFIRM-ONELINE: {"name":{{.*}}]}
|
||||||
|
|
||||||
|
// 'Module2' imports 'Module', so we're also checking we don't get transitive dependencies.
|
||||||
|
import Module2
|
||||||
6
test/Driver/loaded_module_trace_append.swift
Normal file
6
test/Driver/loaded_module_trace_append.swift
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// RUN: env SWIFT_LOADED_MODULE_TRACE_PATH=%t %target-build-swift -module-name loaded_module_trace_append %s -o- > /dev/null
|
||||||
|
// RUN: env SWIFT_LOADED_MODULE_TRACE_PATH=%t %target-build-swift -module-name loaded_module_trace_append2 %s -o- > /dev/null
|
||||||
|
// RUN: %FileCheck %s < %t
|
||||||
|
|
||||||
|
// CHECK: {"name":"loaded_module_trace_append",{{.*}}]}
|
||||||
|
// CHECK-NEXT: {"name":"loaded_module_trace_append2",{{.*}}]}
|
||||||
11
test/Driver/loaded_module_trace_env.swift
Normal file
11
test/Driver/loaded_module_trace_env.swift
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// RUN: env SWIFT_LOADED_MODULE_TRACE_PATH=%t %target-build-swift -module-name loaded_module_trace_env %s -o- > /dev/null
|
||||||
|
// RUN: %FileCheck %s < %t
|
||||||
|
|
||||||
|
// CHECK: {
|
||||||
|
// CHECK: "name":"loaded_module_trace_env"
|
||||||
|
// CHECK: "arch":"{{[^"]*}}"
|
||||||
|
// CHECK: "swiftmodules":[
|
||||||
|
// CHECK: "{{[^"]*}}/Swift.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/SwiftOnoneSupport.swiftmodule"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: }
|
||||||
19
test/Driver/loaded_module_trace_foundation.swift
Normal file
19
test/Driver/loaded_module_trace_foundation.swift
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// RUN: %target-build-swift -o %t -module-name loaded_module_trace_foundation %s -emit-loaded-module-trace -emit-loaded-module-trace-path - 2>&1 | %FileCheck %s
|
||||||
|
|
||||||
|
// REQUIRES: objc_interop
|
||||||
|
|
||||||
|
// CHECK: {
|
||||||
|
// CHECK: "name":"loaded_module_trace_foundation"
|
||||||
|
// CHECK: "arch":"{{[^"]*}}"
|
||||||
|
// CHECK: "swiftmodules":[
|
||||||
|
// CHECK: "{{[^"]*}}/ObjectiveC.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Dispatch.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Darwin.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Foundation.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Swift.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/IOKit.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/SwiftOnoneSupport.swiftmodule"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
|
import Foundation
|
||||||
18
test/Driver/loaded_module_trace_header.swift
Normal file
18
test/Driver/loaded_module_trace_header.swift
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// RUN: env SWIFT_LOADED_MODULE_TRACE_PATH=%t %target-build-swift -module-name loaded_module_trace_header %s -o- -import-objc-header %S/Inputs/loaded_module_trace_header.h > /dev/null
|
||||||
|
// RUN: %FileCheck %s < %t
|
||||||
|
|
||||||
|
// REQUIRES: objc_interop
|
||||||
|
|
||||||
|
// CHECK: {
|
||||||
|
// CHECK: "name":"loaded_module_trace_header"
|
||||||
|
// CHECK: "arch":"{{[^"]*}}"
|
||||||
|
// CHECK: "swiftmodules":[
|
||||||
|
// CHECK: "{{[^"]*}}/ObjectiveC.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Dispatch.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Darwin.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Foundation.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Swift.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/IOKit.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/SwiftOnoneSupport.swiftmodule"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: }
|
||||||
20
test/Driver/loaded_module_trace_multifile.swift
Normal file
20
test/Driver/loaded_module_trace_multifile.swift
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// RUN: rm -rf %t && mkdir -p %t
|
||||||
|
// RUN: %target-build-swift -emit-module -module-name Module %S/Inputs/loaded_module_trace_empty.swift -o %t/Module.swiftmodule
|
||||||
|
// RUN: %target-build-swift -emit-module -module-name Module2 %S/Inputs/loaded_module_trace_empty.swift -o %t/Module2.swiftmodule
|
||||||
|
// RUN: %target-build-swift %s %S/Inputs/loaded_module_trace_imports_module.swift -emit-loaded-module-trace-path %t/multifile.trace.json -emit-library -o %t/loaded_module_trace_multifile -I %t
|
||||||
|
// RUN: %FileCheck %s < %t/multifile.trace.json
|
||||||
|
|
||||||
|
// This file only imports Module2, but the other file imports Module: hopefully they both appear!
|
||||||
|
|
||||||
|
// CHECK: {
|
||||||
|
// CHECK: "name":"loaded_module_trace_multifile"
|
||||||
|
// CHECK: "arch":"{{[^"]*}}"
|
||||||
|
// CHECK: "swiftmodules":[
|
||||||
|
// CHECK: "{{[^"]*}}/Module2.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Module.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/Swift.swiftmodule"
|
||||||
|
// CHECK: "{{[^"]*}}/SwiftOnoneSupport.swiftmodule"
|
||||||
|
// CHECK: ]
|
||||||
|
// CHECK: }
|
||||||
|
|
||||||
|
import Module2
|
||||||
11
test/Serialization/Recovery/Inputs/custom-modules/Typedefs.h
Normal file
11
test/Serialization/Recovery/Inputs/custom-modules/Typedefs.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#if !BAD
|
||||||
|
typedef int MysteryTypedef;
|
||||||
|
#else
|
||||||
|
typedef _Bool MysteryTypedef;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ImportedType {
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MysteryTypedef ImportedTypeAssoc __attribute__((swift_name("ImportedType.Assoc")));
|
||||||
@@ -1 +1,2 @@
|
|||||||
module Overrides { header "Overrides.h" }
|
module Overrides { header "Overrides.h" }
|
||||||
|
module Typedefs { header "Typedefs.h" }
|
||||||
|
|||||||
62
test/Serialization/Recovery/typedefs.swift
Normal file
62
test/Serialization/Recovery/typedefs.swift
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// RUN: rm -rf %t && mkdir -p %t
|
||||||
|
// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules %s
|
||||||
|
|
||||||
|
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
|
||||||
|
|
||||||
|
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -enable-experimental-deserialization-recovery | %FileCheck -check-prefix CHECK-RECOVERY %s
|
||||||
|
|
||||||
|
// RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery -DVERIFY %s -verify
|
||||||
|
// RUN: %target-swift-frontend -emit-silgen -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery %s | %FileCheck -check-prefix CHECK-SIL %s
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
|
||||||
|
import Typedefs
|
||||||
|
import Lib
|
||||||
|
|
||||||
|
// CHECK-SIL-LABEL: sil hidden @_T08typedefs11testSymbolsyyF
|
||||||
|
func testSymbols() {
|
||||||
|
// Check that the symbols are not using 'Bool'.
|
||||||
|
// CHECK-SIL: function_ref @_T03Lib1xs5Int32Vfau
|
||||||
|
_ = Lib.x
|
||||||
|
// CHECK-SIL: function_ref @_T03Lib9usesAssocs5Int32VSgfau
|
||||||
|
_ = Lib.usesAssoc
|
||||||
|
} // CHECK-SIL: end sil function '_T08typedefs11testSymbolsyyF'
|
||||||
|
|
||||||
|
#if VERIFY
|
||||||
|
let _: String = useAssoc(ImportedType.self) // expected-error {{cannot convert call result type '_.Assoc?' to expected type 'String'}}
|
||||||
|
let _: Bool? = useAssoc(ImportedType.self) // expected-error {{cannot convert value of type 'Int32?' to specified type 'Bool?'}}
|
||||||
|
let _: Int32? = useAssoc(ImportedType.self)
|
||||||
|
|
||||||
|
let _: String = useAssoc(AnotherType.self) // expected-error {{cannot convert call result type '_.Assoc?' to expected type 'String'}}
|
||||||
|
let _: Bool? = useAssoc(AnotherType.self) // expected-error {{cannot convert value of type 'AnotherType.Assoc?' to specified type 'Bool?'}}
|
||||||
|
let _: Int32? = useAssoc(AnotherType.self)
|
||||||
|
#endif // VERIFY
|
||||||
|
|
||||||
|
#else // TEST
|
||||||
|
|
||||||
|
import Typedefs
|
||||||
|
|
||||||
|
// CHECK-DAG: let x: MysteryTypedef
|
||||||
|
// CHECK-RECOVERY-DAG: let x: Int32
|
||||||
|
public let x: MysteryTypedef = 0
|
||||||
|
|
||||||
|
public protocol HasAssoc {
|
||||||
|
associatedtype Assoc
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ImportedType: HasAssoc {}
|
||||||
|
|
||||||
|
public struct AnotherType: HasAssoc {
|
||||||
|
public typealias Assoc = MysteryTypedef
|
||||||
|
}
|
||||||
|
|
||||||
|
public func useAssoc<T: HasAssoc>(_: T.Type) -> T.Assoc? { return nil }
|
||||||
|
|
||||||
|
// CHECK-DAG: let usesAssoc: ImportedType.Assoc?
|
||||||
|
// CHECK-RECOVERY-DAG: let usesAssoc: Int32?
|
||||||
|
public let usesAssoc = useAssoc(ImportedType.self)
|
||||||
|
// CHECK-DAG: let usesAssoc2: AnotherType.Assoc?
|
||||||
|
// CHECK-RECOVERY-DAG: let usesAssoc2: AnotherType.Assoc?
|
||||||
|
public let usesAssoc2 = useAssoc(AnotherType.self)
|
||||||
|
|
||||||
|
#endif // TEST
|
||||||
Reference in New Issue
Block a user