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#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/StringSwitch.h"
13#include <cassert>
14#include <string.h>
15
16using namespace clang::driver;
17using namespace clang::driver::types;
18
19struct TypeInfo {
20  const char *Name;
21  const char *Flags;
22  const char *TempSuffix;
23  ID PreprocessedType;
24};
25
26static const TypeInfo TypeInfos[] = {
27#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \
28  { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, },
29#include "clang/Driver/Types.def"
30#undef TYPE
31};
32static const unsigned numTypes = llvm::array_lengthof(TypeInfos);
33
34static const TypeInfo &getInfo(unsigned id) {
35  assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
36  return TypeInfos[id - 1];
37}
38
39const char *types::getTypeName(ID Id) {
40  return getInfo(Id).Name;
41}
42
43types::ID types::getPreprocessedType(ID Id) {
44  return getInfo(Id).PreprocessedType;
45}
46
47const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
48  if (Id == TY_Object && CLMode)
49    return "obj";
50  if (Id == TY_Image && CLMode)
51    return "exe";
52  if (Id == TY_PP_Asm && CLMode)
53    return "asm";
54  return getInfo(Id).TempSuffix;
55}
56
57bool types::onlyAssembleType(ID Id) {
58  return strchr(getInfo(Id).Flags, 'a');
59}
60
61bool types::onlyPrecompileType(ID Id) {
62  return strchr(getInfo(Id).Flags, 'p');
63}
64
65bool types::canTypeBeUserSpecified(ID Id) {
66  return strchr(getInfo(Id).Flags, 'u');
67}
68
69bool types::appendSuffixForType(ID Id) {
70  return strchr(getInfo(Id).Flags, 'A');
71}
72
73bool types::canLipoType(ID Id) {
74  return (Id == TY_Nothing ||
75          Id == TY_Image ||
76          Id == TY_Object ||
77          Id == TY_LTO_BC);
78}
79
80bool types::isAcceptedByClang(ID Id) {
81  switch (Id) {
82  default:
83    return false;
84
85  case TY_Asm:
86  case TY_C: case TY_PP_C:
87  case TY_CL:
88  case TY_CUDA: case TY_PP_CUDA:
89  case TY_CUDA_DEVICE:
90  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
91  case TY_CXX: case TY_PP_CXX:
92  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
93  case TY_CHeader: case TY_PP_CHeader:
94  case TY_CLHeader:
95  case TY_ObjCHeader: case TY_PP_ObjCHeader:
96  case TY_CXXHeader: case TY_PP_CXXHeader:
97  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
98  case TY_AST: case TY_ModuleFile:
99  case TY_LLVM_IR: case TY_LLVM_BC:
100    return true;
101  }
102}
103
104bool types::isObjC(ID Id) {
105  switch (Id) {
106  default:
107    return false;
108
109  case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
110  case TY_ObjCXX: case TY_PP_ObjCXX:
111  case TY_ObjCHeader: case TY_PP_ObjCHeader:
112  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias:
113    return true;
114  }
115}
116
117bool types::isCXX(ID Id) {
118  switch (Id) {
119  default:
120    return false;
121
122  case TY_CXX: case TY_PP_CXX:
123  case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
124  case TY_CXXHeader: case TY_PP_CXXHeader:
125  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
126  case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
127    return true;
128  }
129}
130
131bool types::isLLVMIR(ID Id) {
132  switch (Id) {
133  default:
134    return false;
135
136  case TY_LLVM_IR:
137  case TY_LLVM_BC:
138  case TY_LTO_IR:
139  case TY_LTO_BC:
140    return true;
141  }
142}
143
144bool types::isCuda(ID Id) {
145  switch (Id) {
146  default:
147    return false;
148
149  case TY_CUDA:
150  case TY_PP_CUDA:
151  case TY_CUDA_DEVICE:
152    return true;
153  }
154}
155
156types::ID types::lookupTypeForExtension(const char *Ext) {
157  return llvm::StringSwitch<types::ID>(Ext)
158           .Case("c", TY_C)
159           .Case("i", TY_PP_C)
160           .Case("m", TY_ObjC)
161           .Case("M", TY_ObjCXX)
162           .Case("h", TY_CHeader)
163           .Case("C", TY_CXX)
164           .Case("H", TY_CXXHeader)
165           .Case("f", TY_PP_Fortran)
166           .Case("F", TY_Fortran)
167           .Case("s", TY_PP_Asm)
168           .Case("asm", TY_PP_Asm)
169           .Case("S", TY_Asm)
170           .Case("o", TY_Object)
171           .Case("obj", TY_Object)
172           .Case("lib", TY_Object)
173           .Case("ii", TY_PP_CXX)
174           .Case("mi", TY_PP_ObjC)
175           .Case("mm", TY_ObjCXX)
176           .Case("bc", TY_LLVM_BC)
177           .Case("cc", TY_CXX)
178           .Case("CC", TY_CXX)
179           .Case("cl", TY_CL)
180           .Case("cp", TY_CXX)
181           .Case("cu", TY_CUDA)
182           .Case("cui", TY_PP_CUDA)
183           .Case("hh", TY_CXXHeader)
184           .Case("ll", TY_LLVM_IR)
185           .Case("hpp", TY_CXXHeader)
186           .Case("ads", TY_Ada)
187           .Case("adb", TY_Ada)
188           .Case("ast", TY_AST)
189           .Case("c++", TY_CXX)
190           .Case("C++", TY_CXX)
191           .Case("cxx", TY_CXX)
192           .Case("cpp", TY_CXX)
193           .Case("CPP", TY_CXX)
194           .Case("CXX", TY_CXX)
195           .Case("for", TY_PP_Fortran)
196           .Case("FOR", TY_PP_Fortran)
197           .Case("fpp", TY_Fortran)
198           .Case("FPP", TY_Fortran)
199           .Case("f90", TY_PP_Fortran)
200           .Case("f95", TY_PP_Fortran)
201           .Case("F90", TY_Fortran)
202           .Case("F95", TY_Fortran)
203           .Case("mii", TY_PP_ObjCXX)
204           .Case("pcm", TY_ModuleFile)
205           .Case("pch", TY_PCH)
206           .Case("gch", TY_PCH)
207           .Case("rs", TY_RenderScript)
208           .Default(TY_INVALID);
209}
210
211types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
212  for (unsigned i=0; i<numTypes; ++i) {
213    types::ID Id = (types::ID) (i + 1);
214    if (canTypeBeUserSpecified(Id) &&
215        strcmp(Name, getInfo(Id).Name) == 0)
216      return Id;
217  }
218
219  return TY_INVALID;
220}
221
222// FIXME: Why don't we just put this list in the defs file, eh.
223void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
224  if (Id != TY_Object) {
225    if (getPreprocessedType(Id) != TY_INVALID) {
226      P.push_back(phases::Preprocess);
227    }
228
229    if (onlyPrecompileType(Id)) {
230      P.push_back(phases::Precompile);
231    } else {
232      if (!onlyAssembleType(Id)) {
233        P.push_back(phases::Compile);
234        P.push_back(phases::Backend);
235      }
236      P.push_back(phases::Assemble);
237    }
238  }
239
240  if (!onlyPrecompileType(Id) && Id != TY_CUDA_DEVICE) {
241    P.push_back(phases::Link);
242  }
243  assert(0 < P.size() && "Not enough phases in list");
244  assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
245}
246
247ID types::lookupCXXTypeForCType(ID Id) {
248  switch (Id) {
249  default:
250    return Id;
251
252  case types::TY_C:
253    return types::TY_CXX;
254  case types::TY_PP_C:
255    return types::TY_PP_CXX;
256  case types::TY_CHeader:
257    return types::TY_CXXHeader;
258  case types::TY_PP_CHeader:
259    return types::TY_PP_CXXHeader;
260  }
261}
262