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