Types.cpp revision 360784
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 "clang/Driver/DriverDiagnostic.h"
12#include "clang/Driver/Options.h"
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Option/Arg.h"
17#include <cassert>
18#include <cstring>
19
20using namespace clang::driver;
21using namespace clang::driver::types;
22
23struct TypeInfo {
24  const char *Name;
25  const char *TempSuffix;
26  ID PreprocessedType;
27  const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases;
28};
29
30static const TypeInfo TypeInfos[] = {
31#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \
32  { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, },
33#include "clang/Driver/Types.def"
34#undef TYPE
35};
36static const unsigned numTypes = llvm::array_lengthof(TypeInfos);
37
38static const TypeInfo &getInfo(unsigned id) {
39  assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
40  return TypeInfos[id - 1];
41}
42
43const char *types::getTypeName(ID Id) {
44  return getInfo(Id).Name;
45}
46
47types::ID types::getPreprocessedType(ID Id) {
48  ID PPT = getInfo(Id).PreprocessedType;
49  assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) !=
50          (PPT == TY_INVALID)) &&
51         "Unexpected Preprocess Type.");
52  return PPT;
53}
54
55static bool isPrepeocessedModuleType(ID Id) {
56  return Id == TY_CXXModule || Id == TY_PP_CXXModule;
57}
58
59types::ID types::getPrecompiledType(ID Id) {
60  if (isPrepeocessedModuleType(Id))
61    return TY_ModuleFile;
62  if (onlyPrecompileType(Id))
63    return TY_PCH;
64  return TY_INVALID;
65}
66
67const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
68  if (CLMode) {
69    switch (Id) {
70    case TY_Object:
71    case TY_LTO_BC:
72      return "obj";
73    case TY_Image:
74      return "exe";
75    case TY_PP_Asm:
76      return "asm";
77    default:
78      break;
79    }
80  }
81  return getInfo(Id).TempSuffix;
82}
83
84bool types::onlyAssembleType(ID Id) {
85  return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) &&
86         !llvm::is_contained(getInfo(Id).Phases, phases::Compile) &&
87         !llvm::is_contained(getInfo(Id).Phases, phases::Backend);
88}
89
90bool types::onlyPrecompileType(ID Id) {
91  return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) &&
92         !isPrepeocessedModuleType(Id);
93}
94
95bool types::canTypeBeUserSpecified(ID Id) {
96  static const clang::driver::types::ID kStaticLangageTypes[] = {
97      TY_CUDA_DEVICE,   TY_HIP_DEVICE,    TY_PP_CHeader,
98      TY_PP_ObjCHeader, TY_PP_CXXHeader,  TY_PP_ObjCXXHeader,
99      TY_PP_CXXModule,  TY_LTO_IR,        TY_LTO_BC,
100      TY_Plist,         TY_RewrittenObjC, TY_RewrittenLegacyObjC,
101      TY_Remap,         TY_PCH,           TY_Object,
102      TY_Image,         TY_dSYM,          TY_Dependencies,
103      TY_CUDA_FATBIN,   TY_HIP_FATBIN};
104  return !llvm::is_contained(kStaticLangageTypes, Id);
105}
106
107bool types::appendSuffixForType(ID Id) {
108  return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN ||
109         Id == TY_HIP_FATBIN;
110}
111
112bool types::canLipoType(ID Id) {
113  return (Id == TY_Nothing ||
114          Id == TY_Image ||
115          Id == TY_Object ||
116          Id == TY_LTO_BC);
117}
118
119bool types::isAcceptedByClang(ID Id) {
120  switch (Id) {
121  default:
122    return false;
123
124  case TY_Asm:
125  case TY_C: case TY_PP_C:
126  case TY_CL:
127  case TY_CUDA: case TY_PP_CUDA:
128  case TY_CUDA_DEVICE:
129  case TY_HIP:
130  case TY_PP_HIP:
131  case TY_HIP_DEVICE:
132  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
133  case TY_CXX: case TY_PP_CXX:
134  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
135  case TY_CHeader: case TY_PP_CHeader:
136  case TY_CLHeader:
137  case TY_ObjCHeader: case TY_PP_ObjCHeader:
138  case TY_CXXHeader: case TY_PP_CXXHeader:
139  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
140  case TY_CXXModule: case TY_PP_CXXModule:
141  case TY_AST: case TY_ModuleFile:
142  case TY_LLVM_IR: case TY_LLVM_BC:
143    return true;
144  }
145}
146
147bool types::isObjC(ID Id) {
148  switch (Id) {
149  default:
150    return false;
151
152  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
153  case TY_ObjCXX: case TY_PP_ObjCXX:
154  case TY_ObjCHeader: case TY_PP_ObjCHeader:
155  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias:
156    return true;
157  }
158}
159
160bool types::isCXX(ID Id) {
161  switch (Id) {
162  default:
163    return false;
164
165  case TY_CXX: case TY_PP_CXX:
166  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
167  case TY_CXXHeader: case TY_PP_CXXHeader:
168  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
169  case TY_CXXModule: case TY_PP_CXXModule:
170  case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
171  case TY_HIP:
172  case TY_PP_HIP:
173  case TY_HIP_DEVICE:
174    return true;
175  }
176}
177
178bool types::isLLVMIR(ID Id) {
179  switch (Id) {
180  default:
181    return false;
182
183  case TY_LLVM_IR:
184  case TY_LLVM_BC:
185  case TY_LTO_IR:
186  case TY_LTO_BC:
187    return true;
188  }
189}
190
191bool types::isCuda(ID Id) {
192  switch (Id) {
193  default:
194    return false;
195
196  case TY_CUDA:
197  case TY_PP_CUDA:
198  case TY_CUDA_DEVICE:
199    return true;
200  }
201}
202
203bool types::isHIP(ID Id) {
204  switch (Id) {
205  default:
206    return false;
207
208  case TY_HIP:
209  case TY_PP_HIP:
210  case TY_HIP_DEVICE:
211    return true;
212  }
213}
214
215bool types::isFortran(ID Id) {
216  switch (Id) {
217  default:
218    return false;
219
220  case TY_Fortran: case TY_PP_Fortran:
221    return true;
222  }
223}
224
225bool types::isSrcFile(ID Id) {
226  return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
227}
228
229types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
230  return llvm::StringSwitch<types::ID>(Ext)
231           .Case("c", TY_C)
232           .Case("C", TY_CXX)
233           .Case("F", TY_Fortran)
234           .Case("f", TY_PP_Fortran)
235           .Case("h", TY_CHeader)
236           .Case("H", TY_CXXHeader)
237           .Case("i", TY_PP_C)
238           .Case("m", TY_ObjC)
239           .Case("M", TY_ObjCXX)
240           .Case("o", TY_Object)
241           .Case("S", TY_Asm)
242           .Case("s", TY_PP_Asm)
243           .Case("bc", TY_LLVM_BC)
244           .Case("cc", TY_CXX)
245           .Case("CC", TY_CXX)
246           .Case("cl", TY_CL)
247           .Case("cp", TY_CXX)
248           .Case("cu", TY_CUDA)
249           .Case("hh", TY_CXXHeader)
250           .Case("ii", TY_PP_CXX)
251           .Case("ll", TY_LLVM_IR)
252           .Case("mi", TY_PP_ObjC)
253           .Case("mm", TY_ObjCXX)
254           .Case("rs", TY_RenderScript)
255           .Case("adb", TY_Ada)
256           .Case("ads", TY_Ada)
257           .Case("asm", TY_PP_Asm)
258           .Case("ast", TY_AST)
259           .Case("ccm", TY_CXXModule)
260           .Case("cpp", TY_CXX)
261           .Case("CPP", TY_CXX)
262           .Case("c++", TY_CXX)
263           .Case("C++", TY_CXX)
264           .Case("cui", TY_PP_CUDA)
265           .Case("cxx", TY_CXX)
266           .Case("CXX", TY_CXX)
267           .Case("F90", TY_Fortran)
268           .Case("f90", TY_PP_Fortran)
269           .Case("F95", TY_Fortran)
270           .Case("f95", TY_PP_Fortran)
271           .Case("for", TY_PP_Fortran)
272           .Case("FOR", TY_PP_Fortran)
273           .Case("fpp", TY_Fortran)
274           .Case("FPP", TY_Fortran)
275           .Case("gch", TY_PCH)
276           .Case("hip", TY_HIP)
277           .Case("hpp", TY_CXXHeader)
278           .Case("iim", TY_PP_CXXModule)
279           .Case("lib", TY_Object)
280           .Case("mii", TY_PP_ObjCXX)
281           .Case("obj", TY_Object)
282           .Case("ifs", TY_IFS)
283           .Case("pch", TY_PCH)
284           .Case("pcm", TY_ModuleFile)
285           .Case("c++m", TY_CXXModule)
286           .Case("cppm", TY_CXXModule)
287           .Case("cxxm", TY_CXXModule)
288           .Default(TY_INVALID);
289}
290
291types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
292  for (unsigned i=0; i<numTypes; ++i) {
293    types::ID Id = (types::ID) (i + 1);
294    if (canTypeBeUserSpecified(Id) &&
295        strcmp(Name, getInfo(Id).Name) == 0)
296      return Id;
297  }
298
299  return TY_INVALID;
300}
301
302// FIXME: Why don't we just put this list in the defs file, eh.
303// FIXME: The list is now in Types.def but for now this function will verify
304//        the old behavior and a subsequent change will delete most of the body.
305void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
306  P = getInfo(Id).Phases;
307  assert(0 < P.size() && "Not enough phases in list");
308  assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
309}
310
311void types::getCompilationPhases(const clang::driver::Driver &Driver,
312                                 llvm::opt::DerivedArgList &DAL, ID Id,
313                                 llvm::SmallVectorImpl<phases::ID> &P) {
314  llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
315  types::getCompilationPhases(Id, PhaseList);
316
317  // Filter to compiler mode. When the compiler is run as a preprocessor then
318  // compilation is not an option.
319  // -S runs the compiler in Assembly listing mode.
320  if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
321      DAL.getLastArg(options::OPT__SLASH_EP) ||
322      DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
323      DAL.getLastArg(options::OPT__SLASH_P))
324    llvm::copy_if(PhaseList, std::back_inserter(P),
325                  [](phases::ID Phase) { return Phase <= phases::Preprocess; });
326
327  // --precompile only runs up to precompilation.
328  // This is a clang extension and is not compatible with GCC.
329  else if (DAL.getLastArg(options::OPT__precompile))
330    llvm::copy_if(PhaseList, std::back_inserter(P),
331                  [](phases::ID Phase) { return Phase <= phases::Precompile; });
332
333  // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
334  else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
335           DAL.getLastArg(options::OPT_print_supported_cpus) ||
336           DAL.getLastArg(options::OPT_module_file_info) ||
337           DAL.getLastArg(options::OPT_verify_pch) ||
338           DAL.getLastArg(options::OPT_rewrite_objc) ||
339           DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
340           DAL.getLastArg(options::OPT__migrate) ||
341           DAL.getLastArg(options::OPT__analyze) ||
342           DAL.getLastArg(options::OPT_emit_ast))
343    llvm::copy_if(PhaseList, std::back_inserter(P),
344                  [](phases::ID Phase) { return Phase <= phases::Compile; });
345
346  else if (DAL.getLastArg(options::OPT_S) ||
347           DAL.getLastArg(options::OPT_emit_llvm))
348    llvm::copy_if(PhaseList, std::back_inserter(P),
349                  [](phases::ID Phase) { return Phase <= phases::Backend; });
350
351  else if (DAL.getLastArg(options::OPT_c))
352    llvm::copy_if(PhaseList, std::back_inserter(P),
353                  [](phases::ID Phase) { return Phase <= phases::Assemble; });
354
355  // Generally means, do every phase until Link.
356  else
357    P = PhaseList;
358}
359
360ID types::lookupCXXTypeForCType(ID Id) {
361  switch (Id) {
362  default:
363    return Id;
364
365  case types::TY_C:
366    return types::TY_CXX;
367  case types::TY_PP_C:
368    return types::TY_PP_CXX;
369  case types::TY_CHeader:
370    return types::TY_CXXHeader;
371  case types::TY_PP_CHeader:
372    return types::TY_PP_CXXHeader;
373  }
374}
375
376ID types::lookupHeaderTypeForSourceType(ID Id) {
377  switch (Id) {
378  default:
379    return Id;
380
381  // FIXME: Handle preprocessed input types.
382  case types::TY_C:
383    return types::TY_CHeader;
384  case types::TY_CXX:
385  case types::TY_CXXModule:
386    return types::TY_CXXHeader;
387  case types::TY_ObjC:
388    return types::TY_ObjCHeader;
389  case types::TY_ObjCXX:
390    return types::TY_ObjCXXHeader;
391  case types::TY_CL:
392    return types::TY_CLHeader;
393  }
394}
395