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 = llvm::array_lengthof(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 types::ID types::getPrecompiledType(ID Id) { 69 if (isPreprocessedModuleType(Id)) 70 return TY_ModuleFile; 71 if (onlyPrecompileType(Id)) 72 return TY_PCH; 73 return TY_INVALID; 74 } 75 76 const char *types::getTypeTempSuffix(ID Id, bool CLMode) { 77 if (CLMode) { 78 switch (Id) { 79 case TY_Object: 80 case TY_LTO_BC: 81 return "obj"; 82 case TY_Image: 83 return "exe"; 84 case TY_PP_Asm: 85 return "asm"; 86 default: 87 break; 88 } 89 } 90 return getInfo(Id).TempSuffix; 91 } 92 93 bool types::onlyPrecompileType(ID Id) { 94 return getInfo(Id).Phases.contains(phases::Precompile) && 95 !isPreprocessedModuleType(Id); 96 } 97 98 bool types::canTypeBeUserSpecified(ID Id) { 99 static const clang::driver::types::ID kStaticLangageTypes[] = { 100 TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader, 101 TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, 102 TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, 103 TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, 104 TY_Remap, TY_PCH, TY_Object, 105 TY_Image, TY_dSYM, TY_Dependencies, 106 TY_CUDA_FATBIN, TY_HIP_FATBIN}; 107 return !llvm::is_contained(kStaticLangageTypes, Id); 108 } 109 110 bool types::appendSuffixForType(ID Id) { 111 return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN || 112 Id == TY_HIP_FATBIN; 113 } 114 115 bool types::canLipoType(ID Id) { 116 return (Id == TY_Nothing || 117 Id == TY_Image || 118 Id == TY_Object || 119 Id == TY_LTO_BC); 120 } 121 122 bool types::isAcceptedByClang(ID Id) { 123 switch (Id) { 124 default: 125 return false; 126 127 case TY_Asm: 128 case TY_C: case TY_PP_C: 129 case TY_CL: case TY_CLCXX: 130 case TY_CUDA: case TY_PP_CUDA: 131 case TY_CUDA_DEVICE: 132 case TY_HIP: 133 case TY_PP_HIP: 134 case TY_HIP_DEVICE: 135 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 136 case TY_CXX: case TY_PP_CXX: 137 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 138 case TY_CHeader: case TY_PP_CHeader: 139 case TY_CLHeader: 140 case TY_ObjCHeader: case TY_PP_ObjCHeader: 141 case TY_CXXHeader: case TY_PP_CXXHeader: 142 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 143 case TY_CXXModule: case TY_PP_CXXModule: 144 case TY_AST: case TY_ModuleFile: case TY_PCH: 145 case TY_LLVM_IR: case TY_LLVM_BC: 146 return true; 147 } 148 } 149 150 bool types::isObjC(ID Id) { 151 switch (Id) { 152 default: 153 return false; 154 155 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 156 case TY_ObjCXX: case TY_PP_ObjCXX: 157 case TY_ObjCHeader: case TY_PP_ObjCHeader: 158 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias: 159 return true; 160 } 161 } 162 163 bool types::isOpenCL(ID Id) { return Id == TY_CL || Id == TY_CLCXX; } 164 165 bool types::isCXX(ID Id) { 166 switch (Id) { 167 default: 168 return false; 169 170 case TY_CXX: case TY_PP_CXX: 171 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 172 case TY_CXXHeader: case TY_PP_CXXHeader: 173 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 174 case TY_CXXModule: case TY_PP_CXXModule: 175 case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: 176 case TY_HIP: 177 case TY_PP_HIP: 178 case TY_HIP_DEVICE: 179 return true; 180 } 181 } 182 183 bool types::isLLVMIR(ID Id) { 184 switch (Id) { 185 default: 186 return false; 187 188 case TY_LLVM_IR: 189 case TY_LLVM_BC: 190 case TY_LTO_IR: 191 case TY_LTO_BC: 192 return true; 193 } 194 } 195 196 bool types::isCuda(ID Id) { 197 switch (Id) { 198 default: 199 return false; 200 201 case TY_CUDA: 202 case TY_PP_CUDA: 203 case TY_CUDA_DEVICE: 204 return true; 205 } 206 } 207 208 bool types::isHIP(ID Id) { 209 switch (Id) { 210 default: 211 return false; 212 213 case TY_HIP: 214 case TY_PP_HIP: 215 case TY_HIP_DEVICE: 216 return true; 217 } 218 } 219 220 bool types::isFortran(ID Id) { 221 switch (Id) { 222 default: 223 return false; 224 225 case TY_Fortran: case TY_PP_Fortran: 226 return true; 227 } 228 } 229 230 bool types::isSrcFile(ID Id) { 231 return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; 232 } 233 234 types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { 235 return llvm::StringSwitch<types::ID>(Ext) 236 .Case("c", TY_C) 237 .Case("C", TY_CXX) 238 .Case("F", TY_Fortran) 239 .Case("f", TY_PP_Fortran) 240 .Case("h", TY_CHeader) 241 .Case("H", TY_CXXHeader) 242 .Case("i", TY_PP_C) 243 .Case("m", TY_ObjC) 244 .Case("M", TY_ObjCXX) 245 .Case("o", TY_Object) 246 .Case("S", TY_Asm) 247 .Case("s", TY_PP_Asm) 248 .Case("bc", TY_LLVM_BC) 249 .Case("cc", TY_CXX) 250 .Case("CC", TY_CXX) 251 .Case("cl", TY_CL) 252 .Case("clcpp", TY_CLCXX) 253 .Case("cp", TY_CXX) 254 .Case("cu", TY_CUDA) 255 .Case("hh", TY_CXXHeader) 256 .Case("ii", TY_PP_CXX) 257 .Case("ll", TY_LLVM_IR) 258 .Case("mi", TY_PP_ObjC) 259 .Case("mm", TY_ObjCXX) 260 .Case("rs", TY_RenderScript) 261 .Case("adb", TY_Ada) 262 .Case("ads", TY_Ada) 263 .Case("asm", TY_PP_Asm) 264 .Case("ast", TY_AST) 265 .Case("ccm", TY_CXXModule) 266 .Case("cpp", TY_CXX) 267 .Case("CPP", TY_CXX) 268 .Case("c++", TY_CXX) 269 .Case("C++", TY_CXX) 270 .Case("cui", TY_PP_CUDA) 271 .Case("cxx", TY_CXX) 272 .Case("CXX", TY_CXX) 273 .Case("F90", TY_Fortran) 274 .Case("f90", TY_PP_Fortran) 275 .Case("F95", TY_Fortran) 276 .Case("f95", TY_PP_Fortran) 277 .Case("for", TY_PP_Fortran) 278 .Case("FOR", TY_PP_Fortran) 279 .Case("fpp", TY_Fortran) 280 .Case("FPP", TY_Fortran) 281 .Case("gch", TY_PCH) 282 .Case("hip", TY_HIP) 283 .Case("hpp", TY_CXXHeader) 284 .Case("hxx", TY_CXXHeader) 285 .Case("iim", TY_PP_CXXModule) 286 .Case("lib", TY_Object) 287 .Case("mii", TY_PP_ObjCXX) 288 .Case("obj", TY_Object) 289 .Case("ifs", TY_IFS) 290 .Case("pch", TY_PCH) 291 .Case("pcm", TY_ModuleFile) 292 .Case("c++m", TY_CXXModule) 293 .Case("cppm", TY_CXXModule) 294 .Case("cxxm", TY_CXXModule) 295 .Default(TY_INVALID); 296 } 297 298 types::ID types::lookupTypeForTypeSpecifier(const char *Name) { 299 for (unsigned i=0; i<numTypes; ++i) { 300 types::ID Id = (types::ID) (i + 1); 301 if (canTypeBeUserSpecified(Id) && 302 strcmp(Name, getInfo(Id).Name) == 0) 303 return Id; 304 } 305 // Accept "cu" as an alias for "cuda" for NVCC compatibility 306 if (strcmp(Name, "cu") == 0) { 307 return types::TY_CUDA; 308 } 309 return TY_INVALID; 310 } 311 312 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 313 types::getCompilationPhases(ID Id, phases::ID LastPhase) { 314 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> P; 315 const auto &Info = getInfo(Id); 316 for (int I = 0; I <= LastPhase; ++I) 317 if (Info.Phases.contains(static_cast<phases::ID>(I))) 318 P.push_back(static_cast<phases::ID>(I)); 319 assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); 320 return P; 321 } 322 323 llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> 324 types::getCompilationPhases(const clang::driver::Driver &Driver, 325 llvm::opt::DerivedArgList &DAL, ID Id) { 326 phases::ID LastPhase; 327 328 // Filter to compiler mode. When the compiler is run as a preprocessor then 329 // compilation is not an option. 330 // -S runs the compiler in Assembly listing mode. 331 if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) || 332 DAL.getLastArg(options::OPT__SLASH_EP) || 333 DAL.getLastArg(options::OPT_M, options::OPT_MM) || 334 DAL.getLastArg(options::OPT__SLASH_P)) 335 LastPhase = phases::Preprocess; 336 337 // --precompile only runs up to precompilation. 338 // This is a clang extension and is not compatible with GCC. 339 else if (DAL.getLastArg(options::OPT__precompile)) 340 LastPhase = phases::Precompile; 341 342 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. 343 else if (DAL.getLastArg(options::OPT_fsyntax_only) || 344 DAL.getLastArg(options::OPT_print_supported_cpus) || 345 DAL.getLastArg(options::OPT_module_file_info) || 346 DAL.getLastArg(options::OPT_verify_pch) || 347 DAL.getLastArg(options::OPT_rewrite_objc) || 348 DAL.getLastArg(options::OPT_rewrite_legacy_objc) || 349 DAL.getLastArg(options::OPT__migrate) || 350 DAL.getLastArg(options::OPT__analyze) || 351 DAL.getLastArg(options::OPT_emit_ast)) 352 LastPhase = phases::Compile; 353 354 else if (DAL.getLastArg(options::OPT_S) || 355 DAL.getLastArg(options::OPT_emit_llvm)) 356 LastPhase = phases::Backend; 357 358 else if (DAL.getLastArg(options::OPT_c)) 359 LastPhase = phases::Assemble; 360 361 // Generally means, do every phase until Link. 362 else 363 LastPhase = phases::LastPhase; 364 365 return types::getCompilationPhases(Id, LastPhase); 366 } 367 368 ID types::lookupCXXTypeForCType(ID Id) { 369 switch (Id) { 370 default: 371 return Id; 372 373 case types::TY_C: 374 return types::TY_CXX; 375 case types::TY_PP_C: 376 return types::TY_PP_CXX; 377 case types::TY_CHeader: 378 return types::TY_CXXHeader; 379 case types::TY_PP_CHeader: 380 return types::TY_PP_CXXHeader; 381 } 382 } 383 384 ID types::lookupHeaderTypeForSourceType(ID Id) { 385 switch (Id) { 386 default: 387 return Id; 388 389 // FIXME: Handle preprocessed input types. 390 case types::TY_C: 391 return types::TY_CHeader; 392 case types::TY_CXX: 393 case types::TY_CXXModule: 394 return types::TY_CXXHeader; 395 case types::TY_ObjC: 396 return types::TY_ObjCHeader; 397 case types::TY_ObjCXX: 398 return types::TY_ObjCXXHeader; 399 case types::TY_CL: 400 case types::TY_CLCXX: 401 return types::TY_CLHeader; 402 } 403 } 404