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 | } |
34 | |
35 | namespace clang { |
36 | namespace CodeGen { |
37 | class CGFunctionInfo; |
38 | class CodeGenFunction; |
39 | } |
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, |
92 | llvm::Value *Offset); |
93 | /// Emits a try / catch statement. This function is intended to be called by |
94 | /// subclasses, and provides a generic mechanism for generating these, which |
95 | /// should be usable by all runtimes. The caller must provide the functions |
96 | /// to call when entering and exiting a \@catch() block, and the function |
97 | /// used to rethrow exceptions. If the begin and end catch functions are |
98 | /// NULL, then the function assumes that the EH personality function provides |
99 | /// the thrown object directly. |
100 | void EmitTryCatchStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S, |
101 | llvm::FunctionCallee beginCatchFn, |
102 | llvm::FunctionCallee endCatchFn, |
103 | llvm::FunctionCallee exceptionRethrowFn); |
104 | |
105 | void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn, |
106 | const VarDecl *paramDecl); |
107 | |
108 | /// Emits an \@synchronize() statement, using the \p syncEnterFn and |
109 | /// \p syncExitFn arguments as the functions called to lock and unlock |
110 | /// the object. This function can be called by subclasses that use |
111 | /// zero-cost exception handling. |
112 | void EmitAtSynchronizedStmt(CodeGenFunction &CGF, |
113 | const ObjCAtSynchronizedStmt &S, |
114 | llvm::FunctionCallee syncEnterFn, |
115 | llvm::FunctionCallee syncExitFn); |
116 | |
117 | public: |
118 | virtual ~CGObjCRuntime(); |
119 | |
120 | std::string getSymbolNameForMethod(const ObjCMethodDecl *method, |
121 | bool includeCategoryName = true); |
122 | |
123 | /// Generate the function required to register all Objective-C components in |
124 | /// this compilation unit with the runtime library. |
125 | virtual llvm::Function *ModuleInitFunction() = 0; |
126 | |
127 | /// Get a selector for the specified name and type values. |
128 | /// The result should have the LLVM type for ASTContext::getObjCSelType(). |
129 | virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) = 0; |
130 | |
131 | /// Get the address of a selector for the specified name and type values. |
132 | /// This is a rarely-used language extension, but sadly it exists. |
133 | /// |
134 | /// The result should have the LLVM type for a pointer to |
135 | /// ASTContext::getObjCSelType(). |
136 | virtual Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) = 0; |
137 | |
138 | /// Get a typed selector. |
139 | virtual llvm::Value *GetSelector(CodeGenFunction &CGF, |
140 | const ObjCMethodDecl *Method) = 0; |
141 | |
142 | /// Get the type constant to catch for the given ObjC pointer type. |
143 | /// This is used externally to implement catching ObjC types in C++. |
144 | /// Runtimes which don't support this should add the appropriate |
145 | /// error to Sema. |
146 | virtual llvm::Constant *GetEHType(QualType T) = 0; |
147 | |
148 | virtual CatchTypeInfo getCatchAllTypeInfo() { return { .RTTI: nullptr, .Flags: 0 }; } |
149 | |
150 | /// Generate a constant string object. |
151 | virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0; |
152 | |
153 | /// Generate a category. A category contains a list of methods (and |
154 | /// accompanying metadata) and a list of protocols. |
155 | virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; |
156 | |
157 | /// Generate a class structure for this class. |
158 | virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; |
159 | |
160 | /// Register an class alias. |
161 | virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0; |
162 | |
163 | /// Generate an Objective-C message send operation. |
164 | /// |
165 | /// \param Method - The method being called, this may be null if synthesizing |
166 | /// a property setter or getter. |
167 | virtual CodeGen::RValue |
168 | GenerateMessageSend(CodeGen::CodeGenFunction &CGF, |
169 | ReturnValueSlot ReturnSlot, |
170 | QualType ResultType, |
171 | Selector Sel, |
172 | llvm::Value *Receiver, |
173 | const CallArgList &CallArgs, |
174 | const ObjCInterfaceDecl *Class = nullptr, |
175 | const ObjCMethodDecl *Method = nullptr) = 0; |
176 | |
177 | /// Generate an Objective-C message send operation. |
178 | /// |
179 | /// This variant allows for the call to be substituted with an optimized |
180 | /// variant. |
181 | CodeGen::RValue |
182 | GeneratePossiblySpecializedMessageSend(CodeGenFunction &CGF, |
183 | ReturnValueSlot Return, |
184 | QualType ResultType, |
185 | Selector Sel, |
186 | llvm::Value *Receiver, |
187 | const CallArgList& Args, |
188 | const ObjCInterfaceDecl *OID, |
189 | const ObjCMethodDecl *Method, |
190 | bool isClassMessage); |
191 | |
192 | /// Generate an Objective-C message send operation to the super |
193 | /// class initiated in a method for Class and with the given Self |
194 | /// object. |
195 | /// |
196 | /// \param Method - The method being called, this may be null if synthesizing |
197 | /// a property setter or getter. |
198 | virtual CodeGen::RValue |
199 | GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, |
200 | ReturnValueSlot ReturnSlot, |
201 | QualType ResultType, |
202 | Selector Sel, |
203 | const ObjCInterfaceDecl *Class, |
204 | bool isCategoryImpl, |
205 | llvm::Value *Self, |
206 | bool IsClassMessage, |
207 | const CallArgList &CallArgs, |
208 | const ObjCMethodDecl *Method = nullptr) = 0; |
209 | |
210 | /// Walk the list of protocol references from a class, category or |
211 | /// protocol to traverse the DAG formed from it's inheritance hierarchy. Find |
212 | /// the list of protocols that ends each walk at either a runtime |
213 | /// protocol or a non-runtime protocol with no parents. For the common case of |
214 | /// just a list of standard runtime protocols this just returns the same list |
215 | /// that was passed in. |
216 | std::vector<const ObjCProtocolDecl *> |
217 | GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin, |
218 | ObjCProtocolDecl::protocol_iterator end); |
219 | |
220 | /// Emit the code to return the named protocol as an object, as in a |
221 | /// \@protocol expression. |
222 | virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, |
223 | const ObjCProtocolDecl *OPD) = 0; |
224 | |
225 | /// Generate the named protocol. Protocols contain method metadata but no |
226 | /// implementations. |
227 | virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0; |
228 | |
229 | /// GetOrEmitProtocol - Get the protocol object for the given |
230 | /// declaration, emitting it if necessary. The return value has type |
231 | /// ProtocolPtrTy. |
232 | virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) = 0; |
233 | |
234 | /// Generate a function preamble for a method with the specified |
235 | /// types. |
236 | |
237 | // FIXME: Current this just generates the Function definition, but really this |
238 | // should also be generating the loads of the parameters, as the runtime |
239 | // should have full control over how parameters are passed. |
240 | virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, |
241 | const ObjCContainerDecl *CD) = 0; |
242 | |
243 | /// Generates prologue for direct Objective-C Methods. |
244 | virtual void GenerateDirectMethodPrologue(CodeGenFunction &CGF, |
245 | llvm::Function *Fn, |
246 | const ObjCMethodDecl *OMD, |
247 | const ObjCContainerDecl *CD) = 0; |
248 | |
249 | /// Return the runtime function for getting properties. |
250 | virtual llvm::FunctionCallee GetPropertyGetFunction() = 0; |
251 | |
252 | /// Return the runtime function for setting properties. |
253 | virtual llvm::FunctionCallee GetPropertySetFunction() = 0; |
254 | |
255 | /// Return the runtime function for optimized setting properties. |
256 | virtual llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, |
257 | bool copy) = 0; |
258 | |
259 | // API for atomic copying of qualified aggregates in getter. |
260 | virtual llvm::FunctionCallee GetGetStructFunction() = 0; |
261 | // API for atomic copying of qualified aggregates in setter. |
262 | virtual llvm::FunctionCallee GetSetStructFunction() = 0; |
263 | /// API for atomic copying of qualified aggregates with non-trivial copy |
264 | /// assignment (c++) in setter. |
265 | virtual llvm::FunctionCallee GetCppAtomicObjectSetFunction() = 0; |
266 | /// API for atomic copying of qualified aggregates with non-trivial copy |
267 | /// assignment (c++) in getter. |
268 | virtual llvm::FunctionCallee GetCppAtomicObjectGetFunction() = 0; |
269 | |
270 | /// GetClass - Return a reference to the class for the given |
271 | /// interface decl. |
272 | virtual llvm::Value *GetClass(CodeGenFunction &CGF, |
273 | const ObjCInterfaceDecl *OID) = 0; |
274 | |
275 | |
276 | virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { |
277 | llvm_unreachable("autoreleasepool unsupported in this ABI" ); |
278 | } |
279 | |
280 | /// EnumerationMutationFunction - Return the function that's called by the |
281 | /// compiler when a mutation is detected during foreach iteration. |
282 | virtual llvm::FunctionCallee EnumerationMutationFunction() = 0; |
283 | |
284 | virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, |
285 | const ObjCAtSynchronizedStmt &S) = 0; |
286 | virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, |
287 | const ObjCAtTryStmt &S) = 0; |
288 | virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, |
289 | const ObjCAtThrowStmt &S, |
290 | bool ClearInsertionPoint=true) = 0; |
291 | virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, |
292 | Address AddrWeakObj) = 0; |
293 | virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, |
294 | llvm::Value *src, Address dest) = 0; |
295 | virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, |
296 | llvm::Value *src, Address dest, |
297 | bool threadlocal=false) = 0; |
298 | virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, |
299 | llvm::Value *src, Address dest, |
300 | llvm::Value *ivarOffset) = 0; |
301 | virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, |
302 | llvm::Value *src, Address dest) = 0; |
303 | |
304 | virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, |
305 | QualType ObjectTy, |
306 | llvm::Value *BaseValue, |
307 | const ObjCIvarDecl *Ivar, |
308 | unsigned CVRQualifiers) = 0; |
309 | virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, |
310 | const ObjCInterfaceDecl *Interface, |
311 | const ObjCIvarDecl *Ivar) = 0; |
312 | virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, |
313 | Address DestPtr, |
314 | Address SrcPtr, |
315 | llvm::Value *Size) = 0; |
316 | virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, |
317 | const CodeGen::CGBlockInfo &blockInfo) = 0; |
318 | virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, |
319 | const CodeGen::CGBlockInfo &blockInfo) = 0; |
320 | virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, |
321 | const CGBlockInfo &blockInfo) { |
322 | return {}; |
323 | } |
324 | |
325 | /// Returns an i8* which points to the byref layout information. |
326 | virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, |
327 | QualType T) = 0; |
328 | |
329 | struct MessageSendInfo { |
330 | const CGFunctionInfo &CallInfo; |
331 | llvm::PointerType *MessengerType; |
332 | |
333 | MessageSendInfo(const CGFunctionInfo &callInfo, |
334 | llvm::PointerType *messengerType) |
335 | : CallInfo(callInfo), MessengerType(messengerType) {} |
336 | }; |
337 | |
338 | MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method, |
339 | QualType resultType, |
340 | CallArgList &callArgs); |
341 | bool canMessageReceiverBeNull(CodeGenFunction &CGF, |
342 | const ObjCMethodDecl *method, |
343 | bool isSuper, |
344 | const ObjCInterfaceDecl *classReceiver, |
345 | llvm::Value *receiver); |
346 | static bool isWeakLinkedClass(const ObjCInterfaceDecl *cls); |
347 | |
348 | /// Destroy the callee-destroyed arguments of the given method, |
349 | /// if it has any. Used for nil-receiver paths in message sends. |
350 | /// Never does anything if the method does not satisfy |
351 | /// hasParamDestroyedInCallee(). |
352 | /// |
353 | /// \param callArgs - just the formal arguments, not including implicit |
354 | /// arguments such as self and cmd |
355 | static void destroyCalleeDestroyedArguments(CodeGenFunction &CGF, |
356 | const ObjCMethodDecl *method, |
357 | const CallArgList &callArgs); |
358 | |
359 | // FIXME: This probably shouldn't be here, but the code to compute |
360 | // it is here. |
361 | unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM, |
362 | const ObjCInterfaceDecl *ID, |
363 | const ObjCIvarDecl *Ivar); |
364 | }; |
365 | |
366 | /// Creates an instance of an Objective-C runtime class. |
367 | //TODO: This should include some way of selecting which runtime to target. |
368 | CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); |
369 | CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); |
370 | } |
371 | } |
372 | #endif |
373 | |