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_CXXStdModule, 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 MainInput.getType() != types::TY_CXXStdModule) {
1218 Diags.
Report(diag::err_module_defined_outside_of_module_source)
1219 << InputDeps.ModuleName << MainInput.getFilename();
1230 for (
const auto JobIndex : Indices) {
1231 assert(Jobs[JobIndex] &&
"Expected valid job!");
1232 Out.push_back(std::move(Jobs[JobIndex]));
1239 CompilationGraph &Graph,
1241 for (
auto &Job : NonScannableJobs) {
1242 if (Job->getCreator().isLinkJob())
1243 Graph.createJobNode<ImageJobNode>(std::move(Job));
1245 Graph.createJobNode<MiscJobNode>(std::move(Job));
1255 CompilationGraph &Graph,
1258 for (
auto &Job : UnusedStdlibModuleJobs) {
1259 auto &NewNode = Graph.createJobNode<MiscJobNode>(std::move(Job));
1260 StdlibModuleNodesToPrune.push_back(&NewNode);
1262 return StdlibModuleNodesToPrune;
1270 const auto &SourceAction = Job.
getSource();
1271 return C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(),
1272 SourceAction.getOffloadingDeviceKind());
1276static std::unique_ptr<Command>
1279 DerivedArgList &Args =
C.getArgs();
1280 const OptTable &Opts =
C.getDriver().getOpts();
1281 Arg *InputArg =
makeInputArg(Args, Opts,
"<discovered clang module>");
1289 ArgStringList JobArgs;
1290 JobArgs.reserve(BuildArgs.size());
1291 for (
const auto &Arg : BuildArgs)
1292 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1294 const auto &D =
C.getDriver();
1295 return std::make_unique<Command>(
1297 D.getDriverProgramPath(), JobArgs,
1310 ArrayRef<std::unique_ptr<Command>> ImportingJobs,
1312 llvm::DenseSet<deps::ModuleID> AlreadySeen;
1313 for (
auto &&[ImportingJob, ModuleDepsGraph] :
1314 llvm::zip_equal(llvm::make_pointee_range(ImportingJobs),
1315 ModuleDepGraphsForScannedJobs)) {
1316 for (
auto &MD : ModuleDepsGraph) {
1317 const auto Inserted = AlreadySeen.insert(MD.
ID).second;
1322 Graph.createJobNode<ClangModuleJobNode>(std::move(ClangModuleJob),
1334 for (
auto &&[Job, InputDeps] : llvm::zip_equal(
1335 llvm::make_pointee_range(ScannedJobs), InputDepsForScannedJobs)) {
1336 const auto &BuildArgs = InputDeps.BuildArgs;
1337 ArgStringList JobArgs;
1338 JobArgs.reserve(BuildArgs.size());
1341 for (
const auto &Arg : BuildArgs)
1342 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1344 Job.replaceArguments(std::move(JobArgs));
1353 CompilationGraph &Graph,
1356 for (
auto &&[Job, InputDeps] :
1357 llvm::zip_equal(ScannedJobs, InputDepsForScannedJobs)) {
1358 if (InputDeps.ModuleName.empty())
1359 Graph.createJobNode<NonModuleTUJobNode>(std::move(Job),
1360 std::move(InputDeps));
1362 Graph.createJobNode<NamedModuleJobNode>(std::move(Job),
1363 std::move(InputDeps));
1367template <
typename LookupT,
typename KeyRangeT>
1369 const LookupT &SrcNodeLookup,
1370 const KeyRangeT &SrcNodeLookupKeys,
1371 CGEdge::EdgeKind Kind) {
1372 for (
const auto &Key : SrcNodeLookupKeys) {
1373 const auto It = SrcNodeLookup.find(Key);
1374 if (It == SrcNodeLookup.end())
1377 auto &SrcNode = *It->second;
1378 Graph.createEdge(Kind, SrcNode, TgtNode);
1384 llvm::DenseMap<StringRef, CGNode *> NodeByOutputFiles;
1385 for (
auto *Node : Graph) {
1386 for (
const auto &Output :
cast<JobNode>(Node)->Job->getOutputFilenames()) {
1387 [[maybe_unused]]
const bool Inserted =
1388 NodeByOutputFiles.try_emplace(Output, Node).second;
1390 "Driver should not produce multiple jobs with identical outputs!");
1394 for (
auto *Node : Graph) {
1395 const auto &InputInfos =
cast<JobNode>(Node)->Job->getInputInfos();
1396 auto InputFilenames = llvm::map_range(
1397 InputInfos, [](
const auto &II) {
return II.getFilename(); });
1400 CGEdge::EdgeKind::Regular);
1410 llvm::DenseMap<deps::ModuleID, CGNode *> ClangModuleNodeByID;
1411 llvm::DenseMap<ModuleNameAndTriple, CGNode *> NamedModuleNodeByID;
1414 bool HasDuplicateModuleError =
false;
1415 for (
auto *Node : Graph) {
1416 llvm::TypeSwitch<CGNode *>(Node)
1417 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1418 [[maybe_unused]]
const bool Inserted =
1419 ClangModuleNodeByID.try_emplace(ClangModuleNode->MD.
ID, Node)
1422 "Multiple Clang module nodes with the same module ID!");
1424 .Case([&](NamedModuleJobNode *NamedModuleNode) {
1425 StringRef ModuleName = NamedModuleNode->InputDeps.ModuleName;
1427 const auto [It, Inserted] = NamedModuleNodeByID.try_emplace(ID, Node);
1434 StringRef PrevFile =
1437 Diags.
Report(diag::err_modules_driver_named_module_redefinition)
1438 << ModuleName << PrevFile << CurFile;
1439 HasDuplicateModuleError =
true;
1443 if (HasDuplicateModuleError)
1447 for (
auto *Node : Graph) {
1448 llvm::TypeSwitch<CGNode *>(Node)
1449 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1452 CGEdge::EdgeKind::ModuleDependency);
1454 .Case([&](ScannedJobNode *NodeWithInputDeps) {
1456 NodeWithInputDeps->InputDeps.ClangModuleDeps,
1457 CGEdge::EdgeKind::ModuleDependency);
1459 StringRef Triple =
getTriple(*NodeWithInputDeps->Job);
1460 const auto NamedModuleDepIDs =
1461 llvm::map_range(NodeWithInputDeps->InputDeps.NamedModuleDeps,
1462 [&](StringRef ModuleName) {
1463 return ModuleNameAndTriple{ModuleName, Triple};
1467 CGEdge::EdgeKind::ModuleDependency);
1481 for (
auto *PrunableJobNodeRoot : UnusedStdlibModuleJobNodes) {
1482 auto ReachableJobNodes =
1483 llvm::map_range(llvm::depth_first(
cast<CGNode>(PrunableJobNodeRoot)),
1484 llvm::CastTo<JobNode>);
1485 auto ReachableNonImageNodes = llvm::make_filter_range(
1486 ReachableJobNodes, [](
auto *N) {
return !llvm::isa<ImageJobNode>(N); });
1487 PrunableJobNodes.insert_range(ReachableNonImageNodes);
1491 llvm::DenseMap<ImageJobNode *, llvm::SmallPtrSet<JobNode *, 4>>
1492 PrunableJobNodesByImageNode;
1493 for (
auto *PrunableJobNode : PrunableJobNodes) {
1494 auto ReachableJobNodes = llvm::depth_first(
cast<CGNode>(PrunableJobNode));
1495 auto ReachableImageJobNodes = llvm::map_range(
1496 llvm::make_filter_range(ReachableJobNodes, llvm::IsaPred<ImageJobNode>),
1497 llvm::CastTo<ImageJobNode>);
1499 for (
auto *ImageNode : ReachableImageJobNodes)
1500 PrunableJobNodesByImageNode[ImageNode].insert(PrunableJobNode);
1505 for (
auto &[ImageNode, PrunableJobNodeInputs] : PrunableJobNodesByImageNode) {
1507 for (
auto *JN : PrunableJobNodeInputs)
1508 llvm::append_range(OutputsToRemove, JN->Job->getOutputFilenames());
1510 auto NewArgs = ImageNode->Job->getArguments();
1511 llvm::erase_if(NewArgs, [&](StringRef Arg) {
1512 return llvm::is_contained(OutputsToRemove, Arg);
1514 ImageNode->Job->replaceArguments(NewArgs);
1518 for (
auto *JN : PrunableJobNodes) {
1521 Graph.removeNode(*JN);
1529 for (
auto *Node : Graph)
1530 for (
auto *Edge : Node->getEdges())
1531 HasIncomingEdge.insert(&Edge->getTargetNode());
1533 auto AllNonRootNodes = llvm::iterator_range(Graph);
1534 auto &Root = Graph.createRoot();
1536 for (
auto *Node : AllNonRootNodes) {
1537 if (HasIncomingEdge.contains(Node))
1539 Graph.createEdge(CGEdge::EdgeKind::Rooted, Root, *Node);
1545 StringRef ModuleName) {
1549 llvm::replace(SanitizedModuleName,
':',
'-');
1550 auto ModuleOutputPath =
C.getDriver().GetTemporaryPath(
1552 return ModuleOutputPath;
1557 NamedModuleJobNode &Node,
1558 StringRef ModuleOutputPath) {
1559 auto &Job = *Node.Job;
1561 auto JobArgs = Job.getArguments();
1563 TCArgs.MakeArgString(
"-fmodule-output=" + ModuleOutputPath));
1564 Job.replaceArguments(std::move(JobArgs));
1570 NamedModuleJobNode &Node,
1571 StringRef ModuleOutputPath) {
1572 const StringRef ModuleName = Node.InputDeps.ModuleName;
1574 auto DependentNodes = llvm::drop_begin(llvm::depth_first<CGNode *>(&Node));
1575 auto DependentScannedNodes = llvm::map_range(
1576 llvm::make_filter_range(DependentNodes, llvm::IsaPred<ScannedJobNode>),
1577 llvm::CastTo<ScannedJobNode>);
1579 for (ScannedJobNode *DependentNode : DependentScannedNodes) {
1580 auto &DependentJob = *DependentNode->Job;
1582 auto JobArgs = DependentJob.getArguments();
1583 JobArgs.push_back(TCArgs.MakeArgString(
"-fmodule-file=" + ModuleName +
"=" +
1585 DependentJob.replaceArguments(std::move(JobArgs));
1595 CompilationGraph &Graph) {
1596 const auto NamedModuleNodes = llvm::map_range(
1597 llvm::make_filter_range(Graph, llvm::IsaPred<NamedModuleJobNode>),
1598 llvm::CastTo<NamedModuleJobNode>);
1600 for (NamedModuleJobNode *Node : NamedModuleNodes) {
1601 const auto &Job = *Node->Job;
1605 const bool IsStdModule =
1606 Job.getInputInfos().front().getType() == types::TY_CXXStdModule;
1608 StringRef ModuleOutputPath = Job.getOutputFilenames().front();
1613 const StringRef ModuleName = Node->InputDeps.ModuleName;
1615 C.addTempFile(
C.getArgs().MakeArgString(ModuleOutputPath));
1624 CompilationGraph &&Graph) {
1625 llvm::ReversePostOrderTraversal<CompilationGraph *> TopologicallySortedNodes(
1628 "First node in topological order must be the root!");
1629 auto TopologicallySortedJobNodes = llvm::map_range(
1630 llvm::drop_begin(TopologicallySortedNodes), llvm::CastTo<JobNode>);
1631 for (
auto *JN : TopologicallySortedJobNodes)
1632 C.addCommand(std::move(JN->Job));
1637 llvm::PrettyStackTraceString CrashInfo(
"Running modules driver.");
1639 auto Jobs =
C.getJobs().takeJobs();
1650 if (!MaybeModuleCachePath) {
1651 Diags.
Report(diag::err_default_modules_cache_not_available);
1655 auto MaybeCWD =
C.getDriver().getVFS().getCurrentWorkingDirectory();
1656 const auto CWD = MaybeCWD ? std::move(*MaybeCWD) :
".";
1659 *MaybeModuleCachePath, CWD, Diags);
1660 if (!MaybeScanResults) {
1661 Diags.
Report(diag::err_dependency_scan_failed);
1664 auto &ScanResult = *MaybeScanResults;
1667 CompilationGraph Graph;
1675 ScanResult.InputDepsForScannedJobs, Diags))
1680 Graph,
C, ScannedJobs,
1681 std::move(ScanResult.ModuleDepGraphsForScannedJobs));
1683 std::move(ScanResult.InputDepsForScannedJobs));
1691 Diags.
Report(diag::remark_printing_module_graph);
1693 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)