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