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