1 //===- Action.cpp - Abstract compilation steps ----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Driver/Action.h" 10 #include "llvm/Support/ErrorHandling.h" 11 #include <cassert> 12 #include <string> 13 14 using namespace clang; 15 using namespace driver; 16 using namespace llvm::opt; 17 18 Action::~Action() = default; 19 20 const char *Action::getClassName(ActionClass AC) { 21 switch (AC) { 22 case InputClass: return "input"; 23 case BindArchClass: return "bind-arch"; 24 case OffloadClass: 25 return "offload"; 26 case PreprocessJobClass: return "preprocessor"; 27 case PrecompileJobClass: return "precompiler"; 28 case HeaderModulePrecompileJobClass: return "header-module-precompiler"; 29 case ExtractAPIJobClass: 30 return "api-extractor"; 31 case AnalyzeJobClass: return "analyzer"; 32 case MigrateJobClass: return "migrator"; 33 case CompileJobClass: return "compiler"; 34 case BackendJobClass: return "backend"; 35 case AssembleJobClass: return "assembler"; 36 case IfsMergeJobClass: return "interface-stub-merger"; 37 case LinkJobClass: return "linker"; 38 case LipoJobClass: return "lipo"; 39 case DsymutilJobClass: return "dsymutil"; 40 case VerifyDebugInfoJobClass: return "verify-debug-info"; 41 case VerifyPCHJobClass: return "verify-pch"; 42 case OffloadBundlingJobClass: 43 return "clang-offload-bundler"; 44 case OffloadUnbundlingJobClass: 45 return "clang-offload-unbundler"; 46 case OffloadWrapperJobClass: 47 return "clang-offload-wrapper"; 48 case LinkerWrapperJobClass: 49 return "clang-linker-wrapper"; 50 case StaticLibJobClass: 51 return "static-lib-linker"; 52 } 53 54 llvm_unreachable("invalid class"); 55 } 56 57 void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) { 58 // Offload action set its own kinds on their dependences. 59 if (Kind == OffloadClass) 60 return; 61 // Unbundling actions use the host kinds. 62 if (Kind == OffloadUnbundlingJobClass) 63 return; 64 65 assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) && 66 "Setting device kind to a different device??"); 67 assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??"); 68 OffloadingDeviceKind = OKind; 69 OffloadingArch = OArch; 70 71 for (auto *A : Inputs) 72 A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch); 73 } 74 75 void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) { 76 // Offload action set its own kinds on their dependences. 77 if (Kind == OffloadClass) 78 return; 79 80 assert(OffloadingDeviceKind == OFK_None && 81 "Setting a host kind in a device action."); 82 ActiveOffloadKindMask |= OKinds; 83 OffloadingArch = OArch; 84 85 for (auto *A : Inputs) 86 A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch); 87 } 88 89 void Action::propagateOffloadInfo(const Action *A) { 90 if (unsigned HK = A->getOffloadingHostActiveKinds()) 91 propagateHostOffloadInfo(HK, A->getOffloadingArch()); 92 else 93 propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(), 94 A->getOffloadingArch()); 95 } 96 97 std::string Action::getOffloadingKindPrefix() const { 98 switch (OffloadingDeviceKind) { 99 case OFK_None: 100 break; 101 case OFK_Host: 102 llvm_unreachable("Host kind is not an offloading device kind."); 103 break; 104 case OFK_Cuda: 105 return "device-cuda"; 106 case OFK_OpenMP: 107 return "device-openmp"; 108 case OFK_HIP: 109 return "device-hip"; 110 111 // TODO: Add other programming models here. 112 } 113 114 if (!ActiveOffloadKindMask) 115 return {}; 116 117 std::string Res("host"); 118 assert(!((ActiveOffloadKindMask & OFK_Cuda) && 119 (ActiveOffloadKindMask & OFK_HIP)) && 120 "Cannot offload CUDA and HIP at the same time"); 121 if (ActiveOffloadKindMask & OFK_Cuda) 122 Res += "-cuda"; 123 if (ActiveOffloadKindMask & OFK_HIP) 124 Res += "-hip"; 125 if (ActiveOffloadKindMask & OFK_OpenMP) 126 Res += "-openmp"; 127 128 // TODO: Add other programming models here. 129 130 return Res; 131 } 132 133 /// Return a string that can be used as prefix in order to generate unique files 134 /// for each offloading kind. 135 std::string 136 Action::GetOffloadingFileNamePrefix(OffloadKind Kind, 137 StringRef NormalizedTriple, 138 bool CreatePrefixForHost) { 139 // Don't generate prefix for host actions unless required. 140 if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host)) 141 return {}; 142 143 std::string Res("-"); 144 Res += GetOffloadKindName(Kind); 145 Res += "-"; 146 Res += NormalizedTriple; 147 return Res; 148 } 149 150 /// Return a string with the offload kind name. If that is not defined, we 151 /// assume 'host'. 152 StringRef Action::GetOffloadKindName(OffloadKind Kind) { 153 switch (Kind) { 154 case OFK_None: 155 case OFK_Host: 156 return "host"; 157 case OFK_Cuda: 158 return "cuda"; 159 case OFK_OpenMP: 160 return "openmp"; 161 case OFK_HIP: 162 return "hip"; 163 164 // TODO: Add other programming models here. 165 } 166 167 llvm_unreachable("invalid offload kind"); 168 } 169 170 void InputAction::anchor() {} 171 172 InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id) 173 : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {} 174 175 void BindArchAction::anchor() {} 176 177 BindArchAction::BindArchAction(Action *Input, StringRef ArchName) 178 : Action(BindArchClass, Input), ArchName(ArchName) {} 179 180 void OffloadAction::anchor() {} 181 182 OffloadAction::OffloadAction(const HostDependence &HDep) 183 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) { 184 OffloadingArch = HDep.getBoundArch(); 185 ActiveOffloadKindMask = HDep.getOffloadKinds(); 186 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(), 187 HDep.getBoundArch()); 188 } 189 190 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty) 191 : Action(OffloadClass, DDeps.getActions(), Ty), 192 DevToolChains(DDeps.getToolChains()) { 193 auto &OKinds = DDeps.getOffloadKinds(); 194 auto &BArchs = DDeps.getBoundArchs(); 195 196 // If all inputs agree on the same kind, use it also for this action. 197 if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); })) 198 OffloadingDeviceKind = OKinds.front(); 199 200 // If we have a single dependency, inherit the architecture from it. 201 if (OKinds.size() == 1) 202 OffloadingArch = BArchs.front(); 203 204 // Propagate info to the dependencies. 205 for (unsigned i = 0, e = getInputs().size(); i != e; ++i) 206 getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]); 207 } 208 209 OffloadAction::OffloadAction(const HostDependence &HDep, 210 const DeviceDependences &DDeps) 211 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()), 212 DevToolChains(DDeps.getToolChains()) { 213 // We use the kinds of the host dependence for this action. 214 OffloadingArch = HDep.getBoundArch(); 215 ActiveOffloadKindMask = HDep.getOffloadKinds(); 216 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(), 217 HDep.getBoundArch()); 218 219 // Add device inputs and propagate info to the device actions. Do work only if 220 // we have dependencies. 221 for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i) 222 if (auto *A = DDeps.getActions()[i]) { 223 getInputs().push_back(A); 224 A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i], 225 DDeps.getBoundArchs()[i]); 226 } 227 } 228 229 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const { 230 if (!HostTC) 231 return; 232 assert(!getInputs().empty() && "No dependencies for offload action??"); 233 auto *A = getInputs().front(); 234 Work(A, HostTC, A->getOffloadingArch()); 235 } 236 237 void OffloadAction::doOnEachDeviceDependence( 238 const OffloadActionWorkTy &Work) const { 239 auto I = getInputs().begin(); 240 auto E = getInputs().end(); 241 if (I == E) 242 return; 243 244 // We expect to have the same number of input dependences and device tool 245 // chains, except if we also have a host dependence. In that case we have one 246 // more dependence than we have device tool chains. 247 assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) && 248 "Sizes of action dependences and toolchains are not consistent!"); 249 250 // Skip host action 251 if (HostTC) 252 ++I; 253 254 auto TI = DevToolChains.begin(); 255 for (; I != E; ++I, ++TI) 256 Work(*I, *TI, (*I)->getOffloadingArch()); 257 } 258 259 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const { 260 doOnHostDependence(Work); 261 doOnEachDeviceDependence(Work); 262 } 263 264 void OffloadAction::doOnEachDependence(bool IsHostDependence, 265 const OffloadActionWorkTy &Work) const { 266 if (IsHostDependence) 267 doOnHostDependence(Work); 268 else 269 doOnEachDeviceDependence(Work); 270 } 271 272 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; } 273 274 Action *OffloadAction::getHostDependence() const { 275 assert(hasHostDependence() && "Host dependence does not exist!"); 276 assert(!getInputs().empty() && "No dependencies for offload action??"); 277 return HostTC ? getInputs().front() : nullptr; 278 } 279 280 bool OffloadAction::hasSingleDeviceDependence( 281 bool DoNotConsiderHostActions) const { 282 if (DoNotConsiderHostActions) 283 return getInputs().size() == (HostTC ? 2 : 1); 284 return !HostTC && getInputs().size() == 1; 285 } 286 287 Action * 288 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const { 289 assert(hasSingleDeviceDependence(DoNotConsiderHostActions) && 290 "Single device dependence does not exist!"); 291 // The previous assert ensures the number of entries in getInputs() is 292 // consistent with what we are doing here. 293 return HostTC ? getInputs()[1] : getInputs().front(); 294 } 295 296 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC, 297 const char *BoundArch, 298 OffloadKind OKind) { 299 DeviceActions.push_back(&A); 300 DeviceToolChains.push_back(&TC); 301 DeviceBoundArchs.push_back(BoundArch); 302 DeviceOffloadKinds.push_back(OKind); 303 } 304 305 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC, 306 const char *BoundArch, 307 const DeviceDependences &DDeps) 308 : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) { 309 for (auto K : DDeps.getOffloadKinds()) 310 HostOffloadKinds |= K; 311 } 312 313 void JobAction::anchor() {} 314 315 JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) 316 : Action(Kind, Input, Type) {} 317 318 JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) 319 : Action(Kind, Inputs, Type) {} 320 321 void PreprocessJobAction::anchor() {} 322 323 PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) 324 : JobAction(PreprocessJobClass, Input, OutputType) {} 325 326 void PrecompileJobAction::anchor() {} 327 328 PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) 329 : JobAction(PrecompileJobClass, Input, OutputType) {} 330 331 PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input, 332 types::ID OutputType) 333 : JobAction(Kind, Input, OutputType) { 334 assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind"); 335 } 336 337 void HeaderModulePrecompileJobAction::anchor() {} 338 339 HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction( 340 Action *Input, types::ID OutputType, const char *ModuleName) 341 : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType), 342 ModuleName(ModuleName) {} 343 344 void ExtractAPIJobAction::anchor() {} 345 346 ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType) 347 : JobAction(ExtractAPIJobClass, Inputs, OutputType) {} 348 349 void AnalyzeJobAction::anchor() {} 350 351 AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) 352 : JobAction(AnalyzeJobClass, Input, OutputType) {} 353 354 void MigrateJobAction::anchor() {} 355 356 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) 357 : JobAction(MigrateJobClass, Input, OutputType) {} 358 359 void CompileJobAction::anchor() {} 360 361 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) 362 : JobAction(CompileJobClass, Input, OutputType) {} 363 364 void BackendJobAction::anchor() {} 365 366 BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType) 367 : JobAction(BackendJobClass, Input, OutputType) {} 368 369 void AssembleJobAction::anchor() {} 370 371 AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) 372 : JobAction(AssembleJobClass, Input, OutputType) {} 373 374 void IfsMergeJobAction::anchor() {} 375 376 IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type) 377 : JobAction(IfsMergeJobClass, Inputs, Type) {} 378 379 void LinkJobAction::anchor() {} 380 381 LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type) 382 : JobAction(LinkJobClass, Inputs, Type) {} 383 384 void LipoJobAction::anchor() {} 385 386 LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type) 387 : JobAction(LipoJobClass, Inputs, Type) {} 388 389 void DsymutilJobAction::anchor() {} 390 391 DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) 392 : JobAction(DsymutilJobClass, Inputs, Type) {} 393 394 void VerifyJobAction::anchor() {} 395 396 VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input, 397 types::ID Type) 398 : JobAction(Kind, Input, Type) { 399 assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && 400 "ActionClass is not a valid VerifyJobAction"); 401 } 402 403 void VerifyDebugInfoJobAction::anchor() {} 404 405 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input, 406 types::ID Type) 407 : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {} 408 409 void VerifyPCHJobAction::anchor() {} 410 411 VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type) 412 : VerifyJobAction(VerifyPCHJobClass, Input, Type) {} 413 414 void OffloadBundlingJobAction::anchor() {} 415 416 OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs) 417 : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {} 418 419 void OffloadUnbundlingJobAction::anchor() {} 420 421 OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input) 422 : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {} 423 424 void OffloadWrapperJobAction::anchor() {} 425 426 OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs, 427 types::ID Type) 428 : JobAction(OffloadWrapperJobClass, Inputs, Type) {} 429 430 void LinkerWrapperJobAction::anchor() {} 431 432 LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs, 433 types::ID Type) 434 : JobAction(LinkerWrapperJobClass, Inputs, Type) {} 435 436 void StaticLibJobAction::anchor() {} 437 438 StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type) 439 : JobAction(StaticLibJobClass, Inputs, Type) {} 440