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 | |