diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/Action.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 82 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChain.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 78 | ||||
-rw-r--r-- | clang/lib/Driver/Types.cpp | 2 |
5 files changed, 141 insertions, 36 deletions
diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index f9090438751..d4c7040a233 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -26,6 +26,7 @@ const char *Action::getClassName(ActionClass AC) { return "offload"; case PreprocessJobClass: return "preprocessor"; case PrecompileJobClass: return "precompiler"; + case HeaderModulePrecompileJobClass: return "header-module-precompiler"; case AnalyzeJobClass: return "analyzer"; case MigrateJobClass: return "migrator"; case CompileJobClass: return "compiler"; @@ -319,6 +320,19 @@ void PrecompileJobAction::anchor() {} PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) : JobAction(PrecompileJobClass, Input, OutputType) {} +PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input, + types::ID OutputType) + : JobAction(Kind, Input, OutputType) { + assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind"); +} + +void HeaderModulePrecompileJobAction::anchor() {} + +HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction( + Action *Input, types::ID OutputType, const char *ModuleName) + : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType), + ModuleName(ModuleName) {} + void AnalyzeJobAction::anchor() {} AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 908ffa3bd10..81369f995da 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3010,6 +3010,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, OffloadingActionBuilder OffloadBuilder(C, Args, Inputs); // Construct the actions to perform. + HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; ActionList LinkerInputs; llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL; @@ -3106,13 +3107,29 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, break; } + // Each precompiled header file after a module file action is a module + // header of that same module file, rather than being compiled to a + // separate PCH. + if (Phase == phases::Precompile && HeaderModuleAction && + getPrecompiledType(InputType) == types::TY_PCH) { + HeaderModuleAction->addModuleHeaderInput(Current); + Current = nullptr; + break; + } + + // FIXME: Should we include any prior module file outputs as inputs of + // later actions in the same command line? + // Otherwise construct the appropriate action. - auto *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current); + Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current); // We didn't create a new action, so we will just move to the next phase. if (NewCurrent == Current) continue; + if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent)) + HeaderModuleAction = HMA; + Current = NewCurrent; // Use the current host action in any of the offloading actions, if @@ -3192,10 +3209,25 @@ Action *Driver::ConstructPhaseAction( types::ID OutputTy = getPrecompiledType(Input->getType()); assert(OutputTy != types::TY_INVALID && "Cannot precompile this input type!"); + + // If we're given a module name, precompile header file inputs as a + // module, not as a precompiled header. + const char *ModName = nullptr; + if (OutputTy == types::TY_PCH) { + if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ)) + ModName = A->getValue(); + if (ModName) + OutputTy = types::TY_ModuleFile; + } + if (Args.hasArg(options::OPT_fsyntax_only)) { // Syntax checks should not emit a PCH file OutputTy = types::TY_Nothing; } + + if (ModName) + return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy, + ModName); return C.MakeAction<PrecompileJobAction>(Input, OutputTy); } case phases::Compile: { @@ -3448,7 +3480,7 @@ class ToolSelector final { /// - Backend + Compile. const Tool * combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo, - const ActionList *&Inputs, + ActionList &Inputs, ActionList &CollapsedOffloadAction) { if (ActionInfo.size() < 3 || !canCollapseAssembleAction()) return nullptr; @@ -3474,13 +3506,13 @@ class ToolSelector final { if (!T->hasIntegratedAssembler()) return nullptr; - Inputs = &CJ->getInputs(); + Inputs = CJ->getInputs(); AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, /*NumElements=*/3); return T; } const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo, - const ActionList *&Inputs, + ActionList &Inputs, ActionList &CollapsedOffloadAction) { if (ActionInfo.size() < 2 || !canCollapseAssembleAction()) return nullptr; @@ -3507,13 +3539,13 @@ class ToolSelector final { if (!T->hasIntegratedAssembler()) return nullptr; - Inputs = &BJ->getInputs(); + Inputs = BJ->getInputs(); AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, /*NumElements=*/2); return T; } const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo, - const ActionList *&Inputs, + ActionList &Inputs, ActionList &CollapsedOffloadAction) { if (ActionInfo.size() < 2) return nullptr; @@ -3545,7 +3577,7 @@ class ToolSelector final { if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode)) return nullptr; - Inputs = &CJ->getInputs(); + Inputs = CJ->getInputs(); AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo, /*NumElements=*/2); return T; @@ -3555,22 +3587,28 @@ class ToolSelector final { /// preprocessor action, and the current input is indeed a preprocessor /// action. If combining results in the collapse of offloading actions, those /// are appended to \a CollapsedOffloadAction. - void combineWithPreprocessor(const Tool *T, const ActionList *&Inputs, + void combineWithPreprocessor(const Tool *T, ActionList &Inputs, ActionList &CollapsedOffloadAction) { if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP()) return; // Attempt to get a preprocessor action dependence. ActionList PreprocessJobOffloadActions; - auto *PJ = getPrevDependentAction(*Inputs, PreprocessJobOffloadActions); - if (!PJ || !isa<PreprocessJobAction>(PJ)) - return; + ActionList NewInputs; + for (Action *A : Inputs) { + auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions); + if (!PJ || !isa<PreprocessJobAction>(PJ)) { + NewInputs.push_back(A); + continue; + } - // This is legal to combine. Append any offload action we found and set the - // current inputs to preprocessor inputs. - CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(), - PreprocessJobOffloadActions.end()); - Inputs = &PJ->getInputs(); + // This is legal to combine. Append any offload action we found and add the + // current input to preprocessor inputs. + CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(), + PreprocessJobOffloadActions.end()); + NewInputs.append(PJ->input_begin(), PJ->input_end()); + } + Inputs = NewInputs; } public: @@ -3588,7 +3626,7 @@ public: /// connected to collapsed actions are updated accordingly. The latter enables /// the caller of the selector to process them afterwards instead of just /// dropping them. If no suitable tool is found, null will be returned. - const Tool *getTool(const ActionList *&Inputs, + const Tool *getTool(ActionList &Inputs, ActionList &CollapsedOffloadAction) { // // Get the largest chain of actions that we could combine. @@ -3624,7 +3662,7 @@ public: if (!T) T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction); if (!T) { - Inputs = &BaseAction->getInputs(); + Inputs = BaseAction->getInputs(); T = TC.SelectTool(*BaseAction); } @@ -3769,7 +3807,7 @@ InputInfo Driver::BuildJobsForActionNoCache( } - const ActionList *Inputs = &A->getInputs(); + ActionList Inputs = A->getInputs(); const JobAction *JA = cast<JobAction>(A); ActionList CollapsedOffloadActions; @@ -3795,7 +3833,7 @@ InputInfo Driver::BuildJobsForActionNoCache( // Only use pipes when there is exactly one input. InputInfoList InputInfos; - for (const Action *Input : *Inputs) { + for (const Action *Input : Inputs) { // Treat dsymutil and verify sub-jobs as being at the top-level too, they // shouldn't get temporary output names. // FIXME: Clean this up. @@ -3814,6 +3852,10 @@ InputInfo Driver::BuildJobsForActionNoCache( if (JA->getType() == types::TY_dSYM) BaseInput = InputInfos[0].getFilename(); + // ... and in header module compilations, which use the module name. + if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA)) + BaseInput = ModuleJA->getModuleName(); + // Append outputs of offload device jobs to the input list if (!OffloadDependencesInputInfo.empty()) InputInfos.append(OffloadDependencesInputInfo.begin(), diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index d5004df593b..8933e905fce 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -302,6 +302,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::CompileJobClass: case Action::PrecompileJobClass: + case Action::HeaderModulePrecompileJobClass: case Action::PreprocessJobClass: case Action::AnalyzeJobClass: case Action::MigrateJobClass: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 201fd678345..01262871143 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3144,17 +3144,54 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Check number of inputs for sanity. We need at least one input. assert(Inputs.size() >= 1 && "Must have at least one input."); - const InputInfo &Input = Inputs[0]; // CUDA/HIP compilation may have multiple inputs (source file + results of // device-side compilations). OpenMP device jobs also take the host IR as a - // second input. All other jobs are expected to have exactly one - // input. + // second input. Module precompilation accepts a list of header files to + // include as part of the module. All other jobs are expected to have exactly + // one input. bool IsCuda = JA.isOffloading(Action::OFK_Cuda); bool IsHIP = JA.isOffloading(Action::OFK_HIP); bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); - assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || - Inputs.size() == 1) && - "Unable to handle multiple inputs."); + bool IsModulePrecompile = + isa<PrecompileJobAction>(JA) && JA.getType() == types::TY_ModuleFile; + bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA); + + // A header module compilation doesn't have a main input file, so invent a + // fake one as a placeholder. + // FIXME: Pick the language based on the header file language. + const char *ModuleName = [&]{ + auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ); + return ModuleNameArg ? ModuleNameArg->getValue() : ""; + }(); + InputInfo HeaderModuleInput(types::TY_CXXModule, ModuleName, ModuleName); + + const InputInfo &Input = + IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0]; + + InputInfoList ModuleHeaderInputs; + const InputInfo *CudaDeviceInput = nullptr; + const InputInfo *OpenMPDeviceInput = nullptr; + for (const InputInfo &I : Inputs) { + if (&I == &Input) { + // This is the primary input. + } else if (IsModulePrecompile && + types::getPrecompiledType(I.getType()) == types::TY_PCH) { + types::ID Expected = + types::lookupHeaderTypeForSourceType(Inputs[0].getType()); + if (I.getType() != Expected) { + D.Diag(diag::err_drv_module_header_wrong_kind) + << I.getFilename() << types::getTypeName(I.getType()) + << types::getTypeName(Expected); + } + ModuleHeaderInputs.push_back(I); + } else if ((IsCuda || IsHIP) && !CudaDeviceInput) { + CudaDeviceInput = &I; + } else if (IsOpenMPDevice && !OpenMPDeviceInput) { + OpenMPDeviceInput = &I; + } else { + llvm_unreachable("unexpectedly given multiple inputs"); + } + } const llvm::Triple *AuxTriple = IsCuda ? getToolChain().getAuxTriple() : nullptr; @@ -3267,7 +3304,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (JA.getType() == types::TY_Nothing) CmdArgs.push_back("-fsyntax-only"); else if (JA.getType() == types::TY_ModuleFile) - CmdArgs.push_back("-emit-module-interface"); + CmdArgs.push_back(IsHeaderModulePrecompile + ? "-emit-header-module" + : "-emit-module-interface"); else if (UsePCH) CmdArgs.push_back("-emit-pch"); else @@ -4729,10 +4768,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addDashXForInput(Args, Input, CmdArgs); - if (Input.isFilename()) - CmdArgs.push_back(Input.getFilename()); - else - Input.getInputArg().renderAsInput(Args, CmdArgs); + ArrayRef<InputInfo> FrontendInputs = Input; + if (IsHeaderModulePrecompile) + FrontendInputs = ModuleHeaderInputs; + else if (Input.isNothing()) + FrontendInputs = {}; + + for (const InputInfo &Input : FrontendInputs) { + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); + else + Input.getInputArg().renderAsInput(Args, CmdArgs); + } Args.AddAllArgs(CmdArgs, options::OPT_undef); @@ -4765,10 +4812,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (IsCuda) { // Host-side cuda compilation receives all device-side outputs in a single // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary. - if (Inputs.size() > 1) { - assert(Inputs.size() == 2 && "More than one GPU binary!"); + if (CudaDeviceInput) { CmdArgs.push_back("-fcuda-include-gpubinary"); - CmdArgs.push_back(Inputs[1].getFilename()); + CmdArgs.push_back(CudaDeviceInput->getFilename()); } if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false)) @@ -4785,9 +4831,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // only the relevant declarations are emitted. if (IsOpenMPDevice) { CmdArgs.push_back("-fopenmp-is-device"); - if (Inputs.size() == 2) { + if (OpenMPDeviceInput) { CmdArgs.push_back("-fopenmp-host-ir-file-path"); - CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename())); + CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename())); } } diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 45bb699cfb8..9d2737bbc71 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -312,9 +312,11 @@ ID types::lookupHeaderTypeForSourceType(ID Id) { default: return Id; + // FIXME: Handle preprocessed input types. case types::TY_C: return types::TY_CHeader; case types::TY_CXX: + case types::TY_CXXModule: return types::TY_CXXHeader; case types::TY_ObjC: return types::TY_ObjCHeader; |