ObjCRuntime.h revision 263508
1//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
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/// \file
11/// \brief Defines types useful for describing an Objective-C runtime.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_OBJCRUNTIME_H
16#define LLVM_CLANG_OBJCRUNTIME_H
17
18#include "clang/Basic/VersionTuple.h"
19#include "llvm/ADT/Triple.h"
20#include "llvm/Support/ErrorHandling.h"
21
22namespace clang {
23
24/// \brief The basic abstraction for the target Objective-C runtime.
25class ObjCRuntime {
26public:
27  /// \brief The basic Objective-C runtimes that we know about.
28  enum Kind {
29    /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
30    /// X platforms that use the non-fragile ABI; the version is a
31    /// release of that OS.
32    MacOSX,
33
34    /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on
35    /// Mac OS X platforms that use the fragile ABI; the version is a
36    /// release of that OS.
37    FragileMacOSX,
38
39    /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS
40    /// simulator;  it is always non-fragile.  The version is a release
41    /// version of iOS.
42    iOS,
43
44    /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
45    /// fragile Objective-C ABI
46    GCC,
47
48    /// 'gnustep' is the modern non-fragile GNUstep runtime.
49    GNUstep,
50
51    /// 'objfw' is the Objective-C runtime included in ObjFW
52    ObjFW
53  };
54
55private:
56  Kind TheKind;
57  VersionTuple Version;
58
59public:
60  /// A bogus initialization of the runtime.
61  ObjCRuntime() : TheKind(MacOSX) {}
62
63  ObjCRuntime(Kind kind, const VersionTuple &version)
64    : TheKind(kind), Version(version) {}
65
66  void set(Kind kind, VersionTuple version) {
67    TheKind = kind;
68    Version = version;
69  }
70
71  Kind getKind() const { return TheKind; }
72  const VersionTuple &getVersion() const { return Version; }
73
74  /// \brief Does this runtime follow the set of implied behaviors for a
75  /// "non-fragile" ABI?
76  bool isNonFragile() const {
77    switch (getKind()) {
78    case FragileMacOSX: return false;
79    case GCC: return false;
80    case MacOSX: return true;
81    case GNUstep: return true;
82    case ObjFW: return true;
83    case iOS: return true;
84    }
85    llvm_unreachable("bad kind");
86  }
87
88  /// The inverse of isNonFragile():  does this runtime follow the set of
89  /// implied behaviors for a "fragile" ABI?
90  bool isFragile() const { return !isNonFragile(); }
91
92  /// The default dispatch mechanism to use for the specified architecture
93  bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
94    // The GNUstep runtime uses a newer dispatch method by default from
95    // version 1.6 onwards
96    if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) {
97      if (Arch == llvm::Triple::arm ||
98          Arch == llvm::Triple::x86 ||
99          Arch == llvm::Triple::x86_64)
100        return false;
101    }
102    // Mac runtimes use legacy dispatch everywhere now.
103    return true;
104  }
105
106  /// \brief Is this runtime basically of the GNU family of runtimes?
107  bool isGNUFamily() const {
108    switch (getKind()) {
109    case FragileMacOSX:
110    case MacOSX:
111    case iOS:
112      return false;
113    case GCC:
114    case GNUstep:
115    case ObjFW:
116      return true;
117    }
118    llvm_unreachable("bad kind");
119  }
120
121  /// \brief Is this runtime basically of the NeXT family of runtimes?
122  bool isNeXTFamily() const {
123    // For now, this is just the inverse of isGNUFamily(), but that's
124    // not inherently true.
125    return !isGNUFamily();
126  }
127
128  /// \brief Does this runtime allow ARC at all?
129  bool allowsARC() const {
130    switch (getKind()) {
131    case FragileMacOSX: return false;
132    case MacOSX: return true;
133    case iOS: return true;
134    case GCC: return false;
135    case GNUstep: return true;
136    case ObjFW: return true;
137    }
138    llvm_unreachable("bad kind");
139  }
140
141  /// \brief Does this runtime natively provide the ARC entrypoints?
142  ///
143  /// ARC cannot be directly supported on a platform that does not provide
144  /// these entrypoints, although it may be supportable via a stub
145  /// library.
146  bool hasNativeARC() const {
147    switch (getKind()) {
148    case FragileMacOSX: return false;
149    case MacOSX: return getVersion() >= VersionTuple(10, 7);
150    case iOS: return getVersion() >= VersionTuple(5);
151
152    case GCC: return false;
153    case GNUstep: return getVersion() >= VersionTuple(1, 6);
154    case ObjFW: return true;
155    }
156    llvm_unreachable("bad kind");
157  }
158
159  /// \brief Does this runtime supports optimized setter entrypoints?
160  bool hasOptimizedSetter() const {
161    switch (getKind()) {
162      case MacOSX:
163        return getVersion() >= VersionTuple(10, 8);
164      case iOS:
165        return (getVersion() >= VersionTuple(6));
166      case GNUstep:
167        return getVersion() >= VersionTuple(1, 7);
168
169      default:
170      return false;
171    }
172  }
173
174  /// Does this runtime allow the use of __weak?
175  bool allowsWeak() const {
176    return hasNativeWeak();
177  }
178
179  /// \brief Does this runtime natively provide ARC-compliant 'weak'
180  /// entrypoints?
181  bool hasNativeWeak() const {
182    // Right now, this is always equivalent to whether the runtime
183    // natively supports ARC decision.
184    return hasNativeARC();
185  }
186
187  /// \brief Does this runtime directly support the subscripting methods?
188  ///
189  /// This is really a property of the library, not the runtime.
190  bool hasSubscripting() const {
191    switch (getKind()) {
192    case FragileMacOSX: return false;
193    case MacOSX: return getVersion() >= VersionTuple(10, 8);
194    case iOS: return getVersion() >= VersionTuple(6);
195
196    // This is really a lie, because some implementations and versions
197    // of the runtime do not support ARC.  Probably -fgnu-runtime
198    // should imply a "maximal" runtime or something?
199    case GCC: return true;
200    case GNUstep: return true;
201    case ObjFW: return true;
202    }
203    llvm_unreachable("bad kind");
204  }
205
206  /// \brief Does this runtime allow sizeof or alignof on object types?
207  bool allowsSizeofAlignof() const {
208    return isFragile();
209  }
210
211  /// \brief Does this runtime allow pointer arithmetic on objects?
212  ///
213  /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
214  /// yields true) [].
215  bool allowsPointerArithmetic() const {
216    switch (getKind()) {
217    case FragileMacOSX:
218    case GCC:
219      return true;
220    case MacOSX:
221    case iOS:
222    case GNUstep:
223    case ObjFW:
224      return false;
225    }
226    llvm_unreachable("bad kind");
227  }
228
229  /// \brief Is subscripting pointer arithmetic?
230  bool isSubscriptPointerArithmetic() const {
231    return allowsPointerArithmetic();
232  }
233
234  /// \brief Does this runtime provide an objc_terminate function?
235  ///
236  /// This is used in handlers for exceptions during the unwind process;
237  /// without it, abort() must be used in pure ObjC files.
238  bool hasTerminate() const {
239    switch (getKind()) {
240    case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
241    case MacOSX: return getVersion() >= VersionTuple(10, 8);
242    case iOS: return getVersion() >= VersionTuple(5);
243    case GCC: return false;
244    case GNUstep: return false;
245    case ObjFW: return false;
246    }
247    llvm_unreachable("bad kind");
248  }
249
250  /// \brief Does this runtime support weakly importing classes?
251  bool hasWeakClassImport() const {
252    switch (getKind()) {
253    case MacOSX: return true;
254    case iOS: return true;
255    case FragileMacOSX: return false;
256    case GCC: return true;
257    case GNUstep: return true;
258    case ObjFW: return true;
259    }
260    llvm_unreachable("bad kind");
261  }
262
263  /// \brief Does this runtime use zero-cost exceptions?
264  bool hasUnwindExceptions() const {
265    switch (getKind()) {
266    case MacOSX: return true;
267    case iOS: return true;
268    case FragileMacOSX: return false;
269    case GCC: return true;
270    case GNUstep: return true;
271    case ObjFW: return true;
272    }
273    llvm_unreachable("bad kind");
274  }
275
276  bool hasAtomicCopyHelper() const {
277    switch (getKind()) {
278    case FragileMacOSX:
279    case MacOSX:
280    case iOS:
281      return true;
282    case GNUstep:
283      return getVersion() >= VersionTuple(1, 7);
284    default: return false;
285    }
286  }
287
288  /// \brief Try to parse an Objective-C runtime specification from the given
289  /// string.
290  ///
291  /// \return true on error.
292  bool tryParse(StringRef input);
293
294  std::string getAsString() const;
295
296  friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
297    return left.getKind() == right.getKind() &&
298           left.getVersion() == right.getVersion();
299  }
300
301  friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
302    return !(left == right);
303  }
304};
305
306raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
307
308}  // end namespace clang
309
310#endif
311