2121#include " clang/Driver/Job.h"
2222#include " clang/Driver/Tool.h"
2323#include " clang/Driver/ToolChain.h"
24+ #include " clang/Driver/Types.h"
2425#include " clang/Frontend/StandaloneDiagnostic.h"
2526#include " llvm/ADT/DenseSet.h"
2627#include " llvm/ADT/DepthFirstIterator.h"
@@ -47,6 +48,14 @@ using namespace clang;
4748using namespace driver ;
4849using namespace modules ;
4950
51+ void driver::modules::diagnoseModulesDriverArgs (llvm::opt::DerivedArgList &DAL,
52+ DiagnosticsEngine &Diags) {
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);
56+ }
57+ }
58+
5059namespace clang ::driver::modules {
5160static bool fromJSON (const llvm::json::Value &Params,
5261 StdModuleManifest::Module::LocalArguments &LocalArgs,
@@ -1252,6 +1261,16 @@ static SmallVector<JobNode *> createNodesForUnusedStdlibModuleJobs(
12521261 return StdlibModuleNodesToPrune;
12531262}
12541263
1264+ // Returns the derived argument list for the tool chain responsible
1265+ // for creating \p Job.
1266+ static const DerivedArgList &getToolChainArgs (Compilation &C,
1267+ const Command &Job) {
1268+ const auto &TC = Job.getCreator ().getToolChain ();
1269+ const auto &SourceAction = Job.getSource ();
1270+ return C.getArgsForToolChain (&TC, SourceAction.getOffloadingArch (),
1271+ SourceAction.getOffloadingDeviceKind ());
1272+ }
1273+
12551274// / Creates a job for the Clang module described by \p MD.
12561275static std::unique_ptr<Command>
12571276createClangModulePrecompileJob (Compilation &C, const Command &ImportingJob,
@@ -1263,9 +1282,7 @@ createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob,
12631282 Action *PA = C.MakeAction <PrecompileJobAction>(IA, types::ID::TY_ModuleFile);
12641283 PA->propagateOffloadInfo (&ImportingJob.getSource ());
12651284
1266- const auto &TC = ImportingJob.getCreator ().getToolChain ();
1267- const auto &TCArgs = C.getArgsForToolChain (&TC, PA->getOffloadingArch (),
1268- PA->getOffloadingDeviceKind ());
1285+ const auto &TCArgs = getToolChainArgs (C, ImportingJob);
12691286
12701287 const auto &BuildArgs = MD.getBuildArguments ();
12711288 ArgStringList JobArgs;
@@ -1319,12 +1336,7 @@ installScanCommandLines(Compilation &C,
13191336 ArgStringList JobArgs;
13201337 JobArgs.reserve (BuildArgs.size ());
13211338
1322- const auto &SourceAction = Job.getSource ();
1323- const auto &TC = Job.getCreator ().getToolChain ();
1324- auto &TCArgs =
1325- C.getArgsForToolChain (&TC, SourceAction.getOffloadingArch (),
1326- SourceAction.getOffloadingDeviceKind ());
1327-
1339+ auto &TCArgs = getToolChainArgs (C, Job);
13281340 for (const auto &Arg : BuildArgs)
13291341 JobArgs.push_back (TCArgs.MakeArgString (Arg));
13301342
@@ -1527,6 +1539,73 @@ static void createAndConnectRoot(CompilationGraph &Graph) {
15271539 }
15281540}
15291541
1542+ // / Creates a temporary output path for \p ModuleName.
1543+ static std::string createModuleOutputPath (const Compilation &C,
1544+ StringRef ModuleName) {
1545+ // Sanitize the ':' included in parition names. It is illegal for filenames on
1546+ // Windows.
1547+ SmallString<32 > SanitizedModuleName (ModuleName);
1548+ llvm::replace (SanitizedModuleName, ' :' , ' -' );
1549+ auto ModuleOutputPath = C.getDriver ().GetTemporaryPath (
1550+ SanitizedModuleName, types::getTypeTempSuffix (types::TY_ModuleFile));
1551+ return ModuleOutputPath;
1552+ }
1553+
1554+ // / Adds the '-fmodule-output=' argument for the module produced by \p Node.
1555+ static void configureNamedModuleOutputArg (Compilation &C,
1556+ NamedModuleJobNode &Node,
1557+ StringRef ModuleOutputPath) {
1558+ auto &Job = *Node.Job ;
1559+ const auto &TCArgs = getToolChainArgs (C, Job);
1560+ auto JobArgs = Job.getArguments ();
1561+ JobArgs.push_back (
1562+ TCArgs.MakeArgString (" -fmodule-output=" + ModuleOutputPath));
1563+ Job.replaceArguments (std::move (JobArgs));
1564+ }
1565+
1566+ // / Propagates the '-fmodule-file=' mapping for the named module described by
1567+ // / \p Node to each dependent job.
1568+ static void propagateModuleFileMappingArg (Compilation &C,
1569+ NamedModuleJobNode &Node,
1570+ StringRef ModuleOutputPath) {
1571+ const StringRef ModuleName = Node.InputDeps .ModuleName ;
1572+
1573+ auto DependentNodes = llvm::drop_begin (llvm::depth_first<CGNode *>(&Node));
1574+ auto DependentScannedNodes = llvm::map_range (
1575+ llvm::make_filter_range (DependentNodes, llvm::IsaPred<ScannedJobNode>),
1576+ llvm::CastTo<ScannedJobNode>);
1577+
1578+ for (ScannedJobNode *DependentNode : DependentScannedNodes) {
1579+ auto &DependentJob = *DependentNode->Job ;
1580+ const auto &TCArgs = getToolChainArgs (C, DependentJob);
1581+ auto JobArgs = DependentJob.getArguments ();
1582+ JobArgs.push_back (TCArgs.MakeArgString (" -fmodule-file=" + ModuleName + " =" +
1583+ ModuleOutputPath));
1584+ DependentJob.replaceArguments (std::move (JobArgs));
1585+ }
1586+ }
1587+
1588+ // / Finalizes command lines for C++20 named module dependencies.
1589+ // /
1590+ // / The command lines produced by dependency scanning are only adjusted to
1591+ // / handle discovered Clang modules. For C++20 named modules, we update the
1592+ // / command-lines here.
1593+ static void fixupNamedModuleCommandLines (Compilation &C,
1594+ CompilationGraph &Graph) {
1595+ const auto NamedModuleNodes = llvm::map_range (
1596+ llvm::make_filter_range (Graph, llvm::IsaPred<NamedModuleJobNode>),
1597+ llvm::CastTo<NamedModuleJobNode>);
1598+
1599+ for (NamedModuleJobNode *Node : NamedModuleNodes) {
1600+ const StringRef ModuleName = Node->InputDeps .ModuleName ;
1601+ const auto ModuleOutputPath = createModuleOutputPath (C, ModuleName);
1602+ C.addTempFile (C.getArgs ().MakeArgString (ModuleOutputPath));
1603+
1604+ configureNamedModuleOutputArg (C, *Node, ModuleOutputPath);
1605+ propagateModuleFileMappingArg (C, *Node, ModuleOutputPath);
1606+ }
1607+ }
1608+
15301609// / Moves jobs from \p Graph into \p C in the graph's topological order.
15311610static void feedJobsBackIntoCompilation (Compilation &C,
15321611 CompilationGraph &&Graph) {
@@ -1600,7 +1679,6 @@ void driver::modules::runModulesDriver(
16001679 if (!Diags.isLastDiagnosticIgnored ())
16011680 llvm::WriteGraph<const CompilationGraph *>(llvm::errs (), &Graph);
16021681
1603- // TODO: Fix-up command-lines for named module imports.
1604-
1682+ fixupNamedModuleCommandLines (C, Graph);
16051683 feedJobsBackIntoCompilation (C, std::move (Graph));
16061684}
0 commit comments