summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGObjCRuntime.h
blob: fa16c198adbc7cfd5cf6cd44bceed33a360ed70f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//===----- CGObjCRuntime.h - Interface to ObjC Runtimes ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides an abstract class for Objective-C code generation.  Concrete
// subclasses of this implement code generation for specific Objective-C
// runtime libraries.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H
#define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H
#include "CGBuilder.h"
#include "CGCall.h"
#include "CGCleanup.h"
#include "CGValue.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" // Selector

namespace llvm {
  class Constant;
  class Function;
  class Module;
  class StructLayout;
  class StructType;
  class Type;
  class Value;
}

namespace clang {
namespace CodeGen {
  class CodeGenFunction;
}

  class FieldDecl;
  class ObjCAtTryStmt;
  class ObjCAtThrowStmt;
  class ObjCAtSynchronizedStmt;
  class ObjCContainerDecl;
  class ObjCCategoryImplDecl;
  class ObjCImplementationDecl;
  class ObjCInterfaceDecl;
  class ObjCMessageExpr;
  class ObjCMethodDecl;
  class ObjCProtocolDecl;
  class Selector;
  class ObjCIvarDecl;
  class ObjCStringLiteral;
  class BlockDeclRefExpr;

namespace CodeGen {
  class CodeGenModule;
  class CGBlockInfo;

// FIXME: Several methods should be pure virtual but aren't to avoid the
// partially-implemented subclass breaking.

/// Implements runtime-specific code generation functions.
class CGObjCRuntime {
protected:
  CodeGen::CodeGenModule &CGM;
  CGObjCRuntime(CodeGen::CodeGenModule &CGM) : CGM(CGM) {}

  // Utility functions for unified ivar access. These need to
  // eventually be folded into other places (the structure layout
  // code).

  /// Compute an offset to the given ivar, suitable for passing to
  /// EmitValueForIvarAtOffset.  Note that the correct handling of
  /// bit-fields is carefully coordinated by these two, use caution!
  ///
  /// The latter overload is suitable for computing the offset of a
  /// sythesized ivar.
  uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
                                 const ObjCInterfaceDecl *OID,
                                 const ObjCIvarDecl *Ivar);
  uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
                                 const ObjCImplementationDecl *OID,
                                 const ObjCIvarDecl *Ivar);

  LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
                                  const ObjCInterfaceDecl *OID,
                                  llvm::Value *BaseValue,
                                  const ObjCIvarDecl *Ivar,
                                  unsigned CVRQualifiers,
                                  llvm::Value *Offset);
  /// Emits a try / catch statement.  This function is intended to be called by
  /// subclasses, and provides a generic mechanism for generating these, which
  /// should be usable by all runtimes.  The caller must provide the functions
  /// to call when entering and exiting a \@catch() block, and the function
  /// used to rethrow exceptions.  If the begin and end catch functions are
  /// NULL, then the function assumes that the EH personality function provides
  /// the thrown object directly.
  void EmitTryCatchStmt(CodeGenFunction &CGF,
                        const ObjCAtTryStmt &S,
                        llvm::Constant *beginCatchFn,
                        llvm::Constant *endCatchFn,
                        llvm::Constant *exceptionRethrowFn);

  void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn,
                            const VarDecl *paramDecl);

  /// Emits an \@synchronize() statement, using the \p syncEnterFn and
  /// \p syncExitFn arguments as the functions called to lock and unlock
  /// the object.  This function can be called by subclasses that use
  /// zero-cost exception handling.
  void EmitAtSynchronizedStmt(CodeGenFunction &CGF,
                            const ObjCAtSynchronizedStmt &S,
                            llvm::Function *syncEnterFn,
                            llvm::Function *syncExitFn);

public:
  virtual ~CGObjCRuntime();

  /// Generate the function required to register all Objective-C components in
  /// this compilation unit with the runtime library.
  virtual llvm::Function *ModuleInitFunction() = 0;

  /// Get a selector for the specified name and type values.
  /// The result should have the LLVM type for ASTContext::getObjCSelType().
  virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) = 0;

  /// Get the address of a selector for the specified name and type values.
  /// This is a rarely-used language extension, but sadly it exists.
  ///
  /// The result should have the LLVM type for a pointer to
  /// ASTContext::getObjCSelType().
  virtual Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) = 0;

  /// Get a typed selector.
  virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
                                   const ObjCMethodDecl *Method) = 0;

  /// Get the type constant to catch for the given ObjC pointer type.
  /// This is used externally to implement catching ObjC types in C++.
  /// Runtimes which don't support this should add the appropriate
  /// error to Sema.
  virtual llvm::Constant *GetEHType(QualType T) = 0;

  virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; }

  /// Generate a constant string object.
  virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0;

  /// Generate a category.  A category contains a list of methods (and
  /// accompanying metadata) and a list of protocols.
  virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0;

  /// Generate a class structure for this class.
  virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0;

  /// Register an class alias.
  virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0;

  /// Generate an Objective-C message send operation.
  ///
  /// \param Method - The method being called, this may be null if synthesizing
  /// a property setter or getter.
  virtual CodeGen::RValue
  GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                      ReturnValueSlot ReturnSlot,
                      QualType ResultType,
                      Selector Sel,
                      llvm::Value *Receiver,
                      const CallArgList &CallArgs,
                      const ObjCInterfaceDecl *Class = nullptr,
                      const ObjCMethodDecl *Method = nullptr) = 0;

  /// Generate an Objective-C message send operation to the super
  /// class initiated in a method for Class and with the given Self
  /// object.
  ///
  /// \param Method - The method being called, this may be null if synthesizing
  /// a property setter or getter.
  virtual CodeGen::RValue
  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                           ReturnValueSlot ReturnSlot,
                           QualType ResultType,
                           Selector Sel,
                           const ObjCInterfaceDecl *Class,
                           bool isCategoryImpl,
                           llvm::Value *Self,
                           bool IsClassMessage,
                           const CallArgList &CallArgs,
                           const ObjCMethodDecl *Method = nullptr) = 0;

  /// Emit the code to return the named protocol as an object, as in a
  /// \@protocol expression.
  virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
                                           const ObjCProtocolDecl *OPD) = 0;

  /// Generate the named protocol.  Protocols contain method metadata but no
  /// implementations.
  virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0;

  /// Generate a function preamble for a method with the specified
  /// types.

  // FIXME: Current this just generates the Function definition, but really this
  // should also be generating the loads of the parameters, as the runtime
  // should have full control over how parameters are passed.
  virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
                                         const ObjCContainerDecl *CD) = 0;

  /// Return the runtime function for getting properties.
  virtual llvm::Constant *GetPropertyGetFunction() = 0;

  /// Return the runtime function for setting properties.
  virtual llvm::Constant *GetPropertySetFunction() = 0;

  /// Return the runtime function for optimized setting properties.
  virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
                                                          bool copy) = 0;

  // API for atomic copying of qualified aggregates in getter.
  virtual llvm::Constant *GetGetStructFunction() = 0;
  // API for atomic copying of qualified aggregates in setter.
  virtual llvm::Constant *GetSetStructFunction() = 0;
  /// API for atomic copying of qualified aggregates with non-trivial copy
  /// assignment (c++) in setter.
  virtual llvm::Constant *GetCppAtomicObjectSetFunction() = 0;
  /// API for atomic copying of qualified aggregates with non-trivial copy
  /// assignment (c++) in getter.
  virtual llvm::Constant *GetCppAtomicObjectGetFunction() = 0;

  /// GetClass - Return a reference to the class for the given
  /// interface decl.
  virtual llvm::Value *GetClass(CodeGenFunction &CGF,
                                const ObjCInterfaceDecl *OID) = 0;


  virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
    llvm_unreachable("autoreleasepool unsupported in this ABI");
  }

  /// EnumerationMutationFunction - Return the function that's called by the
  /// compiler when a mutation is detected during foreach iteration.
  virtual llvm::Constant *EnumerationMutationFunction() = 0;

  virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
                                    const ObjCAtSynchronizedStmt &S) = 0;
  virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
                           const ObjCAtTryStmt &S) = 0;
  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
                             const ObjCAtThrowStmt &S,
                             bool ClearInsertionPoint=true) = 0;
  virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
                                        Address AddrWeakObj) = 0;
  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
                                  llvm::Value *src, Address dest) = 0;
  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
                                    llvm::Value *src, Address dest,
                                    bool threadlocal=false) = 0;
  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
                                  llvm::Value *src, Address dest,
                                  llvm::Value *ivarOffset) = 0;
  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
                                        llvm::Value *src, Address dest) = 0;

  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
                                      QualType ObjectTy,
                                      llvm::Value *BaseValue,
                                      const ObjCIvarDecl *Ivar,
                                      unsigned CVRQualifiers) = 0;
  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                                      const ObjCInterfaceDecl *Interface,
                                      const ObjCIvarDecl *Ivar) = 0;
  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
                                        Address DestPtr,
                                        Address SrcPtr,
                                        llvm::Value *Size) = 0;
  virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
                                  const CodeGen::CGBlockInfo &blockInfo) = 0;
  virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
                                  const CodeGen::CGBlockInfo &blockInfo) = 0;
  virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
                                          const CGBlockInfo &blockInfo) {
    return {};
  }

  /// Returns an i8* which points to the byref layout information.
  virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
                                           QualType T) = 0;

  struct MessageSendInfo {
    const CGFunctionInfo &CallInfo;
    llvm::PointerType *MessengerType;

    MessageSendInfo(const CGFunctionInfo &callInfo,
                    llvm::PointerType *messengerType)
      : CallInfo(callInfo), MessengerType(messengerType) {}
  };

  MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method,
                                     QualType resultType,
                                     CallArgList &callArgs);

  // FIXME: This probably shouldn't be here, but the code to compute
  // it is here.
  unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM,
                                    const ObjCInterfaceDecl *ID,
                                    const ObjCIvarDecl *Ivar);
};

/// Creates an instance of an Objective-C runtime class.
//TODO: This should include some way of selecting which runtime to target.
CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM);
CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM);
}
}
#endif