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   case TY_AST:
87     return true;
88   }
89 }
90 
91 bool types::isCXX(ID Id) {
92   switch (Id) {
93   default:
94     return false;
95 
96   case TY_CXX: case TY_PP_CXX:
97   case TY_ObjCXX: case TY_PP_ObjCXX:
98   case TY_CXXHeader: case TY_PP_CXXHeader:
99   case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
100     return true;
101   }
102 }
103 
104 types::ID types::lookupTypeForExtension(const char *Ext) {
105   unsigned N = strlen(Ext);
106 
107   switch (N) {
108   case 1:
109     if (memcmp(Ext, "c", 1) == 0) return TY_C;
110     if (memcmp(Ext, "i", 1) == 0) return TY_PP_C;
111     if (memcmp(Ext, "m", 1) == 0) return TY_ObjC;
112     if (memcmp(Ext, "M", 1) == 0) return TY_ObjCXX;
113     if (memcmp(Ext, "h", 1) == 0) return TY_CHeader;
114     if (memcmp(Ext, "C", 1) == 0) return TY_CXX;
115     if (memcmp(Ext, "H", 1) == 0) return TY_CXXHeader;
116     if (memcmp(Ext, "f", 1) == 0) return TY_PP_Fortran;
117     if (memcmp(Ext, "F", 1) == 0) return TY_Fortran;
118     if (memcmp(Ext, "s", 1) == 0) return TY_PP_Asm;
119     if (memcmp(Ext, "S", 1) == 0) return TY_Asm;
120   case 2:
121     if (memcmp(Ext, "ii", 2) == 0) return TY_PP_CXX;
122     if (memcmp(Ext, "mi", 2) == 0) return TY_PP_ObjC;
123     if (memcmp(Ext, "mm", 2) == 0) return TY_ObjCXX;
124     if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
125     if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
126     if (memcmp(Ext, "cp", 2) == 0) return TY_CXX;
127     if (memcmp(Ext, "hh", 2) == 0) return TY_CXXHeader;
128     break;
129   case 3:
130     if (memcmp(Ext, "ads", 3) == 0) return TY_Ada;
131     if (memcmp(Ext, "adb", 3) == 0) return TY_Ada;
132     if (memcmp(Ext, "ast", 3) == 0) return TY_AST;
133     if (memcmp(Ext, "cxx", 3) == 0) return TY_CXX;
134     if (memcmp(Ext, "cpp", 3) == 0) return TY_CXX;
135     if (memcmp(Ext, "CPP", 3) == 0) return TY_CXX;
136     if (memcmp(Ext, "cXX", 3) == 0) return TY_CXX;
137     if (memcmp(Ext, "for", 3) == 0) return TY_PP_Fortran;
138     if (memcmp(Ext, "FOR", 3) == 0) return TY_PP_Fortran;
139     if (memcmp(Ext, "fpp", 3) == 0) return TY_Fortran;
140     if (memcmp(Ext, "FPP", 3) == 0) return TY_Fortran;
141     if (memcmp(Ext, "f90", 3) == 0) return TY_PP_Fortran;
142     if (memcmp(Ext, "f95", 3) == 0) return TY_PP_Fortran;
143     if (memcmp(Ext, "F90", 3) == 0) return TY_Fortran;
144     if (memcmp(Ext, "F95", 3) == 0) return TY_Fortran;
145     if (memcmp(Ext, "mii", 3) == 0) return TY_PP_ObjCXX;
146     break;
147   }
148 
149   return TY_INVALID;
150 }
151 
152 types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
153   unsigned N = strlen(Name);
154 
155   for (unsigned i=0; i<numTypes; ++i) {
156     types::ID Id = (types::ID) (i + 1);
157     if (canTypeBeUserSpecified(Id) &&
158         memcmp(Name, getInfo(Id).Name, N + 1) == 0)
159       return Id;
160   }
161 
162   return TY_INVALID;
163 }
164 
165 // FIXME: Why don't we just put this list in the defs file, eh.
166 
167 unsigned types::getNumCompilationPhases(ID Id) {
168   if (Id == TY_Object)
169     return 1;
170 
171   unsigned N = 0;
172   if (getPreprocessedType(Id) != TY_INVALID)
173     N += 1;
174 
175   if (onlyAssembleType(Id))
176     return N + 2; // assemble, link
177   if (onlyPrecompileType(Id))
178     return N + 1; // precompile
179 
180   return N + 3; // compile, assemble, link
181 }
182 
183 phases::ID types::getCompilationPhase(ID Id, unsigned N) {
184   assert(N < getNumCompilationPhases(Id) && "Invalid index.");
185 
186   if (Id == TY_Object)
187     return phases::Link;
188 
189   if (getPreprocessedType(Id) != TY_INVALID) {
190     if (N == 0)
191       return phases::Preprocess;
192     --N;
193   }
194 
195   if (onlyAssembleType(Id))
196     return N == 0 ? phases::Assemble : phases::Link;
197 
198   if (onlyPrecompileType(Id))
199     return phases::Precompile;
200 
201   if (N == 0)
202     return phases::Compile;
203   if (N == 1)
204     return phases::Assemble;
205 
206   return phases::Link;
207 }
208