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