26#include "llvm/ADT/DenseSet.h"
27#include "llvm/ADT/DepthFirstIterator.h"
28#include "llvm/ADT/DirectedGraph.h"
29#include "llvm/ADT/PostOrderIterator.h"
30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/SmallVectorExtras.h"
32#include "llvm/ADT/TypeSwitch.h"
33#include "llvm/ADT/iterator_range.h"
34#include "llvm/Option/ArgList.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/GraphWriter.h"
37#include "llvm/Support/JSON.h"
38#include "llvm/Support/Path.h"
39#include "llvm/Support/PrettyStackTrace.h"
40#include "llvm/Support/ThreadPool.h"
41#include "llvm/Support/VirtualFileSystem.h"
53 if (!DAL.hasFlag(options::OPT_fmodules_reduced_bmi,
54 options::OPT_fno_modules_reduced_bmi,
true)) {
55 Diags.
Report(diag::err_drv_modules_driver_requires_reduced_bmi);
60static bool fromJSON(
const llvm::json::Value &Params,
63 llvm::json::ObjectMapper O(Params, P);
64 return O.mapOptional(
"system-include-directories",
68static bool fromJSON(
const llvm::json::Value &Params,
71 llvm::json::ObjectMapper O(Params, P);
72 return O.map(
"is-std-library", ModuleEntry.
IsStdlib) &&
74 O.map(
"source-path", ModuleEntry.
SourcePath) &&
75 O.mapOptional(
"local-arguments", ModuleEntry.
LocalArgs);
78static bool fromJSON(
const llvm::json::Value &Params,
80 llvm::json::ObjectMapper O(Params, P);
81 return O.map(
"modules", Manifest.
Modules);
87 auto ParsedOrErr = llvm::json::parse(Buffer);
89 return ParsedOrErr.takeError();
92 llvm::json::Path::Root Root;
93 if (!
fromJSON(*ParsedOrErr, Manifest, Root))
94 return Root.getError();
105 StringRef ManifestPath) {
106 StringRef ManifestDir = llvm::sys::path::parent_path(ManifestPath);
109 auto PrependManifestDir = [&](StringRef Path) {
110 TempPath = ManifestDir;
111 llvm::sys::path::append(TempPath, Path);
112 return std::string(TempPath);
115 for (
auto &Entry : ManifestEntries) {
116 Entry.SourcePath = PrependManifestDir(Entry.SourcePath);
117 if (!Entry.LocalArgs)
120 for (
auto &IncludeDir : Entry.LocalArgs->SystemIncludeDirs)
121 IncludeDir = PrependManifestDir(IncludeDir);
127 llvm::vfs::FileSystem &VFS) {
128 auto MemBufOrErr =
VFS.getBufferForFile(ManifestPath);
130 return llvm::createFileError(ManifestPath, MemBufOrErr.getError());
132 auto ManifestOrErr =
parseManifest((*MemBufOrErr)->getBuffer());
134 return ManifestOrErr.takeError();
135 auto Manifest = std::move(*ManifestOrErr);
144 DerivedArgList &Args =
C.getArgs();
145 const OptTable &Opts =
C.getDriver().getOpts();
146 for (
const auto &Entry : ManifestEntries) {
148 makeInputArg(Args, Opts, Args.MakeArgString(Entry.SourcePath));
149 Inputs.emplace_back(types::TY_CXXModule, InputArg);
154 llvm::DenseMap<StringRef, const StdModuleManifest::Module *>;
160 for (
auto &Entry : ManifestEntries) {
161 [[maybe_unused]]
const bool Inserted =
162 ManifestEntryBySource.try_emplace(Entry.SourcePath, &Entry).second;
164 "Manifest defines multiple modules with the same source path.");
166 return ManifestEntryBySource;
175 if (
const auto It = ManifestEntryBySource.find(II.getFilename());
176 It != ManifestEntryBySource.end())
185 ArgStringList &CC1Args,
188 const DerivedArgList &TCArgs =
192 for (
const auto &IncludeDir : SystemIncludeDirs)
205 for (
auto &Job : Jobs) {
213 auto CC1Args = Job->getArguments();
215 CC1Args.push_back(
"-Wno-reserved-module-identifier");
216 if (Entry->LocalArgs)
218 Entry->LocalArgs->SystemIncludeDirs);
219 Job->replaceArguments(CC1Args);
224static std::optional<std::string>
226 if (
const Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
227 return A->getValue();
230 return std::string(Path);
240 return !InputInfos.empty() &&
types::isSrcFile(InputInfos.front().getType());
246class ScanningWorkerPool {
249 deps::DependencyScanningService &ScanningService) {
251 Slots.emplace_back(ScanningService);
254 std::iota(AvailableSlots.begin(), AvailableSlots.end(), 0);
262 [[nodiscard]]
auto scopedAcquire() {
263 std::unique_lock<std::mutex> UL(Lock);
264 CV.wait(UL, [&] {
return !AvailableSlots.empty(); });
265 const size_t Index = AvailableSlots.pop_back_val();
266 auto ReleaseHandle = [
this, Index](WorkerBundle *) { release(Index); };
267 return std::unique_ptr<WorkerBundle, decltype(ReleaseHandle)>(
268 &Slots[Index], ReleaseHandle);
273 void release(
size_t Index) {
275 std::scoped_lock<std::mutex> SL(Lock);
276 AvailableSlots.push_back(Index);
282 struct WorkerBundle {
283 WorkerBundle(deps::DependencyScanningService &ScanningService)
284 : Worker(std::make_unique<deps::DependencyScanningWorker>(
287 std::unique_ptr<deps::DependencyScanningWorker> Worker;
288 llvm::DenseSet<deps::ModuleID> SeenModules;
292 std::condition_variable CV;
293 SmallVector<size_t> AvailableSlots;
294 SmallVector<WorkerBundle, 0> Slots;
300static std::pair<std::unique_ptr<llvm::ThreadPoolInterface>,
301 std::unique_ptr<ScanningWorkerPool>>
303 size_t NumScanInputs,
bool HasStdlibModuleInputs,
308#if LLVM_ENABLE_THREADS
309 std::unique_ptr<llvm::ThreadPoolInterface> ThreadPool;
312 if (NumScanInputs == 1 || (HasStdlibModuleInputs && NumScanInputs <= 2)) {
313 auto S = llvm::optimal_concurrency(1);
314 ThreadPool = std::make_unique<llvm::SingleThreadExecutor>(std::move(S));
317 auto ThreadPoolStrategy = llvm::optimal_concurrency(
318 NumScanInputs -
static_cast<size_t>(HasStdlibModuleInputs));
319 ThreadPool = std::make_unique<llvm::DefaultThreadPool>(
320 std::move(ThreadPoolStrategy));
321 const size_t MaxConcurrency = ThreadPool->getMaxConcurrency();
322 const size_t MaxConcurrentlyScannedInputs =
324 (HasStdlibModuleInputs && NumScanInputs < MaxConcurrency ? 1 : 0);
325 WorkerCount = std::min(MaxConcurrency, MaxConcurrentlyScannedInputs);
328 auto ThreadPool = std::make_unique<llvm::SingleThreadExecutor>();
329 size_t WorkerCount = 1;
332 return {std::move(ThreadPool),
333 std::make_unique<ScanningWorkerPool>(WorkerCount, ScanningService)};
345struct StdlibModuleScanScheduler {
346 StdlibModuleScanScheduler(
const llvm::DenseMap<ModuleNameAndTriple, size_t>
347 &StdlibModuleScanIndexByID)
348 : StdlibModuleScanIndexByID(StdlibModuleScanIndexByID) {
349 ScheduledScanInputs.reserve(StdlibModuleScanIndexByID.size());
359 std::scoped_lock<std::mutex> Guard(Lock);
360 for (
const auto &ModuleName : NamedModuleDeps) {
361 const auto It = StdlibModuleScanIndexByID.find({ModuleName, Triple});
362 if (It == StdlibModuleScanIndexByID.end())
364 const size_t ScanIndex = It->second;
365 const bool AlreadyScheduled =
366 !ScheduledScanInputs.insert(ScanIndex).second;
367 if (AlreadyScheduled)
369 NewScanInputs.push_back(ScanIndex);
371 return NewScanInputs;
375 const llvm::DenseMap<ModuleNameAndTriple, size_t> &StdlibModuleScanIndexByID;
376 llvm::SmallDenseSet<size_t> ScheduledScanInputs;
386 this->LangOpts = &LangOpts;
392 StandaloneDiags.emplace_back(*LangOpts, StoredDiag);
397 return std::move(StandaloneDiags);
411class StandaloneDiagReporter {
417 OwnedFileMgr = llvm::makeIntrusiveRefCnt<FileManager>(std::move(Opts));
419 llvm::makeIntrusiveRefCnt<SourceManager>(Diags, *OwnedFileMgr);
426 llvm::StringMap<SourceLocation> SrcLocCache;
428 for (
const auto &StandaloneDiag : StandaloneDiags) {
430 getFileManager(), getSourceManager(), StandaloneDiag, SrcLocCache);
443 return *OwnedFileMgr;
459 StandaloneDiagReporter Reporter(Diags);
460 for (
auto &SingleScanDiags : AllScanDiags)
461 Reporter.Report(SingleScanDiags);
466 StringRef OutputDir) {
467 assert(!ID.ModuleName.empty() && !ID.ContextHash.empty() &&
468 "Invalid ModuleID!");
470 llvm::sys::path::append(ExplicitPCMPath, ID.ContextHash,
471 ID.ModuleName +
"-" + ID.ContextHash +
".pcm");
472 return std::string(ExplicitPCMPath);
480 ModuleLookupController(StringRef OutputDir) : OutputDir(OutputDir) {}
482 std::string lookupModuleOutput(
const deps::ModuleDeps &MD,
491 llvm::reportFatalInternalError(
492 "call to lookupModuleOutput with unexpected ModuleOutputKind");
495 std::unique_ptr<DependencyActionController> clone()
const override {
496 return std::make_unique<ModuleLookupController>(OutputDir);
504struct InputDependencies {
506 std::string ModuleName;
513 std::vector<deps::ModuleID> ClangModuleDeps;
519 std::vector<std::string> NamedModuleDeps;
523 std::vector<std::string> FileDeps;
527 std::vector<std::string> BuildArgs;
532 InputDependencies InputDeps;
533 InputDeps.ModuleName = std::move(TUDeps.ID.ModuleName);
534 InputDeps.NamedModuleDeps = std::move(TUDeps.NamedModuleDeps);
535 InputDeps.ClangModuleDeps = std::move(TUDeps.ClangModuleDeps);
536 InputDeps.FileDeps = std::move(TUDeps.FileDeps);
537 assert(TUDeps.Commands.size() == 1 &&
"Expected exactly one command");
538 InputDeps.BuildArgs = std::move(TUDeps.Commands.front().Arguments);
546 CommandLine.reserve(JobArgs.size() + 1);
548 for (
const char *Arg : JobArgs)
549 CommandLine.emplace_back(Arg);
557static std::pair<std::optional<deps::TranslationUnitDeps>,
560 StringRef WorkingDirectory,
561 ModuleLookupController &LookupController) {
562 StandaloneDiagCollector DiagConsumer;
563 std::optional<deps::TranslationUnitDeps> MaybeTUDeps;
567 auto WorkerBundleHandle = WorkerPool.scopedAcquire();
570 if (WorkerBundleHandle->Worker->computeDependencies(
571 WorkingDirectory, CC1CommandLine, DepConsumer, LookupController,
576 return {std::move(MaybeTUDeps), DiagConsumer.takeDiagnostics()};
580struct DependencyScanResult {
582 SmallVector<size_t> ScannedJobIndices;
585 SmallVector<InputDependencies, 0> InputDepsForScannedJobs;
589 SmallVector<deps::ModuleDepsGraph, 0> ModuleDepGraphsForScannedJobs;
592 SmallVector<size_t> UnusedStdlibModuleJobIndices;
595 SmallVector<size_t> NonScannableJobIndices;
607 ArrayRef<std::unique_ptr<Command>> Jobs,
608 llvm::DenseMap<StringRef, const StdModuleManifest::Module *> ManifestLookup,
609 StringRef ModuleCachePath, StringRef WorkingDirectory,
611 llvm::PrettyStackTraceString CrashInfo(
"Performing module dependency scan.");
616 for (
const auto &&[Index, Job] : llvm::enumerate(Jobs)) {
618 ScannableJobIndices.push_back(Index);
620 NonScannableJobIndices.push_back(Index);
627 llvm::DenseMap<ModuleNameAndTriple, size_t> StdlibModuleScanIndexByID;
628 for (
const auto &&[ScanIndex, JobIndex] :
629 llvm::enumerate(ScannableJobIndices)) {
630 const Command &ScanJob = *Jobs[JobIndex];
631 if (
const auto *Entry =
634 [[maybe_unused]]
const bool Inserted =
635 StdlibModuleScanIndexByID.try_emplace(ID, ScanIndex).second;
637 "Multiple jobs build the same module for the same triple.");
639 UserInputScanIndices.push_back(ScanIndex);
644 const size_t NumScanInputs = ScannableJobIndices.size();
645 const bool HasStdlibModuleInputs = !StdlibModuleScanIndexByID.empty();
650 std::unique_ptr<llvm::ThreadPoolInterface> ThreadPool;
651 std::unique_ptr<ScanningWorkerPool> WorkerPool;
653 NumScanInputs, HasStdlibModuleInputs, ScanningService);
655 StdlibModuleScanScheduler StdlibModuleRegistry(StdlibModuleScanIndexByID);
656 ModuleLookupController LookupController(ModuleCachePath);
664 std::atomic<bool> HasError{
false};
669 ScanOneAndScheduleNew = [&](
size_t ScanIndex) {
670 const size_t JobIndex = ScannableJobIndices[ScanIndex];
671 const Command &Job = *Jobs[JobIndex];
673 Job, *WorkerPool, WorkingDirectory, LookupController);
677 assert(AllScanDiags[ScanIndex].empty() &&
678 "Each slot should be written to at most once.");
679 AllScanDiags[ScanIndex] = std::move(ScanDiags);
682 HasError.store(
true, std::memory_order_relaxed);
687 const auto NewScanInputs = StdlibModuleRegistry.getNewScanInputs(
688 MaybeTUDeps->NamedModuleDeps,
getTriple(Job));
689 for (
const size_t NewScanIndex : NewScanInputs)
691 [&, NewScanIndex]() { ScanOneAndScheduleNew(NewScanIndex); });
693 assert(!AllScanResults[ScanIndex].has_value() &&
694 "Each slot should be written to at most once.");
695 AllScanResults[ScanIndex] = std::move(MaybeTUDeps);
699 for (
const size_t ScanIndex : UserInputScanIndices)
700 ThreadPool->async([&ScanOneAndScheduleNew, ScanIndex]() {
701 ScanOneAndScheduleNew(ScanIndex);
706 if (HasError.load(std::memory_order_relaxed))
710 DependencyScanResult
Result;
711 for (
auto &&[JobIndex, MaybeTUDeps] :
712 llvm::zip_equal(ScannableJobIndices, AllScanResults)) {
714 Result.ScannedJobIndices.push_back(JobIndex);
715 Result.ModuleDepGraphsForScannedJobs.push_back(
716 std::move(MaybeTUDeps->ModuleGraph));
717 Result.InputDepsForScannedJobs.push_back(
720 Result.UnusedStdlibModuleJobIndices.push_back(JobIndex);
722 Result.NonScannableJobIndices = std::move(NonScannableJobIndices);
725 llvm::SmallDenseSet<size_t> SeenJobIndices;
726 SeenJobIndices.insert_range(
Result.ScannedJobIndices);
727 SeenJobIndices.insert_range(
Result.UnusedStdlibModuleJobIndices);
728 SeenJobIndices.insert_range(
Result.NonScannableJobIndices);
729 assert(llvm::all_of(llvm::index_range(0, Jobs.size()),
730 [&](
size_t JobIndex) {
731 return SeenJobIndices.contains(JobIndex);
733 "Scan result must partition all jobs");
742using CGNodeBase = llvm::DGNode<CGNode, CGEdge>;
743using CGEdgeBase = llvm::DGEdge<CGNode, CGEdge>;
744using CGBase = llvm::DirectedGraph<CGNode, CGEdge>;
747class CGNode :
public CGNodeBase {
749 enum class NodeKind {
758 CGNode(
const NodeKind K) : Kind(K) {}
759 CGNode(
const CGNode &) =
delete;
760 CGNode(CGNode &&) =
delete;
761 CGNode &operator=(
const CGNode &) =
delete;
762 CGNode &operator=(CGNode &&) =
delete;
763 virtual ~CGNode() = 0;
765 NodeKind
getKind()
const {
return Kind; }
770CGNode::~CGNode() =
default;
779class RootNode :
public CGNode {
781 RootNode() : CGNode(
NodeKind::Root) {}
782 ~RootNode()
override =
default;
784 static bool classof(
const CGNode *N) {
785 return N->getKind() == NodeKind::Root;
790class JobNode :
public CGNode {
792 JobNode(std::unique_ptr<Command> &&Job, NodeKind Kind)
793 : CGNode(
Kind), Job(std::move(Job)) {
794 assert(this->Job &&
"Expected valid job!");
796 virtual ~JobNode()
override = 0;
798 std::unique_ptr<Command> Job;
800 static bool classof(
const CGNode *N) {
801 return N->getKind() != NodeKind::Root;
804JobNode::~JobNode() =
default;
807class ClangModuleJobNode :
public JobNode {
809 ClangModuleJobNode(std::unique_ptr<Command> &&Job, deps::ModuleDeps &&MD)
810 : JobNode(std::move(Job),
NodeKind::ClangModuleCC1Job),
812 ~ClangModuleJobNode()
override =
default;
816 static bool classof(
const CGNode *N) {
817 return N->getKind() == NodeKind::ClangModuleCC1Job;
822class ScannedJobNode :
public JobNode {
824 ScannedJobNode(std::unique_ptr<Command> &&Job, InputDependencies &&InputDeps,
826 : JobNode(std::move(Job),
Kind), InputDeps(std::move(InputDeps)) {}
827 ~ScannedJobNode()
override =
default;
829 InputDependencies InputDeps;
831 static bool classof(
const CGNode *N) {
832 return N->getKind() == NodeKind::NamedModuleCC1Job ||
833 N->getKind() == NodeKind::NonModuleCC1Job;
839class NamedModuleJobNode :
public ScannedJobNode {
841 NamedModuleJobNode(std::unique_ptr<Command> &&Job,
842 InputDependencies &&InputDeps)
843 : ScannedJobNode(std::move(Job), std::move(InputDeps),
845 ~NamedModuleJobNode()
override =
default;
847 static bool classof(
const CGNode *N) {
848 return N->getKind() == NodeKind::NamedModuleCC1Job;
854class NonModuleTUJobNode :
public ScannedJobNode {
856 NonModuleTUJobNode(std::unique_ptr<Command> &&Job,
857 InputDependencies &&InputDeps)
858 : ScannedJobNode(std::move(Job), std::move(InputDeps),
860 ~NonModuleTUJobNode()
override =
default;
862 static bool classof(
const CGNode *N) {
863 return N->getKind() == NodeKind::NonModuleCC1Job;
869class ImageJobNode :
public JobNode {
871 ImageJobNode(std::unique_ptr<Command> &&Job)
872 : JobNode(std::move(Job),
NodeKind::ImageJob) {}
873 ~ImageJobNode()
override =
default;
875 static bool classof(
const CGNode *N) {
876 return N->getKind() == NodeKind::ImageJob;
883class MiscJobNode :
public JobNode {
885 MiscJobNode(std::unique_ptr<Command> &&Job)
886 : JobNode(std::move(Job),
NodeKind::MiscJob) {}
887 ~MiscJobNode()
override =
default;
889 static bool classof(
const CGNode *N) {
890 return N->getKind() == NodeKind::MiscJob;
898class CGEdge :
public CGEdgeBase {
900 enum class EdgeKind {
906 CGEdge(CGNode &N, EdgeKind K) : CGEdgeBase(N), Kind(K) {}
907 CGEdge(
const CGEdge &) =
delete;
908 CGEdge &operator=(
const CGEdge &) =
delete;
909 CGEdge(CGEdge &&) =
delete;
910 CGEdge &operator=(CGEdge &&) =
delete;
912 EdgeKind
getKind()
const {
return Kind; }
923class CompilationGraph :
public CGBase {
925 CompilationGraph() =
default;
926 CompilationGraph(
const CompilationGraph &) =
delete;
927 CompilationGraph &operator=(
const CompilationGraph &) =
delete;
928 CompilationGraph(CompilationGraph &&G) =
default;
929 CompilationGraph &operator=(CompilationGraph &&) =
default;
930 ~CompilationGraph() =
default;
932 CGNode &getRoot()
const {
933 assert(Root &&
"Root node has not yet been created!");
937 RootNode &createRoot() {
938 assert(!Root &&
"Root node has already been created!");
939 auto &RootRef = createNodeImpl<RootNode>();
944 template <
typename T,
typename... Args> T &createJobNode(Args &&...Arg) {
945 static_assert(std::is_base_of<JobNode, T>::value,
946 "T must be derived from JobNode");
947 return createNodeImpl<T>(std::forward<Args>(Arg)...);
950 CGEdge &createEdge(CGEdge::EdgeKind Kind, CGNode &Src, CGNode &Dst) {
951 auto Edge = std::make_unique<CGEdge>(Dst, Kind);
952 CGEdge &EdgeRef = *Edge;
953 AllEdges.push_back(std::move(Edge));
954 connect(Src, Dst, EdgeRef);
959 using CGBase::addNode;
960 using CGBase::connect;
962 template <
typename T,
typename... Args> T &createNodeImpl(Args &&...Arg) {
963 auto Node = std::make_unique<T>(std::forward<Args>(Arg)...);
965 AllNodes.push_back(std::move(Node));
970 CGNode *Root =
nullptr;
971 SmallVector<std::unique_ptr<CGNode>> AllNodes;
972 SmallVector<std::unique_ptr<CGEdge>> AllEdges;
982template <>
struct GraphTraits<CGNode *> {
1007template <>
struct GraphTraits<CompilationGraph *> : GraphTraits<CGNode *> {
1021template <>
struct GraphTraits<const CGNode *> {
1025 return &E->getTargetNode();
1050struct GraphTraits<const CompilationGraph *> : GraphTraits<const CGNode *> {
1071 return "Module Dependency Graph";
1075 return "\tnode [shape=Mrecord, colorscheme=set23, style=filled];\n";
1086 return llvm::TypeSwitch<NodeRef, std::string>(N)
1087 .Case([](
const ClangModuleJobNode *ClangModuleNode) {
1088 const auto &ID = ClangModuleNode->MD.
ID;
1089 return llvm::formatv(
"{0}-{1}", ID.ModuleName, ID.ContextHash).str();
1091 .Case([](
const NamedModuleJobNode *NamedModuleNode) {
1092 return llvm::formatv(
"{0}-{1}", NamedModuleNode->InputDeps.ModuleName,
1096 .Case([](
const NonModuleTUJobNode *NonModuleTUNode) {
1097 const auto &Job = *NonModuleTUNode->Job;
1102 .DefaultUnreachable(
"Unexpected node kind! Is this node hidden?");
1106 return llvm::TypeSwitch<NodeRef, std::string>(N)
1107 .Case([](
const ClangModuleJobNode *ClangModuleNode) {
1108 const auto &ID = ClangModuleNode->MD.
ID;
1109 return llvm::formatv(
"Module type: Clang module \\| Module name: {0} "
1111 ID.ModuleName, ID.ContextHash)
1114 .Case([](
const NamedModuleJobNode *NamedModuleNode) {
1115 const auto &Job = *NamedModuleNode->Job;
1116 return llvm::formatv(
1117 "Filename: {0} \\| Module type: Named module \\| "
1118 "Module name: {1} \\| Triple: {2}",
1120 NamedModuleNode->InputDeps.ModuleName,
getTriple(Job))
1123 .Case([](
const NonModuleTUJobNode *NonModuleTUNode) {
1124 const auto &Job = *NonModuleTUNode->Job;
1125 return llvm::formatv(
"Filename: {0} \\| Triple: {1}",
1129 .DefaultUnreachable(
"Unexpected node kind! Is this node hidden?");
1133 switch (N->getKind()) {
1134 case CGNode::NodeKind::ClangModuleCC1Job:
1135 return "fillcolor=1";
1136 case CGNode::NodeKind::NamedModuleCC1Job:
1137 return "fillcolor=2";
1138 case CGNode::NodeKind::NonModuleCC1Job:
1139 return "fillcolor=3";
1141 llvm_unreachable(
"Unexpected node kind! Is this node hidden?");
1157 :
Base(O, G, IsSimple), EscapedIDByNodeRef(G->size()) {}
1160 auto IsNodeVisible = [&](NodeRef N) {
return !DTraits.isNodeHidden(N, G); };
1161 auto VisibleNodes = llvm::filter_to_vector(nodes(G), IsNodeVisible);
1163 writeNodeDefinitions(VisibleNodes);
1165 writeNodeRelations(VisibleNodes);
1169 using Base::DOTTraits;
1170 using Base::GTraits;
1171 using Base::NodeRef;
1174 for (NodeRef Node : VisibleNodes) {
1175 std::string EscapedNodeID =
1176 DOT::EscapeString(DTraits.getNodeIdentifier(Node, G));
1177 const std::string NodeLabel = DTraits.getNodeLabel(Node, G);
1178 const std::string NodeAttrs = DTraits.getNodeAttributes(Node, G);
1179 O <<
'\t' <<
'"' << EscapedNodeID <<
"\" [" << NodeAttrs <<
", label=\"{ "
1180 << DOT::EscapeString(NodeLabel) <<
" }\"];\n";
1181 EscapedIDByNodeRef.try_emplace(Node, std::move(EscapedNodeID));
1186 auto IsNodeVisible = [&](NodeRef N) {
return !DTraits.isNodeHidden(N, G); };
1187 for (NodeRef Node : VisibleNodes) {
1188 auto DstNodes = llvm::make_range(GTraits::child_begin(Node),
1189 GTraits::child_end(Node));
1190 auto VisibleDstNodes = llvm::make_filter_range(DstNodes, IsNodeVisible);
1191 StringRef EscapedSrcNodeID = EscapedIDByNodeRef.at(Node);
1192 for (NodeRef DstNode : VisibleDstNodes) {
1193 StringRef EscapedTgtNodeID = EscapedIDByNodeRef.at(DstNode);
1194 O <<
'\t' <<
'"' << EscapedSrcNodeID <<
"\" -> \"" << EscapedTgtNodeID
1200 DenseMap<NodeRef, std::string> EscapedIDByNodeRef;
1208 ArrayRef<std::unique_ptr<Command>> ScannedJobs,
1211 for (
const auto &&[Job, InputDeps] : llvm::zip_equal(
1212 llvm::make_pointee_range(ScannedJobs), InputDepsForScannedJobs)) {
1213 const auto &MainInput = Job.getInputInfos().front();
1214 const bool DefinesNamedModule = !InputDeps.ModuleName.empty();
1216 if (DefinesNamedModule && MainInput.getType() != types::TY_CXXModule) {
1217 Diags.
Report(diag::err_module_defined_outside_of_module_source)
1218 << InputDeps.ModuleName << MainInput.getFilename();
1229 for (
const auto JobIndex : Indices) {
1230 assert(Jobs[JobIndex] &&
"Expected valid job!");
1231 Out.push_back(std::move(Jobs[JobIndex]));
1238 CompilationGraph &Graph,
1240 for (
auto &Job : NonScannableJobs) {
1241 if (Job->getCreator().isLinkJob())
1242 Graph.createJobNode<ImageJobNode>(std::move(Job));
1244 Graph.createJobNode<MiscJobNode>(std::move(Job));
1254 CompilationGraph &Graph,
1257 for (
auto &Job : UnusedStdlibModuleJobs) {
1258 auto &NewNode = Graph.createJobNode<MiscJobNode>(std::move(Job));
1259 StdlibModuleNodesToPrune.push_back(&NewNode);
1261 return StdlibModuleNodesToPrune;
1269 const auto &SourceAction = Job.
getSource();
1270 return C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(),
1271 SourceAction.getOffloadingDeviceKind());
1275static std::unique_ptr<Command>
1278 DerivedArgList &Args =
C.getArgs();
1279 const OptTable &Opts =
C.getDriver().getOpts();
1280 Arg *InputArg =
makeInputArg(Args, Opts,
"<discovered clang module>");
1288 ArgStringList JobArgs;
1289 JobArgs.reserve(BuildArgs.size());
1290 for (
const auto &Arg : BuildArgs)
1291 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1293 const auto &D =
C.getDriver();
1294 return std::make_unique<Command>(
1296 D.getClangProgramPath(), JobArgs,
1309 ArrayRef<std::unique_ptr<Command>> ImportingJobs,
1311 llvm::DenseSet<deps::ModuleID> AlreadySeen;
1312 for (
auto &&[ImportingJob, ModuleDepsGraph] :
1313 llvm::zip_equal(llvm::make_pointee_range(ImportingJobs),
1314 ModuleDepGraphsForScannedJobs)) {
1315 for (
auto &MD : ModuleDepsGraph) {
1316 const auto Inserted = AlreadySeen.insert(MD.
ID).second;
1321 Graph.createJobNode<ClangModuleJobNode>(std::move(ClangModuleJob),
1333 for (
auto &&[Job, InputDeps] : llvm::zip_equal(
1334 llvm::make_pointee_range(ScannedJobs), InputDepsForScannedJobs)) {
1335 const auto &BuildArgs = InputDeps.BuildArgs;
1336 ArgStringList JobArgs;
1337 JobArgs.reserve(BuildArgs.size());
1340 for (
const auto &Arg : BuildArgs)
1341 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1343 Job.replaceArguments(std::move(JobArgs));
1352 CompilationGraph &Graph,
1355 for (
auto &&[Job, InputDeps] :
1356 llvm::zip_equal(ScannedJobs, InputDepsForScannedJobs)) {
1357 if (InputDeps.ModuleName.empty())
1358 Graph.createJobNode<NonModuleTUJobNode>(std::move(Job),
1359 std::move(InputDeps));
1361 Graph.createJobNode<NamedModuleJobNode>(std::move(Job),
1362 std::move(InputDeps));
1366template <
typename LookupT,
typename KeyRangeT>
1368 const LookupT &SrcNodeLookup,
1369 const KeyRangeT &SrcNodeLookupKeys,
1370 CGEdge::EdgeKind Kind) {
1371 for (
const auto &Key : SrcNodeLookupKeys) {
1372 const auto It = SrcNodeLookup.find(Key);
1373 if (It == SrcNodeLookup.end())
1376 auto &SrcNode = *It->second;
1377 Graph.createEdge(Kind, SrcNode, TgtNode);
1383 llvm::DenseMap<StringRef, CGNode *> NodeByOutputFiles;
1384 for (
auto *Node : Graph) {
1385 for (
const auto &Output :
cast<JobNode>(Node)->Job->getOutputFilenames()) {
1386 [[maybe_unused]]
const bool Inserted =
1387 NodeByOutputFiles.try_emplace(Output, Node).second;
1389 "Driver should not produce multiple jobs with identical outputs!");
1393 for (
auto *Node : Graph) {
1394 const auto &InputInfos =
cast<JobNode>(Node)->Job->getInputInfos();
1395 auto InputFilenames = llvm::map_range(
1396 InputInfos, [](
const auto &II) {
return II.getFilename(); });
1399 CGEdge::EdgeKind::Regular);
1409 llvm::DenseMap<deps::ModuleID, CGNode *> ClangModuleNodeByID;
1410 llvm::DenseMap<ModuleNameAndTriple, CGNode *> NamedModuleNodeByID;
1413 bool HasDuplicateModuleError =
false;
1414 for (
auto *Node : Graph) {
1415 llvm::TypeSwitch<CGNode *>(Node)
1416 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1417 [[maybe_unused]]
const bool Inserted =
1418 ClangModuleNodeByID.try_emplace(ClangModuleNode->MD.
ID, Node)
1421 "Multiple Clang module nodes with the same module ID!");
1423 .Case([&](NamedModuleJobNode *NamedModuleNode) {
1424 StringRef ModuleName = NamedModuleNode->InputDeps.ModuleName;
1426 const auto [It, Inserted] = NamedModuleNodeByID.try_emplace(ID, Node);
1433 StringRef PrevFile =
1436 Diags.
Report(diag::err_modules_driver_named_module_redefinition)
1437 << ModuleName << PrevFile << CurFile;
1438 HasDuplicateModuleError =
true;
1442 if (HasDuplicateModuleError)
1446 for (
auto *Node : Graph) {
1447 llvm::TypeSwitch<CGNode *>(Node)
1448 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1451 CGEdge::EdgeKind::ModuleDependency);
1453 .Case([&](ScannedJobNode *NodeWithInputDeps) {
1455 NodeWithInputDeps->InputDeps.ClangModuleDeps,
1456 CGEdge::EdgeKind::ModuleDependency);
1458 StringRef Triple =
getTriple(*NodeWithInputDeps->Job);
1459 const auto NamedModuleDepIDs =
1460 llvm::map_range(NodeWithInputDeps->InputDeps.NamedModuleDeps,
1461 [&](StringRef ModuleName) {
1462 return ModuleNameAndTriple{ModuleName, Triple};
1466 CGEdge::EdgeKind::ModuleDependency);
1480 for (
auto *PrunableJobNodeRoot : UnusedStdlibModuleJobNodes) {
1481 auto ReachableJobNodes =
1482 llvm::map_range(llvm::depth_first(
cast<CGNode>(PrunableJobNodeRoot)),
1483 llvm::CastTo<JobNode>);
1484 auto ReachableNonImageNodes = llvm::make_filter_range(
1485 ReachableJobNodes, [](
auto *N) {
return !llvm::isa<ImageJobNode>(N); });
1486 PrunableJobNodes.insert_range(ReachableNonImageNodes);
1490 llvm::DenseMap<ImageJobNode *, llvm::SmallPtrSet<JobNode *, 4>>
1491 PrunableJobNodesByImageNode;
1492 for (
auto *PrunableJobNode : PrunableJobNodes) {
1493 auto ReachableJobNodes = llvm::depth_first(
cast<CGNode>(PrunableJobNode));
1494 auto ReachableImageJobNodes = llvm::map_range(
1495 llvm::make_filter_range(ReachableJobNodes, llvm::IsaPred<ImageJobNode>),
1496 llvm::CastTo<ImageJobNode>);
1498 for (
auto *ImageNode : ReachableImageJobNodes)
1499 PrunableJobNodesByImageNode[ImageNode].insert(PrunableJobNode);
1504 for (
auto &[ImageNode, PrunableJobNodeInputs] : PrunableJobNodesByImageNode) {
1506 for (
auto *JN : PrunableJobNodeInputs)
1507 llvm::append_range(OutputsToRemove, JN->Job->getOutputFilenames());
1509 auto NewArgs = ImageNode->Job->getArguments();
1510 llvm::erase_if(NewArgs, [&](StringRef Arg) {
1511 return llvm::is_contained(OutputsToRemove, Arg);
1513 ImageNode->Job->replaceArguments(NewArgs);
1517 for (
auto *JN : PrunableJobNodes) {
1520 Graph.removeNode(*JN);
1528 for (
auto *Node : Graph)
1529 for (
auto *Edge : Node->getEdges())
1530 HasIncomingEdge.insert(&Edge->getTargetNode());
1532 auto AllNonRootNodes = llvm::iterator_range(Graph);
1533 auto &Root = Graph.createRoot();
1535 for (
auto *Node : AllNonRootNodes) {
1536 if (HasIncomingEdge.contains(Node))
1538 Graph.createEdge(CGEdge::EdgeKind::Rooted, Root, *Node);
1544 StringRef ModuleName) {
1548 llvm::replace(SanitizedModuleName,
':',
'-');
1549 auto ModuleOutputPath =
C.getDriver().GetTemporaryPath(
1551 return ModuleOutputPath;
1556 NamedModuleJobNode &Node,
1557 StringRef ModuleOutputPath) {
1558 auto &Job = *Node.Job;
1560 auto JobArgs = Job.getArguments();
1562 TCArgs.MakeArgString(
"-fmodule-output=" + ModuleOutputPath));
1563 Job.replaceArguments(std::move(JobArgs));
1569 NamedModuleJobNode &Node,
1570 StringRef ModuleOutputPath) {
1571 const StringRef ModuleName = Node.InputDeps.ModuleName;
1573 auto DependentNodes = llvm::drop_begin(llvm::depth_first<CGNode *>(&Node));
1574 auto DependentScannedNodes = llvm::map_range(
1575 llvm::make_filter_range(DependentNodes, llvm::IsaPred<ScannedJobNode>),
1576 llvm::CastTo<ScannedJobNode>);
1578 for (ScannedJobNode *DependentNode : DependentScannedNodes) {
1579 auto &DependentJob = *DependentNode->Job;
1581 auto JobArgs = DependentJob.getArguments();
1582 JobArgs.push_back(TCArgs.MakeArgString(
"-fmodule-file=" + ModuleName +
"=" +
1584 DependentJob.replaceArguments(std::move(JobArgs));
1594 CompilationGraph &Graph) {
1595 const auto NamedModuleNodes = llvm::map_range(
1596 llvm::make_filter_range(Graph, llvm::IsaPred<NamedModuleJobNode>),
1597 llvm::CastTo<NamedModuleJobNode>);
1599 for (NamedModuleJobNode *Node : NamedModuleNodes) {
1600 const StringRef ModuleName = Node->InputDeps.ModuleName;
1602 C.addTempFile(
C.getArgs().MakeArgString(ModuleOutputPath));
1611 CompilationGraph &&Graph) {
1612 llvm::ReversePostOrderTraversal<CompilationGraph *> TopologicallySortedNodes(
1615 "First node in topological order must be the root!");
1616 auto TopologicallySortedJobNodes = llvm::map_range(
1617 llvm::drop_begin(TopologicallySortedNodes), llvm::CastTo<JobNode>);
1618 for (
auto *JN : TopologicallySortedJobNodes)
1619 C.addCommand(std::move(JN->Job));
1624 llvm::PrettyStackTraceString CrashInfo(
"Running modules driver.");
1626 auto Jobs =
C.getJobs().takeJobs();
1637 if (!MaybeModuleCachePath) {
1638 Diags.
Report(diag::err_default_modules_cache_not_available);
1642 auto MaybeCWD =
C.getDriver().getVFS().getCurrentWorkingDirectory();
1643 const auto CWD = MaybeCWD ? std::move(*MaybeCWD) :
".";
1646 *MaybeModuleCachePath, CWD, Diags);
1647 if (!MaybeScanResults) {
1648 Diags.
Report(diag::err_dependency_scan_failed);
1651 auto &ScanResult = *MaybeScanResults;
1654 CompilationGraph Graph;
1662 ScanResult.InputDepsForScannedJobs, Diags))
1667 Graph,
C, ScannedJobs,
1668 std::move(ScanResult.ModuleDepGraphsForScannedJobs));
1670 std::move(ScanResult.InputDepsForScannedJobs));
1678 Diags.
Report(diag::remark_printing_module_graph);
1680 llvm::WriteGraph<const CompilationGraph *>(llvm::errs(), &Graph);
Defines the Diagnostic-related interfaces.
static Decl::Kind getKind(const Decl *D)
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static void feedJobsBackIntoCompilation(Compilation &C, CompilationGraph &&Graph)
Moves jobs from Graph into C in the graph's topological order.
static std::optional< DependencyScanResult > scanDependencies(ArrayRef< std::unique_ptr< Command > > Jobs, llvm::DenseMap< StringRef, const StdModuleManifest::Module * > ManifestLookup, StringRef ModuleCachePath, StringRef WorkingDirectory, DiagnosticsEngine &Diags)
Scans the compilations job list Jobs for module dependencies.
static std::string constructPCMPath(const deps::ModuleID &ID, StringRef OutputDir)
Construct a path for the explicitly built PCM.
static StringRef getTriple(const Command &Job)
static void reportAllScanDiagnostics(SmallVectorImpl< SmallVector< StandaloneDiagnostic, 0 > > &&AllScanDiags, DiagnosticsEngine &Diags)
Report the diagnostics collected during each dependency scan.
static const StdModuleManifest::Module * getManifestEntryForCommand(const Command &Job, const ManifestEntryLookup &ManifestEntryBySource)
Returns the manifest entry corresponding to Job, or nullptr if none exists.
static bool isDependencyScannableJob(const Command &Job)
Returns true if a dependency scan can be performed using Job.
static std::pair< std::unique_ptr< llvm::ThreadPoolInterface >, std::unique_ptr< ScanningWorkerPool > > createOptimalThreadAndWorkerPool(size_t NumScanInputs, bool HasStdlibModuleInputs, deps::DependencyScanningService &ScanningService)
static StringRef getFirstInputFilename(const Command &Job)
static SmallVector< std::unique_ptr< Command > > takeJobsAtIndices(SmallVectorImpl< std::unique_ptr< Command > > &Jobs, ArrayRef< size_t > Indices)
static void configureNamedModuleOutputArg(Compilation &C, NamedModuleJobNode &Node, StringRef ModuleOutputPath)
Adds the '-fmodule-output=' argument for the module produced by Node.
static void pruneUnusedStdlibModuleJobs(CompilationGraph &Graph, ArrayRef< JobNode * > UnusedStdlibModuleJobNodes)
Prunes the compilation graph of any jobs which build Standard library modules not required in this co...
static const DerivedArgList & getToolChainArgs(Compilation &C, const Command &Job)
static bool validateScannedJobInputKinds(ArrayRef< std::unique_ptr< Command > > ScannedJobs, ArrayRef< InputDependencies > InputDepsForScannedJobs, DiagnosticsEngine &Diags)
Validates that each module-defining source is of type TY_CXXModule.
static Expected< StdModuleManifest > parseManifest(StringRef Buffer)
Parses the Standard library module manifest from Buffer.
static void createNodesForScannedJobs(CompilationGraph &Graph, SmallVectorImpl< std::unique_ptr< Command > > &&ScannedJobs, SmallVectorImpl< InputDependencies > &&InputDepsForScannedJobs)
Creates nodes for all jobs which were scanned for dependencies.
std::pair< StringRef, StringRef > ModuleNameAndTriple
static void createAndConnectRoot(CompilationGraph &Graph)
Creates the root node and connects it to all nodes with no incoming edges ensuring that every node in...
static void makeManifestPathsAbsolute(MutableArrayRef< StdModuleManifest::Module > ManifestEntries, StringRef ManifestPath)
Converts each file path in manifest from relative to absolute.
static SmallVector< std::string, 0 > buildCommandLine(const Command &Job)
Constructs the full command line, including the executable, for Job.
static void applyArgsForStdModuleManifestInputs(Compilation &C, const ManifestEntryLookup &ManifestEntryBySource, MutableArrayRef< std::unique_ptr< Command > > Jobs)
Apply command-line modifications specific for inputs originating from the Standard library module man...
static std::string createModuleOutputPath(const Compilation &C, StringRef ModuleName)
Creates a temporary output path for ModuleName.
static bool createModuleDependencyEdges(CompilationGraph &Graph, DiagnosticsEngine &Diags)
Create edges for module dependencies in Graph.
static std::pair< std::optional< deps::TranslationUnitDeps >, SmallVector< StandaloneDiagnostic, 0 > > scanDependenciesForJob(const Command &Job, ScanningWorkerPool &WorkerPool, StringRef WorkingDirectory, ModuleLookupController &LookupController)
Performs a dependency scan for a single job.
static void fixupNamedModuleCommandLines(Compilation &C, CompilationGraph &Graph)
Finalizes command lines for C++20 named module dependencies.
static void addSystemIncludeDirsFromManifest(Compilation &C, Command &Job, ArgStringList &CC1Args, ArrayRef< std::string > SystemIncludeDirs)
Adds all SystemIncludeDirs to the CC1Args of Job.
static InputDependencies makeInputDeps(deps::TranslationUnitDeps &&TUDeps)
static void createNodesForNonScannableJobs(CompilationGraph &Graph, SmallVectorImpl< std::unique_ptr< Command > > &&NonScannableJobs)
Creates nodes for all jobs that could not be scanned (e.g. image jobs, ...).
static SmallVector< JobNode * > createNodesForUnusedStdlibModuleJobs(CompilationGraph &Graph, SmallVectorImpl< std::unique_ptr< Command > > &&UnusedStdlibModuleJobs)
Creates nodes for the Standard library module jobs not discovered as dependencies.
static std::unique_ptr< Command > createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob, const deps::ModuleDeps &MD)
Creates a job for the Clang module described by MD.
static ManifestEntryLookup buildManifestLookupMap(ArrayRef< StdModuleManifest::Module > ManifestEntries)
Builds a mapping from a module's source path to its entry in the manifest.
static void propagateModuleFileMappingArg(Compilation &C, NamedModuleJobNode &Node, StringRef ModuleOutputPath)
Propagates the '-fmodule-file=' mapping for the named module described by Node to each dependent job.
static void createRegularEdges(CompilationGraph &Graph)
Create edges for regular (non-module) dependencies in Graph.
static void createClangModuleJobsAndNodes(CompilationGraph &Graph, Compilation &C, ArrayRef< std::unique_ptr< Command > > ImportingJobs, SmallVectorImpl< deps::ModuleDepsGraph > &&ModuleDepGraphsForScannedJobs)
Creates a ClangModuleJobNode with associated job for each unique Clang module in ModuleDepGraphsForSc...
static void installScanCommandLines(Compilation &C, MutableArrayRef< std::unique_ptr< Command > > ScannedJobs, ArrayRef< InputDependencies > InputDepsForScannedJobs)
Installs the command lines produced by the dependency scan into ScannedJobs.
static void connectEdgesViaLookup(CompilationGraph &Graph, CGNode &TgtNode, const LookupT &SrcNodeLookup, const KeyRangeT &SrcNodeLookupKeys, CGEdge::EdgeKind Kind)
static bool isCC1Job(const Command &Job)
llvm::DenseMap< StringRef, const StdModuleManifest::Module * > ManifestEntryLookup
static std::optional< std::string > getModuleCachePath(llvm::opt::DerivedArgList &Args)
Computes the -fmodule-cache-path for this compilation.
This file defines functionality to support driver managed builds for compilations which use Clang mod...
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info)
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool hasSourceManager() const
bool isLastDiagnosticIgnored() const
Determine whether the previous diagnostic was ignored.
SourceManager & getSourceManager() const
Level
The level of the diagnostic, after it has been through mapping.
DiagnosticConsumer * getClient()
Implements support for file system lookup, file system caching, and directory search management.
Keeps track of options that affect how file operations are performed.
std::string WorkingDir
If set, paths are resolved as if the working directory was set to the value of WorkingDir.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
This class handles loading and caching of source files into memory.
FileManager & getFileManager() const
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
The dependency scanning service contains shared configuration and state that is used by the individua...
TranslationUnitDeps takeTranslationUnitDeps()
Action - Represent an abstract compilation step to perform.
const char * getOffloadingArch() const
void propagateOffloadInfo(const Action *A)
Set the offload info of this action to be the same as the provided action, and propagate it to its de...
OffloadKind getOffloadingDeviceKind() const
Command - An executable path/name and argument vector to execute.
const Action & getSource() const
getSource - Return the Action which caused the creation of this job.
const Tool & getCreator() const
getCreator - Return the Tool which caused the creation of this job.
const llvm::opt::ArgStringList & getArguments() const
const char * getExecutable() const
const std::vector< InputInfo > & getInputInfos() const
Compilation - A set of tasks to perform for a single driver invocation.
static bool getDefaultModuleCachePath(SmallVectorImpl< char > &Result)
Compute the default -fmodule-cache-path.
GraphWriterBase< GraphType, GraphWriter< GraphType > > Base
GraphWriter(llvm::raw_ostream &O, const GraphType &G, bool IsSimple)
const CompilationGraph * GraphType
@ VFS
Remove unused -ivfsoverlay arguments.
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
@ ModuleFile
The module file (.pcm). Required.
void buildStdModuleManifestInputs(ArrayRef< StdModuleManifest::Module > ManifestEntries, Compilation &C, InputList &Inputs)
Constructs compilation inputs for each module listed in the provided Standard library module manifest...
void runModulesDriver(Compilation &C, ArrayRef< StdModuleManifest::Module > ManifestEntries)
Scans the compilation inputs for module dependencies and adjusts the compilation to build and supply ...
llvm::Expected< StdModuleManifest > readStdModuleManifest(llvm::StringRef ManifestPath, llvm::vfs::FileSystem &VFS)
Reads the Standard library module manifest at ManifestPath.
static bool fromJSON(const llvm::json::Value &Params, StdModuleManifest::Module::LocalArguments &LocalArgs, llvm::json::Path P)
void diagnoseModulesDriverArgs(llvm::opt::DerivedArgList &DAL, DiagnosticsEngine &Diags)
Emits diagnostics for arguments incompatible with -fmodules-driver.
bool isSrcFile(ID Id)
isSrcFile - Is this a source file, i.e.
const char * getTypeTempSuffix(ID Id, bool CLStyle=false)
getTypeTempSuffix - Return the suffix to use when creating a temp file of this type,...
llvm::opt::Arg * makeInputArg(llvm::opt::DerivedArgList &Args, const llvm::opt::OptTable &Opts, StringRef Value, bool Claim=true)
Creates and adds a synthesized input argument.
llvm::SmallVector< InputTy, 16 > InputList
A list of inputs and their types for the given arguments.
NodeKind
A kind of a syntax node, used for implementing casts.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static bool classof(const OMPClause *T)
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
U cast(CodeGen::Address addr)
StoredDiagnostic translateStandaloneDiag(FileManager &FileMgr, SourceManager &SrcMgr, const StandaloneDiagnostic &StandaloneDiag, llvm::StringMap< SourceLocation > &SrcLocCache)
Translates StandaloneDiag into a StoredDiagnostic, associating it with the provided FileManager and S...
Diagnostic wrappers for TextAPI types for error reporting.
int const char * function
The configuration knobs for the dependency scanning service.
ModuleID ID
The identifier of the module.
std::vector< ModuleID > ClangModuleDeps
A list of module identifiers this module directly depends on, not including transitive dependencies.
const std::vector< std::string > & getBuildArguments() const
Get (or compute) the compiler invocation that can be used to build this module.
This is used to identify a specific module.
The full dependencies and module graph for a specific input.
static constexpr ResponseFileSupport AtFileUTF8()
std::vector< std::string > SystemIncludeDirs
std::optional< LocalArguments > LocalArgs
The parsed Standard library module manifest.
std::vector< Module > Modules
static bool renderGraphFromBottomUp()
static std::string getNodeIdentifier(NodeRef N, GraphRef)
static std::string getNodeLabel(NodeRef N, GraphRef)
static std::string getGraphName(GraphRef)
const CompilationGraph * GraphRef
static std::string getNodeAttributes(NodeRef N, GraphRef)
static bool isNodeHidden(NodeRef N, GraphRef)
static std::string getGraphProperties(GraphRef)
DOTGraphTraits(bool IsSimple=false)
static ChildEdgeIteratorType child_edge_end(NodeRef N)
mapped_iterator< CGNode::iterator, decltype(&CGGetTargetNode)> ChildIteratorType
static ChildEdgeIteratorType child_edge_begin(NodeRef N)
CGNode::iterator ChildEdgeIteratorType
static ChildIteratorType child_end(NodeRef N)
static NodeRef CGGetTargetNode(CGEdge *E)
static NodeRef getEntryNode(NodeRef N)
static ChildIteratorType child_begin(NodeRef N)
static NodeRef getEntryNode(GraphRef G)
static nodes_iterator nodes_begin(GraphRef G)
CompilationGraph::iterator nodes_iterator
static nodes_iterator nodes_end(GraphRef G)
CompilationGraph * GraphRef
static ChildIteratorType child_begin(NodeRef N)
mapped_iterator< CGNode::const_iterator, decltype(&CGGetTargetNode)> ChildIteratorType
static ChildEdgeIteratorType child_edge_end(NodeRef N)
static ChildEdgeIteratorType child_edge_begin(NodeRef N)
CGNode::const_iterator ChildEdgeIteratorType
static ChildIteratorType child_end(NodeRef N)
static NodeRef getEntryNode(NodeRef N)
static NodeRef CGGetTargetNode(const CGEdge *E)
const CompilationGraph * GraphRef
static nodes_iterator nodes_begin(GraphRef G)
static NodeRef getEntryNode(GraphRef G)
CompilationGraph::const_iterator nodes_iterator
static nodes_iterator nodes_end(GraphRef G)