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 "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/StringSwitch.h" 12 #include "llvm/ADT/SmallVector.h" 13 #include <cassert> 14 #include <cstring> 15 16 using namespace clang::driver; 17 using namespace clang::driver::types; 18 19 struct TypeInfo { 20 const char *Name; 21 const char *Flags; 22 const char *TempSuffix; 23 ID PreprocessedType; 24 const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases; 25 }; 26 27 static const TypeInfo TypeInfos[] = { 28 #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS, ...) \ 29 { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, }, 30 #include "clang/Driver/Types.def" 31 #undef TYPE 32 }; 33 static const unsigned numTypes = llvm::array_lengthof(TypeInfos); 34 35 static const TypeInfo &getInfo(unsigned id) { 36 assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); 37 return TypeInfos[id - 1]; 38 } 39 40 const char *types::getTypeName(ID Id) { 41 return getInfo(Id).Name; 42 } 43 44 types::ID types::getPreprocessedType(ID Id) { 45 ID PPT = getInfo(Id).PreprocessedType; 46 assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) != 47 (PPT == TY_INVALID)) && 48 "Unexpected Preprocess Type."); 49 return PPT; 50 } 51 52 static bool isPrepeocessedModuleType(ID Id) { 53 return Id == TY_CXXModule || Id == TY_PP_CXXModule; 54 } 55 56 types::ID types::getPrecompiledType(ID Id) { 57 if (isPrepeocessedModuleType(Id)) 58 return TY_ModuleFile; 59 if (onlyPrecompileType(Id)) 60 return TY_PCH; 61 return TY_INVALID; 62 } 63 64 const char *types::getTypeTempSuffix(ID Id, bool CLMode) { 65 if (CLMode) { 66 switch (Id) { 67 case TY_Object: 68 case TY_LTO_BC: 69 return "obj"; 70 case TY_Image: 71 return "exe"; 72 case TY_PP_Asm: 73 return "asm"; 74 default: 75 break; 76 } 77 } 78 return getInfo(Id).TempSuffix; 79 } 80 81 bool types::onlyAssembleType(ID Id) { 82 return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) && 83 !llvm::is_contained(getInfo(Id).Phases, phases::Compile) && 84 !llvm::is_contained(getInfo(Id).Phases, phases::Backend); 85 } 86 87 bool types::onlyPrecompileType(ID Id) { 88 return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) && 89 !isPrepeocessedModuleType(Id); 90 } 91 92 bool types::canTypeBeUserSpecified(ID Id) { 93 return strchr(getInfo(Id).Flags, 'u'); 94 } 95 96 bool types::appendSuffixForType(ID Id) { 97 return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN || 98 Id == TY_HIP_FATBIN; 99 } 100 101 bool types::canLipoType(ID Id) { 102 return (Id == TY_Nothing || 103 Id == TY_Image || 104 Id == TY_Object || 105 Id == TY_LTO_BC); 106 } 107 108 bool types::isAcceptedByClang(ID Id) { 109 switch (Id) { 110 default: 111 return false; 112 113 case TY_Asm: 114 case TY_C: case TY_PP_C: 115 case TY_CL: 116 case TY_CUDA: case TY_PP_CUDA: 117 case TY_CUDA_DEVICE: 118 case TY_HIP: 119 case TY_PP_HIP: 120 case TY_HIP_DEVICE: 121 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 122 case TY_CXX: case TY_PP_CXX: 123 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 124 case TY_CHeader: case TY_PP_CHeader: 125 case TY_CLHeader: 126 case TY_ObjCHeader: case TY_PP_ObjCHeader: 127 case TY_CXXHeader: case TY_PP_CXXHeader: 128 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 129 case TY_CXXModule: case TY_PP_CXXModule: 130 case TY_AST: case TY_ModuleFile: 131 case TY_LLVM_IR: case TY_LLVM_BC: 132 return true; 133 } 134 } 135 136 bool types::isObjC(ID Id) { 137 switch (Id) { 138 default: 139 return false; 140 141 case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: 142 case TY_ObjCXX: case TY_PP_ObjCXX: 143 case TY_ObjCHeader: case TY_PP_ObjCHeader: 144 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias: 145 return true; 146 } 147 } 148 149 bool types::isCXX(ID Id) { 150 switch (Id) { 151 default: 152 return false; 153 154 case TY_CXX: case TY_PP_CXX: 155 case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: 156 case TY_CXXHeader: case TY_PP_CXXHeader: 157 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 158 case TY_CXXModule: case TY_PP_CXXModule: 159 case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: 160 case TY_HIP: 161 case TY_PP_HIP: 162 case TY_HIP_DEVICE: 163 return true; 164 } 165 } 166 167 bool types::isLLVMIR(ID Id) { 168 switch (Id) { 169 default: 170 return false; 171 172 case TY_LLVM_IR: 173 case TY_LLVM_BC: 174 case TY_LTO_IR: 175 case TY_LTO_BC: 176 return true; 177 } 178 } 179 180 bool types::isCuda(ID Id) { 181 switch (Id) { 182 default: 183 return false; 184 185 case TY_CUDA: 186 case TY_PP_CUDA: 187 case TY_CUDA_DEVICE: 188 return true; 189 } 190 } 191 192 bool types::isHIP(ID Id) { 193 switch (Id) { 194 default: 195 return false; 196 197 case TY_HIP: 198 case TY_PP_HIP: 199 case TY_HIP_DEVICE: 200 return true; 201 } 202 } 203 204 bool types::isSrcFile(ID Id) { 205 return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; 206 } 207 208 types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { 209 return llvm::StringSwitch<types::ID>(Ext) 210 .Case("c", TY_C) 211 .Case("C", TY_CXX) 212 .Case("F", TY_Fortran) 213 .Case("f", TY_PP_Fortran) 214 .Case("h", TY_CHeader) 215 .Case("H", TY_CXXHeader) 216 .Case("i", TY_PP_C) 217 .Case("m", TY_ObjC) 218 .Case("M", TY_ObjCXX) 219 .Case("o", TY_Object) 220 .Case("S", TY_Asm) 221 .Case("s", TY_PP_Asm) 222 .Case("bc", TY_LLVM_BC) 223 .Case("cc", TY_CXX) 224 .Case("CC", TY_CXX) 225 .Case("cl", TY_CL) 226 .Case("cp", TY_CXX) 227 .Case("cu", TY_CUDA) 228 .Case("hh", TY_CXXHeader) 229 .Case("ii", TY_PP_CXX) 230 .Case("ll", TY_LLVM_IR) 231 .Case("mi", TY_PP_ObjC) 232 .Case("mm", TY_ObjCXX) 233 .Case("rs", TY_RenderScript) 234 .Case("adb", TY_Ada) 235 .Case("ads", TY_Ada) 236 .Case("asm", TY_PP_Asm) 237 .Case("ast", TY_AST) 238 .Case("ccm", TY_CXXModule) 239 .Case("cpp", TY_CXX) 240 .Case("CPP", TY_CXX) 241 .Case("c++", TY_CXX) 242 .Case("C++", TY_CXX) 243 .Case("cui", TY_PP_CUDA) 244 .Case("cxx", TY_CXX) 245 .Case("CXX", TY_CXX) 246 .Case("F90", TY_Fortran) 247 .Case("f90", TY_PP_Fortran) 248 .Case("F95", TY_Fortran) 249 .Case("f95", TY_PP_Fortran) 250 .Case("for", TY_PP_Fortran) 251 .Case("FOR", TY_PP_Fortran) 252 .Case("fpp", TY_Fortran) 253 .Case("FPP", TY_Fortran) 254 .Case("gch", TY_PCH) 255 .Case("hip", TY_HIP) 256 .Case("hpp", TY_CXXHeader) 257 .Case("iim", TY_PP_CXXModule) 258 .Case("lib", TY_Object) 259 .Case("mii", TY_PP_ObjCXX) 260 .Case("obj", TY_Object) 261 .Case("pch", TY_PCH) 262 .Case("pcm", TY_ModuleFile) 263 .Case("c++m", TY_CXXModule) 264 .Case("cppm", TY_CXXModule) 265 .Case("cxxm", TY_CXXModule) 266 .Default(TY_INVALID); 267 } 268 269 types::ID types::lookupTypeForTypeSpecifier(const char *Name) { 270 for (unsigned i=0; i<numTypes; ++i) { 271 types::ID Id = (types::ID) (i + 1); 272 if (canTypeBeUserSpecified(Id) && 273 strcmp(Name, getInfo(Id).Name) == 0) 274 return Id; 275 } 276 277 return TY_INVALID; 278 } 279 280 // FIXME: Why don't we just put this list in the defs file, eh. 281 // FIXME: The list is now in Types.def but for now this function will verify 282 // the old behavior and a subsequent change will delete most of the body. 283 void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) { 284 P = getInfo(Id).Phases; 285 assert(0 < P.size() && "Not enough phases in list"); 286 assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); 287 } 288 289 ID types::lookupCXXTypeForCType(ID Id) { 290 switch (Id) { 291 default: 292 return Id; 293 294 case types::TY_C: 295 return types::TY_CXX; 296 case types::TY_PP_C: 297 return types::TY_PP_CXX; 298 case types::TY_CHeader: 299 return types::TY_CXXHeader; 300 case types::TY_PP_CHeader: 301 return types::TY_PP_CXXHeader; 302 } 303 } 304 305 ID types::lookupHeaderTypeForSourceType(ID Id) { 306 switch (Id) { 307 default: 308 return Id; 309 310 // FIXME: Handle preprocessed input types. 311 case types::TY_C: 312 return types::TY_CHeader; 313 case types::TY_CXX: 314 case types::TY_CXXModule: 315 return types::TY_CXXHeader; 316 case types::TY_ObjC: 317 return types::TY_ObjCHeader; 318 case types::TY_ObjCXX: 319 return types::TY_ObjCXXHeader; 320 case types::TY_CL: 321 return types::TY_CLHeader; 322 } 323 } 324