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