Skip to content

Commit 7b4835f

Browse files
committed
Fix direct clang cc1 emit-pcm commands with vfs overlay on Windows
Explicit module builds currently fail on Windows because direct-clang-cc1-module-build emit-pcm commands take overlaid system module map files as inputs but miss the clang VFS overlay. This change adds the overlay and fixes explicit module builds on Windows.
1 parent 73fd67b commit 7b4835f

File tree

8 files changed

+166
-8
lines changed

8 files changed

+166
-8
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ class ASTContext final {
435435

436436
/// The block list where we can find special actions based on module name;
437437
BlockListStore blockListConfig;
438+
439+
llvm::BumpPtrAllocator ClangInvocationFileMappingAllocator;
440+
438441
private:
439442
/// The current generation number, which reflects the number of
440443
/// times that external modules have been loaded.

include/swift/ClangImporter/ClangImporter.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ namespace dependencies {
7474
namespace swift {
7575
enum class ResultConvention : uint8_t;
7676
class ASTContext;
77+
class CASOptions;
7778
class CompilerInvocation;
7879
class ClangImporterOptions;
7980
class ClangInheritanceInfo;
@@ -82,6 +83,7 @@ class ClangNode;
8283
class ConcreteDeclRef;
8384
class Decl;
8485
class DeclContext;
86+
class DiagnosticEngine;
8587
class EffectiveClangContext;
8688
class EnumDecl;
8789
class FuncDecl;
@@ -881,6 +883,33 @@ struct ClangInvocationFileMapping {
881883
bool requiresBuiltinHeadersInSystemModules;
882884
};
883885

886+
class ClangInvocationFileMappingContext {
887+
public:
888+
const LangOptions &LangOpts;
889+
SearchPathOptions &SearchPathOpts;
890+
ClangImporterOptions &ClangImporterOpts;
891+
const CASOptions &CASOpts;
892+
DiagnosticEngine &Diags;
893+
894+
ClangInvocationFileMappingContext(
895+
const LangOptions &LangOpts, SearchPathOptions &SearchPathOpts,
896+
ClangImporterOptions &ClangImporterOpts, const CASOptions &CASOpts,
897+
DiagnosticEngine &Diags)
898+
: LangOpts(LangOpts), SearchPathOpts(SearchPathOpts),
899+
ClangImporterOpts(ClangImporterOpts), CASOpts(CASOpts),
900+
Diags(Diags) {}
901+
902+
virtual void *Allocate(unsigned long bytes, unsigned alignment) const = 0;
903+
904+
template <typename T>
905+
MutableArrayRef<T> Allocate(unsigned numElts) const {
906+
T *res = (T *) Allocate(sizeof(T) * numElts, alignof(T));
907+
for (unsigned i = 0; i != numElts; ++i)
908+
new (res+i) T();
909+
return {res, numElts};
910+
}
911+
};
912+
884913
/// On Linux, some platform libraries (glibc, libstdc++) are not modularized.
885914
/// We inject modulemaps for those libraries into their include directories
886915
/// to allow using them from Swift.
@@ -892,6 +921,11 @@ ClangInvocationFileMapping getClangInvocationFileMapping(
892921
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs = nullptr,
893922
bool suppressDiagnostic = false);
894923

924+
ClangInvocationFileMapping getClangInvocationFileMapping(
925+
const ClangInvocationFileMappingContext &ctx,
926+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs = nullptr,
927+
bool suppressDiagnostic = false);
928+
895929
/// Apply the given file mapping to the specified 'fileSystem', used
896930
/// primarily to inject modulemaps on platforms with non-modularized
897931
/// platform libraries.
@@ -901,6 +935,12 @@ ClangInvocationFileMapping applyClangInvocationMapping(
901935
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
902936
bool suppressDiagnostics = false);
903937

938+
ClangInvocationFileMapping applyClangInvocationMapping(
939+
const ClangInvocationFileMappingContext &ctx,
940+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
941+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
942+
bool suppressDiagnostics = false);
943+
904944
/// Information used to compute the access level of inherited C++ members.
905945
class ClangInheritanceInfo {
906946
/// The cumulative inheritance access specifier, that is used to compute the

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "llvm/CAS/ActionCache.h"
5050
#include "llvm/CAS/ObjectStore.h"
5151
#include "llvm/Option/ArgList.h"
52+
#include "llvm/Support/Allocator.h"
5253
#include "llvm/Support/BLAKE3.h"
5354
#include "llvm/Support/HashingOutputBackend.h"
5455
#include "llvm/Support/MemoryBuffer.h"
@@ -562,6 +563,8 @@ class CompilerInstance {
562563

563564
bool isWholeModuleCompilation() const { return PrimaryBufferIDs.empty(); }
564565

566+
llvm::BumpPtrAllocator ClangInvocationFileMappingAllocator;
567+
565568
public:
566569
// Out of line to avoid having to import SILModule.h.
567570
CompilerInstance();

lib/ClangImporter/ClangIncludePaths.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,25 @@ ClangImporter::createClangArgs(const ClangImporterOptions &ClangImporterOpts,
200200
return clangDriverArgs;
201201
}
202202

203+
namespace {
204+
class ClangInvocationFileMappingContextWithASTContext
205+
: public ClangInvocationFileMappingContext {
206+
const ASTContext &Ctx;
207+
208+
public:
209+
ClangInvocationFileMappingContextWithASTContext(const ASTContext &Ctx)
210+
: ClangInvocationFileMappingContext(Ctx.LangOpts, Ctx.SearchPathOpts,
211+
Ctx.ClangImporterOpts, Ctx.CASOpts, Ctx.Diags), Ctx(Ctx) {}
212+
213+
void *Allocate(unsigned long bytes, unsigned alignment) const override {
214+
return Ctx.Allocate(bytes, alignment);
215+
}
216+
};
217+
} // namespace
218+
203219
static SmallVector<std::pair<std::string, std::string>, 2>
204-
getLibcFileMapping(const ASTContext &ctx, StringRef modulemapFileName,
220+
getLibcFileMapping(const ClangInvocationFileMappingContext &ctx,
221+
StringRef modulemapFileName,
205222
std::optional<ArrayRef<StringRef>> maybeHeaderFileNames,
206223
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &vfs,
207224
bool suppressDiagnostic) {
@@ -267,7 +284,8 @@ getLibcFileMapping(const ASTContext &ctx, StringRef modulemapFileName,
267284
}
268285

269286
static void getLibStdCxxFileMapping(
270-
ClangInvocationFileMapping &fileMapping, const ASTContext &ctx,
287+
ClangInvocationFileMapping &fileMapping,
288+
const ClangInvocationFileMappingContext &ctx,
271289
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &vfs,
272290
bool suppressDiagnostic) {
273291
assert(ctx.LangOpts.EnableCXXInterop &&
@@ -472,7 +490,8 @@ GetPlatformAuxiliaryFile(StringRef Platform, StringRef File,
472490
}
473491

474492
void GetWindowsFileMappings(
475-
ClangInvocationFileMapping &fileMapping, const ASTContext &Context,
493+
ClangInvocationFileMapping &fileMapping,
494+
const ClangInvocationFileMappingContext &Context,
476495
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &driverVFS,
477496
bool &requiresBuiltinHeadersInSystemModules) {
478497
const llvm::Triple &Triple = Context.LangOpts.Target;
@@ -612,7 +631,16 @@ void GetWindowsFileMappings(
612631
} // namespace
613632

614633
ClangInvocationFileMapping swift::getClangInvocationFileMapping(
615-
const ASTContext &ctx, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
634+
const ASTContext &ctx,
635+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
636+
bool suppressDiagnostic) {
637+
ClangInvocationFileMappingContextWithASTContext Ctx(ctx);
638+
return getClangInvocationFileMapping(Ctx, vfs, suppressDiagnostic);
639+
}
640+
641+
ClangInvocationFileMapping swift::getClangInvocationFileMapping(
642+
const ClangInvocationFileMappingContext &ctx,
643+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
616644
bool suppressDiagnostic) {
617645
ClangInvocationFileMapping result;
618646
if (!vfs)
@@ -683,10 +711,21 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping(
683711
return result;
684712
}
685713

686-
ClangInvocationFileMapping swift::applyClangInvocationMapping(const ASTContext &ctx,
687-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
688-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
689-
bool suppressDiagnostics) {
714+
ClangInvocationFileMapping swift::applyClangInvocationMapping(
715+
const ASTContext &ctx,
716+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
717+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
718+
bool suppressDiagnostics) {
719+
ClangInvocationFileMappingContextWithASTContext Ctx(ctx);
720+
return applyClangInvocationMapping(Ctx, baseVFS, fileSystem,
721+
suppressDiagnostics);
722+
}
723+
724+
ClangInvocationFileMapping swift::applyClangInvocationMapping(
725+
const ClangInvocationFileMappingContext &ctx,
726+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> baseVFS,
727+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &fileSystem,
728+
bool suppressDiagnostics) {
690729
if (ctx.CASOpts.HasImmutableFileSystem)
691730
return ClangInvocationFileMapping();
692731

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,14 @@ ModuleDependencyInfo ModuleDependencyScanner::bridgeClangModuleDependency(
19921992
}
19931993
}
19941994

1995+
// Pass the -sdk flag to make the system header VFS overlay finable
1996+
// for the -direct-clang-cc1-module-build emit-pcm command on Windows.
1997+
StringRef SDKPath = ScanASTContext.SearchPathOpts.getSDKPath();
1998+
if (!SDKPath.empty()) {
1999+
swiftArgs.push_back("-sdk");
2000+
swiftArgs.push_back(SDKPath.str());
2001+
}
2002+
19952003
// Add args reported by the scanner.
19962004
auto clangArgs = invocation.getCC1CommandLine();
19972005
llvm::for_each(clangArgs, addClangArg);

lib/Frontend/Frontend.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,15 @@ bool CompilerInstance::setUpASTContextIfNeeded() {
365365
Invocation.getLangOptions().DebuggerSupport)
366366
Invocation.getLangOptions().EnableDeserializationSafety = false;
367367

368+
if (!Invocation.getCASOptions().requireCASFS() &&
369+
Invocation.getClangImporterOptions().DirectClangCC1ModuleBuild &&
370+
Invocation.getFrontendOptions().RequestedAction ==
371+
FrontendOptions::ActionType::EmitPCM) {
372+
// For non-caching builds, transfer the ownership to the ASTContext.
373+
Context->ClangInvocationFileMappingAllocator =
374+
std::move(ClangInvocationFileMappingAllocator);
375+
}
376+
368377
if (setUpModuleLoaders())
369378
return true;
370379
if (setUpPluginLoader())
@@ -559,6 +568,26 @@ void CompilerInstance::setupCachingDiagnosticsProcessorIfNeeded() {
559568
CDP->startDiagnosticCapture();
560569
}
561570

571+
namespace {
572+
// This is used before ASTContext is initialized.
573+
class ClangInvocationFileMappingContextPreASTContext
574+
: public ClangInvocationFileMappingContext {
575+
llvm::BumpPtrAllocator &Allocator;
576+
577+
public:
578+
ClangInvocationFileMappingContextPreASTContext(
579+
const LangOptions &LangOpts, SearchPathOptions &SearchPathOpts,
580+
ClangImporterOptions &ClangImporterOpts, const CASOptions &CASOpts,
581+
DiagnosticEngine &Diags, llvm::BumpPtrAllocator &Allocator)
582+
: ClangInvocationFileMappingContext(LangOpts, SearchPathOpts,
583+
ClangImporterOpts, CASOpts, Diags), Allocator(Allocator) {}
584+
585+
void *Allocate(unsigned long bytes, unsigned alignment) const override {
586+
return Allocator.Allocate(bytes, alignment);
587+
}
588+
};
589+
} // namespace
590+
562591
bool CompilerInstance::setup(const CompilerInvocation &Invoke,
563592
std::string &Error, ArrayRef<const char *> Args) {
564593
Invocation = Invoke;
@@ -708,6 +737,25 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
708737
new llvm::vfs::OverlayFileSystem(MemFS);
709738
OverlayVFS->pushOverlay(SourceMgr.getFileSystem());
710739
SourceMgr.setFileSystem(std::move(OverlayVFS));
740+
} else {
741+
// For non-caching -direct-clang-cc1-module-build emit-pcm build,
742+
// setup the clang VFS so it can find system modulemap files
743+
// (like vcruntime.modulemap) as an input file.
744+
if (Invocation.getClangImporterOptions().DirectClangCC1ModuleBuild &&
745+
Invocation.getFrontendOptions().RequestedAction ==
746+
FrontendOptions::ActionType::EmitPCM) {
747+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
748+
SourceMgr.getFileSystem();
749+
ClangInvocationFileMappingContextPreASTContext ClangContext(
750+
Invocation.getLangOptions(), Invocation.getSearchPathOptions(),
751+
Invocation.getClangImporterOptions(), Invocation.getCASOptions(),
752+
Diagnostics, ClangInvocationFileMappingAllocator);
753+
ClangInvocationFileMapping FileMapping = applyClangInvocationMapping(
754+
ClangContext, nullptr, VFS, /*suppressDiagnostic=*/false);
755+
if (!FileMapping.redirectedFiles.empty()) {
756+
SourceMgr.setFileSystem(std::move(VFS));
757+
}
758+
}
711759
}
712760

713761
auto ExpectedOverlay =
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module SAL [system] {
2+
header "sal.h"
3+
export *
4+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// REQUIRES: OS=windows-msvc
2+
3+
// Test that the -direct-clang-cc1-module-build is able to create a module from the VC runtime with an overlaid modulemap file
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: split-file %s %t
7+
8+
// RUN: %swift_frontend_plain -target %target-triple -module-cache-path %t/clang-module-cache -scan-dependencies -module-name Test -sdk %S/Inputs/WinSDK %t/Test.swift -o %t/deps.json
9+
// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:SAL > %t/SAL.cmd
10+
// RUN: %swift_frontend_plain @%t/SAL.cmd
11+
12+
//--- Test.swift
13+
import SAL

0 commit comments

Comments
 (0)