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