Changeset View
Changeset View
Standalone View
Standalone View
lib/Driver/Driver.cpp
Show First 20 Lines • Show All 928 Lines • ▼ Show 20 Lines | if (C.getArgs().hasArg(options::OPT_print_multi_directory)) { | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
// Display an action graph human-readably. Action A is the "sink" node | // Display an action graph human-readably. Action A is the "sink" node | ||||
// and latest-occuring action. Traversal is in pre-order, visiting the | // and latest-occuring action. Traversal is in pre-order, visiting the | ||||
// inputs to each action before printing the action itself. | // inputs to each action before printing the action itself. | ||||
static unsigned PrintActions1(const Compilation &C, Action *A, | static unsigned PrintActions1(const Compilation &C, const Action *A, | ||||
std::map<Action *, unsigned> &Ids) { | std::map<const Action *, unsigned> &Ids) { | ||||
if (Ids.count(A)) // A was already visited. | if (Ids.count(A)) // A was already visited. | ||||
return Ids[A]; | return Ids[A]; | ||||
std::string str; | std::string str; | ||||
llvm::raw_string_ostream os(str); | llvm::raw_string_ostream os(str); | ||||
os << Action::getClassName(A->getKind()) << ", "; | os << Action::getClassName(A->getKind()) << ", "; | ||||
if (InputAction *IA = dyn_cast<InputAction>(A)) { | if (const InputAction *IA = dyn_cast<InputAction>(A)) { | ||||
os << "\"" << IA->getInputArg().getValue() << "\""; | os << "\"" << IA->getInputArg().getValue() << "\""; | ||||
} else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { | } else if (const BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { | ||||
os << '"' << BIA->getArchName() << '"' << ", {" | os << '"' << BIA->getArchName() << '"' << ", {" | ||||
<< PrintActions1(C, *BIA->begin(), Ids) << "}"; | << PrintActions1(C, BIA->begin()->get(), Ids) << "}"; | ||||
} else if (CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) { | } else if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) { | ||||
os << '"' << CDA->getGpuArchName() << '"' << ", {" | os << '"' << CDA->getGpuArchName() << '"' << ", {" | ||||
<< PrintActions1(C, *CDA->begin(), Ids) << "}"; | << PrintActions1(C, CDA->begin()->get(), Ids) << "}"; | ||||
} else { | } else { | ||||
const ActionList *AL; | const ActionList *AL; | ||||
if (CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) { | if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) { | ||||
os << "{" << PrintActions1(C, *CHA->begin(), Ids) << "}" | os << "{" << PrintActions1(C, CHA->begin()->get(), Ids) << "}" | ||||
<< ", gpu binaries "; | << ", gpu binaries "; | ||||
AL = &CHA->getDeviceActions(); | AL = &CHA->getDeviceActions(); | ||||
} else | } else | ||||
AL = &A->getInputs(); | AL = &A->getInputs(); | ||||
if (AL->size()) { | if (AL->size()) { | ||||
const char *Prefix = "{"; | const char *Prefix = "{"; | ||||
for (Action *PreRequisite : *AL) { | for (const std::shared_ptr<Action> &PreRequisite : *AL) { | ||||
os << Prefix << PrintActions1(C, PreRequisite, Ids); | os << Prefix << PrintActions1(C, PreRequisite.get(), Ids); | ||||
Prefix = ", "; | Prefix = ", "; | ||||
} | } | ||||
os << "}"; | os << "}"; | ||||
} else | } else | ||||
os << "{}"; | os << "{}"; | ||||
} | } | ||||
unsigned Id = Ids.size(); | unsigned Id = Ids.size(); | ||||
Ids[A] = Id; | Ids[A] = Id; | ||||
llvm::errs() << Id << ": " << os.str() << ", " | llvm::errs() << Id << ": " << os.str() << ", " | ||||
<< types::getTypeName(A->getType()) << "\n"; | << types::getTypeName(A->getType()) << "\n"; | ||||
return Id; | return Id; | ||||
} | } | ||||
// Print the action graphs in a compilation C. | // Print the action graphs in a compilation C. | ||||
// For example "clang -c file1.c file2.c" is composed of two subgraphs. | // For example "clang -c file1.c file2.c" is composed of two subgraphs. | ||||
void Driver::PrintActions(const Compilation &C) const { | void Driver::PrintActions(const Compilation &C) const { | ||||
std::map<Action *, unsigned> Ids; | std::map<const Action *, unsigned> Ids; | ||||
for (Action *A : C.getActions()) | for (const std::shared_ptr<Action> &A : C.getActions()) | ||||
PrintActions1(C, A, Ids); | PrintActions1(C, A.get(), Ids); | ||||
} | } | ||||
/// \brief Check whether the given input tree contains any compilation or | /// \brief Check whether the given input tree contains any compilation or | ||||
/// assembly actions. | /// assembly actions. | ||||
static bool ContainsCompileOrAssembleAction(const Action *A) { | static bool ContainsCompileOrAssembleAction(const Action *A) { | ||||
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) || | if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) || | ||||
isa<AssembleJobAction>(A)) | isa<AssembleJobAction>(A)) | ||||
return true; | return true; | ||||
for (const Action *Input : *A) | for (const std::shared_ptr<Action> Input : *A) | ||||
if (ContainsCompileOrAssembleAction(Input)) | if (ContainsCompileOrAssembleAction(Input.get())) | ||||
return true; | return true; | ||||
return false; | return false; | ||||
} | } | ||||
void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, | void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, | ||||
const InputList &BAInputs) const { | const InputList &BAInputs) const { | ||||
DerivedArgList &Args = C.getArgs(); | DerivedArgList &Args = C.getArgs(); | ||||
Show All 25 Lines | void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, | ||||
if (!Archs.size()) | if (!Archs.size()) | ||||
Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName())); | Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName())); | ||||
ActionList SingleActions; | ActionList SingleActions; | ||||
BuildActions(C, TC, Args, BAInputs, SingleActions); | BuildActions(C, TC, Args, BAInputs, SingleActions); | ||||
// Add in arch bindings for every top level action, as well as lipo and | // Add in arch bindings for every top level action, as well as lipo and | ||||
// dsymutil steps if needed. | // dsymutil steps if needed. | ||||
for (Action* Act : SingleActions) { | for (const std::shared_ptr<Action> &Act : SingleActions) { | ||||
// Make sure we can lipo this kind of output. If not (and it is an actual | // Make sure we can lipo this kind of output. If not (and it is an actual | ||||
// output) then we disallow, since we can't create an output file with the | // output) then we disallow, since we can't create an output file with the | ||||
// right name without overwriting it. We could remove this oddity by just | // right name without overwriting it. We could remove this oddity by just | ||||
// changing the output names to include the arch, which would also fix | // changing the output names to include the arch, which would also fix | ||||
// -save-temps. Compatibility wins for now. | // -save-temps. Compatibility wins for now. | ||||
if (Archs.size() > 1 && !types::canLipoType(Act->getType())) | if (Archs.size() > 1 && !types::canLipoType(Act->getType())) | ||||
Diag(clang::diag::err_drv_invalid_output_with_multiple_archs) | Diag(clang::diag::err_drv_invalid_output_with_multiple_archs) | ||||
<< types::getTypeName(Act->getType()); | << types::getTypeName(Act->getType()); | ||||
ActionList Inputs; | ActionList Inputs; | ||||
for (unsigned i = 0, e = Archs.size(); i != e; ++i) { | for (unsigned i = 0, e = Archs.size(); i != e; ++i) | ||||
tra: unneeded {} | |||||
Inputs.push_back( | Inputs.push_back(std::make_shared<BindArchAction>(Act, Archs[i])); | ||||
new BindArchAction(std::unique_ptr<Action>(Act), Archs[i])); | |||||
if (i != 0) | |||||
Inputs.back()->setOwnsInputs(false); | |||||
} | |||||
// Lipo if necessary, we do it this way because we need to set the arch flag | // Lipo if necessary, we do it this way because we need to set the arch flag | ||||
// so that -Xarch_ gets overwritten. | // so that -Xarch_ gets overwritten. | ||||
if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) | if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) | ||||
Actions.append(Inputs.begin(), Inputs.end()); | Actions.append(Inputs.begin(), Inputs.end()); | ||||
else | else | ||||
Actions.push_back(new LipoJobAction(Inputs, Act->getType())); | Actions.push_back( | ||||
std::make_shared<LipoJobAction>(Inputs, Act->getType())); | |||||
// Handle debug info queries. | // Handle debug info queries. | ||||
Arg *A = Args.getLastArg(options::OPT_g_Group); | Arg *A = Args.getLastArg(options::OPT_g_Group); | ||||
if (A && !A->getOption().matches(options::OPT_g0) && | if (A && !A->getOption().matches(options::OPT_g0) && | ||||
!A->getOption().matches(options::OPT_gstabs) && | !A->getOption().matches(options::OPT_gstabs) && | ||||
ContainsCompileOrAssembleAction(Actions.back())) { | ContainsCompileOrAssembleAction(Actions.back().get())) { | ||||
// Add a 'dsymutil' step if necessary, when debug info is enabled and we | // Add a 'dsymutil' step if necessary, when debug info is enabled and we | ||||
// have a compile input. We need to run 'dsymutil' ourselves in such cases | // have a compile input. We need to run 'dsymutil' ourselves in such cases | ||||
// because the debug info will refer to a temporary object file which | // because the debug info will refer to a temporary object file which | ||||
// will be removed at the end of the compilation process. | // will be removed at the end of the compilation process. | ||||
if (Act->getType() == types::TY_Image) { | if (Act->getType() == types::TY_Image) { | ||||
ActionList Inputs; | ActionList Inputs; | ||||
Inputs.push_back(Actions.back()); | Inputs.push_back(Actions.back()); | ||||
Actions.pop_back(); | Actions.pop_back(); | ||||
Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); | Actions.push_back( | ||||
std::make_shared<DsymutilJobAction>(Inputs, types::TY_dSYM)); | |||||
} | } | ||||
// Verify the debug info output. | // Verify the debug info output. | ||||
if (Args.hasArg(options::OPT_verify_debug_info)) { | if (Args.hasArg(options::OPT_verify_debug_info)) { | ||||
std::unique_ptr<Action> VerifyInput(Actions.back()); | std::shared_ptr<Action> LastAction = Actions.back(); | ||||
Actions.pop_back(); | Actions.pop_back(); | ||||
Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput), | Actions.push_back(std::make_shared<VerifyDebugInfoJobAction>( | ||||
types::TY_Nothing)); | LastAction, types::TY_Nothing)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/// \brief Check that the file referenced by Value exists. If it doesn't, | /// \brief Check that the file referenced by Value exists. If it doesn't, | ||||
/// issue a diagnostic and return false. | /// issue a diagnostic and return false. | ||||
static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, | static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | |||||
// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE | // For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE | ||||
// input action and then wraps each in CudaDeviceAction paired with | // input action and then wraps each in CudaDeviceAction paired with | ||||
// appropriate GPU arch name. In case of partial (i.e preprocessing | // appropriate GPU arch name. In case of partial (i.e preprocessing | ||||
// only) or device-only compilation, each device action is added to /p | // only) or device-only compilation, each device action is added to /p | ||||
// Actions and /p Current is released. Otherwise the function creates | // Actions and /p Current is released. Otherwise the function creates | ||||
// and returns a new CudaHostAction which wraps /p Current and device | // and returns a new CudaHostAction which wraps /p Current and device | ||||
// side actions. | // side actions. | ||||
static std::unique_ptr<Action> | static std::shared_ptr<Action> | ||||
buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, | buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, | ||||
std::unique_ptr<Action> HostAction, ActionList &Actions) { | std::shared_ptr<Action> HostAction, ActionList &Actions) { | ||||
Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only, | Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only, | ||||
options::OPT_cuda_device_only); | options::OPT_cuda_device_only); | ||||
// Host-only compilation case. | // Host-only compilation case. | ||||
if (PartialCompilationArg && | if (PartialCompilationArg && | ||||
PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only)) | PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only)) | ||||
return std::unique_ptr<Action>( | return std::make_shared<CudaHostAction>(std::move(HostAction), | ||||
new CudaHostAction(std::move(HostAction), {})); | ActionList()); | ||||
// Collect all cuda_gpu_arch parameters, removing duplicates. | // Collect all cuda_gpu_arch parameters, removing duplicates. | ||||
SmallVector<const char *, 4> GpuArchList; | SmallVector<const char *, 4> GpuArchList; | ||||
llvm::StringSet<> GpuArchNames; | llvm::StringSet<> GpuArchNames; | ||||
for (Arg *A : Args) { | for (Arg *A : Args) { | ||||
if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) { | if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) { | ||||
A->claim(); | A->claim(); | ||||
if (GpuArchNames.insert(A->getValue()).second) | if (GpuArchNames.insert(A->getValue()).second) | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (PartialCompilation || DeviceOnlyCompilation) { | ||||
if (Args.hasArg(options::OPT_o) && | if (Args.hasArg(options::OPT_o) && | ||||
(!DeviceOnlyCompilation || GpuArchList.size() > 1)) { | (!DeviceOnlyCompilation || GpuArchList.size() > 1)) { | ||||
C.getDriver().Diag( | C.getDriver().Diag( | ||||
clang::diag::err_drv_output_argument_with_multiple_files); | clang::diag::err_drv_output_argument_with_multiple_files); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) | ||||
Actions.push_back(new CudaDeviceAction( | Actions.push_back(std::make_shared<CudaDeviceAction>( | ||||
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I], | CudaDeviceActions[I], GpuArchList[I], | ||||
/* AtTopLevel */ true)); | /* AtTopLevel */ true)); | ||||
// Kill host action in case of device-only compilation. | // Kill host action in case of device-only compilation. | ||||
if (DeviceOnlyCompilation) | if (DeviceOnlyCompilation) | ||||
HostAction.reset(nullptr); | return nullptr; | ||||
return HostAction; | return HostAction; | ||||
} | } | ||||
// Outputs of device actions during complete CUDA compilation get created | // Outputs of device actions during complete CUDA compilation get created | ||||
// with AtTopLevel=false and become inputs for the host action. | // with AtTopLevel=false and become inputs for the host action. | ||||
ActionList DeviceActions; | ActionList DeviceActions; | ||||
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) | for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) | ||||
DeviceActions.push_back(new CudaDeviceAction( | DeviceActions.push_back( | ||||
std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I], | std::make_shared<CudaDeviceAction>(CudaDeviceActions[I], GpuArchList[I], | ||||
/* AtTopLevel */ false)); | /* AtTopLevel */ false)); | ||||
// Return a new host action that incorporates original host action and all | // Return a new host action that incorporates original host action and all | ||||
// device actions. | // device actions. | ||||
return std::unique_ptr<Action>( | return std::make_shared<CudaHostAction>(std::move(HostAction), DeviceActions); | ||||
new CudaHostAction(std::move(HostAction), DeviceActions)); | |||||
} | } | ||||
void Driver::BuildActions(Compilation &C, const ToolChain &TC, | void Driver::BuildActions(Compilation &C, const ToolChain &TC, | ||||
DerivedArgList &Args, const InputList &Inputs, | DerivedArgList &Args, const InputList &Inputs, | ||||
ActionList &Actions) const { | ActionList &Actions) const { | ||||
llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); | llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); | ||||
if (!SuppressMissingInputWarning && Inputs.empty()) { | if (!SuppressMissingInputWarning && Inputs.empty()) { | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | for (auto &I : Inputs) { | ||||
phases::ID CudaInjectionPhase = FinalPhase; | phases::ID CudaInjectionPhase = FinalPhase; | ||||
for (const auto &Phase : PL) | for (const auto &Phase : PL) | ||||
if (Phase <= FinalPhase && Phase == phases::Compile) { | if (Phase <= FinalPhase && Phase == phases::Compile) { | ||||
CudaInjectionPhase = Phase; | CudaInjectionPhase = Phase; | ||||
break; | break; | ||||
} | } | ||||
// Build the pipeline for this file. | // Build the pipeline for this file. | ||||
std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType)); | std::shared_ptr<Action> Current = | ||||
std::make_shared<InputAction>(*InputArg, InputType); | |||||
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end(); | for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end(); | ||||
i != e; ++i) { | i != e; ++i) { | ||||
phases::ID Phase = *i; | phases::ID Phase = *i; | ||||
// We are done if this step is past what the user requested. | // We are done if this step is past what the user requested. | ||||
if (Phase > FinalPhase) | if (Phase > FinalPhase) | ||||
break; | break; | ||||
// Queue linker inputs. | // Queue linker inputs. | ||||
if (Phase == phases::Link) { | if (Phase == phases::Link) { | ||||
assert((i + 1) == e && "linking must be final compilation step."); | assert((i + 1) == e && "linking must be final compilation step."); | ||||
LinkerInputs.push_back(Current.release()); | LinkerInputs.push_back(std::move(Current)); | ||||
break; | break; | ||||
} | } | ||||
// Some types skip the assembler phase (e.g., llvm-bc), but we can't | // Some types skip the assembler phase (e.g., llvm-bc), but we can't | ||||
// encode this in the steps because the intermediate type depends on | // encode this in the steps because the intermediate type depends on | ||||
// arguments. Just special case here. | // arguments. Just special case here. | ||||
if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm) | if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm) | ||||
continue; | continue; | ||||
Show All 9 Lines | for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end(); | ||||
} | } | ||||
if (Current->getType() == types::TY_Nothing) | if (Current->getType() == types::TY_Nothing) | ||||
break; | break; | ||||
} | } | ||||
// If we ended with something, add to the output list. | // If we ended with something, add to the output list. | ||||
if (Current) | if (Current) | ||||
Actions.push_back(Current.release()); | Actions.push_back(std::move(Current)); | ||||
} | } | ||||
// Add a link action if necessary. | // Add a link action if necessary. | ||||
if (!LinkerInputs.empty()) | if (!LinkerInputs.empty()) | ||||
Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image)); | Actions.push_back( | ||||
std::make_shared<LinkJobAction>(LinkerInputs, types::TY_Image)); | |||||
// If we are linking, claim any options which are obviously only used for | // If we are linking, claim any options which are obviously only used for | ||||
// compilation. | // compilation. | ||||
if (FinalPhase == phases::Link && PL.size() == 1) { | if (FinalPhase == phases::Link && PL.size() == 1) { | ||||
Args.ClaimAllArgs(options::OPT_CompileOnly_Group); | Args.ClaimAllArgs(options::OPT_CompileOnly_Group); | ||||
Args.ClaimAllArgs(options::OPT_cl_compile_Group); | Args.ClaimAllArgs(options::OPT_cl_compile_Group); | ||||
} | } | ||||
// Claim ignored clang-cl options. | // Claim ignored clang-cl options. | ||||
Args.ClaimAllArgs(options::OPT_cl_ignored_Group); | Args.ClaimAllArgs(options::OPT_cl_ignored_Group); | ||||
// Claim --cuda-host-only arg which may be passed to non-CUDA | // Claim --cuda-host-only arg which may be passed to non-CUDA | ||||
// compilations and should not trigger warnings there. | // compilations and should not trigger warnings there. | ||||
Args.ClaimAllArgs(options::OPT_cuda_host_only); | Args.ClaimAllArgs(options::OPT_cuda_host_only); | ||||
} | } | ||||
std::unique_ptr<Action> | std::shared_ptr<Action> | ||||
Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, | Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, | ||||
phases::ID Phase, | phases::ID Phase, | ||||
std::unique_ptr<Action> Input) const { | std::shared_ptr<Action> Input) const { | ||||
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); | llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); | ||||
// Build the appropriate action. | // Build the appropriate action. | ||||
switch (Phase) { | switch (Phase) { | ||||
case phases::Link: | case phases::Link: | ||||
llvm_unreachable("link action invalid here."); | llvm_unreachable("link action invalid here."); | ||||
case phases::Preprocess: { | case phases::Preprocess: { | ||||
types::ID OutputTy; | types::ID OutputTy; | ||||
// -{M, MM} alter the output type. | // -{M, MM} alter the output type. | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | void Driver::BuildJobs(Compilation &C) const { | ||||
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | ||||
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); | Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); | ||||
// It is an error to provide a -o option if we are making multiple output | // It is an error to provide a -o option if we are making multiple output | ||||
// files. | // files. | ||||
if (FinalOutput) { | if (FinalOutput) { | ||||
unsigned NumOutputs = 0; | unsigned NumOutputs = 0; | ||||
for (const Action *A : C.getActions()) | for (const std::shared_ptr<Action> &A : C.getActions()) | ||||
if (A->getType() != types::TY_Nothing) | if (A->getType() != types::TY_Nothing) | ||||
++NumOutputs; | ++NumOutputs; | ||||
if (NumOutputs > 1) { | if (NumOutputs > 1) { | ||||
Diag(clang::diag::err_drv_output_argument_with_multiple_files); | Diag(clang::diag::err_drv_output_argument_with_multiple_files); | ||||
FinalOutput = nullptr; | FinalOutput = nullptr; | ||||
} | } | ||||
} | } | ||||
// Collect the list of architectures. | // Collect the list of architectures. | ||||
llvm::StringSet<> ArchNames; | llvm::StringSet<> ArchNames; | ||||
if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) | if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) | ||||
for (const Arg *A : C.getArgs()) | for (const Arg *A : C.getArgs()) | ||||
if (A->getOption().matches(options::OPT_arch)) | if (A->getOption().matches(options::OPT_arch)) | ||||
ArchNames.insert(A->getValue()); | ArchNames.insert(A->getValue()); | ||||
for (Action *A : C.getActions()) { | for (const std::shared_ptr<Action>& A : C.getActions()) { | ||||
// If we are linking an image for multiple archs then the linker wants | // If we are linking an image for multiple archs then the linker wants | ||||
// -arch_multiple and -final_output <final image name>. Unfortunately, this | // -arch_multiple and -final_output <final image name>. Unfortunately, this | ||||
// doesn't fit in cleanly because we have to pass this information down. | // doesn't fit in cleanly because we have to pass this information down. | ||||
// | // | ||||
// FIXME: This is a hack; find a cleaner way to integrate this into the | // FIXME: This is a hack; find a cleaner way to integrate this into the | ||||
// process. | // process. | ||||
const char *LinkingOutput = nullptr; | const char *LinkingOutput = nullptr; | ||||
if (isa<LipoJobAction>(A)) { | if (isa<LipoJobAction>(A)) { | ||||
if (FinalOutput) | if (FinalOutput) | ||||
LinkingOutput = FinalOutput->getValue(); | LinkingOutput = FinalOutput->getValue(); | ||||
else | else | ||||
LinkingOutput = getDefaultImageName(); | LinkingOutput = getDefaultImageName(); | ||||
} | } | ||||
InputInfo II; | InputInfo II; | ||||
BuildJobsForAction(C, A, &C.getDefaultToolChain(), | BuildJobsForAction(C, A.get(), &C.getDefaultToolChain(), | ||||
/*BoundArch*/ nullptr, | /*BoundArch*/ nullptr, | ||||
/*AtTopLevel*/ true, | /*AtTopLevel*/ true, | ||||
/*MultipleArchs*/ ArchNames.size() > 1, | /*MultipleArchs*/ ArchNames.size() > 1, | ||||
/*LinkingOutput*/ LinkingOutput, II); | /*LinkingOutput*/ LinkingOutput, II); | ||||
} | } | ||||
// If the user passed -Qunused-arguments or there were errors, don't warn | // If the user passed -Qunused-arguments or there were errors, don't warn | ||||
// about any unused arguments. | // about any unused arguments. | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | void Driver::BuildJobsForAction(Compilation &C, const Action *A, | ||||
const char *LinkingOutput, | const char *LinkingOutput, | ||||
InputInfo &Result) const { | InputInfo &Result) const { | ||||
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); | ||||
InputInfoList CudaDeviceInputInfos; | InputInfoList CudaDeviceInputInfos; | ||||
if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) { | if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) { | ||||
InputInfo II; | InputInfo II; | ||||
// Append outputs of device jobs to the input list. | // Append outputs of device jobs to the input list. | ||||
for (const Action *DA : CHA->getDeviceActions()) { | for (const std::shared_ptr<Action> &DA : CHA->getDeviceActions()) { | ||||
BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel, | BuildJobsForAction(C, DA.get(), TC, nullptr, AtTopLevel, | ||||
/*MultipleArchs*/ false, LinkingOutput, II); | /*MultipleArchs*/ false, LinkingOutput, II); | ||||
CudaDeviceInputInfos.push_back(II); | CudaDeviceInputInfos.push_back(II); | ||||
} | } | ||||
// Override current action with a real host compile action and continue | // Override current action with a real host compile action and continue | ||||
// processing it. | // processing it. | ||||
A = *CHA->begin(); | A = CHA->begin()->get(); | ||||
} | } | ||||
if (const InputAction *IA = dyn_cast<InputAction>(A)) { | if (const InputAction *IA = dyn_cast<InputAction>(A)) { | ||||
// FIXME: It would be nice to not claim this here; maybe the old scheme of | // FIXME: It would be nice to not claim this here; maybe the old scheme of | ||||
// just using Args was better? | // just using Args was better? | ||||
const Arg &Input = IA->getInputArg(); | const Arg &Input = IA->getInputArg(); | ||||
Input.claim(); | Input.claim(); | ||||
if (Input.getOption().matches(options::OPT_INPUT)) { | if (Input.getOption().matches(options::OPT_INPUT)) { | ||||
Show All 11 Lines | if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { | ||||
if (ArchName) | if (ArchName) | ||||
TC = &getToolChain( | TC = &getToolChain( | ||||
C.getArgs(), | C.getArgs(), | ||||
computeTargetTriple(DefaultTargetTriple, C.getArgs(), ArchName)); | computeTargetTriple(DefaultTargetTriple, C.getArgs(), ArchName)); | ||||
else | else | ||||
TC = &C.getDefaultToolChain(); | TC = &C.getDefaultToolChain(); | ||||
BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel, | BuildJobsForAction(C, BAA->begin()->get(), TC, ArchName, AtTopLevel, | ||||
MultipleArchs, LinkingOutput, Result); | MultipleArchs, LinkingOutput, Result); | ||||
return; | return; | ||||
} | } | ||||
if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) { | if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) { | ||||
// Initial processing of CudaDeviceAction carries host params. | // Initial processing of CudaDeviceAction carries host params. | ||||
// Call BuildJobsForAction() again, now with correct device parameters. | // Call BuildJobsForAction() again, now with correct device parameters. | ||||
assert(CDA->getGpuArchName() && "No GPU name in device action."); | assert(CDA->getGpuArchName() && "No GPU name in device action."); | ||||
BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(), | BuildJobsForAction(C, CDA->begin()->get(), C.getCudaDeviceToolChain(), | ||||
CDA->getGpuArchName(), CDA->isAtTopLevel(), | CDA->getGpuArchName(), CDA->isAtTopLevel(), | ||||
/*MultipleArchs*/ true, LinkingOutput, Result); | /*MultipleArchs*/ true, LinkingOutput, Result); | ||||
return; | return; | ||||
} | } | ||||
const ActionList *Inputs = &A->getInputs(); | const ActionList *Inputs = &A->getInputs(); | ||||
const JobAction *JA = cast<JobAction>(A); | const JobAction *JA = cast<JobAction>(A); | ||||
const CudaHostAction *CollapsedCHA = nullptr; | const CudaHostAction *CollapsedCHA = nullptr; | ||||
const Tool *T = | const Tool *T = | ||||
selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA); | selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA); | ||||
if (!T) | if (!T) | ||||
return; | return; | ||||
// If we've collapsed action list that contained CudaHostAction we | // If we've collapsed action list that contained CudaHostAction we | ||||
// need to build jobs for device-side inputs it may have held. | // need to build jobs for device-side inputs it may have held. | ||||
if (CollapsedCHA) { | if (CollapsedCHA) { | ||||
InputInfo II; | InputInfo II; | ||||
for (const Action *DA : CollapsedCHA->getDeviceActions()) { | for (const std::shared_ptr<Action> &DA : CollapsedCHA->getDeviceActions()) { | ||||
BuildJobsForAction(C, DA, TC, "", AtTopLevel, | BuildJobsForAction(C, DA.get(), TC, "", AtTopLevel, | ||||
/*MultipleArchs*/ false, LinkingOutput, II); | /*MultipleArchs*/ false, LinkingOutput, II); | ||||
CudaDeviceInputInfos.push_back(II); | CudaDeviceInputInfos.push_back(II); | ||||
} | } | ||||
} | } | ||||
// Only use pipes when there is exactly one input. | // Only use pipes when there is exactly one input. | ||||
InputInfoList InputInfos; | InputInfoList InputInfos; | ||||
for (const Action *Input : *Inputs) { | for (const std::shared_ptr<Action> &Input : *Inputs) { | ||||
// Treat dsymutil and verify sub-jobs as being at the top-level too, they | // Treat dsymutil and verify sub-jobs as being at the top-level too, they | ||||
// shouldn't get temporary output names. | // shouldn't get temporary output names. | ||||
// FIXME: Clean this up. | // FIXME: Clean this up. | ||||
bool SubJobAtTopLevel = false; | bool SubJobAtTopLevel = false; | ||||
if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A))) | if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A))) | ||||
SubJobAtTopLevel = true; | SubJobAtTopLevel = true; | ||||
InputInfo II; | InputInfo II; | ||||
BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, | BuildJobsForAction(C, Input.get(), TC, BoundArch, SubJobAtTopLevel, | ||||
LinkingOutput, II); | MultipleArchs, LinkingOutput, II); | ||||
InputInfos.push_back(II); | InputInfos.push_back(II); | ||||
} | } | ||||
// Always use the first input as the base input. | // Always use the first input as the base input. | ||||
const char *BaseInput = InputInfos[0].getBaseInput(); | const char *BaseInput = InputInfos[0].getBaseInput(); | ||||
// ... except dsymutil actions, which use their actual input as the base | // ... except dsymutil actions, which use their actual input as the base | ||||
// input. | // input. | ||||
▲ Show 20 Lines • Show All 508 Lines • Show Last 20 Lines |
unneeded {}