| 1 | //===----- CGObjCRuntime.h - Interface to ObjC Runtimes ---------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This provides an abstract class for Objective-C code generation. Concrete |
| 10 | // subclasses of this implement code generation for specific Objective-C |
| 11 | // runtime libraries. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H |
| 16 | #define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H |
| 17 | #include "CGBuilder.h" |
| 18 | #include "CGCall.h" |
| 19 | #include "CGCleanup.h" |
| 20 | #include "CGValue.h" |
| 21 | #include "clang/AST/DeclObjC.h" |
| 22 | #include "clang/Basic/IdentifierTable.h" // Selector |
| 23 | #include "llvm/ADT/UniqueVector.h" |
| 24 | |
| 25 | namespace llvm { |
| 26 | class Constant; |
| 27 | class Function; |
| 28 | class Module; |
| 29 | class StructLayout; |
| 30 | class StructType; |
| 31 | class Type; |
| 32 | class Value; |
| 33 | } // namespace llvm |
| 34 | |
| 35 | namespace clang { |
| 36 | namespace CodeGen { |
| 37 | class CGFunctionInfo; |
| 38 | class CodeGenFunction; |
| 39 | } // namespace CodeGen |
| 40 | |
| 41 | class FieldDecl; |
| 42 | class ObjCAtTryStmt; |
| 43 | class ObjCAtThrowStmt; |
| 44 | class ObjCAtSynchronizedStmt; |
| 45 | class ObjCContainerDecl; |
| 46 | class ObjCCategoryImplDecl; |
| 47 | class ObjCImplementationDecl; |
| 48 | class ObjCInterfaceDecl; |
| 49 | class ObjCMessageExpr; |
| 50 | class ObjCMethodDecl; |
| 51 | class ObjCProtocolDecl; |
| 52 | class Selector; |
| 53 | class ObjCIvarDecl; |
| 54 | class ObjCStringLiteral; |
| 55 | class BlockDeclRefExpr; |
| 56 | |
| 57 | namespace CodeGen { |
| 58 | class CodeGenModule; |
| 59 | class CGBlockInfo; |
| 60 | |
| 61 | // FIXME: Several methods should be pure virtual but aren't to avoid the |
| 62 | // partially-implemented subclass breaking. |
| 63 | |
| 64 | /// Implements runtime-specific code generation functions. |
| 65 | class CGObjCRuntime { |
| 66 | protected: |
| 67 | CodeGen::CodeGenModule &CGM; |
| 68 | CGObjCRuntime(CodeGen::CodeGenModule &CGM) : CGM(CGM) {} |
| 69 | |
| 70 | // Utility functions for unified ivar access. These need to |
| 71 | // eventually be folded into other places (the structure layout |
| 72 | // code). |
| 73 | |
| 74 | /// Compute an offset to the given ivar, suitable for passing to |
| 75 | /// EmitValueForIvarAtOffset. Note that the correct handling of |
| 76 | /// bit-fields is carefully coordinated by these two, use caution! |
| 77 | /// |
| 78 | /// The latter overload is suitable for computing the offset of a |
| 79 | /// sythesized ivar. |
| 80 | uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, |
| 81 | const ObjCInterfaceDecl *OID, |
| 82 | const ObjCIvarDecl *Ivar); |
| 83 | uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, |
| 84 | const ObjCImplementationDecl *OID, |
| 85 | const ObjCIvarDecl *Ivar); |
| 86 | |
| 87 | LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, |
| 88 | const ObjCInterfaceDecl *OID, |
| 89 | llvm::Value *BaseValue, |
| 90 | const ObjCIvarDecl *Ivar, |
| 91 | unsigned CVRQualifiers, llvm::Value *Offset); |
| 92 | /// Emits a try / catch statement. This function is intended to be called by |
| 93 | /// subclasses, and provides a generic mechanism for generating these, which |
| 94 | /// should be usable by all runtimes. The caller must provide the functions |
| 95 | /// to call when entering and exiting a \@catch() block, and the function |
| 96 | /// used to rethrow exceptions. If the begin and end catch functions are |
| 97 | /// NULL, then the function assumes that the EH personality function provides |
| 98 | /// the thrown object directly. |
| 99 | void EmitTryCatchStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S, |
| 100 | llvm::FunctionCallee beginCatchFn, |
| 101 | llvm::FunctionCallee endCatchFn, |
| 102 | llvm::FunctionCallee exceptionRethrowFn); |
| 103 | |
| 104 | void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn, |
| 105 | const VarDecl *paramDecl); |
| 106 | |
| 107 | /// Emits an \@synchronize() statement, using the \p syncEnterFn and |
| 108 | /// \p syncExitFn arguments as the functions called to lock and unlock |
| 109 | /// the object. This function can be called by subclasses that use |
| 110 | /// zero-cost exception handling. |
| 111 | void EmitAtSynchronizedStmt(CodeGenFunction &CGF, |
| 112 | const ObjCAtSynchronizedStmt &S, |
| 113 | llvm::FunctionCallee syncEnterFn, |
| 114 | llvm::FunctionCallee syncExitFn); |
| 115 | |
| 116 | public: |
| 117 | virtual ~CGObjCRuntime(); |
| 118 | |
| 119 | std::string getSymbolNameForMethod(const ObjCMethodDecl *method, |
| 120 | bool includeCategoryName = true); |
| 121 | |
| 122 | /// Generate the function required to register all Objective-C components in |
| 123 | /// this compilation unit with the runtime library. |
| 124 | virtual llvm::Function *ModuleInitFunction() = 0; |
| 125 | |
| 126 | /// Get a selector for the specified name and type values. |
| 127 | /// The result should have the LLVM type for ASTContext::getObjCSelType(). |
| 128 | virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) = 0; |
| 129 | |
| 130 | /// Get the address of a selector for the specified name and type values. |
| 131 | /// This is a rarely-used language extension, but sadly it exists. |
| 132 | /// |
| 133 | /// The result should have the LLVM type for a pointer to |
| 134 | /// ASTContext::getObjCSelType(). |
| 135 | virtual Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) = 0; |
| 136 | |
| 137 | /// Get a typed selector. |
| 138 | virtual llvm::Value *GetSelector(CodeGenFunction &CGF, |
| 139 | const ObjCMethodDecl *Method) = 0; |
| 140 | |
| 141 | /// Get the type constant to catch for the given ObjC pointer type. |
| 142 | /// This is used externally to implement catching ObjC types in C++. |
| 143 | /// Runtimes which don't support this should add the appropriate |
| 144 | /// error to Sema. |
| 145 | virtual llvm::Constant *GetEHType(QualType T) = 0; |
| 146 | |
| 147 | virtual CatchTypeInfo getCatchAllTypeInfo() { return {.RTTI: nullptr, .Flags: 0}; } |
| 148 | |
| 149 | /// Generate a constant string object. |
| 150 | virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0; |
| 151 | |
| 152 | /// Generate a category. A category contains a list of methods (and |
| 153 | /// accompanying metadata) and a list of protocols. |
| 154 | virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; |
| 155 | |
| 156 | /// Generate a class structure for this class. |
| 157 | virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; |
| 158 | |
| 159 | /// Register an class alias. |
| 160 | virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0; |
| 161 | |
| 162 | /// Generate an Objective-C message send operation. |
| 163 | /// |
| 164 | /// \param Method - The method being called, this may be null if synthesizing |
| 165 | /// a property setter or getter. |
| 166 | virtual CodeGen::RValue |
| 167 | GenerateMessageSend(CodeGen::CodeGenFunction &CGF, ReturnValueSlot ReturnSlot, |
| 168 | QualType ResultType, Selector Sel, llvm::Value *Receiver, |
| 169 | const CallArgList &CallArgs, |
| 170 | const ObjCInterfaceDecl *Class = nullptr, |
| 171 | const ObjCMethodDecl *Method = nullptr) = 0; |
| 172 | |
| 173 | /// Generate an Objective-C message send operation. |
| 174 | /// |
| 175 | /// This variant allows for the call to be substituted with an optimized |
| 176 | /// variant. |
| 177 | CodeGen::RValue GeneratePossiblySpecializedMessageSend( |
| 178 | CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, |
| 179 | Selector Sel, llvm::Value *Receiver, const CallArgList &Args, |
| 180 | const ObjCInterfaceDecl *OID, const ObjCMethodDecl *Method, |
| 181 | bool isClassMessage); |
| 182 | |
| 183 | /// Generate an Objective-C message send operation to the super |
| 184 | /// class initiated in a method for Class and with the given Self |
| 185 | /// object. |
| 186 | /// |
| 187 | /// \param Method - The method being called, this may be null if synthesizing |
| 188 | /// a property setter or getter. |
| 189 | virtual CodeGen::RValue GenerateMessageSendSuper( |
| 190 | CodeGen::CodeGenFunction &CGF, ReturnValueSlot ReturnSlot, |
| 191 | QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, |
| 192 | bool isCategoryImpl, llvm::Value *Self, bool IsClassMessage, |
| 193 | const CallArgList &CallArgs, const ObjCMethodDecl *Method = nullptr) = 0; |
| 194 | |
| 195 | /// Walk the list of protocol references from a class, category or |
| 196 | /// protocol to traverse the DAG formed from it's inheritance hierarchy. Find |
| 197 | /// the list of protocols that ends each walk at either a runtime |
| 198 | /// protocol or a non-runtime protocol with no parents. For the common case of |
| 199 | /// just a list of standard runtime protocols this just returns the same list |
| 200 | /// that was passed in. |
| 201 | std::vector<const ObjCProtocolDecl *> |
| 202 | GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin, |
| 203 | ObjCProtocolDecl::protocol_iterator end); |
| 204 | |
| 205 | /// Emit the code to return the named protocol as an object, as in a |
| 206 | /// \@protocol expression. |
| 207 | virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, |
| 208 | const ObjCProtocolDecl *OPD) = 0; |
| 209 | |
| 210 | /// Generate the named protocol. Protocols contain method metadata but no |
| 211 | /// implementations. |
| 212 | virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0; |
| 213 | |
| 214 | /// GetOrEmitProtocol - Get the protocol object for the given |
| 215 | /// declaration, emitting it if necessary. The return value has type |
| 216 | /// ProtocolPtrTy. |
| 217 | virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) = 0; |
| 218 | |
| 219 | /// Generate a function preamble for a method with the specified |
| 220 | /// types. |
| 221 | |
| 222 | // FIXME: Current this just generates the Function definition, but really this |
| 223 | // should also be generating the loads of the parameters, as the runtime |
| 224 | // should have full control over how parameters are passed. |
| 225 | virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, |
| 226 | const ObjCContainerDecl *CD) = 0; |
| 227 | |
| 228 | /// Generates prologue for direct Objective-C Methods. |
| 229 | virtual void GenerateDirectMethodPrologue(CodeGenFunction &CGF, |
| 230 | llvm::Function *Fn, |
| 231 | const ObjCMethodDecl *OMD, |
| 232 | const ObjCContainerDecl *CD) = 0; |
| 233 | |
| 234 | /// Return the runtime function for getting properties. |
| 235 | virtual llvm::FunctionCallee GetPropertyGetFunction() = 0; |
| 236 | |
| 237 | /// Return the runtime function for setting properties. |
| 238 | virtual llvm::FunctionCallee GetPropertySetFunction() = 0; |
| 239 | |
| 240 | /// Return the runtime function for optimized setting properties. |
| 241 | virtual llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, |
| 242 | bool copy) = 0; |
| 243 | |
| 244 | // API for atomic copying of qualified aggregates in getter. |
| 245 | virtual llvm::FunctionCallee GetGetStructFunction() = 0; |
| 246 | // API for atomic copying of qualified aggregates in setter. |
| 247 | virtual llvm::FunctionCallee GetSetStructFunction() = 0; |
| 248 | /// API for atomic copying of qualified aggregates with non-trivial copy |
| 249 | /// assignment (c++) in setter. |
| 250 | virtual llvm::FunctionCallee GetCppAtomicObjectSetFunction() = 0; |
| 251 | /// API for atomic copying of qualified aggregates with non-trivial copy |
| 252 | /// assignment (c++) in getter. |
| 253 | virtual llvm::FunctionCallee GetCppAtomicObjectGetFunction() = 0; |
| 254 | |
| 255 | /// GetClass - Return a reference to the class for the given |
| 256 | /// interface decl. |
| 257 | virtual llvm::Value *GetClass(CodeGenFunction &CGF, |
| 258 | const ObjCInterfaceDecl *OID) = 0; |
| 259 | |
| 260 | virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { |
| 261 | llvm_unreachable("autoreleasepool unsupported in this ABI" ); |
| 262 | } |
| 263 | |
| 264 | /// EnumerationMutationFunction - Return the function that's called by the |
| 265 | /// compiler when a mutation is detected during foreach iteration. |
| 266 | virtual llvm::FunctionCallee EnumerationMutationFunction() = 0; |
| 267 | |
| 268 | virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, |
| 269 | const ObjCAtSynchronizedStmt &S) = 0; |
| 270 | virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, |
| 271 | const ObjCAtTryStmt &S) = 0; |
| 272 | virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, |
| 273 | const ObjCAtThrowStmt &S, |
| 274 | bool ClearInsertionPoint = true) = 0; |
| 275 | virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, |
| 276 | Address AddrWeakObj) = 0; |
| 277 | virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, |
| 278 | llvm::Value *src, Address dest) = 0; |
| 279 | virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, |
| 280 | llvm::Value *src, Address dest, |
| 281 | bool threadlocal = false) = 0; |
| 282 | virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, |
| 283 | llvm::Value *src, Address dest, |
| 284 | llvm::Value *ivarOffset) = 0; |
| 285 | virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, |
| 286 | llvm::Value *src, Address dest) = 0; |
| 287 | |
| 288 | virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, |
| 289 | QualType ObjectTy, llvm::Value *BaseValue, |
| 290 | const ObjCIvarDecl *Ivar, |
| 291 | unsigned CVRQualifiers) = 0; |
| 292 | virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, |
| 293 | const ObjCInterfaceDecl *Interface, |
| 294 | const ObjCIvarDecl *Ivar) = 0; |
| 295 | virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, |
| 296 | Address DestPtr, Address SrcPtr, |
| 297 | llvm::Value *Size) = 0; |
| 298 | virtual llvm::Constant * |
| 299 | BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, |
| 300 | const CodeGen::CGBlockInfo &blockInfo) = 0; |
| 301 | virtual llvm::Constant * |
| 302 | BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, |
| 303 | const CodeGen::CGBlockInfo &blockInfo) = 0; |
| 304 | virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, |
| 305 | const CGBlockInfo &blockInfo) { |
| 306 | return {}; |
| 307 | } |
| 308 | |
| 309 | /// Returns an i8* which points to the byref layout information. |
| 310 | virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, |
| 311 | QualType T) = 0; |
| 312 | |
| 313 | struct MessageSendInfo { |
| 314 | const CGFunctionInfo &CallInfo; |
| 315 | llvm::PointerType *MessengerType; |
| 316 | |
| 317 | MessageSendInfo(const CGFunctionInfo &callInfo, |
| 318 | llvm::PointerType *messengerType) |
| 319 | : CallInfo(callInfo), MessengerType(messengerType) {} |
| 320 | }; |
| 321 | |
| 322 | MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method, |
| 323 | QualType resultType, |
| 324 | CallArgList &callArgs); |
| 325 | bool canMessageReceiverBeNull(CodeGenFunction &CGF, |
| 326 | const ObjCMethodDecl *method, bool isSuper, |
| 327 | const ObjCInterfaceDecl *classReceiver, |
| 328 | llvm::Value *receiver); |
| 329 | static bool isWeakLinkedClass(const ObjCInterfaceDecl *cls); |
| 330 | |
| 331 | /// Destroy the callee-destroyed arguments of the given method, |
| 332 | /// if it has any. Used for nil-receiver paths in message sends. |
| 333 | /// Never does anything if the method does not satisfy |
| 334 | /// hasParamDestroyedInCallee(). |
| 335 | /// |
| 336 | /// \param callArgs - just the formal arguments, not including implicit |
| 337 | /// arguments such as self and cmd |
| 338 | static void destroyCalleeDestroyedArguments(CodeGenFunction &CGF, |
| 339 | const ObjCMethodDecl *method, |
| 340 | const CallArgList &callArgs); |
| 341 | |
| 342 | // FIXME: This probably shouldn't be here, but the code to compute |
| 343 | // it is here. |
| 344 | unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM, |
| 345 | const ObjCInterfaceDecl *ID, |
| 346 | const ObjCIvarDecl *Ivar); |
| 347 | }; |
| 348 | |
| 349 | /// Creates an instance of an Objective-C runtime class. |
| 350 | // TODO: This should include some way of selecting which runtime to target. |
| 351 | CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); |
| 352 | CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); |
| 353 | } // namespace CodeGen |
| 354 | } // namespace clang |
| 355 | #endif |
| 356 | |