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