1 //===--- Types.cpp - Driver input & temporary type information ----------*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/Driver/Types.h" 11 12 #include <string.h> 13 #include <cassert> 14 15 using namespace clang::driver; 16 using namespace clang::driver::types; 17 18 struct Info { 19 const char *Name; 20 const char *Flags; 21 const char *TempSuffix; 22 ID PreprocessedType; 23 }; 24 25 static Info TypeInfos[] = { 26 #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \ 27 { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, }, 28 #include "clang/Driver/Types.def" 29 #undef TYPE 30 }; 31 static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]); 32 33 static Info &getInfo(unsigned id) { 34 assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); 35 return TypeInfos[id - 1]; 36 } 37 38 const char *types::getTypeName(ID Id) { 39 return getInfo(Id).Name; 40 } 41 42 types::ID types::getPreprocessedType(ID Id) { 43 return getInfo(Id).PreprocessedType; 44 } 45 46 const char *types::getTypeTempSuffix(ID Id) { 47 return getInfo(Id).TempSuffix; 48 } 49 50 bool types::onlyAssembleType(ID Id) { 51 return strchr(getInfo(Id).Flags, 'a'); 52 } 53 54 bool types::onlyPrecompileType(ID Id) { 55 return strchr(getInfo(Id).Flags, 'p'); 56 } 57 58 bool types::canTypeBeUserSpecified(ID Id) { 59 return strchr(getInfo(Id).Flags, 'u'); 60 } 61 62 bool types::appendSuffixForType(ID Id) { 63 return strchr(getInfo(Id).Flags, 'A'); 64 } 65 66 bool types::canLipoType(ID Id) { 67 return (Id == TY_Nothing || 68 Id == TY_Image || 69 Id == TY_Object); 70 } 71 72 bool types::isAcceptedByClang(ID Id) { 73 switch (Id) { 74 default: 75 return false; 76 77 case TY_Asm: 78 case TY_C: case TY_PP_C: 79 case TY_ObjC: case TY_PP_ObjC: 80 case TY_CXX: case TY_PP_CXX: 81 case TY_ObjCXX: case TY_PP_ObjCXX: 82 case TY_CHeader: case TY_PP_CHeader: 83 case TY_ObjCHeader: case TY_PP_ObjCHeader: 84 case TY_CXXHeader: case TY_PP_CXXHeader: 85 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 86 return true; 87 } 88 } 89 90 bool types::isCXX(ID Id) { 91 switch (Id) { 92 default: 93 return false; 94 95 case TY_CXX: case TY_PP_CXX: 96 case TY_ObjCXX: case TY_PP_ObjCXX: 97 case TY_CXXHeader: case TY_PP_CXXHeader: 98 case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: 99 return true; 100 } 101 } 102 103 types::ID types::lookupTypeForExtension(const char *Ext) { 104 unsigned N = strlen(Ext); 105 106 switch (N) { 107 case 1: 108 if (memcmp(Ext, "c", 1) == 0) return TY_C; 109 if (memcmp(Ext, "i", 1) == 0) return TY_PP_C; 110 if (memcmp(Ext, "m", 1) == 0) return TY_ObjC; 111 if (memcmp(Ext, "M", 1) == 0) return TY_ObjCXX; 112 if (memcmp(Ext, "h", 1) == 0) return TY_CHeader; 113 if (memcmp(Ext, "C", 1) == 0) return TY_CXX; 114 if (memcmp(Ext, "H", 1) == 0) return TY_CXXHeader; 115 if (memcmp(Ext, "f", 1) == 0) return TY_PP_Fortran; 116 if (memcmp(Ext, "F", 1) == 0) return TY_Fortran; 117 if (memcmp(Ext, "s", 1) == 0) return TY_PP_Asm; 118 if (memcmp(Ext, "S", 1) == 0) return TY_Asm; 119 case 2: 120 if (memcmp(Ext, "ii", 2) == 0) return TY_PP_CXX; 121 if (memcmp(Ext, "mi", 2) == 0) return TY_PP_ObjC; 122 if (memcmp(Ext, "mm", 2) == 0) return TY_ObjCXX; 123 if (memcmp(Ext, "cc", 2) == 0) return TY_CXX; 124 if (memcmp(Ext, "cc", 2) == 0) return TY_CXX; 125 if (memcmp(Ext, "cp", 2) == 0) return TY_CXX; 126 if (memcmp(Ext, "hh", 2) == 0) return TY_CXXHeader; 127 break; 128 case 3: 129 if (memcmp(Ext, "ads", 3) == 0) return TY_Ada; 130 if (memcmp(Ext, "adb", 3) == 0) return TY_Ada; 131 if (memcmp(Ext, "cxx", 3) == 0) return TY_CXX; 132 if (memcmp(Ext, "cpp", 3) == 0) return TY_CXX; 133 if (memcmp(Ext, "CPP", 3) == 0) return TY_CXX; 134 if (memcmp(Ext, "cXX", 3) == 0) return TY_CXX; 135 if (memcmp(Ext, "for", 3) == 0) return TY_PP_Fortran; 136 if (memcmp(Ext, "FOR", 3) == 0) return TY_PP_Fortran; 137 if (memcmp(Ext, "fpp", 3) == 0) return TY_Fortran; 138 if (memcmp(Ext, "FPP", 3) == 0) return TY_Fortran; 139 if (memcmp(Ext, "f90", 3) == 0) return TY_PP_Fortran; 140 if (memcmp(Ext, "f95", 3) == 0) return TY_PP_Fortran; 141 if (memcmp(Ext, "F90", 3) == 0) return TY_Fortran; 142 if (memcmp(Ext, "F95", 3) == 0) return TY_Fortran; 143 if (memcmp(Ext, "mii", 3) == 0) return TY_PP_ObjCXX; 144 break; 145 } 146 147 return TY_INVALID; 148 } 149 150 types::ID types::lookupTypeForTypeSpecifier(const char *Name) { 151 unsigned N = strlen(Name); 152 153 for (unsigned i=0; i<numTypes; ++i) { 154 types::ID Id = (types::ID) (i + 1); 155 if (canTypeBeUserSpecified(Id) && 156 memcmp(Name, getInfo(Id).Name, N + 1) == 0) 157 return Id; 158 } 159 160 return TY_INVALID; 161 } 162 163 // FIXME: Why don't we just put this list in the defs file, eh. 164 165 unsigned types::getNumCompilationPhases(ID Id) { 166 if (Id == TY_Object) 167 return 1; 168 169 unsigned N = 0; 170 if (getPreprocessedType(Id) != TY_INVALID) 171 N += 1; 172 173 if (onlyAssembleType(Id)) 174 return N + 2; // assemble, link 175 if (onlyPrecompileType(Id)) 176 return N + 1; // precompile 177 178 return N + 3; // compile, assemble, link 179 } 180 181 phases::ID types::getCompilationPhase(ID Id, unsigned N) { 182 assert(N < getNumCompilationPhases(Id) && "Invalid index."); 183 184 if (Id == TY_Object) 185 return phases::Link; 186 187 if (getPreprocessedType(Id) != TY_INVALID) { 188 if (N == 0) 189 return phases::Preprocess; 190 --N; 191 } 192 193 if (onlyAssembleType(Id)) 194 return N == 0 ? phases::Assemble : phases::Link; 195 196 if (onlyPrecompileType(Id)) 197 return phases::Precompile; 198 199 if (N == 0) 200 return phases::Compile; 201 if (N == 1) 202 return phases::Assemble; 203 204 return phases::Link; 205 } 206