1 //===- Action.h - Abstract compilation steps --------------------*- C++ -*-===// 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 #ifndef LLVM_CLANG_DRIVER_ACTION_H 10 #define LLVM_CLANG_DRIVER_ACTION_H 11 12 #include "clang/Basic/LLVM.h" 13 #include "clang/Driver/Types.h" 14 #include "clang/Driver/Util.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/iterator_range.h" 20 #include <string> 21 22 namespace llvm { 23 namespace opt { 24 25 class Arg; 26 27 } // namespace opt 28 } // namespace llvm 29 30 namespace clang { 31 namespace driver { 32 33 class ToolChain; 34 35 /// Action - Represent an abstract compilation step to perform. 36 /// 37 /// An action represents an edge in the compilation graph; typically 38 /// it is a job to transform an input using some tool. 39 /// 40 /// The current driver is hard wired to expect actions which produce a 41 /// single primary output, at least in terms of controlling the 42 /// compilation. Actions can produce auxiliary files, but can only 43 /// produce a single output to feed into subsequent actions. 44 /// 45 /// Actions are usually owned by a Compilation, which creates new 46 /// actions via MakeAction(). 47 class Action { 48 public: 49 using size_type = ActionList::size_type; 50 using input_iterator = ActionList::iterator; 51 using input_const_iterator = ActionList::const_iterator; 52 using input_range = llvm::iterator_range<input_iterator>; 53 using input_const_range = llvm::iterator_range<input_const_iterator>; 54 55 enum ActionClass { 56 InputClass = 0, 57 BindArchClass, 58 OffloadClass, 59 PreprocessJobClass, 60 PrecompileJobClass, 61 HeaderModulePrecompileJobClass, 62 AnalyzeJobClass, 63 MigrateJobClass, 64 CompileJobClass, 65 BackendJobClass, 66 AssembleJobClass, 67 LinkJobClass, 68 IfsMergeJobClass, 69 LipoJobClass, 70 DsymutilJobClass, 71 VerifyDebugInfoJobClass, 72 VerifyPCHJobClass, 73 OffloadBundlingJobClass, 74 OffloadUnbundlingJobClass, 75 OffloadWrapperJobClass, 76 StaticLibJobClass, 77 78 JobClassFirst = PreprocessJobClass, 79 JobClassLast = StaticLibJobClass 80 }; 81 82 // The offloading kind determines if this action is binded to a particular 83 // programming model. Each entry reserves one bit. We also have a special kind 84 // to designate the host offloading tool chain. 85 enum OffloadKind { 86 OFK_None = 0x00, 87 88 // The host offloading tool chain. 89 OFK_Host = 0x01, 90 91 // The device offloading tool chains - one bit for each programming model. 92 OFK_Cuda = 0x02, 93 OFK_OpenMP = 0x04, 94 OFK_HIP = 0x08, 95 }; 96 97 static const char *getClassName(ActionClass AC); 98 99 private: 100 ActionClass Kind; 101 102 /// The output type of this action. 103 types::ID Type; 104 105 ActionList Inputs; 106 107 /// Flag that is set to true if this action can be collapsed with others 108 /// actions that depend on it. This is true by default and set to false when 109 /// the action is used by two different tool chains, which is enabled by the 110 /// offloading support implementation. 111 bool CanBeCollapsedWithNextDependentAction = true; 112 113 protected: 114 /// 115 /// Offload information. 116 /// 117 118 /// The host offloading kind - a combination of kinds encoded in a mask. 119 /// Multiple programming models may be supported simultaneously by the same 120 /// host. 121 unsigned ActiveOffloadKindMask = 0u; 122 123 /// Offloading kind of the device. 124 OffloadKind OffloadingDeviceKind = OFK_None; 125 126 /// The Offloading architecture associated with this action. 127 const char *OffloadingArch = nullptr; 128 129 Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {} 130 Action(ActionClass Kind, Action *Input, types::ID Type) 131 : Action(Kind, ActionList({Input}), Type) {} 132 Action(ActionClass Kind, Action *Input) 133 : Action(Kind, ActionList({Input}), Input->getType()) {} 134 Action(ActionClass Kind, const ActionList &Inputs, types::ID Type) 135 : Kind(Kind), Type(Type), Inputs(Inputs) {} 136 137 public: 138 virtual ~Action(); 139 140 const char *getClassName() const { return Action::getClassName(getKind()); } 141 142 ActionClass getKind() const { return Kind; } 143 types::ID getType() const { return Type; } 144 145 ActionList &getInputs() { return Inputs; } 146 const ActionList &getInputs() const { return Inputs; } 147 148 size_type size() const { return Inputs.size(); } 149 150 input_iterator input_begin() { return Inputs.begin(); } 151 input_iterator input_end() { return Inputs.end(); } 152 input_range inputs() { return input_range(input_begin(), input_end()); } 153 input_const_iterator input_begin() const { return Inputs.begin(); } 154 input_const_iterator input_end() const { return Inputs.end(); } 155 input_const_range inputs() const { 156 return input_const_range(input_begin(), input_end()); 157 } 158 159 /// Mark this action as not legal to collapse. 160 void setCannotBeCollapsedWithNextDependentAction() { 161 CanBeCollapsedWithNextDependentAction = false; 162 } 163 164 /// Return true if this function can be collapsed with others. 165 bool isCollapsingWithNextDependentActionLegal() const { 166 return CanBeCollapsedWithNextDependentAction; 167 } 168 169 /// Return a string containing the offload kind of the action. 170 std::string getOffloadingKindPrefix() const; 171 172 /// Return a string that can be used as prefix in order to generate unique 173 /// files for each offloading kind. By default, no prefix is used for 174 /// non-device kinds, except if \a CreatePrefixForHost is set. 175 static std::string 176 GetOffloadingFileNamePrefix(OffloadKind Kind, 177 StringRef NormalizedTriple, 178 bool CreatePrefixForHost = false); 179 180 /// Return a string containing a offload kind name. 181 static StringRef GetOffloadKindName(OffloadKind Kind); 182 183 /// Set the device offload info of this action and propagate it to its 184 /// dependences. 185 void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch); 186 187 /// Append the host offload info of this action and propagate it to its 188 /// dependences. 189 void propagateHostOffloadInfo(unsigned OKinds, const char *OArch); 190 191 /// Set the offload info of this action to be the same as the provided action, 192 /// and propagate it to its dependences. 193 void propagateOffloadInfo(const Action *A); 194 195 unsigned getOffloadingHostActiveKinds() const { 196 return ActiveOffloadKindMask; 197 } 198 199 OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; } 200 const char *getOffloadingArch() const { return OffloadingArch; } 201 202 /// Check if this action have any offload kinds. Note that host offload kinds 203 /// are only set if the action is a dependence to a host offload action. 204 bool isHostOffloading(OffloadKind OKind) const { 205 return ActiveOffloadKindMask & OKind; 206 } 207 bool isDeviceOffloading(OffloadKind OKind) const { 208 return OffloadingDeviceKind == OKind; 209 } 210 bool isOffloading(OffloadKind OKind) const { 211 return isHostOffloading(OKind) || isDeviceOffloading(OKind); 212 } 213 }; 214 215 class InputAction : public Action { 216 const llvm::opt::Arg &Input; 217 std::string Id; 218 virtual void anchor(); 219 220 public: 221 InputAction(const llvm::opt::Arg &Input, types::ID Type, 222 StringRef Id = StringRef()); 223 224 const llvm::opt::Arg &getInputArg() const { return Input; } 225 226 void setId(StringRef _Id) { Id = _Id.str(); } 227 StringRef getId() const { return Id; } 228 229 static bool classof(const Action *A) { 230 return A->getKind() == InputClass; 231 } 232 }; 233 234 class BindArchAction : public Action { 235 virtual void anchor(); 236 237 /// The architecture to bind, or 0 if the default architecture 238 /// should be bound. 239 StringRef ArchName; 240 241 public: 242 BindArchAction(Action *Input, StringRef ArchName); 243 244 StringRef getArchName() const { return ArchName; } 245 246 static bool classof(const Action *A) { 247 return A->getKind() == BindArchClass; 248 } 249 }; 250 251 /// An offload action combines host or/and device actions according to the 252 /// programming model implementation needs and propagates the offloading kind to 253 /// its dependences. 254 class OffloadAction final : public Action { 255 virtual void anchor(); 256 257 public: 258 /// Type used to communicate device actions. It associates bound architecture, 259 /// toolchain, and offload kind to each action. 260 class DeviceDependences final { 261 public: 262 using ToolChainList = SmallVector<const ToolChain *, 3>; 263 using BoundArchList = SmallVector<const char *, 3>; 264 using OffloadKindList = SmallVector<OffloadKind, 3>; 265 266 private: 267 // Lists that keep the information for each dependency. All the lists are 268 // meant to be updated in sync. We are adopting separate lists instead of a 269 // list of structs, because that simplifies forwarding the actions list to 270 // initialize the inputs of the base Action class. 271 272 /// The dependence actions. 273 ActionList DeviceActions; 274 275 /// The offloading toolchains that should be used with the action. 276 ToolChainList DeviceToolChains; 277 278 /// The architectures that should be used with this action. 279 BoundArchList DeviceBoundArchs; 280 281 /// The offload kind of each dependence. 282 OffloadKindList DeviceOffloadKinds; 283 284 public: 285 /// Add a action along with the associated toolchain, bound arch, and 286 /// offload kind. 287 void add(Action &A, const ToolChain &TC, const char *BoundArch, 288 OffloadKind OKind); 289 290 /// Get each of the individual arrays. 291 const ActionList &getActions() const { return DeviceActions; } 292 const ToolChainList &getToolChains() const { return DeviceToolChains; } 293 const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; } 294 const OffloadKindList &getOffloadKinds() const { 295 return DeviceOffloadKinds; 296 } 297 }; 298 299 /// Type used to communicate host actions. It associates bound architecture, 300 /// toolchain, and offload kinds to the host action. 301 class HostDependence final { 302 /// The dependence action. 303 Action &HostAction; 304 305 /// The offloading toolchain that should be used with the action. 306 const ToolChain &HostToolChain; 307 308 /// The architectures that should be used with this action. 309 const char *HostBoundArch = nullptr; 310 311 /// The offload kind of each dependence. 312 unsigned HostOffloadKinds = 0u; 313 314 public: 315 HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, 316 const unsigned OffloadKinds) 317 : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch), 318 HostOffloadKinds(OffloadKinds) {} 319 320 /// Constructor version that obtains the offload kinds from the device 321 /// dependencies. 322 HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, 323 const DeviceDependences &DDeps); 324 Action *getAction() const { return &HostAction; } 325 const ToolChain *getToolChain() const { return &HostToolChain; } 326 const char *getBoundArch() const { return HostBoundArch; } 327 unsigned getOffloadKinds() const { return HostOffloadKinds; } 328 }; 329 330 using OffloadActionWorkTy = 331 llvm::function_ref<void(Action *, const ToolChain *, const char *)>; 332 333 private: 334 /// The host offloading toolchain that should be used with the action. 335 const ToolChain *HostTC = nullptr; 336 337 /// The tool chains associated with the list of actions. 338 DeviceDependences::ToolChainList DevToolChains; 339 340 public: 341 OffloadAction(const HostDependence &HDep); 342 OffloadAction(const DeviceDependences &DDeps, types::ID Ty); 343 OffloadAction(const HostDependence &HDep, const DeviceDependences &DDeps); 344 345 /// Execute the work specified in \a Work on the host dependence. 346 void doOnHostDependence(const OffloadActionWorkTy &Work) const; 347 348 /// Execute the work specified in \a Work on each device dependence. 349 void doOnEachDeviceDependence(const OffloadActionWorkTy &Work) const; 350 351 /// Execute the work specified in \a Work on each dependence. 352 void doOnEachDependence(const OffloadActionWorkTy &Work) const; 353 354 /// Execute the work specified in \a Work on each host or device dependence if 355 /// \a IsHostDependenceto is true or false, respectively. 356 void doOnEachDependence(bool IsHostDependence, 357 const OffloadActionWorkTy &Work) const; 358 359 /// Return true if the action has a host dependence. 360 bool hasHostDependence() const; 361 362 /// Return the host dependence of this action. This function is only expected 363 /// to be called if the host dependence exists. 364 Action *getHostDependence() const; 365 366 /// Return true if the action has a single device dependence. If \a 367 /// DoNotConsiderHostActions is set, ignore the host dependence, if any, while 368 /// accounting for the number of dependences. 369 bool hasSingleDeviceDependence(bool DoNotConsiderHostActions = false) const; 370 371 /// Return the single device dependence of this action. This function is only 372 /// expected to be called if a single device dependence exists. If \a 373 /// DoNotConsiderHostActions is set, a host dependence is allowed. 374 Action * 375 getSingleDeviceDependence(bool DoNotConsiderHostActions = false) const; 376 377 static bool classof(const Action *A) { return A->getKind() == OffloadClass; } 378 }; 379 380 class JobAction : public Action { 381 virtual void anchor(); 382 383 protected: 384 JobAction(ActionClass Kind, Action *Input, types::ID Type); 385 JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); 386 387 public: 388 static bool classof(const Action *A) { 389 return (A->getKind() >= JobClassFirst && 390 A->getKind() <= JobClassLast); 391 } 392 }; 393 394 class PreprocessJobAction : public JobAction { 395 void anchor() override; 396 397 public: 398 PreprocessJobAction(Action *Input, types::ID OutputType); 399 400 static bool classof(const Action *A) { 401 return A->getKind() == PreprocessJobClass; 402 } 403 }; 404 405 class PrecompileJobAction : public JobAction { 406 void anchor() override; 407 408 protected: 409 PrecompileJobAction(ActionClass Kind, Action *Input, types::ID OutputType); 410 411 public: 412 PrecompileJobAction(Action *Input, types::ID OutputType); 413 414 static bool classof(const Action *A) { 415 return A->getKind() == PrecompileJobClass || 416 A->getKind() == HeaderModulePrecompileJobClass; 417 } 418 }; 419 420 class HeaderModulePrecompileJobAction : public PrecompileJobAction { 421 void anchor() override; 422 423 const char *ModuleName; 424 425 public: 426 HeaderModulePrecompileJobAction(Action *Input, types::ID OutputType, 427 const char *ModuleName); 428 429 static bool classof(const Action *A) { 430 return A->getKind() == HeaderModulePrecompileJobClass; 431 } 432 433 void addModuleHeaderInput(Action *Input) { 434 getInputs().push_back(Input); 435 } 436 437 const char *getModuleName() const { return ModuleName; } 438 }; 439 440 class AnalyzeJobAction : public JobAction { 441 void anchor() override; 442 443 public: 444 AnalyzeJobAction(Action *Input, types::ID OutputType); 445 446 static bool classof(const Action *A) { 447 return A->getKind() == AnalyzeJobClass; 448 } 449 }; 450 451 class MigrateJobAction : public JobAction { 452 void anchor() override; 453 454 public: 455 MigrateJobAction(Action *Input, types::ID OutputType); 456 457 static bool classof(const Action *A) { 458 return A->getKind() == MigrateJobClass; 459 } 460 }; 461 462 class CompileJobAction : public JobAction { 463 void anchor() override; 464 465 public: 466 CompileJobAction(Action *Input, types::ID OutputType); 467 468 static bool classof(const Action *A) { 469 return A->getKind() == CompileJobClass; 470 } 471 }; 472 473 class BackendJobAction : public JobAction { 474 void anchor() override; 475 476 public: 477 BackendJobAction(Action *Input, types::ID OutputType); 478 479 static bool classof(const Action *A) { 480 return A->getKind() == BackendJobClass; 481 } 482 }; 483 484 class AssembleJobAction : public JobAction { 485 void anchor() override; 486 487 public: 488 AssembleJobAction(Action *Input, types::ID OutputType); 489 490 static bool classof(const Action *A) { 491 return A->getKind() == AssembleJobClass; 492 } 493 }; 494 495 class IfsMergeJobAction : public JobAction { 496 void anchor() override; 497 498 public: 499 IfsMergeJobAction(ActionList &Inputs, types::ID Type); 500 501 static bool classof(const Action *A) { 502 return A->getKind() == IfsMergeJobClass; 503 } 504 }; 505 506 class LinkJobAction : public JobAction { 507 void anchor() override; 508 509 public: 510 LinkJobAction(ActionList &Inputs, types::ID Type); 511 512 static bool classof(const Action *A) { 513 return A->getKind() == LinkJobClass; 514 } 515 }; 516 517 class LipoJobAction : public JobAction { 518 void anchor() override; 519 520 public: 521 LipoJobAction(ActionList &Inputs, types::ID Type); 522 523 static bool classof(const Action *A) { 524 return A->getKind() == LipoJobClass; 525 } 526 }; 527 528 class DsymutilJobAction : public JobAction { 529 void anchor() override; 530 531 public: 532 DsymutilJobAction(ActionList &Inputs, types::ID Type); 533 534 static bool classof(const Action *A) { 535 return A->getKind() == DsymutilJobClass; 536 } 537 }; 538 539 class VerifyJobAction : public JobAction { 540 void anchor() override; 541 542 public: 543 VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); 544 545 static bool classof(const Action *A) { 546 return A->getKind() == VerifyDebugInfoJobClass || 547 A->getKind() == VerifyPCHJobClass; 548 } 549 }; 550 551 class VerifyDebugInfoJobAction : public VerifyJobAction { 552 void anchor() override; 553 554 public: 555 VerifyDebugInfoJobAction(Action *Input, types::ID Type); 556 557 static bool classof(const Action *A) { 558 return A->getKind() == VerifyDebugInfoJobClass; 559 } 560 }; 561 562 class VerifyPCHJobAction : public VerifyJobAction { 563 void anchor() override; 564 565 public: 566 VerifyPCHJobAction(Action *Input, types::ID Type); 567 568 static bool classof(const Action *A) { 569 return A->getKind() == VerifyPCHJobClass; 570 } 571 }; 572 573 class OffloadBundlingJobAction : public JobAction { 574 void anchor() override; 575 576 public: 577 // Offloading bundling doesn't change the type of output. 578 OffloadBundlingJobAction(ActionList &Inputs); 579 580 static bool classof(const Action *A) { 581 return A->getKind() == OffloadBundlingJobClass; 582 } 583 }; 584 585 class OffloadUnbundlingJobAction final : public JobAction { 586 void anchor() override; 587 588 public: 589 /// Type that provides information about the actions that depend on this 590 /// unbundling action. 591 struct DependentActionInfo final { 592 /// The tool chain of the dependent action. 593 const ToolChain *DependentToolChain = nullptr; 594 595 /// The bound architecture of the dependent action. 596 StringRef DependentBoundArch; 597 598 /// The offload kind of the dependent action. 599 const OffloadKind DependentOffloadKind = OFK_None; 600 601 DependentActionInfo(const ToolChain *DependentToolChain, 602 StringRef DependentBoundArch, 603 const OffloadKind DependentOffloadKind) 604 : DependentToolChain(DependentToolChain), 605 DependentBoundArch(DependentBoundArch), 606 DependentOffloadKind(DependentOffloadKind) {} 607 }; 608 609 private: 610 /// Container that keeps information about each dependence of this unbundling 611 /// action. 612 SmallVector<DependentActionInfo, 6> DependentActionInfoArray; 613 614 public: 615 // Offloading unbundling doesn't change the type of output. 616 OffloadUnbundlingJobAction(Action *Input); 617 618 /// Register information about a dependent action. 619 void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch, 620 OffloadKind Kind) { 621 DependentActionInfoArray.push_back({TC, BoundArch, Kind}); 622 } 623 624 /// Return the information about all depending actions. 625 ArrayRef<DependentActionInfo> getDependentActionsInfo() const { 626 return DependentActionInfoArray; 627 } 628 629 static bool classof(const Action *A) { 630 return A->getKind() == OffloadUnbundlingJobClass; 631 } 632 }; 633 634 class OffloadWrapperJobAction : public JobAction { 635 void anchor() override; 636 637 public: 638 OffloadWrapperJobAction(ActionList &Inputs, types::ID Type); 639 640 static bool classof(const Action *A) { 641 return A->getKind() == OffloadWrapperJobClass; 642 } 643 }; 644 645 class StaticLibJobAction : public JobAction { 646 void anchor() override; 647 648 public: 649 StaticLibJobAction(ActionList &Inputs, types::ID Type); 650 651 static bool classof(const Action *A) { 652 return A->getKind() == StaticLibJobClass; 653 } 654 }; 655 656 } // namespace driver 657 } // namespace clang 658 659 #endif // LLVM_CLANG_DRIVER_ACTION_H 660