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 22 namespace clang { 23 24 /// \brief The basic abstraction for the target Objective-C runtime. 25 class ObjCRuntime { 26 public: 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 55 private: 56 Kind TheKind; 57 VersionTuple Version; 58 59 public: 60 /// A bogus initialization of the runtime. ObjCRuntime()61 ObjCRuntime() : TheKind(MacOSX) {} 62 ObjCRuntime(Kind kind,const VersionTuple & version)63 ObjCRuntime(Kind kind, const VersionTuple &version) 64 : TheKind(kind), Version(version) {} 65 set(Kind kind,VersionTuple version)66 void set(Kind kind, VersionTuple version) { 67 TheKind = kind; 68 Version = version; 69 } 70 getKind()71 Kind getKind() const { return TheKind; } getVersion()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? isNonFragile()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 false; 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? isFragile()90 bool isFragile() const { return !isNonFragile(); } 91 92 /// The default dispatch mechanism to use for the specified architecture isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch)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 // Mac runtimes use legacy dispatch everywhere except x86-64 102 } else if (isNeXTFamily() && isNonFragile()) 103 return Arch != llvm::Triple::x86_64; 104 return true; 105 } 106 107 /// \brief Is this runtime basically of the GNUstep family of runtimes? isGNUFamily()108 bool isGNUFamily() const { 109 switch (getKind()) { 110 case FragileMacOSX: 111 case MacOSX: 112 case iOS: 113 return false; 114 case GCC: 115 case GNUstep: 116 case ObjFW: 117 return true; 118 } 119 llvm_unreachable("bad kind"); 120 } 121 122 /// \brief Is this runtime basically of the NeXT family of runtimes? isNeXTFamily()123 bool isNeXTFamily() const { 124 // For now, this is just the inverse of isGNUFamily(), but that's 125 // not inherently true. 126 return !isGNUFamily(); 127 } 128 129 /// \brief Does this runtime allow ARC at all? allowsARC()130 bool allowsARC() const { 131 switch (getKind()) { 132 case FragileMacOSX: return false; 133 case MacOSX: return true; 134 case iOS: return true; 135 case GCC: return false; 136 case GNUstep: return true; 137 case ObjFW: return true; 138 } 139 llvm_unreachable("bad kind"); 140 } 141 142 /// \brief Does this runtime natively provide the ARC entrypoints? 143 /// 144 /// ARC cannot be directly supported on a platform that does not provide 145 /// these entrypoints, although it may be supportable via a stub 146 /// library. hasNativeARC()147 bool hasNativeARC() const { 148 switch (getKind()) { 149 case FragileMacOSX: return false; 150 case MacOSX: return getVersion() >= VersionTuple(10, 7); 151 case iOS: return getVersion() >= VersionTuple(5); 152 153 case GCC: return false; 154 case GNUstep: return getVersion() >= VersionTuple(1, 6); 155 case ObjFW: return true; 156 } 157 llvm_unreachable("bad kind"); 158 } 159 160 /// Does this runtime allow the use of __weak? allowsWeak()161 bool allowsWeak() const { 162 return hasNativeWeak(); 163 } 164 165 /// \brief Does this runtime natively provide ARC-compliant 'weak' 166 /// entrypoints? hasNativeWeak()167 bool hasNativeWeak() const { 168 // Right now, this is always equivalent to whether the runtime 169 // natively supports ARC decision. 170 return hasNativeARC(); 171 } 172 173 /// \brief Does this runtime directly support the subscripting methods? 174 /// 175 /// This is really a property of the library, not the runtime. hasSubscripting()176 bool hasSubscripting() const { 177 switch (getKind()) { 178 case FragileMacOSX: return false; 179 case MacOSX: return getVersion() >= VersionTuple(10, 8); 180 case iOS: return false; 181 182 // This is really a lie, because some implementations and versions 183 // of the runtime do not support ARC. Probably -fgnu-runtime 184 // should imply a "maximal" runtime or something? 185 case GCC: return true; 186 case GNUstep: return true; 187 case ObjFW: return true; 188 } 189 llvm_unreachable("bad kind"); 190 } 191 192 /// \brief Does this runtime allow sizeof or alignof on object types? allowsSizeofAlignof()193 bool allowsSizeofAlignof() const { 194 return isFragile(); 195 } 196 197 /// \brief Does this runtime allow pointer arithmetic on objects? 198 /// 199 /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic() 200 /// yields true) []. allowsPointerArithmetic()201 bool allowsPointerArithmetic() const { 202 switch (getKind()) { 203 case FragileMacOSX: 204 case GCC: 205 return true; 206 case MacOSX: 207 case iOS: 208 case GNUstep: 209 case ObjFW: 210 return false; 211 } 212 llvm_unreachable("bad kind"); 213 } 214 215 /// \brief Is subscripting pointer arithmetic? isSubscriptPointerArithmetic()216 bool isSubscriptPointerArithmetic() const { 217 return allowsPointerArithmetic(); 218 } 219 220 /// \brief Does this runtime provide an objc_terminate function? 221 /// 222 /// This is used in handlers for exceptions during the unwind process; 223 /// without it, abort() must be used in pure ObjC files. hasTerminate()224 bool hasTerminate() const { 225 switch (getKind()) { 226 case FragileMacOSX: return getVersion() >= VersionTuple(10, 8); 227 case MacOSX: return getVersion() >= VersionTuple(10, 8); 228 case iOS: return getVersion() >= VersionTuple(5); 229 case GCC: return false; 230 case GNUstep: return false; 231 case ObjFW: return false; 232 } 233 llvm_unreachable("bad kind"); 234 } 235 236 /// \brief Does this runtime support weakly importing classes? hasWeakClassImport()237 bool hasWeakClassImport() const { 238 switch (getKind()) { 239 case MacOSX: return true; 240 case iOS: return true; 241 case FragileMacOSX: return false; 242 case GCC: return true; 243 case GNUstep: return true; 244 case ObjFW: return true; 245 } 246 llvm_unreachable("bad kind"); 247 } 248 249 /// \brief Does this runtime use zero-cost exceptions? hasUnwindExceptions()250 bool hasUnwindExceptions() const { 251 switch (getKind()) { 252 case MacOSX: return true; 253 case iOS: return true; 254 case FragileMacOSX: return false; 255 case GCC: return true; 256 case GNUstep: return true; 257 case ObjFW: return true; 258 } 259 llvm_unreachable("bad kind"); 260 } 261 262 /// \brief Try to parse an Objective-C runtime specification from the given 263 /// string. 264 /// 265 /// \return true on error. 266 bool tryParse(StringRef input); 267 268 std::string getAsString() const; 269 270 friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) { 271 return left.getKind() == right.getKind() && 272 left.getVersion() == right.getVersion(); 273 } 274 275 friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) { 276 return !(left == right); 277 } 278 }; 279 280 raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value); 281 282 } // end namespace clang 283 284 #endif 285