1 //===--- Types.cpp - Driver input & temporary type information ------------===// 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/Types.h" 10 #include "clang/Driver/Driver.h" 11 #include "clang/Driver/DriverDiagnostic.h" 12 #include "clang/Driver/Options.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/StringSwitch.h" 16 #include "llvm/Option/Arg.h" 17 #include <cassert> 18 #include <cstring> 19 20 using namespace clang::driver; 21 using namespace clang::driver::types; 22 23 struct TypeInfo { 24 const char *Name; 25 const char *TempSuffix; 26 ID PreprocessedType; 27 class PhasesBitSet { 28 unsigned Bits = 0; 29 30 public: 31 constexpr PhasesBitSet(std::initializer_list<phases::ID> Phases) { 32 for (auto Id : Phases) 33 Bits |= 1 << Id; 34 } 35 bool contains(phases::ID Id) const { return Bits & (1 << Id); } 36 } Phases; 37 }; 38 39 static constexpr TypeInfo TypeInfos[] = { 40 #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \ 41 { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, }, 42 #include "clang/Driver/Types.def" 43 #undef TYPE 44 }; 45 static const unsigned numTypes = std::size(TypeInfos); 46 47 static const TypeInfo &getInfo(unsigned id) { 48 assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); 49 return TypeInfos[id - 1]; 50 } 51 52 const char *types::getTypeName(ID Id) { 53 return getInfo(Id).Name; 54 } 55 56 types::ID types::getPreprocessedType(ID Id) { 57 ID PPT = getInfo(Id).PreprocessedType; 58 assert((getInfo(Id).Phases.contains(phases::Preprocess) != 59 (PPT == TY_INVALID)) && 60 "Unexpected Preprocess Type."); 61 return PPT; 62 } 63 64 static bool isPreprocessedModuleType(ID Id) { 65 return Id == TY_CXXModule || Id == TY_PP_CXXModule; 66 } 67 68 static bool isPreprocessedHeaderUnitType(ID Id) { 69 return Id == TY_CXXSHeader || Id == TY_CXXUHeader || Id == TY_CXXHUHeader || 70 Id == TY_PP_CXXHeaderUnit; 71 } 72 73 types::ID types::getPrecompiledType(ID Id) { 74 if (isPreprocessedModuleType(Id)) 75 return TY_ModuleFile; 76 if (isPreprocessedHeaderUnitType(Id)) 77 return TY_HeaderUnit; 78 if (onlyPrecompileType(Id)) 79 return TY_PCH; 80 return TY_INVALID; 81 } 82 83 const char *types::getTypeTempSuffix(ID Id, bool CLStyle) { 84 if (CLStyle) { 85 switch (Id) { 86 case TY_Object: 87 case TY_LTO_BC: 88 return "obj"; 89 case TY_Image: 90 return "exe"; 91 case TY_PP_Asm: 92 return "asm"; 93 default: 94 break; 95 } 96 } 97 return getInfo(Id).TempSuffix; 98 } 99 100 bool types::onlyPrecompileType(ID Id) { 101 return getInfo(Id).Phases.contains(phases::Precompile) && 102 !isPreprocessedModuleType(Id); 103 } 104 105 bool types::canTypeBeUserSpecified(ID Id) { 106 static const clang::driver::types::ID kStaticLangageTypes[] = { 107 TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader, 108 TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, 109 TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, 110 TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, 111 TY_Remap, TY_PCH, TY_Object, 112 TY_Image, TY_dSYM, TY_Dependencies, 113 TY_CUDA_FATBIN, TY_HIP_FATBIN}; 114 return !llvm::is_contained(kStaticLangageTypes, Id); 115 } 116 117 bool types::appendSuffixForType(ID Id) { 118 return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN || 119 Id == TY_HIP_FATBIN; 120 } 121 122 bool types::canLipoType(ID Id) { 123 return (Id == TY_Nothing || 124 Id == TY_Image || 125 Id == TY_Object || 126 Id == TY_LTO_BC); 127 } 128 129 bool types::isAcceptedByClang(ID Id) { 130 switch (Id) { 131 default: 132 return false; 133 134 case TY_Asm: 135 case TY_C: case TY_PP_C: 136 case TY_CL: case TY_PP_CL: case TY_CLCXX: case TY_PP_CLCXX: 137 case TY_CUDA: case TY_PP_CUDA: 138 case TY_CUDA_DEVICE: 139 case TY_HIP: 140 case TY_PP_HIP: 141 case TY_HIP_DEVICE: 142 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 143 case TY_CXX: case TY_PP_CXX: 144 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 145 case TY_CHeader: case TY_PP_CHeader: 146 case TY_CLHeader: 147 case TY_ObjCHeader: case TY_PP_ObjCHeader: 148 case TY_CXXHeader: case TY_PP_CXXHeader: 149 case TY_CXXSHeader: 150 case TY_CXXUHeader: 151 case TY_CXXHUHeader: 152 case TY_PP_CXXHeaderUnit: 153 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 154 case TY_CXXModule: case TY_PP_CXXModule: 155 case TY_AST: case TY_ModuleFile: case TY_PCH: 156 case TY_LLVM_IR: case TY_LLVM_BC: 157 case TY_API_INFO: 158 return true; 159 } 160 } 161 162 bool types::isAcceptedByFlang(ID Id) { 163 switch (Id) { 164 default: 165 return false; 166 167 case TY_Fortran: 168 case TY_PP_Fortran: 169 return true; 170 case TY_LLVM_IR: 171 case TY_LLVM_BC: 172 return true; 173 } 174 } 175 176 bool types::isDerivedFromC(ID Id) { 177 switch (Id) { 178 default: 179 return false; 180 181 case TY_PP_C: 182 case TY_C: 183 case TY_CL: 184 case TY_PP_CL: 185 case TY_CLCXX: 186 case TY_PP_CLCXX: 187 case TY_PP_CUDA: 188 case TY_CUDA: 189 case TY_CUDA_DEVICE: 190 case TY_PP_HIP: 191 case TY_HIP: 192 case TY_HIP_DEVICE: 193 case TY_PP_ObjC: 194 case TY_PP_ObjC_Alias: 195 case TY_ObjC: 196 case TY_PP_CXX: 197 case TY_CXX: 198 case TY_PP_ObjCXX: 199 case TY_PP_ObjCXX_Alias: 200 case TY_ObjCXX: 201 case TY_RenderScript: 202 case TY_PP_CHeader: 203 case TY_CHeader: 204 case TY_CLHeader: 205 case TY_PP_ObjCHeader: 206 case TY_ObjCHeader: 207 case TY_PP_CXXHeader: 208 case TY_CXXHeader: 209 case TY_PP_ObjCXXHeader: 210 case TY_ObjCXXHeader: 211 case TY_CXXModule: 212 case TY_PP_CXXModule: 213 return true; 214 } 215 } 216 217 bool types::isObjC(ID Id) { 218 switch (Id) { 219 default: 220 return false; 221 222 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 223 case TY_ObjCXX: case TY_PP_ObjCXX: 224 case TY_ObjCHeader: case TY_PP_ObjCHeader: 225 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias: 226 return true; 227 } 228 } 229 230 bool types::isOpenCL(ID Id) { return Id == TY_CL || Id == TY_CLCXX; } 231 232 bool types::isCXX(ID Id) { 233 switch (Id) { 234 default: 235 return false; 236 237 case TY_CXX: case TY_PP_CXX: 238 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 239 case TY_CXXHeader: case TY_PP_CXXHeader: 240 case TY_CXXSHeader: 241 case TY_CXXUHeader: 242 case TY_CXXHUHeader: 243 case TY_PP_CXXHeaderUnit: 244 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 245 case TY_CXXModule: 246 case TY_PP_CXXModule: 247 case TY_ModuleFile: 248 case TY_PP_CLCXX: 249 case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: 250 case TY_HIP: 251 case TY_PP_HIP: 252 case TY_HIP_DEVICE: 253 return true; 254 } 255 } 256 257 bool types::isLLVMIR(ID Id) { 258 switch (Id) { 259 default: 260 return false; 261 262 case TY_LLVM_IR: 263 case TY_LLVM_BC: 264 case TY_LTO_IR: 265 case TY_LTO_BC: 266 return true; 267 } 268 } 269 270 bool types::isCuda(ID Id) { 271 switch (Id) { 272 default: 273 return false; 274 275 case TY_CUDA: 276 case TY_PP_CUDA: 277 case TY_CUDA_DEVICE: 278 return true; 279 } 280 } 281 282 bool types::isHIP(ID Id) { 283 switch (Id) { 284 default: 285 return false; 286 287 case TY_HIP: 288 case TY_PP_HIP: 289 case TY_HIP_DEVICE: 290 return true; 291 } 292 } 293 294 bool types::isHLSL(ID Id) { return Id == TY_HLSL; } 295 296 bool types::isSrcFile(ID Id) { 297 return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; 298 } 299 300 types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { 301 return llvm::StringSwitch<types::ID>(Ext) 302 .Case("c", TY_C) 303 .Case("C", TY_CXX) 304 .Case("F", TY_Fortran) 305 .Case("f", TY_PP_Fortran) 306 .Case("h", TY_CHeader) 307 .Case("H", TY_CXXHeader) 308 .Case("i", TY_PP_C) 309 .Case("m", TY_ObjC) 310 .Case("M", TY_ObjCXX) 311 .Case("o", TY_Object) 312 .Case("S", TY_Asm) 313 .Case("s", TY_PP_Asm) 314 .Case("bc", TY_LLVM_BC) 315 .Case("cc", TY_CXX) 316 .Case("CC", TY_CXX) 317 .Case("cl", TY_CL) 318 .Case("cli", TY_PP_CL) 319 .Case("clcpp", TY_CLCXX) 320 .Case("clii", TY_PP_CLCXX) 321 .Case("cp", TY_CXX) 322 .Case("cu", TY_CUDA) 323 .Case("hh", TY_CXXHeader) 324 .Case("ii", TY_PP_CXX) 325 .Case("ll", TY_LLVM_IR) 326 .Case("mi", TY_PP_ObjC) 327 .Case("mm", TY_ObjCXX) 328 .Case("rs", TY_RenderScript) 329 .Case("adb", TY_Ada) 330 .Case("ads", TY_Ada) 331 .Case("asm", TY_PP_Asm) 332 .Case("ast", TY_AST) 333 .Case("ccm", TY_CXXModule) 334 .Case("cpp", TY_CXX) 335 .Case("CPP", TY_CXX) 336 .Case("c++", TY_CXX) 337 .Case("C++", TY_CXX) 338 .Case("cui", TY_PP_CUDA) 339 .Case("cxx", TY_CXX) 340 .Case("CXX", TY_CXX) 341 .Case("F03", TY_Fortran) 342 .Case("f03", TY_PP_Fortran) 343 .Case("F08", TY_Fortran) 344 .Case("f08", TY_PP_Fortran) 345 .Case("F90", TY_Fortran) 346 .Case("f90", TY_PP_Fortran) 347 .Case("F95", TY_Fortran) 348 .Case("f95", TY_PP_Fortran) 349 .Case("for", TY_PP_Fortran) 350 .Case("FOR", TY_PP_Fortran) 351 .Case("fpp", TY_Fortran) 352 .Case("FPP", TY_Fortran) 353 .Case("gch", TY_PCH) 354 .Case("hip", TY_HIP) 355 .Case("hipi", TY_PP_HIP) 356 .Case("hpp", TY_CXXHeader) 357 .Case("hxx", TY_CXXHeader) 358 .Case("iim", TY_PP_CXXModule) 359 .Case("iih", TY_PP_CXXHeaderUnit) 360 .Case("lib", TY_Object) 361 .Case("mii", TY_PP_ObjCXX) 362 .Case("obj", TY_Object) 363 .Case("ifs", TY_IFS) 364 .Case("pch", TY_PCH) 365 .Case("pcm", TY_ModuleFile) 366 .Case("c++m", TY_CXXModule) 367 .Case("cppm", TY_CXXModule) 368 .Case("cxxm", TY_CXXModule) 369 .Case("hlsl", TY_HLSL) 370 .Default(TY_INVALID); 371 } 372 373 types::ID types::lookupTypeForTypeSpecifier(const char *Name) { 374 for (unsigned i=0; i<numTypes; ++i) { 375 types::ID Id = (types::ID) (i + 1); 376 if (canTypeBeUserSpecified(Id) && 377 strcmp(Name, getInfo(Id).Name) == 0) 378 return Id; 379 } 380 // Accept "cu" as an alias for "cuda" for NVCC compatibility 381 if (strcmp(Name, "cu") == 0) { 382 return types::TY_CUDA; 383 } 384 return TY_INVALID; 385 } 386 387 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 388 types::getCompilationPhases(ID Id, phases::ID LastPhase) { 389 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> P; 390 const auto &Info = getInfo(Id); 391 for (int I = 0; I <= LastPhase; ++I) 392 if (Info.Phases.contains(static_cast<phases::ID>(I))) 393 P.push_back(static_cast<phases::ID>(I)); 394 assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); 395 return P; 396 } 397 398 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 399 types::getCompilationPhases(const clang::driver::Driver &Driver, 400 llvm::opt::DerivedArgList &DAL, ID Id) { 401 return types::getCompilationPhases(Id, Driver.getFinalPhase(DAL)); 402 } 403 404 ID types::lookupCXXTypeForCType(ID Id) { 405 switch (Id) { 406 default: 407 return Id; 408 409 case types::TY_C: 410 return types::TY_CXX; 411 case types::TY_PP_C: 412 return types::TY_PP_CXX; 413 case types::TY_CHeader: 414 return types::TY_CXXHeader; 415 case types::TY_PP_CHeader: 416 return types::TY_PP_CXXHeader; 417 } 418 } 419 420 ID types::lookupHeaderTypeForSourceType(ID Id) { 421 switch (Id) { 422 default: 423 return Id; 424 425 // FIXME: Handle preprocessed input types. 426 case types::TY_C: 427 return types::TY_CHeader; 428 case types::TY_CXX: 429 case types::TY_CXXModule: 430 return types::TY_CXXHeader; 431 case types::TY_ObjC: 432 return types::TY_ObjCHeader; 433 case types::TY_ObjCXX: 434 return types::TY_ObjCXXHeader; 435 case types::TY_CL: 436 case types::TY_CLCXX: 437 return types::TY_CLHeader; 438 } 439 } 440