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 "clang/Driver/Driver.h" |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "llvm/ADT/StringSwitch.h" |
14 | #include <cassert> |
15 | #include <cstring> |
16 | |
17 | using namespace clang::driver; |
18 | using namespace clang::driver::types; |
19 | |
20 | struct TypeInfo { |
21 | const char *Name; |
22 | const char *TempSuffix; |
23 | ID PreprocessedType; |
24 | class PhasesBitSet { |
25 | unsigned Bits = 0; |
26 | |
27 | public: |
28 | constexpr PhasesBitSet(std::initializer_list<phases::ID> Phases) { |
29 | for (auto Id : Phases) |
30 | Bits |= 1 << Id; |
31 | } |
32 | bool contains(phases::ID Id) const { return Bits & (1 << Id); } |
33 | } Phases; |
34 | }; |
35 | |
36 | static constexpr TypeInfo TypeInfos[] = { |
37 | #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \ |
38 | { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, }, |
39 | #include "clang/Driver/Types.def" |
40 | #undef TYPE |
41 | }; |
42 | static const unsigned numTypes = std::size(TypeInfos); |
43 | |
44 | static const TypeInfo &getInfo(unsigned id) { |
45 | assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); |
46 | return TypeInfos[id - 1]; |
47 | } |
48 | |
49 | const char *types::getTypeName(ID Id) { |
50 | return getInfo(id: Id).Name; |
51 | } |
52 | |
53 | types::ID types::getPreprocessedType(ID Id) { |
54 | ID PPT = getInfo(id: Id).PreprocessedType; |
55 | assert((getInfo(Id).Phases.contains(phases::Preprocess) != |
56 | (PPT == TY_INVALID)) && |
57 | "Unexpected Preprocess Type."); |
58 | return PPT; |
59 | } |
60 | |
61 | static bool isPreprocessedModuleType(ID Id) { |
62 | return Id == TY_CXXModule || Id == TY_PP_CXXModule; |
63 | } |
64 | |
65 | static bool isPreprocessedHeaderUnitType(ID Id) { |
66 | return Id == TY_CXXSHeader || Id == TY_CXXUHeader || Id == TY_CXXHUHeader || |
67 | Id == TY_PP_CXXHeaderUnit; |
68 | } |
69 | |
70 | types::ID types::getPrecompiledType(ID Id) { |
71 | if (isPreprocessedModuleType(Id)) |
72 | return TY_ModuleFile; |
73 | if (isPreprocessedHeaderUnitType(Id)) |
74 | return TY_HeaderUnit; |
75 | if (onlyPrecompileType(Id)) |
76 | return TY_PCH; |
77 | return TY_INVALID; |
78 | } |
79 | |
80 | const char *types::getTypeTempSuffix(ID Id, bool CLStyle) { |
81 | if (CLStyle) { |
82 | switch (Id) { |
83 | case TY_Object: |
84 | case TY_LTO_BC: |
85 | return "obj"; |
86 | case TY_Image: |
87 | return "exe"; |
88 | case TY_PP_Asm: |
89 | return "asm"; |
90 | default: |
91 | break; |
92 | } |
93 | } |
94 | return getInfo(id: Id).TempSuffix; |
95 | } |
96 | |
97 | bool types::onlyPrecompileType(ID Id) { |
98 | return getInfo(id: Id).Phases.contains(Id: phases::Precompile) && |
99 | !isPreprocessedModuleType(Id); |
100 | } |
101 | |
102 | bool types::canTypeBeUserSpecified(ID Id) { |
103 | static const clang::driver::types::ID kStaticLangageTypes[] = { |
104 | TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader, |
105 | TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, |
106 | TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, |
107 | TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, |
108 | TY_Remap, TY_PCH, TY_Object, |
109 | TY_Image, TY_dSYM, TY_Dependencies, |
110 | TY_CUDA_FATBIN, TY_HIP_FATBIN}; |
111 | return !llvm::is_contained(Range: kStaticLangageTypes, Element: Id); |
112 | } |
113 | |
114 | bool types::appendSuffixForType(ID Id) { |
115 | return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN || |
116 | Id == TY_HIP_FATBIN; |
117 | } |
118 | |
119 | bool types::canLipoType(ID Id) { |
120 | return (Id == TY_Nothing || |
121 | Id == TY_Image || |
122 | Id == TY_Object || |
123 | Id == TY_LTO_BC); |
124 | } |
125 | |
126 | bool types::isAcceptedByClang(ID Id) { |
127 | switch (Id) { |
128 | default: |
129 | return false; |
130 | |
131 | case TY_Asm: |
132 | case TY_C: case TY_PP_C: |
133 | case TY_CL: case TY_PP_CL: case TY_CLCXX: case TY_PP_CLCXX: |
134 | case TY_CUDA: case TY_PP_CUDA: |
135 | case TY_CUDA_DEVICE: |
136 | case TY_HIP: |
137 | case TY_PP_HIP: |
138 | case TY_HIP_DEVICE: |
139 | case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: |
140 | case TY_CXX: case TY_PP_CXX: |
141 | case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: |
142 | case TY_CHeader: case TY_PP_CHeader: |
143 | case TY_CLHeader: |
144 | case TY_ObjCHeader: case TY_PP_ObjCHeader: |
145 | case TY_CXXHeader: case TY_PP_CXXHeader: |
146 | case TY_CXXSHeader: |
147 | case TY_CXXUHeader: |
148 | case TY_CXXHUHeader: |
149 | case TY_PP_CXXHeaderUnit: |
150 | case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: |
151 | case TY_CXXModule: case TY_PP_CXXModule: |
152 | case TY_AST: case TY_ModuleFile: case TY_PCH: |
153 | case TY_LLVM_IR: case TY_LLVM_BC: |
154 | case TY_API_INFO: |
155 | return true; |
156 | } |
157 | } |
158 | |
159 | bool types::isAcceptedByFlang(ID Id) { |
160 | switch (Id) { |
161 | default: |
162 | return false; |
163 | |
164 | case TY_Fortran: |
165 | case TY_PP_Fortran: |
166 | return true; |
167 | case TY_LLVM_IR: |
168 | case TY_LLVM_BC: |
169 | return true; |
170 | case TY_PP_CUDA: |
171 | case TY_CUDA: |
172 | return true; |
173 | } |
174 | } |
175 | |
176 | bool types::isDerivedFromC(ID Id) { |
177 | switch (Id) { |
178 | default: |
179 | return false; |
180 | |
181 | case TY_PP_C: |
182 | case TY_C: |
183 | case TY_CL: |
184 | case TY_PP_CL: |
185 | case TY_CLCXX: |
186 | case TY_PP_CLCXX: |
187 | case TY_PP_CUDA: |
188 | case TY_CUDA: |
189 | case TY_CUDA_DEVICE: |
190 | case TY_PP_HIP: |
191 | case TY_HIP: |
192 | case TY_HIP_DEVICE: |
193 | case TY_PP_ObjC: |
194 | case TY_PP_ObjC_Alias: |
195 | case TY_ObjC: |
196 | case TY_PP_CXX: |
197 | case TY_CXX: |
198 | case TY_PP_ObjCXX: |
199 | case TY_PP_ObjCXX_Alias: |
200 | case TY_ObjCXX: |
201 | case TY_PP_CHeader: |
202 | case TY_CHeader: |
203 | case TY_CLHeader: |
204 | case TY_PP_ObjCHeader: |
205 | case TY_ObjCHeader: |
206 | case TY_PP_CXXHeader: |
207 | case TY_CXXHeader: |
208 | case TY_PP_ObjCXXHeader: |
209 | case TY_ObjCXXHeader: |
210 | case TY_CXXModule: |
211 | case TY_PP_CXXModule: |
212 | return true; |
213 | } |
214 | } |
215 | |
216 | bool types::isObjC(ID Id) { |
217 | switch (Id) { |
218 | default: |
219 | return false; |
220 | |
221 | case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: |
222 | case TY_ObjCXX: case TY_PP_ObjCXX: |
223 | case TY_ObjCHeader: case TY_PP_ObjCHeader: |
224 | case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias: |
225 | return true; |
226 | } |
227 | } |
228 | |
229 | bool types::isOpenCL(ID Id) { |
230 | switch (Id) { |
231 | default: |
232 | return false; |
233 | case TY_PP_CL: |
234 | case TY_PP_CLCXX: |
235 | case TY_CL: |
236 | case TY_CLCXX: |
237 | return true; |
238 | } |
239 | } |
240 | |
241 | bool types::isCXX(ID Id) { |
242 | switch (Id) { |
243 | default: |
244 | return false; |
245 | |
246 | case TY_CXX: case TY_PP_CXX: |
247 | case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: |
248 | case TY_CXXHeader: case TY_PP_CXXHeader: |
249 | case TY_CXXSHeader: |
250 | case TY_CXXUHeader: |
251 | case TY_CXXHUHeader: |
252 | case TY_PP_CXXHeaderUnit: |
253 | case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: |
254 | case TY_CXXModule: |
255 | case TY_PP_CXXModule: |
256 | case TY_ModuleFile: |
257 | case TY_PP_CLCXX: |
258 | case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: |
259 | case TY_HIP: |
260 | case TY_PP_HIP: |
261 | case TY_HIP_DEVICE: |
262 | return true; |
263 | } |
264 | } |
265 | |
266 | bool types::isLLVMIR(ID Id) { |
267 | switch (Id) { |
268 | default: |
269 | return false; |
270 | |
271 | case TY_LLVM_IR: |
272 | case TY_LLVM_BC: |
273 | case TY_LTO_IR: |
274 | case TY_LTO_BC: |
275 | return true; |
276 | } |
277 | } |
278 | |
279 | bool types::isCuda(ID Id) { |
280 | switch (Id) { |
281 | default: |
282 | return false; |
283 | |
284 | case TY_CUDA: |
285 | case TY_PP_CUDA: |
286 | case TY_CUDA_DEVICE: |
287 | return true; |
288 | } |
289 | } |
290 | |
291 | bool types::isHIP(ID Id) { |
292 | switch (Id) { |
293 | default: |
294 | return false; |
295 | |
296 | case TY_HIP: |
297 | case TY_PP_HIP: |
298 | case TY_HIP_DEVICE: |
299 | return true; |
300 | } |
301 | } |
302 | |
303 | bool types::isHLSL(ID Id) { return Id == TY_HLSL; } |
304 | |
305 | bool types::isSrcFile(ID Id) { |
306 | return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID; |
307 | } |
308 | |
309 | types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { |
310 | return llvm::StringSwitch<types::ID>(Ext) |
311 | .Case(S: "c", Value: TY_C) |
312 | .Case(S: "C", Value: TY_CXX) |
313 | .Case(S: "F", Value: TY_Fortran) |
314 | .Case(S: "f", Value: TY_PP_Fortran) |
315 | .Case(S: "h", Value: TY_CHeader) |
316 | .Case(S: "H", Value: TY_CXXHeader) |
317 | .Case(S: "i", Value: TY_PP_C) |
318 | .Case(S: "m", Value: TY_ObjC) |
319 | .Case(S: "M", Value: TY_ObjCXX) |
320 | .Case(S: "o", Value: TY_Object) |
321 | .Case(S: "S", Value: TY_Asm) |
322 | .Case(S: "s", Value: TY_PP_Asm) |
323 | .Case(S: "bc", Value: TY_LLVM_BC) |
324 | .Case(S: "cc", Value: TY_CXX) |
325 | .Case(S: "CC", Value: TY_CXX) |
326 | .Case(S: "cl", Value: TY_CL) |
327 | .Case(S: "cli", Value: TY_PP_CL) |
328 | .Case(S: "clcpp", Value: TY_CLCXX) |
329 | .Case(S: "clii", Value: TY_PP_CLCXX) |
330 | .Case(S: "cp", Value: TY_CXX) |
331 | .Case(S: "cu", Value: TY_CUDA) |
332 | .Case(S: "hh", Value: TY_CXXHeader) |
333 | .Case(S: "ii", Value: TY_PP_CXX) |
334 | .Case(S: "ll", Value: TY_LLVM_IR) |
335 | .Case(S: "mi", Value: TY_PP_ObjC) |
336 | .Case(S: "mm", Value: TY_ObjCXX) |
337 | .Case(S: "adb", Value: TY_Ada) |
338 | .Case(S: "ads", Value: TY_Ada) |
339 | .Case(S: "asm", Value: TY_PP_Asm) |
340 | .Case(S: "ast", Value: TY_AST) |
341 | .Case(S: "ccm", Value: TY_CXXModule) |
342 | .Case(S: "cpp", Value: TY_CXX) |
343 | .Case(S: "CPP", Value: TY_CXX) |
344 | .Case(S: "c++", Value: TY_CXX) |
345 | .Case(S: "C++", Value: TY_CXX) |
346 | .Case(S: "cui", Value: TY_PP_CUDA) |
347 | .Case(S: "cxx", Value: TY_CXX) |
348 | .Case(S: "CXX", Value: TY_CXX) |
349 | .Case(S: "F03", Value: TY_Fortran) |
350 | .Case(S: "f03", Value: TY_PP_Fortran) |
351 | .Case(S: "F08", Value: TY_Fortran) |
352 | .Case(S: "f08", Value: TY_PP_Fortran) |
353 | .Case(S: "F90", Value: TY_Fortran) |
354 | .Case(S: "f90", Value: TY_PP_Fortran) |
355 | .Case(S: "F95", Value: TY_Fortran) |
356 | .Case(S: "f95", Value: TY_PP_Fortran) |
357 | .Case(S: "for", Value: TY_PP_Fortran) |
358 | .Case(S: "FOR", Value: TY_PP_Fortran) |
359 | .Case(S: "fpp", Value: TY_Fortran) |
360 | .Case(S: "FPP", Value: TY_Fortran) |
361 | .Case(S: "gch", Value: TY_PCH) |
362 | .Case(S: "hip", Value: TY_HIP) |
363 | .Case(S: "hipi", Value: TY_PP_HIP) |
364 | .Case(S: "hpp", Value: TY_CXXHeader) |
365 | .Case(S: "hxx", Value: TY_CXXHeader) |
366 | .Case(S: "iim", Value: TY_PP_CXXModule) |
367 | .Case(S: "iih", Value: TY_PP_CXXHeaderUnit) |
368 | .Case(S: "lib", Value: TY_Object) |
369 | .Case(S: "mii", Value: TY_PP_ObjCXX) |
370 | .Case(S: "obj", Value: TY_Object) |
371 | .Case(S: "ifs", Value: TY_IFS) |
372 | .Case(S: "pch", Value: TY_PCH) |
373 | .Case(S: "pcm", Value: TY_ModuleFile) |
374 | .Case(S: "c++m", Value: TY_CXXModule) |
375 | .Case(S: "cppm", Value: TY_CXXModule) |
376 | .Case(S: "cxxm", Value: TY_CXXModule) |
377 | .Case(S: "hlsl", Value: TY_HLSL) |
378 | .Default(Value: TY_INVALID); |
379 | } |
380 | |
381 | types::ID types::lookupTypeForTypeSpecifier(const char *Name) { |
382 | for (unsigned i=0; i<numTypes; ++i) { |
383 | types::ID Id = (types::ID) (i + 1); |
384 | if (canTypeBeUserSpecified(Id) && |
385 | strcmp(s1: Name, s2: getInfo(id: Id).Name) == 0) |
386 | return Id; |
387 | } |
388 | // Accept "cu" as an alias for "cuda" for NVCC compatibility |
389 | if (strcmp(s1: Name, s2: "cu") == 0) { |
390 | return types::TY_CUDA; |
391 | } |
392 | return TY_INVALID; |
393 | } |
394 | |
395 | llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> |
396 | types::getCompilationPhases(ID Id, phases::ID LastPhase) { |
397 | llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> P; |
398 | const auto &Info = getInfo(id: Id); |
399 | for (int I = 0; I <= LastPhase; ++I) |
400 | if (Info.Phases.contains(Id: static_cast<phases::ID>(I))) |
401 | P.push_back(Elt: static_cast<phases::ID>(I)); |
402 | assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); |
403 | return P; |
404 | } |
405 | |
406 | llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> |
407 | types::getCompilationPhases(const clang::driver::Driver &Driver, |
408 | llvm::opt::DerivedArgList &DAL, ID Id) { |
409 | return types::getCompilationPhases(Id, LastPhase: Driver.getFinalPhase(DAL)); |
410 | } |
411 | |
412 | ID types::lookupCXXTypeForCType(ID Id) { |
413 | switch (Id) { |
414 | default: |
415 | return Id; |
416 | |
417 | case types::TY_C: |
418 | return types::TY_CXX; |
419 | case types::TY_PP_C: |
420 | return types::TY_PP_CXX; |
421 | case types::TY_CHeader: |
422 | return types::TY_CXXHeader; |
423 | case types::TY_PP_CHeader: |
424 | return types::TY_PP_CXXHeader; |
425 | } |
426 | } |
427 | |
428 | ID types::lookupHeaderTypeForSourceType(ID Id) { |
429 | switch (Id) { |
430 | default: |
431 | return Id; |
432 | |
433 | // FIXME: Handle preprocessed input types. |
434 | case types::TY_C: |
435 | return types::TY_CHeader; |
436 | case types::TY_CXX: |
437 | case types::TY_CXXModule: |
438 | return types::TY_CXXHeader; |
439 | case types::TY_ObjC: |
440 | return types::TY_ObjCHeader; |
441 | case types::TY_ObjCXX: |
442 | return types::TY_ObjCXXHeader; |
443 | case types::TY_CL: |
444 | case types::TY_CLCXX: |
445 | return types::TY_CLHeader; |
446 | } |
447 | } |
448 |
Definitions
- TypeInfo
- PhasesBitSet
- PhasesBitSet
- contains
- TypeInfos
- numTypes
- getInfo
- getTypeName
- getPreprocessedType
- isPreprocessedModuleType
- isPreprocessedHeaderUnitType
- getPrecompiledType
- getTypeTempSuffix
- onlyPrecompileType
- canTypeBeUserSpecified
- appendSuffixForType
- canLipoType
- isAcceptedByClang
- isAcceptedByFlang
- isDerivedFromC
- isObjC
- isOpenCL
- isCXX
- isLLVMIR
- isCuda
- isHIP
- isHLSL
- isSrcFile
- lookupTypeForExtension
- lookupTypeForTypeSpecifier
- getCompilationPhases
- getCompilationPhases
- lookupCXXTypeForCType
Learn to use CMake with our Intro Training
Find out more