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();
648 Opts.
LogPath = DepScanLogPath.str();
651 std::unique_ptr<llvm::ThreadPoolInterface> ThreadPool;
652 std::unique_ptr<ScanningWorkerPool> WorkerPool;
654 NumScanInputs, HasStdlibModuleInputs, ScanningService);
656 StdlibModuleScanScheduler StdlibModuleRegistry(StdlibModuleScanIndexByID);
657 ModuleLookupController LookupController(ModuleCachePath);
665 std::atomic<bool> HasError{
false};
670 ScanOneAndScheduleNew = [&](
size_t ScanIndex) {
671 const size_t JobIndex = ScannableJobIndices[ScanIndex];
672 const Command &Job = *Jobs[JobIndex];
674 Job, *WorkerPool, WorkingDirectory, LookupController);
678 assert(AllScanDiags[ScanIndex].empty() &&
679 "Each slot should be written to at most once.");
680 AllScanDiags[ScanIndex] = std::move(ScanDiags);
683 HasError.store(
true, std::memory_order_relaxed);
688 const auto NewScanInputs = StdlibModuleRegistry.getNewScanInputs(
689 MaybeTUDeps->NamedModuleDeps,
getTriple(Job));
690 for (
const size_t NewScanIndex : NewScanInputs)
692 [&, NewScanIndex]() { ScanOneAndScheduleNew(NewScanIndex); });
694 assert(!AllScanResults[ScanIndex].has_value() &&
695 "Each slot should be written to at most once.");
696 AllScanResults[ScanIndex] = std::move(MaybeTUDeps);
700 for (
const size_t ScanIndex : UserInputScanIndices)
701 ThreadPool->async([&ScanOneAndScheduleNew, ScanIndex]() {
702 ScanOneAndScheduleNew(ScanIndex);
707 if (HasError.load(std::memory_order_relaxed))
711 DependencyScanResult
Result;
712 for (
auto &&[JobIndex, MaybeTUDeps] :
713 llvm::zip_equal(ScannableJobIndices, AllScanResults)) {
715 Result.ScannedJobIndices.push_back(JobIndex);
716 Result.ModuleDepGraphsForScannedJobs.push_back(
717 std::move(MaybeTUDeps->ModuleGraph));
718 Result.InputDepsForScannedJobs.push_back(
721 Result.UnusedStdlibModuleJobIndices.push_back(JobIndex);
723 Result.NonScannableJobIndices = std::move(NonScannableJobIndices);
726 llvm::SmallDenseSet<size_t> SeenJobIndices;
727 SeenJobIndices.insert_range(
Result.ScannedJobIndices);
728 SeenJobIndices.insert_range(
Result.UnusedStdlibModuleJobIndices);
729 SeenJobIndices.insert_range(
Result.NonScannableJobIndices);
730 assert(llvm::all_of(llvm::index_range(0, Jobs.size()),
731 [&](
size_t JobIndex) {
732 return SeenJobIndices.contains(JobIndex);
734 "Scan result must partition all jobs");
743using CGNodeBase = llvm::DGNode<CGNode, CGEdge>;
744using CGEdgeBase = llvm::DGEdge<CGNode, CGEdge>;
745using CGBase = llvm::DirectedGraph<CGNode, CGEdge>;
748class CGNode :
public CGNodeBase {
750 enum class NodeKind {
759 CGNode(
const NodeKind K) : Kind(K) {}
760 CGNode(
const CGNode &) =
delete;
761 CGNode(CGNode &&) =
delete;
762 CGNode &operator=(
const CGNode &) =
delete;
763 CGNode &operator=(CGNode &&) =
delete;
764 virtual ~CGNode() = 0;
766 NodeKind
getKind()
const {
return Kind; }
771CGNode::~CGNode() =
default;
780class RootNode :
public CGNode {
782 RootNode() : CGNode(
NodeKind::Root) {}
783 ~RootNode()
override =
default;
785 static bool classof(
const CGNode *N) {
786 return N->getKind() == NodeKind::Root;
791class JobNode :
public CGNode {
793 JobNode(std::unique_ptr<Command> &&Job, NodeKind Kind)
794 : CGNode(
Kind), Job(std::move(Job)) {
795 assert(this->Job &&
"Expected valid job!");
797 virtual ~JobNode()
override = 0;
799 std::unique_ptr<Command> Job;
801 static bool classof(
const CGNode *N) {
802 return N->getKind() != NodeKind::Root;
805JobNode::~JobNode() =
default;
808class ClangModuleJobNode :
public JobNode {
810 ClangModuleJobNode(std::unique_ptr<Command> &&Job, deps::ModuleDeps &&MD)
811 : JobNode(std::move(Job),
NodeKind::ClangModuleCC1Job),
813 ~ClangModuleJobNode()
override =
default;
817 static bool classof(
const CGNode *N) {
818 return N->getKind() == NodeKind::ClangModuleCC1Job;
823class ScannedJobNode :
public JobNode {
825 ScannedJobNode(std::unique_ptr<Command> &&Job, InputDependencies &&InputDeps,
827 : JobNode(std::move(Job),
Kind), InputDeps(std::move(InputDeps)) {}
828 ~ScannedJobNode()
override =
default;
830 InputDependencies InputDeps;
832 static bool classof(
const CGNode *N) {
833 return N->getKind() == NodeKind::NamedModuleCC1Job ||
834 N->getKind() == NodeKind::NonModuleCC1Job;
840class NamedModuleJobNode :
public ScannedJobNode {
842 NamedModuleJobNode(std::unique_ptr<Command> &&Job,
843 InputDependencies &&InputDeps)
844 : ScannedJobNode(std::move(Job), std::move(InputDeps),
846 ~NamedModuleJobNode()
override =
default;
848 static bool classof(
const CGNode *N) {
849 return N->getKind() == NodeKind::NamedModuleCC1Job;
855class NonModuleTUJobNode :
public ScannedJobNode {
857 NonModuleTUJobNode(std::unique_ptr<Command> &&Job,
858 InputDependencies &&InputDeps)
859 : ScannedJobNode(std::move(Job), std::move(InputDeps),
861 ~NonModuleTUJobNode()
override =
default;
863 static bool classof(
const CGNode *N) {
864 return N->getKind() == NodeKind::NonModuleCC1Job;
870class ImageJobNode :
public JobNode {
872 ImageJobNode(std::unique_ptr<Command> &&Job)
873 : JobNode(std::move(Job),
NodeKind::ImageJob) {}
874 ~ImageJobNode()
override =
default;
876 static bool classof(
const CGNode *N) {
877 return N->getKind() == NodeKind::ImageJob;
884class MiscJobNode :
public JobNode {
886 MiscJobNode(std::unique_ptr<Command> &&Job)
887 : JobNode(std::move(Job),
NodeKind::MiscJob) {}
888 ~MiscJobNode()
override =
default;
890 static bool classof(
const CGNode *N) {
891 return N->getKind() == NodeKind::MiscJob;
899class CGEdge :
public CGEdgeBase {
901 enum class EdgeKind {
907 CGEdge(CGNode &N, EdgeKind K) : CGEdgeBase(N), Kind(K) {}
908 CGEdge(
const CGEdge &) =
delete;
909 CGEdge &operator=(
const CGEdge &) =
delete;
910 CGEdge(CGEdge &&) =
delete;
911 CGEdge &operator=(CGEdge &&) =
delete;
913 EdgeKind
getKind()
const {
return Kind; }
924class CompilationGraph :
public CGBase {
926 CompilationGraph() =
default;
927 CompilationGraph(
const CompilationGraph &) =
delete;
928 CompilationGraph &operator=(
const CompilationGraph &) =
delete;
929 CompilationGraph(CompilationGraph &&G) =
default;
930 CompilationGraph &operator=(CompilationGraph &&) =
default;
931 ~CompilationGraph() =
default;
933 CGNode &getRoot()
const {
934 assert(Root &&
"Root node has not yet been created!");
938 RootNode &createRoot() {
939 assert(!Root &&
"Root node has already been created!");
940 auto &RootRef = createNodeImpl<RootNode>();
945 template <
typename T,
typename... Args>
T &createJobNode(Args &&...Arg) {
946 static_assert(std::is_base_of<JobNode, T>::value,
947 "T must be derived from JobNode");
948 return createNodeImpl<T>(std::forward<Args>(Arg)...);
951 CGEdge &createEdge(CGEdge::EdgeKind Kind, CGNode &Src, CGNode &Dst) {
952 auto Edge = std::make_unique<CGEdge>(Dst, Kind);
953 CGEdge &EdgeRef = *Edge;
954 AllEdges.push_back(std::move(Edge));
955 connect(Src, Dst, EdgeRef);
960 using CGBase::addNode;
961 using CGBase::connect;
963 template <
typename T,
typename... Args>
T &createNodeImpl(Args &&...Arg) {
964 auto Node = std::make_unique<T>(std::forward<Args>(Arg)...);
966 AllNodes.push_back(std::move(Node));
971 CGNode *Root =
nullptr;
972 SmallVector<std::unique_ptr<CGNode>> AllNodes;
973 SmallVector<std::unique_ptr<CGEdge>> AllEdges;
983template <>
struct GraphTraits<CGNode *> {
1008template <>
struct GraphTraits<CompilationGraph *> : GraphTraits<CGNode *> {
1022template <>
struct GraphTraits<const CGNode *> {
1026 return &E->getTargetNode();
1051struct GraphTraits<const CompilationGraph *> : GraphTraits<const CGNode *> {
1072 return "Module Dependency Graph";
1076 return "\tnode [shape=Mrecord, colorscheme=set23, style=filled];\n";
1087 return llvm::TypeSwitch<NodeRef, std::string>(N)
1088 .Case([](
const ClangModuleJobNode *ClangModuleNode) {
1089 const auto &ID = ClangModuleNode->MD.
ID;
1090 return llvm::formatv(
"{0}-{1}", ID.ModuleName, ID.ContextHash).str();
1092 .Case([](
const NamedModuleJobNode *NamedModuleNode) {
1093 return llvm::formatv(
"{0}-{1}", NamedModuleNode->InputDeps.ModuleName,
1097 .Case([](
const NonModuleTUJobNode *NonModuleTUNode) {
1098 const auto &Job = *NonModuleTUNode->Job;
1103 .DefaultUnreachable(
"Unexpected node kind! Is this node hidden?");
1107 return llvm::TypeSwitch<NodeRef, std::string>(N)
1108 .Case([](
const ClangModuleJobNode *ClangModuleNode) {
1109 const auto &ID = ClangModuleNode->MD.
ID;
1110 return llvm::formatv(
"Module type: Clang module \\| Module name: {0} "
1112 ID.ModuleName, ID.ContextHash)
1115 .Case([](
const NamedModuleJobNode *NamedModuleNode) {
1116 const auto &Job = *NamedModuleNode->Job;
1117 return llvm::formatv(
1118 "Filename: {0} \\| Module type: Named module \\| "
1119 "Module name: {1} \\| Triple: {2}",
1121 NamedModuleNode->InputDeps.ModuleName,
getTriple(Job))
1124 .Case([](
const NonModuleTUJobNode *NonModuleTUNode) {
1125 const auto &Job = *NonModuleTUNode->Job;
1126 return llvm::formatv(
"Filename: {0} \\| Triple: {1}",
1130 .DefaultUnreachable(
"Unexpected node kind! Is this node hidden?");
1134 switch (N->getKind()) {
1135 case CGNode::NodeKind::ClangModuleCC1Job:
1136 return "fillcolor=1";
1137 case CGNode::NodeKind::NamedModuleCC1Job:
1138 return "fillcolor=2";
1139 case CGNode::NodeKind::NonModuleCC1Job:
1140 return "fillcolor=3";
1142 llvm_unreachable(
"Unexpected node kind! Is this node hidden?");
1158 :
Base(O, G, IsSimple), EscapedIDByNodeRef(G->size()) {}
1161 auto IsNodeVisible = [&](NodeRef N) {
return !DTraits.isNodeHidden(N, G); };
1162 auto VisibleNodes = llvm::filter_to_vector(nodes(G), IsNodeVisible);
1164 writeNodeDefinitions(VisibleNodes);
1166 writeNodeRelations(VisibleNodes);
1170 using Base::DOTTraits;
1171 using Base::GTraits;
1172 using Base::NodeRef;
1175 for (NodeRef Node : VisibleNodes) {
1176 std::string EscapedNodeID =
1177 DOT::EscapeString(DTraits.getNodeIdentifier(Node, G));
1178 const std::string NodeLabel = DTraits.getNodeLabel(Node, G);
1179 const std::string NodeAttrs = DTraits.getNodeAttributes(Node, G);
1180 O <<
'\t' <<
'"' << EscapedNodeID <<
"\" [" << NodeAttrs <<
", label=\"{ "
1181 << DOT::EscapeString(NodeLabel) <<
" }\"];\n";
1182 EscapedIDByNodeRef.try_emplace(Node, std::move(EscapedNodeID));
1187 auto IsNodeVisible = [&](NodeRef N) {
return !DTraits.isNodeHidden(N, G); };
1188 for (NodeRef Node : VisibleNodes) {
1189 auto DstNodes = llvm::make_range(GTraits::child_begin(Node),
1190 GTraits::child_end(Node));
1191 auto VisibleDstNodes = llvm::make_filter_range(DstNodes, IsNodeVisible);
1192 StringRef EscapedSrcNodeID = EscapedIDByNodeRef.at(Node);
1193 for (NodeRef DstNode : VisibleDstNodes) {
1194 StringRef EscapedTgtNodeID = EscapedIDByNodeRef.at(DstNode);
1195 O <<
'\t' <<
'"' << EscapedSrcNodeID <<
"\" -> \"" << EscapedTgtNodeID
1201 DenseMap<NodeRef, std::string> EscapedIDByNodeRef;
1209 ArrayRef<std::unique_ptr<Command>> ScannedJobs,
1212 for (
const auto &&[Job, InputDeps] : llvm::zip_equal(
1213 llvm::make_pointee_range(ScannedJobs), InputDepsForScannedJobs)) {
1214 const auto &MainInput = Job.getInputInfos().front();
1215 const bool DefinesNamedModule = !InputDeps.ModuleName.empty();
1217 if (DefinesNamedModule && MainInput.getType() != types::TY_CXXModule &&
1218 MainInput.getType() != types::TY_CXXStdModule) {
1219 Diags.
Report(diag::err_module_defined_outside_of_module_source)
1220 << InputDeps.ModuleName << MainInput.getFilename();
1231 for (
const auto JobIndex : Indices) {
1232 assert(Jobs[JobIndex] &&
"Expected valid job!");
1233 Out.push_back(std::move(Jobs[JobIndex]));
1240 CompilationGraph &Graph,
1242 for (
auto &Job : NonScannableJobs) {
1243 if (Job->getCreator().isLinkJob())
1244 Graph.createJobNode<ImageJobNode>(std::move(Job));
1246 Graph.createJobNode<MiscJobNode>(std::move(Job));
1256 CompilationGraph &Graph,
1259 for (
auto &Job : UnusedStdlibModuleJobs) {
1260 auto &NewNode = Graph.createJobNode<MiscJobNode>(std::move(Job));
1261 StdlibModuleNodesToPrune.push_back(&NewNode);
1263 return StdlibModuleNodesToPrune;
1271 const auto &SourceAction = Job.
getSource();
1272 return C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(),
1273 SourceAction.getOffloadingDeviceKind());
1277static std::unique_ptr<Command>
1280 DerivedArgList &Args =
C.getArgs();
1281 const OptTable &Opts =
C.getDriver().getOpts();
1282 Arg *InputArg =
makeInputArg(Args, Opts,
"<discovered clang module>");
1290 ArgStringList JobArgs;
1291 JobArgs.reserve(BuildArgs.size());
1292 for (
const auto &Arg : BuildArgs)
1293 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1295 const auto &D =
C.getDriver();
1296 return std::make_unique<Command>(
1298 D.getDriverProgramPath(), JobArgs,
1311 ArrayRef<std::unique_ptr<Command>> ImportingJobs,
1313 llvm::DenseSet<deps::ModuleID> AlreadySeen;
1314 for (
auto &&[ImportingJob, ModuleDepsGraph] :
1315 llvm::zip_equal(llvm::make_pointee_range(ImportingJobs),
1316 ModuleDepGraphsForScannedJobs)) {
1317 for (
auto &MD : ModuleDepsGraph) {
1318 const auto Inserted = AlreadySeen.insert(MD.
ID).second;
1323 Graph.createJobNode<ClangModuleJobNode>(std::move(ClangModuleJob),
1335 for (
auto &&[Job, InputDeps] : llvm::zip_equal(
1336 llvm::make_pointee_range(ScannedJobs), InputDepsForScannedJobs)) {
1337 const auto &BuildArgs = InputDeps.BuildArgs;
1338 ArgStringList JobArgs;
1339 JobArgs.reserve(BuildArgs.size());
1342 for (
const auto &Arg : BuildArgs)
1343 JobArgs.push_back(TCArgs.MakeArgString(Arg));
1345 Job.replaceArguments(std::move(JobArgs));
1354 CompilationGraph &Graph,
1357 for (
auto &&[Job, InputDeps] :
1358 llvm::zip_equal(ScannedJobs, InputDepsForScannedJobs)) {
1359 if (InputDeps.ModuleName.empty())
1360 Graph.createJobNode<NonModuleTUJobNode>(std::move(Job),
1361 std::move(InputDeps));
1363 Graph.createJobNode<NamedModuleJobNode>(std::move(Job),
1364 std::move(InputDeps));
1368template <
typename LookupT,
typename KeyRangeT>
1370 const LookupT &SrcNodeLookup,
1371 const KeyRangeT &SrcNodeLookupKeys,
1372 CGEdge::EdgeKind Kind) {
1373 for (
const auto &Key : SrcNodeLookupKeys) {
1374 const auto It = SrcNodeLookup.find(Key);
1375 if (It == SrcNodeLookup.end())
1378 auto &SrcNode = *It->second;
1379 Graph.createEdge(Kind, SrcNode, TgtNode);
1385 llvm::DenseMap<StringRef, CGNode *> NodeByOutputFiles;
1386 for (
auto *Node : Graph) {
1387 for (
const auto &Output :
cast<JobNode>(Node)->Job->getOutputFilenames()) {
1388 [[maybe_unused]]
const bool Inserted =
1389 NodeByOutputFiles.try_emplace(Output, Node).second;
1391 "Driver should not produce multiple jobs with identical outputs!");
1395 for (
auto *Node : Graph) {
1396 const auto &InputInfos =
cast<JobNode>(Node)->Job->getInputInfos();
1397 auto InputFilenames = llvm::map_range(
1398 InputInfos, [](
const auto &II) {
return II.getFilename(); });
1401 CGEdge::EdgeKind::Regular);
1411 llvm::DenseMap<deps::ModuleID, CGNode *> ClangModuleNodeByID;
1412 llvm::DenseMap<ModuleNameAndTriple, CGNode *> NamedModuleNodeByID;
1415 bool HasDuplicateModuleError =
false;
1416 for (
auto *Node : Graph) {
1417 llvm::TypeSwitch<CGNode *>(Node)
1418 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1419 [[maybe_unused]]
const bool Inserted =
1420 ClangModuleNodeByID.try_emplace(ClangModuleNode->MD.
ID, Node)
1423 "Multiple Clang module nodes with the same module ID!");
1425 .Case([&](NamedModuleJobNode *NamedModuleNode) {
1426 StringRef ModuleName = NamedModuleNode->InputDeps.ModuleName;
1428 const auto [It, Inserted] = NamedModuleNodeByID.try_emplace(ID, Node);
1435 StringRef PrevFile =
1438 Diags.
Report(diag::err_modules_driver_named_module_redefinition)
1439 << ModuleName << PrevFile << CurFile;
1440 HasDuplicateModuleError =
true;
1444 if (HasDuplicateModuleError)
1448 for (
auto *Node : Graph) {
1449 llvm::TypeSwitch<CGNode *>(Node)
1450 .Case([&](ClangModuleJobNode *ClangModuleNode) {
1453 CGEdge::EdgeKind::ModuleDependency);
1455 .Case([&](ScannedJobNode *NodeWithInputDeps) {
1457 NodeWithInputDeps->InputDeps.ClangModuleDeps,
1458 CGEdge::EdgeKind::ModuleDependency);
1460 StringRef Triple =
getTriple(*NodeWithInputDeps->Job);
1461 const auto NamedModuleDepIDs =
1462 llvm::map_range(NodeWithInputDeps->InputDeps.NamedModuleDeps,
1463 [&](StringRef ModuleName) {
1464 return ModuleNameAndTriple{ModuleName, Triple};
1468 CGEdge::EdgeKind::ModuleDependency);
1482 for (
auto *PrunableJobNodeRoot : UnusedStdlibModuleJobNodes) {
1483 auto ReachableJobNodes =
1484 llvm::map_range(llvm::depth_first(
cast<CGNode>(PrunableJobNodeRoot)),
1485 llvm::CastTo<JobNode>);
1486 auto ReachableNonImageNodes = llvm::make_filter_range(
1487 ReachableJobNodes, [](
auto *N) {
return !llvm::isa<ImageJobNode>(N); });
1488 PrunableJobNodes.insert_range(ReachableNonImageNodes);
1492 llvm::DenseMap<ImageJobNode *, llvm::SmallPtrSet<JobNode *, 4>>
1493 PrunableJobNodesByImageNode;
1494 for (
auto *PrunableJobNode : PrunableJobNodes) {
1495 auto ReachableJobNodes = llvm::depth_first(
cast<CGNode>(PrunableJobNode));
1496 auto ReachableImageJobNodes = llvm::map_range(
1497 llvm::make_filter_range(ReachableJobNodes, llvm::IsaPred<ImageJobNode>),
1498 llvm::CastTo<ImageJobNode>);
1500 for (
auto *ImageNode : ReachableImageJobNodes)
1501 PrunableJobNodesByImageNode[ImageNode].insert(PrunableJobNode);
1506 for (
auto &[ImageNode, PrunableJobNodeInputs] : PrunableJobNodesByImageNode) {
1508 for (
auto *JN : PrunableJobNodeInputs)
1509 llvm::append_range(OutputsToRemove, JN->Job->getOutputFilenames());
1511 auto NewArgs = ImageNode->Job->getArguments();
1512 llvm::erase_if(NewArgs, [&](StringRef Arg) {
1513 return llvm::is_contained(OutputsToRemove, Arg);
1515 ImageNode->Job->replaceArguments(NewArgs);
1519 for (
auto *JN : PrunableJobNodes) {
1522 Graph.removeNode(*JN);
1530 for (
auto *Node : Graph)
1531 for (
auto *Edge : Node->getEdges())
1532 HasIncomingEdge.insert(&Edge->getTargetNode());
1534 auto AllNonRootNodes = llvm::iterator_range(Graph);
1535 auto &Root = Graph.createRoot();
1537 for (
auto *Node : AllNonRootNodes) {
1538 if (HasIncomingEdge.contains(Node))
1540 Graph.createEdge(CGEdge::EdgeKind::Rooted, Root, *Node);
1546 StringRef ModuleName) {
1550 llvm::replace(SanitizedModuleName,
':',
'-');
1551 auto ModuleOutputPath =
C.getDriver().GetTemporaryPath(
1553 return ModuleOutputPath;
1558 NamedModuleJobNode &Node,
1559 StringRef ModuleOutputPath) {
1560 auto &Job = *Node.Job;
1562 auto JobArgs = Job.getArguments();
1564 TCArgs.MakeArgString(
"-fmodule-output=" + ModuleOutputPath));
1565 Job.replaceArguments(std::move(JobArgs));
1571 NamedModuleJobNode &Node,
1572 StringRef ModuleOutputPath) {
1573 const StringRef ModuleName = Node.InputDeps.ModuleName;
1575 auto DependentNodes = llvm::drop_begin(llvm::depth_first<CGNode *>(&Node));
1576 auto DependentScannedNodes = llvm::map_range(
1577 llvm::make_filter_range(DependentNodes, llvm::IsaPred<ScannedJobNode>),
1578 llvm::CastTo<ScannedJobNode>);
1580 for (ScannedJobNode *DependentNode : DependentScannedNodes) {
1581 auto &DependentJob = *DependentNode->Job;
1583 auto JobArgs = DependentJob.getArguments();
1584 JobArgs.push_back(TCArgs.MakeArgString(
"-fmodule-file=" + ModuleName +
"=" +
1586 DependentJob.replaceArguments(std::move(JobArgs));
1596 CompilationGraph &Graph) {
1597 const auto NamedModuleNodes = llvm::map_range(
1598 llvm::make_filter_range(Graph, llvm::IsaPred<NamedModuleJobNode>),
1599 llvm::CastTo<NamedModuleJobNode>);
1601 for (NamedModuleJobNode *Node : NamedModuleNodes) {
1602 const auto &Job = *Node->Job;
1606 const bool IsStdModule =
1607 Job.getInputInfos().front().getType() == types::TY_CXXStdModule;
1609 StringRef ModuleOutputPath = Job.getOutputFilenames().front();
1614 const StringRef ModuleName = Node->InputDeps.ModuleName;
1616 C.addTempFile(
C.getArgs().MakeArgString(ModuleOutputPath));
1625 CompilationGraph &&Graph) {
1626 llvm::ReversePostOrderTraversal<CompilationGraph *> TopologicallySortedNodes(
1629 "First node in topological order must be the root!");
1630 auto TopologicallySortedJobNodes = llvm::map_range(
1631 llvm::drop_begin(TopologicallySortedNodes), llvm::CastTo<JobNode>);
1632 for (
auto *JN : TopologicallySortedJobNodes)
1633 C.addCommand(std::move(JN->Job));
1638 llvm::PrettyStackTraceString CrashInfo(
"Running modules driver.");
1640 auto Jobs =
C.getJobs().takeJobs();
1651 if (!MaybeModuleCachePath) {
1652 Diags.
Report(diag::err_default_modules_cache_not_available);
1656 auto MaybeCWD =
C.getDriver().getVFS().getCurrentWorkingDirectory();
1657 const auto CWD = MaybeCWD ? std::move(*MaybeCWD) :
".";
1659 const llvm::opt::Arg *LogPathArg =
1660 C.getArgs().getLastArg(options::OPT_fdepscan_log_path);
1661 StringRef DepScanLogPath =
1662 LogPathArg ? StringRef(LogPathArg->getValue()).trim() : StringRef();
1663 if (LogPathArg && DepScanLogPath.empty()) {
1664 Diags.
Report(diag::err_drv_depscan_log_path_empty);
1668 auto MaybeScanResults =
1670 DepScanLogPath, Diags);
1671 if (!MaybeScanResults) {
1672 Diags.
Report(diag::err_dependency_scan_failed);
1675 auto &ScanResult = *MaybeScanResults;
1678 CompilationGraph Graph;
1686 ScanResult.InputDepsForScannedJobs, Diags))
1691 Graph,
C, ScannedJobs,
1692 std::move(ScanResult.ModuleDepGraphsForScannedJobs));
1694 std::move(ScanResult.InputDepsForScannedJobs));
1702 Diags.
Report(diag::remark_printing_module_graph);
1704 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::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::optional< DependencyScanResult > scanDependencies(ArrayRef< std::unique_ptr< Command > > Jobs, llvm::DenseMap< StringRef, const StdModuleManifest::Module * > ManifestLookup, StringRef ModuleCachePath, StringRef WorkingDirectory, StringRef DepScanLogPath, DiagnosticsEngine &Diags)
Scans the compilations job list Jobs for module 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.
BoundArch 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.
Top level wrappers for InstallAPI frontend operations.
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...
const FunctionProtoType * T
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.
std::string LogPath
The path to a log file, which logs timing of actions performed by the dependency scanner.
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)