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