clang API Documentation
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