Home | History | Annotate | Download | only in CodeGen
      1 //===----- CGObjCRuntime.h - Interface to ObjC Runtimes ---------*- 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 // This provides an abstract class for Objective-C code generation.  Concrete
     11 // subclasses of this implement code generation for specific Objective-C
     12 // runtime libraries.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef CLANG_CODEGEN_OBCJRUNTIME_H
     17 #define CLANG_CODEGEN_OBCJRUNTIME_H
     18 #include "CGBuilder.h"
     19 #include "CGCall.h"
     20 #include "CGValue.h"
     21 #include "clang/AST/DeclObjC.h"
     22 #include "clang/Basic/IdentifierTable.h" // Selector
     23 
     24 namespace llvm {
     25   class Constant;
     26   class Function;
     27   class Module;
     28   class StructLayout;
     29   class StructType;
     30   class Type;
     31   class Value;
     32 }
     33 
     34 namespace clang {
     35 namespace CodeGen {
     36   class CodeGenFunction;
     37 }
     38 
     39   class FieldDecl;
     40   class ObjCAtTryStmt;
     41   class ObjCAtThrowStmt;
     42   class ObjCAtSynchronizedStmt;
     43   class ObjCContainerDecl;
     44   class ObjCCategoryImplDecl;
     45   class ObjCImplementationDecl;
     46   class ObjCInterfaceDecl;
     47   class ObjCMessageExpr;
     48   class ObjCMethodDecl;
     49   class ObjCProtocolDecl;
     50   class Selector;
     51   class ObjCIvarDecl;
     52   class ObjCStringLiteral;
     53   class BlockDeclRefExpr;
     54 
     55 namespace CodeGen {
     56   class CodeGenModule;
     57   class CGBlockInfo;
     58 
     59 // FIXME: Several methods should be pure virtual but aren't to avoid the
     60 // partially-implemented subclass breaking.
     61 
     62 /// Implements runtime-specific code generation functions.
     63 class CGObjCRuntime {
     64 protected:
     65   CodeGen::CodeGenModule &CGM;
     66   CGObjCRuntime(CodeGen::CodeGenModule &CGM) : CGM(CGM) {}
     67 
     68   // Utility functions for unified ivar access. These need to
     69   // eventually be folded into other places (the structure layout
     70   // code).
     71 
     72   /// Compute an offset to the given ivar, suitable for passing to
     73   /// EmitValueForIvarAtOffset.  Note that the correct handling of
     74   /// bit-fields is carefully coordinated by these two, use caution!
     75   ///
     76   /// The latter overload is suitable for computing the offset of a
     77   /// sythesized ivar.
     78   uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
     79                                  const ObjCInterfaceDecl *OID,
     80                                  const ObjCIvarDecl *Ivar);
     81   uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
     82                                  const ObjCImplementationDecl *OID,
     83                                  const ObjCIvarDecl *Ivar);
     84 
     85   LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
     86                                   const ObjCInterfaceDecl *OID,
     87                                   llvm::Value *BaseValue,
     88                                   const ObjCIvarDecl *Ivar,
     89                                   unsigned CVRQualifiers,
     90                                   llvm::Value *Offset);
     91   /// Emits a try / catch statement.  This function is intended to be called by
     92   /// subclasses, and provides a generic mechanism for generating these, which
     93   /// should be usable by all runtimes.  The caller must provide the functions
     94   /// to call when entering and exiting a \@catch() block, and the function
     95   /// used to rethrow exceptions.  If the begin and end catch functions are
     96   /// NULL, then the function assumes that the EH personality function provides
     97   /// the thrown object directly.
     98   void EmitTryCatchStmt(CodeGenFunction &CGF,
     99                         const ObjCAtTryStmt &S,
    100                         llvm::Constant *beginCatchFn,
    101                         llvm::Constant *endCatchFn,
    102                         llvm::Constant *exceptionRethrowFn);
    103   /// Emits an \@synchronize() statement, using the \p syncEnterFn and
    104   /// \p syncExitFn arguments as the functions called to lock and unlock
    105   /// the object.  This function can be called by subclasses that use
    106   /// zero-cost exception handling.
    107   void EmitAtSynchronizedStmt(CodeGenFunction &CGF,
    108                             const ObjCAtSynchronizedStmt &S,
    109                             llvm::Function *syncEnterFn,
    110                             llvm::Function *syncExitFn);
    111 
    112 public:
    113   virtual ~CGObjCRuntime();
    114 
    115   /// Generate the function required to register all Objective-C components in
    116   /// this compilation unit with the runtime library.
    117   virtual llvm::Function *ModuleInitFunction() = 0;
    118 
    119   /// Get a selector for the specified name and type values. The
    120   /// return value should have the LLVM type for pointer-to
    121   /// ASTContext::getObjCSelType().
    122   virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
    123                                    Selector Sel, bool lval=false) = 0;
    124 
    125   /// Get a typed selector.
    126   virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
    127                                    const ObjCMethodDecl *Method) = 0;
    128 
    129   /// Get the type constant to catch for the given ObjC pointer type.
    130   /// This is used externally to implement catching ObjC types in C++.
    131   /// Runtimes which don't support this should add the appropriate
    132   /// error to Sema.
    133   virtual llvm::Constant *GetEHType(QualType T) = 0;
    134 
    135   /// Generate a constant string object.
    136   virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
    137 
    138   /// Generate a category.  A category contains a list of methods (and
    139   /// accompanying metadata) and a list of protocols.
    140   virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0;
    141 
    142   /// Generate a class structure for this class.
    143   virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0;
    144 
    145   /// Register an class alias.
    146   virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0;
    147 
    148   /// Generate an Objective-C message send operation.
    149   ///
    150   /// \param Method - The method being called, this may be null if synthesizing
    151   /// a property setter or getter.
    152   virtual CodeGen::RValue
    153   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
    154                       ReturnValueSlot ReturnSlot,
    155                       QualType ResultType,
    156                       Selector Sel,
    157                       llvm::Value *Receiver,
    158                       const CallArgList &CallArgs,
    159                       const ObjCInterfaceDecl *Class = nullptr,
    160                       const ObjCMethodDecl *Method = nullptr) = 0;
    161 
    162   /// Generate an Objective-C message send operation to the super
    163   /// class initiated in a method for Class and with the given Self
    164   /// object.
    165   ///
    166   /// \param Method - The method being called, this may be null if synthesizing
    167   /// a property setter or getter.
    168   virtual CodeGen::RValue
    169   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
    170                            ReturnValueSlot ReturnSlot,
    171                            QualType ResultType,
    172                            Selector Sel,
    173                            const ObjCInterfaceDecl *Class,
    174                            bool isCategoryImpl,
    175                            llvm::Value *Self,
    176                            bool IsClassMessage,
    177                            const CallArgList &CallArgs,
    178                            const ObjCMethodDecl *Method = nullptr) = 0;
    179 
    180   /// Emit the code to return the named protocol as an object, as in a
    181   /// \@protocol expression.
    182   virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
    183                                            const ObjCProtocolDecl *OPD) = 0;
    184 
    185   /// Generate the named protocol.  Protocols contain method metadata but no
    186   /// implementations.
    187   virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0;
    188 
    189   /// Generate a function preamble for a method with the specified
    190   /// types.
    191 
    192   // FIXME: Current this just generates the Function definition, but really this
    193   // should also be generating the loads of the parameters, as the runtime
    194   // should have full control over how parameters are passed.
    195   virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
    196                                          const ObjCContainerDecl *CD) = 0;
    197 
    198   /// Return the runtime function for getting properties.
    199   virtual llvm::Constant *GetPropertyGetFunction() = 0;
    200 
    201   /// Return the runtime function for setting properties.
    202   virtual llvm::Constant *GetPropertySetFunction() = 0;
    203 
    204   /// Return the runtime function for optimized setting properties.
    205   virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
    206                                                           bool copy) = 0;
    207 
    208   // API for atomic copying of qualified aggregates in getter.
    209   virtual llvm::Constant *GetGetStructFunction() = 0;
    210   // API for atomic copying of qualified aggregates in setter.
    211   virtual llvm::Constant *GetSetStructFunction() = 0;
    212   /// API for atomic copying of qualified aggregates with non-trivial copy
    213   /// assignment (c++) in setter.
    214   virtual llvm::Constant *GetCppAtomicObjectSetFunction() = 0;
    215   /// API for atomic copying of qualified aggregates with non-trivial copy
    216   /// assignment (c++) in getter.
    217   virtual llvm::Constant *GetCppAtomicObjectGetFunction() = 0;
    218 
    219   /// GetClass - Return a reference to the class for the given
    220   /// interface decl.
    221   virtual llvm::Value *GetClass(CodeGenFunction &CGF,
    222                                 const ObjCInterfaceDecl *OID) = 0;
    223 
    224 
    225   virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
    226     llvm_unreachable("autoreleasepool unsupported in this ABI");
    227   }
    228 
    229   /// EnumerationMutationFunction - Return the function that's called by the
    230   /// compiler when a mutation is detected during foreach iteration.
    231   virtual llvm::Constant *EnumerationMutationFunction() = 0;
    232 
    233   virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
    234                                     const ObjCAtSynchronizedStmt &S) = 0;
    235   virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
    236                            const ObjCAtTryStmt &S) = 0;
    237   virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
    238                              const ObjCAtThrowStmt &S,
    239                              bool ClearInsertionPoint=true) = 0;
    240   virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
    241                                         llvm::Value *AddrWeakObj) = 0;
    242   virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
    243                                   llvm::Value *src, llvm::Value *dest) = 0;
    244   virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
    245                                     llvm::Value *src, llvm::Value *dest,
    246                                     bool threadlocal=false) = 0;
    247   virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
    248                                   llvm::Value *src, llvm::Value *dest,
    249                                   llvm::Value *ivarOffset) = 0;
    250   virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
    251                                         llvm::Value *src, llvm::Value *dest) = 0;
    252 
    253   virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
    254                                       QualType ObjectTy,
    255                                       llvm::Value *BaseValue,
    256                                       const ObjCIvarDecl *Ivar,
    257                                       unsigned CVRQualifiers) = 0;
    258   virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
    259                                       const ObjCInterfaceDecl *Interface,
    260                                       const ObjCIvarDecl *Ivar) = 0;
    261   virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
    262                                         llvm::Value *DestPtr,
    263                                         llvm::Value *SrcPtr,
    264                                         llvm::Value *Size) = 0;
    265   virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
    266                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
    267   virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
    268                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
    269   virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
    270                                            QualType T) = 0;
    271   virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
    272                                                bool Weak = false) = 0;
    273 
    274   struct MessageSendInfo {
    275     const CGFunctionInfo &CallInfo;
    276     llvm::PointerType *MessengerType;
    277 
    278     MessageSendInfo(const CGFunctionInfo &callInfo,
    279                     llvm::PointerType *messengerType)
    280       : CallInfo(callInfo), MessengerType(messengerType) {}
    281   };
    282 
    283   MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method,
    284                                      QualType resultType,
    285                                      CallArgList &callArgs);
    286 
    287   // FIXME: This probably shouldn't be here, but the code to compute
    288   // it is here.
    289   unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM,
    290                                     const ObjCInterfaceDecl *ID,
    291                                     const ObjCIvarDecl *Ivar);
    292 };
    293 
    294 /// Creates an instance of an Objective-C runtime class.
    295 //TODO: This should include some way of selecting which runtime to target.
    296 CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM);
    297 CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM);
    298 }
    299 }
    300 #endif
    301