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