@@ -902,6 +902,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
902
902
invocationArgStrs.push_back (" clang" );
903
903
switch (importerOpts.Mode ) {
904
904
case ClangImporterOptions::Modes::Normal:
905
+ case ClangImporterOptions::Modes::PrecompiledModule:
905
906
getNormalInvocationArguments (invocationArgStrs, ctx, importerOpts);
906
907
break ;
907
908
case ClangImporterOptions::Modes::EmbedBitcode:
@@ -1062,7 +1063,17 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
1062
1063
if (importerOpts.Mode == ClangImporterOptions::Modes::EmbedBitcode)
1063
1064
return importer;
1064
1065
1066
+ // ClangImporter always sets this in Normal mode, so we need to make sure to
1067
+ // set it before bailing out early when configuring ClangImporter for
1068
+ // precompiled modules. This is not a benign langopt, so forgetting this (for
1069
+ // example, if we combined the early exit below with the one above) would make
1070
+ // the compiler instance used to emit PCMs incompatible with the one used to
1071
+ // read them later.
1065
1072
instance.getLangOpts ().NeededByPCHOrCompilationUsesPCH = true ;
1073
+
1074
+ if (importerOpts.Mode == ClangImporterOptions::Modes::PrecompiledModule)
1075
+ return importer;
1076
+
1066
1077
bool canBegin = action->BeginSourceFile (instance,
1067
1078
instance.getFrontendOpts ().Inputs [0 ]);
1068
1079
if (!canBegin)
@@ -1446,43 +1457,82 @@ std::string ClangImporter::getBridgingHeaderContents(StringRef headerPath,
1446
1457
return result;
1447
1458
}
1448
1459
1449
- bool
1450
- ClangImporter::emitBridgingPCH (StringRef headerPath,
1451
- StringRef outputPCHPath) {
1460
+ // / Returns the appropriate source input language based on language options.
1461
+ static clang::Language getLanguageFromOptions (
1462
+ const clang::LangOptions *LangOpts) {
1463
+ if (LangOpts->OpenCL )
1464
+ return clang::Language::OpenCL;
1465
+ if (LangOpts->CUDA )
1466
+ return clang::Language::CUDA;
1467
+ if (LangOpts->ObjC )
1468
+ return LangOpts->CPlusPlus ?
1469
+ clang::Language::ObjCXX : clang::Language::ObjC;
1470
+ return LangOpts->CPlusPlus ? clang::Language::CXX : clang::Language::C;
1471
+ }
1472
+
1473
+ // / Wraps the given frontend action in an index data recording action if the
1474
+ // / frontend options have an index store path specified.
1475
+ static
1476
+ std::unique_ptr<clang::FrontendAction> wrapActionForIndexingIfEnabled (
1477
+ const clang::FrontendOptions &FrontendOpts,
1478
+ std::unique_ptr<clang::FrontendAction> action) {
1479
+ if (!FrontendOpts.IndexStorePath .empty ()) {
1480
+ return clang::index::createIndexDataRecordingAction (
1481
+ FrontendOpts, std::move (action));
1482
+ }
1483
+ return action;
1484
+ }
1485
+
1486
+ std::unique_ptr<clang::CompilerInstance>
1487
+ ClangImporter::cloneCompilerInstanceForPrecompiling () {
1452
1488
auto invocation =
1453
1489
std::make_shared<clang::CompilerInvocation>(*Impl.Invocation );
1454
- invocation->getFrontendOpts ().DisableFree = false ;
1455
- invocation->getFrontendOpts ().Inputs .clear ();
1456
- invocation->getFrontendOpts ().Inputs .push_back (
1457
- clang::FrontendInputFile (headerPath, clang::Language::ObjC));
1458
- invocation->getFrontendOpts ().OutputFile = outputPCHPath;
1459
- invocation->getFrontendOpts ().ProgramAction = clang::frontend::GeneratePCH;
1460
- invocation->getPreprocessorOpts ().resetNonModularOptions ();
1461
- invocation->getLangOpts ()->NeededByPCHOrCompilationUsesPCH = true ;
1462
- invocation->getLangOpts ()->CacheGeneratedPCH = true ;
1463
1490
1464
- clang::CompilerInstance emitInstance (
1491
+ auto &PPOpts = invocation->getPreprocessorOpts ();
1492
+ PPOpts.resetNonModularOptions ();
1493
+
1494
+ auto &FrontendOpts = invocation->getFrontendOpts ();
1495
+ FrontendOpts.DisableFree = false ;
1496
+ FrontendOpts.Inputs .clear ();
1497
+
1498
+ auto clonedInstance = llvm::make_unique<clang::CompilerInstance>(
1465
1499
Impl.Instance ->getPCHContainerOperations (),
1466
1500
&Impl.Instance ->getModuleCache ());
1467
- emitInstance. setInvocation (std::move (invocation));
1468
- emitInstance. createDiagnostics (&Impl.Instance ->getDiagnosticClient (),
1469
- /* ShouldOwnClient=*/ false );
1501
+ clonedInstance-> setInvocation (std::move (invocation));
1502
+ clonedInstance-> createDiagnostics (&Impl.Instance ->getDiagnosticClient (),
1503
+ /* ShouldOwnClient=*/ false );
1470
1504
1471
1505
clang::FileManager &fileManager = Impl.Instance ->getFileManager ();
1472
- emitInstance. setFileManager (&fileManager);
1473
- emitInstance. createSourceManager (fileManager);
1474
- emitInstance. setTarget (&Impl.Instance ->getTarget ());
1506
+ clonedInstance-> setFileManager (&fileManager);
1507
+ clonedInstance-> createSourceManager (fileManager);
1508
+ clonedInstance-> setTarget (&Impl.Instance ->getTarget ());
1475
1509
1476
- std::unique_ptr<clang::FrontendAction> action;
1477
- action.reset (new clang::GeneratePCHAction ());
1478
- if (!emitInstance.getFrontendOpts ().IndexStorePath .empty ()) {
1479
- action = clang::index::
1480
- createIndexDataRecordingAction (emitInstance.getFrontendOpts (),
1481
- std::move (action));
1482
- }
1483
- emitInstance.ExecuteAction (*action);
1510
+ return clonedInstance;
1511
+ }
1512
+
1513
+ bool
1514
+ ClangImporter::emitBridgingPCH (StringRef headerPath,
1515
+ StringRef outputPCHPath) {
1516
+ auto emitInstance = cloneCompilerInstanceForPrecompiling ();
1517
+ auto &invocation = emitInstance->getInvocation ();
1518
+
1519
+ auto LangOpts = invocation.getLangOpts ();
1520
+ LangOpts->NeededByPCHOrCompilationUsesPCH = true ;
1521
+ LangOpts->CacheGeneratedPCH = true ;
1522
+
1523
+ auto language = getLanguageFromOptions (LangOpts);
1524
+ auto inputFile = clang::FrontendInputFile (headerPath, language);
1525
+
1526
+ auto &FrontendOpts = invocation.getFrontendOpts ();
1527
+ FrontendOpts.Inputs = {inputFile};
1528
+ FrontendOpts.OutputFile = outputPCHPath;
1529
+ FrontendOpts.ProgramAction = clang::frontend::GeneratePCH;
1484
1530
1485
- if (emitInstance.getDiagnostics ().hasErrorOccurred ()) {
1531
+ auto action = wrapActionForIndexingIfEnabled (
1532
+ FrontendOpts, llvm::make_unique<clang::GeneratePCHAction>());
1533
+ emitInstance->ExecuteAction (*action);
1534
+
1535
+ if (emitInstance->getDiagnostics ().hasErrorOccurred ()) {
1486
1536
Impl.SwiftContext .Diags .diagnose ({},
1487
1537
diag::bridging_header_pch_error,
1488
1538
outputPCHPath, headerPath);
@@ -1491,6 +1541,65 @@ ClangImporter::emitBridgingPCH(StringRef headerPath,
1491
1541
return false ;
1492
1542
}
1493
1543
1544
+ bool ClangImporter::emitPrecompiledModule (StringRef moduleMapPath,
1545
+ StringRef moduleName,
1546
+ StringRef outputPath) {
1547
+ auto emitInstance = cloneCompilerInstanceForPrecompiling ();
1548
+ auto &invocation = emitInstance->getInvocation ();
1549
+
1550
+ auto LangOpts = invocation.getLangOpts ();
1551
+ LangOpts->setCompilingModule (clang::LangOptions::CMK_ModuleMap);
1552
+ LangOpts->ModuleName = moduleName;
1553
+ LangOpts->CurrentModule = LangOpts->ModuleName ;
1554
+
1555
+ auto language = getLanguageFromOptions (LangOpts);
1556
+ auto inputFile = clang::FrontendInputFile (
1557
+ moduleMapPath, clang::InputKind (
1558
+ language, clang::InputKind::ModuleMap, false ));
1559
+
1560
+ auto &FrontendOpts = invocation.getFrontendOpts ();
1561
+ FrontendOpts.Inputs = {inputFile};
1562
+ FrontendOpts.OriginalModuleMap = moduleMapPath;
1563
+ FrontendOpts.OutputFile = outputPath;
1564
+ FrontendOpts.ProgramAction = clang::frontend::GenerateModule;
1565
+
1566
+ auto action = wrapActionForIndexingIfEnabled (
1567
+ FrontendOpts,
1568
+ llvm::make_unique<clang::GenerateModuleFromModuleMapAction>());
1569
+ emitInstance->ExecuteAction (*action);
1570
+
1571
+ if (emitInstance->getDiagnostics ().hasErrorOccurred ()) {
1572
+ Impl.SwiftContext .Diags .diagnose ({},
1573
+ diag::emit_pcm_error,
1574
+ outputPath, moduleMapPath);
1575
+ return true ;
1576
+ }
1577
+ return false ;
1578
+ }
1579
+
1580
+ bool ClangImporter::dumpPrecompiledModule (StringRef modulePath,
1581
+ StringRef outputPath) {
1582
+ auto dumpInstance = cloneCompilerInstanceForPrecompiling ();
1583
+ auto &invocation = dumpInstance->getInvocation ();
1584
+
1585
+ auto inputFile = clang::FrontendInputFile (
1586
+ modulePath, clang::InputKind (
1587
+ clang::Language::Unknown, clang::InputKind::Precompiled, false ));
1588
+
1589
+ auto &FrontendOpts = invocation.getFrontendOpts ();
1590
+ FrontendOpts.Inputs = {inputFile};
1591
+ FrontendOpts.OutputFile = outputPath;
1592
+
1593
+ auto action = llvm::make_unique<clang::DumpModuleInfoAction>();
1594
+ dumpInstance->ExecuteAction (*action);
1595
+
1596
+ if (dumpInstance->getDiagnostics ().hasErrorOccurred ()) {
1597
+ Impl.SwiftContext .Diags .diagnose ({}, diag::dump_pcm_error, modulePath);
1598
+ return true ;
1599
+ }
1600
+ return false ;
1601
+ }
1602
+
1494
1603
void ClangImporter::collectVisibleTopLevelModuleNames (
1495
1604
SmallVectorImpl<Identifier> &names) const {
1496
1605
SmallVector<clang::Module *, 32 > Modules;
0 commit comments