clang API Documentation

ObjCRuntime.h
Go to the documentation of this file.
00001 //===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 ///
00010 /// \file
00011 /// \brief Defines types useful for describing an Objective-C runtime.
00012 ///
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
00016 #define LLVM_CLANG_BASIC_OBJCRUNTIME_H
00017 
00018 #include "clang/Basic/VersionTuple.h"
00019 #include "llvm/ADT/Triple.h"
00020 #include "llvm/Support/ErrorHandling.h"
00021 
00022 namespace clang {
00023 
00024 /// \brief The basic abstraction for the target Objective-C runtime.
00025 class ObjCRuntime {
00026 public:
00027   /// \brief The basic Objective-C runtimes that we know about.
00028   enum Kind {
00029     /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
00030     /// X platforms that use the non-fragile ABI; the version is a
00031     /// release of that OS.
00032     MacOSX,
00033 
00034     /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on
00035     /// Mac OS X platforms that use the fragile ABI; the version is a
00036     /// release of that OS.
00037     FragileMacOSX,
00038 
00039     /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS
00040     /// simulator;  it is always non-fragile.  The version is a release
00041     /// version of iOS.
00042     iOS,
00043 
00044     /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
00045     /// fragile Objective-C ABI
00046     GCC,
00047 
00048     /// 'gnustep' is the modern non-fragile GNUstep runtime.
00049     GNUstep,
00050 
00051     /// 'objfw' is the Objective-C runtime included in ObjFW
00052     ObjFW
00053   };
00054 
00055 private:
00056   Kind TheKind;
00057   VersionTuple Version;
00058 
00059 public:
00060   /// A bogus initialization of the runtime.
00061   ObjCRuntime() : TheKind(MacOSX) {}
00062 
00063   ObjCRuntime(Kind kind, const VersionTuple &version)
00064     : TheKind(kind), Version(version) {}
00065 
00066   void set(Kind kind, VersionTuple version) {
00067     TheKind = kind;
00068     Version = version;
00069   }
00070 
00071   Kind getKind() const { return TheKind; }
00072   const VersionTuple &getVersion() const { return Version; }
00073 
00074   /// \brief Does this runtime follow the set of implied behaviors for a
00075   /// "non-fragile" ABI?
00076   bool isNonFragile() const {
00077     switch (getKind()) {
00078     case FragileMacOSX: return false;
00079     case GCC: return false;
00080     case MacOSX: return true;
00081     case GNUstep: return true;
00082     case ObjFW: return true;
00083     case iOS: return true;
00084     }
00085     llvm_unreachable("bad kind");
00086   }
00087 
00088   /// The inverse of isNonFragile():  does this runtime follow the set of
00089   /// implied behaviors for a "fragile" ABI?
00090   bool isFragile() const { return !isNonFragile(); }
00091 
00092   /// The default dispatch mechanism to use for the specified architecture
00093   bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
00094     // The GNUstep runtime uses a newer dispatch method by default from
00095     // version 1.6 onwards
00096     if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) {
00097       if (Arch == llvm::Triple::arm ||
00098           Arch == llvm::Triple::x86 ||
00099           Arch == llvm::Triple::x86_64)
00100         return false;
00101     }
00102     else if ((getKind() ==  MacOSX) && isNonFragile() &&
00103              (getVersion() >= VersionTuple(10, 0)) &&
00104              (getVersion() < VersionTuple(10, 6)))
00105         return Arch != llvm::Triple::x86_64;
00106     // Except for deployment target of 10.5 or less,
00107     // Mac runtimes use legacy dispatch everywhere now.
00108     return true;
00109   }
00110 
00111   /// \brief Is this runtime basically of the GNU family of runtimes?
00112   bool isGNUFamily() const {
00113     switch (getKind()) {
00114     case FragileMacOSX:
00115     case MacOSX:
00116     case iOS:
00117       return false;
00118     case GCC:
00119     case GNUstep:
00120     case ObjFW:
00121       return true;
00122     }
00123     llvm_unreachable("bad kind");
00124   }
00125 
00126   /// \brief Is this runtime basically of the NeXT family of runtimes?
00127   bool isNeXTFamily() const {
00128     // For now, this is just the inverse of isGNUFamily(), but that's
00129     // not inherently true.
00130     return !isGNUFamily();
00131   }
00132 
00133   /// \brief Does this runtime allow ARC at all?
00134   bool allowsARC() const {
00135     switch (getKind()) {
00136     case FragileMacOSX: return false;
00137     case MacOSX: return true;
00138     case iOS: return true;
00139     case GCC: return false;
00140     case GNUstep: return true;
00141     case ObjFW: return true;
00142     }
00143     llvm_unreachable("bad kind");
00144   }
00145 
00146   /// \brief Does this runtime natively provide the ARC entrypoints? 
00147   ///
00148   /// ARC cannot be directly supported on a platform that does not provide
00149   /// these entrypoints, although it may be supportable via a stub
00150   /// library.
00151   bool hasNativeARC() const {
00152     switch (getKind()) {
00153     case FragileMacOSX: return false;
00154     case MacOSX: return getVersion() >= VersionTuple(10, 7);
00155     case iOS: return getVersion() >= VersionTuple(5);
00156 
00157     case GCC: return false;
00158     case GNUstep: return getVersion() >= VersionTuple(1, 6);
00159     case ObjFW: return true;
00160     }
00161     llvm_unreachable("bad kind");
00162   }
00163 
00164   /// \brief Does this runtime supports optimized setter entrypoints?
00165   bool hasOptimizedSetter() const {
00166     switch (getKind()) {
00167       case MacOSX:
00168         return getVersion() >= VersionTuple(10, 8);
00169       case iOS:
00170         return (getVersion() >= VersionTuple(6));
00171       case GNUstep:
00172         return getVersion() >= VersionTuple(1, 7);
00173     
00174       default:
00175       return false;
00176     }
00177   }
00178 
00179   /// Does this runtime allow the use of __weak?
00180   bool allowsWeak() const {
00181     return hasNativeWeak();
00182   }
00183 
00184   /// \brief Does this runtime natively provide ARC-compliant 'weak'
00185   /// entrypoints?
00186   bool hasNativeWeak() const {
00187     // Right now, this is always equivalent to whether the runtime
00188     // natively supports ARC decision.
00189     return hasNativeARC();
00190   }
00191 
00192   /// \brief Does this runtime directly support the subscripting methods?
00193   ///
00194   /// This is really a property of the library, not the runtime.
00195   bool hasSubscripting() const {
00196     switch (getKind()) {
00197     case FragileMacOSX: return false;
00198     case MacOSX: return getVersion() >= VersionTuple(10, 8);
00199     case iOS: return getVersion() >= VersionTuple(6);
00200 
00201     // This is really a lie, because some implementations and versions
00202     // of the runtime do not support ARC.  Probably -fgnu-runtime
00203     // should imply a "maximal" runtime or something?
00204     case GCC: return true;
00205     case GNUstep: return true;
00206     case ObjFW: return true;
00207     }
00208     llvm_unreachable("bad kind");
00209   }
00210 
00211   /// \brief Does this runtime allow sizeof or alignof on object types?
00212   bool allowsSizeofAlignof() const {
00213     return isFragile();
00214   }
00215 
00216   /// \brief Does this runtime allow pointer arithmetic on objects?
00217   ///
00218   /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
00219   /// yields true) [].
00220   bool allowsPointerArithmetic() const {
00221     switch (getKind()) {
00222     case FragileMacOSX:
00223     case GCC:
00224       return true;
00225     case MacOSX:
00226     case iOS:
00227     case GNUstep:
00228     case ObjFW:
00229       return false;
00230     }
00231     llvm_unreachable("bad kind");
00232   }
00233 
00234   /// \brief Is subscripting pointer arithmetic?
00235   bool isSubscriptPointerArithmetic() const {
00236     return allowsPointerArithmetic();
00237   }
00238 
00239   /// \brief Does this runtime provide an objc_terminate function?
00240   ///
00241   /// This is used in handlers for exceptions during the unwind process;
00242   /// without it, abort() must be used in pure ObjC files.
00243   bool hasTerminate() const {
00244     switch (getKind()) {
00245     case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
00246     case MacOSX: return getVersion() >= VersionTuple(10, 8);
00247     case iOS: return getVersion() >= VersionTuple(5);
00248     case GCC: return false;
00249     case GNUstep: return false;
00250     case ObjFW: return false;
00251     }
00252     llvm_unreachable("bad kind");
00253   }
00254 
00255   /// \brief Does this runtime support weakly importing classes?
00256   bool hasWeakClassImport() const {
00257     switch (getKind()) {
00258     case MacOSX: return true;
00259     case iOS: return true;
00260     case FragileMacOSX: return false;
00261     case GCC: return true;
00262     case GNUstep: return true;
00263     case ObjFW: return true;
00264     }
00265     llvm_unreachable("bad kind");
00266   }
00267 
00268   /// \brief Does this runtime use zero-cost exceptions?
00269   bool hasUnwindExceptions() const {
00270     switch (getKind()) {
00271     case MacOSX: return true;
00272     case iOS: return true;
00273     case FragileMacOSX: return false;
00274     case GCC: return true;
00275     case GNUstep: return true;
00276     case ObjFW: return true;
00277     }
00278     llvm_unreachable("bad kind");
00279   }
00280 
00281   bool hasAtomicCopyHelper() const {
00282     switch (getKind()) {
00283     case FragileMacOSX:
00284     case MacOSX:
00285     case iOS:
00286       return true;
00287     case GNUstep:
00288       return getVersion() >= VersionTuple(1, 7);
00289     default: return false;
00290     }
00291   }
00292 
00293   /// \brief Try to parse an Objective-C runtime specification from the given
00294   /// string.
00295   ///
00296   /// \return true on error.
00297   bool tryParse(StringRef input);
00298 
00299   std::string getAsString() const;
00300 
00301   friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
00302     return left.getKind() == right.getKind() &&
00303            left.getVersion() == right.getVersion();
00304   }
00305 
00306   friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
00307     return !(left == right);
00308   }
00309 };
00310 
00311 raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
00312 
00313 }  // end namespace clang
00314 
00315 #endif