 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
58.0% |
153 / 264 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
81.1% |
214 / 264 |
| |
|
Line Coverage: |
77.1% |
731 / 948 |
| |
 |
|
 |
1 : //===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
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 Objective-C code generation targetting the GNU runtime. The
11 : // class in this file generates structures used by the GNU Objective-C runtime
12 : // library. These structures are defined in objc/objc.h and objc/objc-api.h in
13 : // the GNU runtime distribution.
14 : //
15 : //===----------------------------------------------------------------------===//
16 :
17 : #include "CGObjCRuntime.h"
18 : #include "CodeGenModule.h"
19 : #include "CodeGenFunction.h"
20 :
21 : #include "clang/AST/ASTContext.h"
22 : #include "clang/AST/Decl.h"
23 : #include "clang/AST/DeclObjC.h"
24 : #include "clang/AST/RecordLayout.h"
25 : #include "clang/AST/StmtObjC.h"
26 :
27 : #include "llvm/Intrinsics.h"
28 : #include "llvm/Module.h"
29 : #include "llvm/ADT/SmallVector.h"
30 : #include "llvm/ADT/StringMap.h"
31 : #include "llvm/Support/Compiler.h"
32 : #include "llvm/Target/TargetData.h"
33 :
34 : #include <map>
35 :
36 :
37 : using namespace clang;
38 : using namespace CodeGen;
39 : using llvm::dyn_cast;
40 :
41 : // The version of the runtime that this class targets. Must match the version
42 : // in the runtime.
43 : static const int RuntimeVersion = 8;
44 : static const int NonFragileRuntimeVersion = 9;
45 : static const int ProtocolVersion = 2;
46 : static const int NonFragileProtocolVersion = 3;
47 :
48 : namespace {
6: branch 8 taken
0: branch 9 not taken
0: branch 19 not taken
0: branch 20 not taken
49 6: class CGObjCGNU : public CodeGen::CGObjCRuntime {
50 : private:
51 : CodeGen::CodeGenModule &CGM;
52 : llvm::Module &TheModule;
53 : const llvm::PointerType *SelectorTy;
54 : const llvm::IntegerType *Int8Ty;
55 : const llvm::PointerType *PtrToInt8Ty;
56 : const llvm::FunctionType *IMPTy;
57 : const llvm::PointerType *IdTy;
58 : const llvm::PointerType *PtrToIdTy;
59 : QualType ASTIdTy;
60 : const llvm::IntegerType *IntTy;
61 : const llvm::PointerType *PtrTy;
62 : const llvm::IntegerType *LongTy;
63 : const llvm::PointerType *PtrToIntTy;
64 : llvm::GlobalAlias *ClassPtrAlias;
65 : llvm::GlobalAlias *MetaClassPtrAlias;
66 : std::vector<llvm::Constant*> Classes;
67 : std::vector<llvm::Constant*> Categories;
68 : std::vector<llvm::Constant*> ConstantStrings;
69 : llvm::StringMap<llvm::Constant*> ObjCStrings;
70 : llvm::Function *LoadFunction;
71 : llvm::StringMap<llvm::Constant*> ExistingProtocols;
72 : typedef std::pair<std::string, std::string> TypedSelector;
73 : std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
74 : llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
75 : // Selectors that we don't emit in GC mode
76 : Selector RetainSel, ReleaseSel, AutoreleaseSel;
77 : // Functions used for GC.
78 : llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn,
79 : *WeakAssignFn, *GlobalAssignFn;
80 : // Some zeros used for GEPs in lots of places.
81 : llvm::Constant *Zeros[2];
82 : llvm::Constant *NULLPtr;
83 : llvm::LLVMContext &VMContext;
84 : private:
85 : llvm::Constant *GenerateIvarList(
86 : const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
87 : const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
88 : const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
89 : llvm::Constant *GenerateMethodList(const std::string &ClassName,
90 : const std::string &CategoryName,
91 : const llvm::SmallVectorImpl<Selector> &MethodSels,
92 : const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
93 : bool isClassMethodList);
94 : llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
95 : llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
96 : llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
97 : llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
98 : llvm::Constant *GenerateProtocolList(
99 : const llvm::SmallVectorImpl<std::string> &Protocols);
100 : // To ensure that all protocols are seen by the runtime, we add a category on
101 : // a class defined in the runtime, declaring no methods, but adopting the
102 : // protocols.
103 : void GenerateProtocolHolderCategory(void);
104 : llvm::Constant *GenerateClassStructure(
105 : llvm::Constant *MetaClass,
106 : llvm::Constant *SuperClass,
107 : unsigned info,
108 : const char *Name,
109 : llvm::Constant *Version,
110 : llvm::Constant *InstanceSize,
111 : llvm::Constant *IVars,
112 : llvm::Constant *Methods,
113 : llvm::Constant *Protocols,
114 : llvm::Constant *IvarOffsets,
115 : llvm::Constant *Properties);
116 : llvm::Constant *GenerateProtocolMethodList(
117 : const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
118 : const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
119 : llvm::Constant *MakeConstantString(const std::string &Str, const std::string
120 : &Name="");
121 : llvm::Constant *ExportUniqueString(const std::string &Str, const std::string
122 : prefix);
123 : llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
124 : std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
125 : llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
126 : llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
127 : std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
128 : llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
129 : llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
130 : const ObjCIvarDecl *Ivar);
131 : void EmitClassRef(const std::string &className);
132 0: llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){
0: branch 1 not taken
0: branch 2 not taken
133 0: if (V->getType() == Ty) return V;
134 0: return B.CreateBitCast(V, Ty);
135 : }
136 : public:
137 : CGObjCGNU(CodeGen::CodeGenModule &cgm);
138 : virtual llvm::Constant *GenerateConstantString(const StringLiteral *);
139 : virtual CodeGen::RValue
140 : GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
141 : QualType ResultType,
142 : Selector Sel,
143 : llvm::Value *Receiver,
144 : bool IsClassMessage,
145 : const CallArgList &CallArgs,
146 : const ObjCMethodDecl *Method);
147 : virtual CodeGen::RValue
148 : GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
149 : QualType ResultType,
150 : Selector Sel,
151 : const ObjCInterfaceDecl *Class,
152 : bool isCategoryImpl,
153 : llvm::Value *Receiver,
154 : bool IsClassMessage,
155 : const CallArgList &CallArgs,
156 : const ObjCMethodDecl *Method);
157 : virtual llvm::Value *GetClass(CGBuilderTy &Builder,
158 : const ObjCInterfaceDecl *OID);
159 : virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
160 : virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
161 : *Method);
162 :
163 : virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
164 : const ObjCContainerDecl *CD);
165 : virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
166 : virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
167 : virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
168 : const ObjCProtocolDecl *PD);
169 : virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
170 : virtual llvm::Function *ModuleInitFunction();
171 : virtual llvm::Function *GetPropertyGetFunction();
172 : virtual llvm::Function *GetPropertySetFunction();
173 : virtual llvm::Constant *EnumerationMutationFunction();
174 :
175 : virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
176 : const Stmt &S);
177 : virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
178 : const ObjCAtThrowStmt &S);
179 : virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
180 : llvm::Value *AddrWeakObj);
181 : virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
182 : llvm::Value *src, llvm::Value *dst);
183 : virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
184 : llvm::Value *src, llvm::Value *dest);
185 : virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
186 : llvm::Value *src, llvm::Value *dest,
187 : llvm::Value *ivarOffset);
188 : virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
189 : llvm::Value *src, llvm::Value *dest);
190 : virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
191 : llvm::Value *DestPtr,
192 : llvm::Value *SrcPtr,
193 : QualType Ty);
194 : virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
195 : QualType ObjectTy,
196 : llvm::Value *BaseValue,
197 : const ObjCIvarDecl *Ivar,
198 : unsigned CVRQualifiers);
199 : virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
200 : const ObjCInterfaceDecl *Interface,
201 : const ObjCIvarDecl *Ivar);
202 : };
203 : } // end anonymous namespace
204 :
205 :
206 : /// Emits a reference to a dummy variable which is emitted with each class.
207 : /// This ensures that a linker error will be generated when trying to link
208 : /// together modules where a referenced class is not defined.
209 2: void CGObjCGNU::EmitClassRef(const std::string &className) {
210 2: std::string symbolRef = "__objc_class_ref_" + className;
211 : // Don't emit two copies of the same symbol
0: branch 2 not taken
2: branch 3 taken
212 2: if (TheModule.getGlobalVariable(symbolRef))
213 0: return;
214 2: std::string symbolName = "__objc_class_name_" + className;
215 2: llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
1: branch 0 taken
1: branch 1 taken
216 2: if (!ClassSymbol) {
217 : ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
218 1: llvm::GlobalValue::ExternalLinkage, 0, symbolName);
219 : }
220 : new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
2: branch 6 taken
0: branch 7 not taken
221 2: llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
222 : }
223 :
224 6: static std::string SymbolNameForClass(const std::string &ClassName) {
225 6: return "_OBJC_CLASS_" + ClassName;
226 : }
227 :
228 : static std::string SymbolNameForMethod(const std::string &ClassName, const
229 15: std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
230 : {
231 15: std::string MethodNameColonStripped = MethodName;
232 : std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
233 15: ':', '_');
234 : return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
2: branch 1 taken
13: branch 2 taken
235 15: CategoryName + "_" + MethodNameColonStripped;
236 : }
237 :
238 7: CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
239 : : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0),
240 7: MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) {
241 : IntTy = cast<llvm::IntegerType>(
242 7: CGM.getTypes().ConvertType(CGM.getContext().IntTy));
243 : LongTy = cast<llvm::IntegerType>(
244 7: CGM.getTypes().ConvertType(CGM.getContext().LongTy));
245 :
246 7: Int8Ty = llvm::Type::getInt8Ty(VMContext);
247 : // C string type. Used in lots of places.
248 7: PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
249 :
250 7: Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
251 7: Zeros[1] = Zeros[0];
252 7: NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
253 : // Get the selector Type.
254 7: QualType selTy = CGM.getContext().getObjCSelType();
0: branch 2 not taken
7: branch 3 taken
0: branch 6 not taken
0: branch 7 not taken
255 7: if (QualType() == selTy) {
256 0: SelectorTy = PtrToInt8Ty;
257 : } else {
258 7: SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
259 : }
260 :
261 7: PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
262 7: PtrTy = PtrToInt8Ty;
263 :
264 : // Object type
265 7: ASTIdTy = CGM.getContext().getObjCIdType();
0: branch 2 not taken
7: branch 3 taken
0: branch 6 not taken
0: branch 7 not taken
266 7: if (QualType() == ASTIdTy) {
267 0: IdTy = PtrToInt8Ty;
268 : } else {
269 7: IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
270 : }
271 7: PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
272 :
273 : // IMP type
274 7: std::vector<const llvm::Type*> IMPArgs;
275 7: IMPArgs.push_back(IdTy);
276 7: IMPArgs.push_back(SelectorTy);
277 7: IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
278 :
0: branch 2 not taken
7: branch 3 taken
0: branch 6 not taken
0: branch 7 not taken
279 7: if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
280 : // Get selectors needed in GC mode
281 0: RetainSel = GetNullarySelector("retain", CGM.getContext());
282 0: ReleaseSel = GetNullarySelector("release", CGM.getContext());
283 0: AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext());
284 :
285 : // Get functions needed in GC mode
286 :
287 : // id objc_assign_ivar(id, id, ptrdiff_t);
288 0: std::vector<const llvm::Type*> Args(1, IdTy);
289 0: Args.push_back(PtrToIdTy);
290 : // FIXME: ptrdiff_t
291 0: Args.push_back(LongTy);
292 0: llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false);
293 0: IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
294 : // id objc_assign_strongCast (id, id*)
295 0: Args.pop_back();
296 0: FTy = llvm::FunctionType::get(IdTy, Args, false);
297 : StrongCastAssignFn =
298 0: CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
299 : // id objc_assign_global(id, id*);
300 0: FTy = llvm::FunctionType::get(IdTy, Args, false);
301 0: GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
302 : // id objc_assign_weak(id, id*);
303 0: FTy = llvm::FunctionType::get(IdTy, Args, false);
304 0: WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
305 : // id objc_read_weak(id*);
306 0: Args.clear();
307 0: Args.push_back(PtrToIdTy);
308 0: FTy = llvm::FunctionType::get(IdTy, Args, false);
309 0: WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
310 : // void *objc_memmove_collectable(void*, void *, size_t);
311 0: Args.clear();
312 0: Args.push_back(PtrToInt8Ty);
313 0: Args.push_back(PtrToInt8Ty);
314 : // FIXME: size_t
315 0: Args.push_back(LongTy);
316 0: FTy = llvm::FunctionType::get(IdTy, Args, false);
317 0: MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
318 7: }
319 7: }
320 :
321 : // This has to perform the lookup every time, since posing and related
322 : // techniques can modify the name -> class mapping.
323 : llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
324 0: const ObjCInterfaceDecl *OID) {
325 0: llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
326 : // With the incompatible ABI, this will need to be replaced with a direct
327 : // reference to the class symbol. For the compatible nonfragile ABI we are
328 : // still performing this lookup at run time but emitting the symbol for the
329 : // class externally so that we can make the switch later.
330 0: EmitClassRef(OID->getNameAsString());
331 0: ClassName = Builder.CreateStructGEP(ClassName, 0);
332 :
333 0: std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
334 : llvm::Constant *ClassLookupFn =
335 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy,
336 : Params,
337 : true),
338 0: "objc_lookup_class");
339 0: return Builder.CreateCall(ClassLookupFn, ClassName);
340 : }
341 :
342 17: llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) {
343 17: llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
14: branch 0 taken
3: branch 1 taken
344 17: if (US == 0)
345 : US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
346 : llvm::GlobalValue::PrivateLinkage,
347 : ".objc_untyped_selector_alias"+Sel.getAsString(),
348 14: NULL, &TheModule);
349 :
350 17: return Builder.CreateLoad(US);
351 : }
352 :
353 : llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
354 0: *Method) {
355 :
356 0: std::string SelName = Method->getSelector().getAsString();
357 0: std::string SelTypes;
358 0: CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
359 : // Typed selectors
360 : TypedSelector Selector = TypedSelector(SelName,
361 0: SelTypes);
362 :
363 : // If it's already cached, return it.
0: branch 1 not taken
0: branch 2 not taken
364 0: if (TypedSelectors[Selector]) {
365 0: return Builder.CreateLoad(TypedSelectors[Selector]);
366 : }
367 :
368 : // If it isn't, cache it.
369 : llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
370 : llvm::PointerType::getUnqual(SelectorTy),
371 : llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName,
372 0: NULL, &TheModule);
373 0: TypedSelectors[Selector] = Sel;
374 :
375 0: return Builder.CreateLoad(Sel);
376 : }
377 :
378 : llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
379 65: const std::string &Name) {
380 65: llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
381 65: return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
382 : }
383 : llvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str,
384 14: const std::string prefix) {
385 14: std::string name = prefix + Str;
386 14: llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
14: branch 0 taken
0: branch 1 not taken
387 14: if (!ConstStr) {
388 14: llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true);
389 : ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
390 14: llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
391 : }
392 14: return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
393 : }
394 :
395 : llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
396 : std::vector<llvm::Constant*> &V, llvm::StringRef Name,
397 57: llvm::GlobalValue::LinkageTypes linkage) {
398 57: llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
399 : return new llvm::GlobalVariable(TheModule, Ty, false,
400 57: llvm::GlobalValue::InternalLinkage, C, Name);
401 : }
402 :
403 : llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
404 : std::vector<llvm::Constant*> &V, llvm::StringRef Name,
405 10: llvm::GlobalValue::LinkageTypes linkage) {
406 10: llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
407 : return new llvm::GlobalVariable(TheModule, Ty, false,
408 10: llvm::GlobalValue::InternalLinkage, C, Name);
409 : }
410 :
411 : /// Generate an NSConstantString object.
412 3: llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
413 :
414 3: std::string Str(SL->getStrData(), SL->getByteLength());
415 :
416 : // Look for an existing one
417 3: llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
0: branch 2 not taken
3: branch 3 taken
418 3: if (old != ObjCStrings.end())
419 0: return old->getValue();
420 :
421 3: std::vector<llvm::Constant*> Ivars;
422 3: Ivars.push_back(NULLPtr);
423 3: Ivars.push_back(MakeConstantString(Str));
424 3: Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
425 : llvm::Constant *ObjCStr = MakeGlobal(
426 : llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
427 3: Ivars, ".objc_str");
428 3: ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
429 3: ObjCStrings[Str] = ObjCStr;
430 3: ConstantStrings.push_back(ObjCStr);
431 3: return ObjCStr;
432 : }
433 :
434 : ///Generates a message send where the super is the receiver. This is a message
435 : ///send to self with special delivery semantics indicating which class's method
436 : ///should be called.
437 : CodeGen::RValue
438 : CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
439 : QualType ResultType,
440 : Selector Sel,
441 : const ObjCInterfaceDecl *Class,
442 : bool isCategoryImpl,
443 : llvm::Value *Receiver,
444 : bool IsClassMessage,
445 : const CallArgList &CallArgs,
446 3: const ObjCMethodDecl *Method) {
0: branch 2 not taken
3: branch 3 taken
447 3: if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
0: branch 1 not taken
0: branch 2 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
448 0: if (Sel == RetainSel || Sel == AutoreleaseSel) {
449 0: return RValue::get(Receiver);
450 : }
0: branch 1 not taken
0: branch 2 not taken
451 0: if (Sel == ReleaseSel) {
452 0: return RValue::get(0);
453 : }
454 : }
455 3: llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
456 :
457 3: CallArgList ActualArgs;
458 :
459 : ActualArgs.push_back(
460 : std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)),
461 3: ASTIdTy));
462 : ActualArgs.push_back(std::make_pair(RValue::get(cmd),
463 3: CGF.getContext().getObjCSelType()));
464 3: ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
465 :
466 3: CodeGenTypes &Types = CGM.getTypes();
467 : const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
468 3: CC_Default, false);
469 : const llvm::FunctionType *impType =
0: branch 0 not taken
3: branch 1 taken
470 3: Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
471 :
472 3: llvm::Value *ReceiverClass = 0;
0: branch 0 not taken
3: branch 1 taken
473 3: if (isCategoryImpl) {
474 0: llvm::Constant *classLookupFunction = 0;
475 0: std::vector<const llvm::Type*> Params;
476 0: Params.push_back(PtrTy);
0: branch 0 not taken
0: branch 1 not taken
477 0: if (IsClassMessage) {
478 : classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
479 0: IdTy, Params, true), "objc_get_meta_class");
480 : } else {
481 : classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
482 0: IdTy, Params, true), "objc_get_class");
483 : }
484 : ReceiverClass = CGF.Builder.CreateCall(classLookupFunction,
485 0: MakeConstantString(Class->getNameAsString()));
486 : } else {
487 : // Set up global aliases for the metaclass or class pointer if they do not
488 : // already exist. These will are forward-references which will be set to
489 : // pointers to the class and metaclass structure created for the runtime
490 : // load function. To send a message to super, we look up the value of the
491 : // super_class pointer from either the class or metaclass structure.
1: branch 0 taken
2: branch 1 taken
492 3: if (IsClassMessage) {
1: branch 0 taken
0: branch 1 not taken
493 1: if (!MetaClassPtrAlias) {
494 : MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
495 : llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
496 1: Class->getNameAsString(), NULL, &TheModule);
497 : }
498 1: ReceiverClass = MetaClassPtrAlias;
499 : } else {
1: branch 0 taken
1: branch 1 taken
500 2: if (!ClassPtrAlias) {
501 : ClassPtrAlias = new llvm::GlobalAlias(IdTy,
502 : llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
503 1: Class->getNameAsString(), NULL, &TheModule);
504 : }
505 2: ReceiverClass = ClassPtrAlias;
506 : }
507 : }
508 : // Cast the pointer to a simplified version of the class structure
509 : ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass,
510 : llvm::PointerType::getUnqual(
511 3: llvm::StructType::get(VMContext, IdTy, IdTy, NULL)));
512 : // Get the superclass pointer
513 3: ReceiverClass = CGF.Builder.CreateStructGEP(ReceiverClass, 1);
514 : // Load the superclass pointer
515 3: ReceiverClass = CGF.Builder.CreateLoad(ReceiverClass);
516 : // Construct the structure used to look up the IMP
517 : llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext,
518 3: Receiver->getType(), IdTy, NULL);
519 3: llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
520 :
521 3: CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
522 : CGF.Builder.CreateStore(ReceiverClass,
523 3: CGF.Builder.CreateStructGEP(ObjCSuper, 1));
524 :
525 : // Get the IMP
526 3: std::vector<const llvm::Type*> Params;
527 3: Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy));
528 3: Params.push_back(SelectorTy);
529 : llvm::Constant *lookupFunction =
530 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(
531 : llvm::PointerType::getUnqual(impType), Params, true),
532 3: "objc_msg_lookup_super");
533 :
534 3: llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
535 : llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
536 3: lookupArgs+2);
537 :
538 3: return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs);
539 : }
540 :
541 : /// Generate code for a message send expression.
542 : CodeGen::RValue
543 : CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
544 : QualType ResultType,
545 : Selector Sel,
546 : llvm::Value *Receiver,
547 : bool IsClassMessage,
548 : const CallArgList &CallArgs,
549 12: const ObjCMethodDecl *Method) {
0: branch 2 not taken
12: branch 3 taken
550 12: if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
0: branch 1 not taken
0: branch 2 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
551 0: if (Sel == RetainSel || Sel == AutoreleaseSel) {
552 0: return RValue::get(Receiver);
553 : }
0: branch 1 not taken
0: branch 2 not taken
554 0: if (Sel == ReleaseSel) {
555 0: return RValue::get(0);
556 : }
557 : }
558 12: CGBuilderTy &Builder = CGF.Builder;
559 12: IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
560 : llvm::Value *cmd;
0: branch 0 not taken
12: branch 1 taken
561 12: if (Method)
562 0: cmd = GetSelector(Builder, Method);
563 : else
564 12: cmd = GetSelector(Builder, Sel);
565 12: CallArgList ActualArgs;
566 :
567 12: Receiver = Builder.CreateBitCast(Receiver, IdTy);
568 : ActualArgs.push_back(
569 12: std::make_pair(RValue::get(Receiver), ASTIdTy));
570 : ActualArgs.push_back(std::make_pair(RValue::get(cmd),
571 12: CGF.getContext().getObjCSelType()));
572 12: ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
573 :
574 12: CodeGenTypes &Types = CGM.getTypes();
575 : const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
576 12: CC_Default, false);
577 : const llvm::FunctionType *impType =
0: branch 0 not taken
12: branch 1 taken
578 12: Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
579 :
580 : llvm::Value *imp;
581 : // For sender-aware dispatch, we pass the sender as the third argument to a
582 : // lookup function. When sending messages from C code, the sender is nil.
583 : // objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
5: branch 2 taken
7: branch 3 taken
584 12: if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
585 :
586 5: std::vector<const llvm::Type*> Params;
587 5: llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType());
588 5: Builder.CreateStore(Receiver, ReceiverPtr);
589 5: Params.push_back(ReceiverPtr->getType());
590 5: Params.push_back(SelectorTy);
591 : llvm::Value *self;
592 :
0: branch 1 not taken
5: branch 2 taken
593 5: if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) {
594 0: self = CGF.LoadObjCSelf();
595 : } else {
596 5: self = llvm::ConstantPointerNull::get(IdTy);
597 : }
598 :
599 5: Params.push_back(self->getType());
600 :
601 : // The lookup function returns a slot, which can be safely cached.
602 : llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
603 5: IntTy, llvm::PointerType::getUnqual(impType), NULL);
604 : llvm::Constant *lookupFunction =
605 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(
606 : llvm::PointerType::getUnqual(SlotTy), Params, true),
607 5: "objc_msg_lookup_sender");
608 :
609 : // The lookup function is guaranteed not to capture the receiver pointer.
1: branch 1 taken
4: branch 2 taken
610 5: if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) {
611 1: LookupFn->setDoesNotCapture(1);
612 : }
613 :
614 : llvm::Value *slot =
615 5: Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self);
616 5: imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
617 : // The lookup function may have changed the receiver, so make sure we use
618 : // the new one.
619 : ActualArgs[0] =
620 5: std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy);
621 : } else {
622 7: std::vector<const llvm::Type*> Params;
623 7: Params.push_back(Receiver->getType());
624 7: Params.push_back(SelectorTy);
625 : llvm::Constant *lookupFunction =
626 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(
627 : llvm::PointerType::getUnqual(impType), Params, true),
628 7: "objc_msg_lookup");
629 :
630 7: imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
631 : }
632 :
633 12: return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs);
634 : }
635 :
636 : /// Generates a MethodList. Used in construction of a objc_class and
637 : /// objc_category structures.
638 : llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
639 : const std::string &CategoryName,
640 : const llvm::SmallVectorImpl<Selector> &MethodSels,
641 : const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
642 22: bool isClassMethodList) {
20: branch 1 taken
2: branch 2 taken
643 22: if (MethodSels.empty())
644 20: return NULLPtr;
645 : // Get the method structure type.
646 : llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext,
647 : PtrToInt8Ty, // Really a selector, but the runtime creates it us.
648 : PtrToInt8Ty, // Method types
649 : llvm::PointerType::getUnqual(IMPTy), //Method pointer
650 2: NULL);
651 2: std::vector<llvm::Constant*> Methods;
652 2: std::vector<llvm::Constant*> Elements;
8: branch 1 taken
2: branch 2 taken
653 10: for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
654 8: Elements.clear();
7: branch 0 taken
1: branch 1 taken
655 8: if (llvm::Constant *Method =
656 : TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
657 : MethodSels[i].getAsString(),
658 8: isClassMethodList))) {
659 7: llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
660 7: Elements.push_back(C);
661 7: Elements.push_back(MethodTypes[i]);
662 : Method = llvm::ConstantExpr::getBitCast(Method,
663 7: llvm::PointerType::getUnqual(IMPTy));
664 7: Elements.push_back(Method);
665 7: Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
666 : }
667 : }
668 :
669 : // Array of method structures
670 : llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
671 2: Methods.size());
672 : llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
673 2: Methods);
674 :
675 : // Structure containing list pointer, array and array count
676 2: llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
677 2: llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext);
678 2: llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
679 : llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext,
680 : NextPtrTy,
681 : IntTy,
682 : ObjCMethodArrayTy,
683 2: NULL);
684 : // Refine next pointer type to concrete type
685 : llvm::cast<llvm::OpaqueType>(
686 2: OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
687 2: ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
688 :
689 2: Methods.clear();
690 : Methods.push_back(llvm::ConstantPointerNull::get(
691 2: llvm::PointerType::getUnqual(ObjCMethodListTy)));
692 : Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
693 2: MethodTypes.size()));
694 2: Methods.push_back(MethodArray);
695 :
696 : // Create an instance of the structure
697 2: return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
698 : }
699 :
700 : /// Generates an IvarList. Used in construction of a objc_class.
701 : llvm::Constant *CGObjCGNU::GenerateIvarList(
702 : const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
703 : const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
704 6: const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
5: branch 1 taken
1: branch 2 taken
705 6: if (IvarNames.size() == 0)
706 5: return NULLPtr;
707 : // Get the method structure type.
708 : llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext,
709 : PtrToInt8Ty,
710 : PtrToInt8Ty,
711 : IntTy,
712 1: NULL);
713 1: std::vector<llvm::Constant*> Ivars;
714 1: std::vector<llvm::Constant*> Elements;
3: branch 1 taken
1: branch 2 taken
715 4: for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
716 3: Elements.clear();
717 3: Elements.push_back(IvarNames[i]);
718 3: Elements.push_back(IvarTypes[i]);
719 3: Elements.push_back(IvarOffsets[i]);
720 3: Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
721 : }
722 :
723 : // Array of method structures
724 : llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
725 1: IvarNames.size());
726 :
727 :
728 1: Elements.clear();
729 1: Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size()));
730 1: Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
731 : // Structure containing array and array count
732 : llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy,
733 : ObjCIvarArrayTy,
734 1: NULL);
735 :
736 : // Create an instance of the structure
737 1: return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
738 : }
739 :
740 : /// Generate a class structure
741 : llvm::Constant *CGObjCGNU::GenerateClassStructure(
742 : llvm::Constant *MetaClass,
743 : llvm::Constant *SuperClass,
744 : unsigned info,
745 : const char *Name,
746 : llvm::Constant *Version,
747 : llvm::Constant *InstanceSize,
748 : llvm::Constant *IVars,
749 : llvm::Constant *Methods,
750 : llvm::Constant *Protocols,
751 : llvm::Constant *IvarOffsets,
752 6: llvm::Constant *Properties) {
753 : // Set up the class structure
754 : // Note: Several of these are char*s when they should be ids. This is
755 : // because the runtime performs this translation on load.
756 : //
757 : // Fields marked New ABI are part of the GNUstep runtime. We emit them
758 : // anyway; the classes will still work with the GNU runtime, they will just
759 : // be ignored.
760 : llvm::StructType *ClassTy = llvm::StructType::get(VMContext,
761 : PtrToInt8Ty, // class_pointer
762 : PtrToInt8Ty, // super_class
763 : PtrToInt8Ty, // name
764 : LongTy, // version
765 : LongTy, // info
766 : LongTy, // instance_size
767 : IVars->getType(), // ivars
768 : Methods->getType(), // methods
769 : // These are all filled in by the runtime, so we pretend
770 : PtrTy, // dtable
771 : PtrTy, // subclass_list
772 : PtrTy, // sibling_class
773 : PtrTy, // protocols
774 : PtrTy, // gc_object_type
775 : // New ABI:
776 : LongTy, // abi_version
777 : IvarOffsets->getType(), // ivar_offsets
778 : Properties->getType(), // properties
779 6: NULL);
780 6: llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
781 : // Fill in the structure
782 6: std::vector<llvm::Constant*> Elements;
783 6: Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
784 6: Elements.push_back(SuperClass);
785 6: Elements.push_back(MakeConstantString(Name, ".class_name"));
786 6: Elements.push_back(Zero);
787 6: Elements.push_back(llvm::ConstantInt::get(LongTy, info));
788 6: Elements.push_back(InstanceSize);
789 6: Elements.push_back(IVars);
790 6: Elements.push_back(Methods);
791 6: Elements.push_back(NULLPtr);
792 6: Elements.push_back(NULLPtr);
793 6: Elements.push_back(NULLPtr);
794 6: Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
795 6: Elements.push_back(NULLPtr);
796 6: Elements.push_back(Zero);
797 6: Elements.push_back(IvarOffsets);
798 6: Elements.push_back(Properties);
799 : // Create an instance of the structure
800 : // This is now an externally visible symbol, so that we can speed up class
801 : // messages in the next ABI.
802 : return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name),
803 6: llvm::GlobalValue::ExternalLinkage);
804 : }
805 :
806 : llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
807 : const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
808 5: const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
809 : // Get the method structure type.
810 : llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext,
811 : PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
812 : PtrToInt8Ty,
813 5: NULL);
814 5: std::vector<llvm::Constant*> Methods;
815 5: std::vector<llvm::Constant*> Elements;
1: branch 1 taken
5: branch 2 taken
816 6: for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
817 1: Elements.clear();
818 1: Elements.push_back(MethodNames[i]);
819 1: Elements.push_back(MethodTypes[i]);
820 1: Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
821 : }
822 : llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
823 5: MethodNames.size());
824 : llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
825 5: Methods);
826 : llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext,
827 5: IntTy, ObjCMethodArrayTy, NULL);
828 5: Methods.clear();
829 5: Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
830 5: Methods.push_back(Array);
831 5: return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
832 : }
833 :
834 : // Create the protocol list structure used in classes, categories and so on
835 : llvm::Constant *CGObjCGNU::GenerateProtocolList(
836 6: const llvm::SmallVectorImpl<std::string> &Protocols) {
837 : llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
838 6: Protocols.size());
839 : llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
840 : PtrTy, //Should be a recurisve pointer, but it's always NULL here.
841 : LongTy,//FIXME: Should be size_t
842 : ProtocolArrayTy,
843 6: NULL);
844 6: std::vector<llvm::Constant*> Elements;
3: branch 2 taken
6: branch 3 taken
845 9: for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
846 : iter != endIter ; iter++) {
847 3: llvm::Constant *protocol = 0;
848 : llvm::StringMap<llvm::Constant*>::iterator value =
849 3: ExistingProtocols.find(*iter);
1: branch 2 taken
2: branch 3 taken
850 3: if (value == ExistingProtocols.end()) {
851 1: protocol = GenerateEmptyProtocol(*iter);
852 : } else {
853 2: protocol = value->getValue();
854 : }
855 : llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
856 3: PtrToInt8Ty);
857 3: Elements.push_back(Ptr);
858 : }
859 : llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
860 6: Elements);
861 6: Elements.clear();
862 6: Elements.push_back(NULLPtr);
863 6: Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
864 6: Elements.push_back(ProtocolArray);
865 6: return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
866 : }
867 :
868 : llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
869 0: const ObjCProtocolDecl *PD) {
870 0: llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
871 : const llvm::Type *T =
872 0: CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
873 0: return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
874 : }
875 :
876 : llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
877 1: const std::string &ProtocolName) {
878 1: llvm::SmallVector<std::string, 0> EmptyStringVector;
879 1: llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector;
880 :
881 1: llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
882 : llvm::Constant *MethodList =
883 1: GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
884 : // Protocols are objects containing lists of the methods implemented and
885 : // protocols adopted.
886 : llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
887 : PtrToInt8Ty,
888 : ProtocolList->getType(),
889 : MethodList->getType(),
890 : MethodList->getType(),
891 : MethodList->getType(),
892 : MethodList->getType(),
893 1: NULL);
894 1: std::vector<llvm::Constant*> Elements;
895 : // The isa pointer must be set to a magic number so the runtime knows it's
896 : // the correct layout.
897 : int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
0: branch 2 not taken
1: branch 3 taken
898 1: NonFragileProtocolVersion : ProtocolVersion;
899 : Elements.push_back(llvm::ConstantExpr::getIntToPtr(
900 1: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
901 1: Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
902 1: Elements.push_back(ProtocolList);
903 1: Elements.push_back(MethodList);
904 1: Elements.push_back(MethodList);
905 1: Elements.push_back(MethodList);
906 1: Elements.push_back(MethodList);
907 1: return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
908 : }
909 :
910 1: void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
911 1: ASTContext &Context = CGM.getContext();
912 1: std::string ProtocolName = PD->getNameAsString();
913 1: llvm::SmallVector<std::string, 16> Protocols;
0: branch 1 not taken
1: branch 2 taken
914 2: for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
915 1: E = PD->protocol_end(); PI != E; ++PI)
916 0: Protocols.push_back((*PI)->getNameAsString());
917 1: llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
918 1: llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
919 1: llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
920 1: llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
1: branch 4 taken
1: branch 5 taken
921 3: for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
922 1: E = PD->instmeth_end(); iter != E; iter++) {
923 1: std::string TypeStr;
924 1: Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
0: branch 2 not taken
1: branch 3 taken
925 1: if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
926 : InstanceMethodNames.push_back(
927 0: MakeConstantString((*iter)->getSelector().getAsString()));
928 0: InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
929 : } else {
930 : OptionalInstanceMethodNames.push_back(
931 1: MakeConstantString((*iter)->getSelector().getAsString()));
932 1: OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
933 : }
934 : }
935 : // Collect information about class methods:
936 1: llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
937 1: llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
938 1: llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
939 1: llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
0: branch 3 not taken
1: branch 4 taken
940 1: for (ObjCProtocolDecl::classmeth_iterator
941 1: iter = PD->classmeth_begin(), endIter = PD->classmeth_end();
942 : iter != endIter ; iter++) {
943 0: std::string TypeStr;
944 0: Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
0: branch 2 not taken
0: branch 3 not taken
945 0: if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
946 : ClassMethodNames.push_back(
947 0: MakeConstantString((*iter)->getSelector().getAsString()));
948 0: ClassMethodTypes.push_back(MakeConstantString(TypeStr));
949 : } else {
950 : OptionalClassMethodNames.push_back(
951 0: MakeConstantString((*iter)->getSelector().getAsString()));
952 0: OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
953 : }
954 : }
955 :
956 1: llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
957 : llvm::Constant *InstanceMethodList =
958 1: GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
959 : llvm::Constant *ClassMethodList =
960 1: GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
961 : llvm::Constant *OptionalInstanceMethodList =
962 : GenerateProtocolMethodList(OptionalInstanceMethodNames,
963 1: OptionalInstanceMethodTypes);
964 : llvm::Constant *OptionalClassMethodList =
965 : GenerateProtocolMethodList(OptionalClassMethodNames,
966 1: OptionalClassMethodTypes);
967 :
968 : // Property metadata: name, attributes, isSynthesized, setter name, setter
969 : // types, getter name, getter types.
970 : // The isSynthesized value is always set to 0 in a protocol. It exists to
971 : // simplify the runtime library by allowing it to use the same data
972 : // structures for protocol metadata everywhere.
973 : llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
974 : PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
975 1: PtrToInt8Ty, NULL);
976 1: std::vector<llvm::Constant*> Properties;
977 1: std::vector<llvm::Constant*> OptionalProperties;
978 :
979 : // Add all of the property methods need adding to the method list and to the
980 : // property metadata list.
0: branch 3 not taken
1: branch 4 taken
981 1: for (ObjCContainerDecl::prop_iterator
982 1: iter = PD->prop_begin(), endIter = PD->prop_end();
983 : iter != endIter ; iter++) {
984 0: std::vector<llvm::Constant*> Fields;
985 0: ObjCPropertyDecl *property = (*iter);
986 :
987 0: Fields.push_back(MakeConstantString(property->getNameAsString()));
988 : Fields.push_back(llvm::ConstantInt::get(Int8Ty,
989 0: property->getPropertyAttributes()));
990 0: Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
0: branch 1 not taken
0: branch 2 not taken
991 0: if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
992 0: std::string TypeStr;
993 0: Context.getObjCEncodingForMethodDecl(getter,TypeStr);
994 0: llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
995 0: InstanceMethodTypes.push_back(TypeEncoding);
996 0: Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
997 0: Fields.push_back(TypeEncoding);
998 : } else {
999 0: Fields.push_back(NULLPtr);
1000 0: Fields.push_back(NULLPtr);
1001 : }
0: branch 1 not taken
0: branch 2 not taken
1002 0: if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
1003 0: std::string TypeStr;
1004 0: Context.getObjCEncodingForMethodDecl(setter,TypeStr);
1005 0: llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1006 0: InstanceMethodTypes.push_back(TypeEncoding);
1007 0: Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
1008 0: Fields.push_back(TypeEncoding);
1009 : } else {
1010 0: Fields.push_back(NULLPtr);
1011 0: Fields.push_back(NULLPtr);
1012 : }
0: branch 1 not taken
0: branch 2 not taken
1013 0: if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
1014 0: OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1015 : } else {
1016 0: Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1017 : }
1018 : }
1019 : llvm::Constant *PropertyArray = llvm::ConstantArray::get(
1020 1: llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
1021 : llvm::Constant* PropertyListInitFields[] =
1022 1: {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
1023 :
1024 : llvm::Constant *PropertyListInit =
1025 1: llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
1026 : llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
1027 : PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
1028 1: PropertyListInit, ".objc_property_list");
1029 :
1030 : llvm::Constant *OptionalPropertyArray =
1031 : llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
1032 1: OptionalProperties.size()) , OptionalProperties);
1033 : llvm::Constant* OptionalPropertyListInitFields[] = {
1034 : llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
1035 1: OptionalPropertyArray };
1036 :
1037 : llvm::Constant *OptionalPropertyListInit =
1038 1: llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false);
1039 : llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
1040 : OptionalPropertyListInit->getType(), false,
1041 : llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
1042 1: ".objc_property_list");
1043 :
1044 : // Protocols are objects containing lists of the methods implemented and
1045 : // protocols adopted.
1046 : llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
1047 : PtrToInt8Ty,
1048 : ProtocolList->getType(),
1049 : InstanceMethodList->getType(),
1050 : ClassMethodList->getType(),
1051 : OptionalInstanceMethodList->getType(),
1052 : OptionalClassMethodList->getType(),
1053 : PropertyList->getType(),
1054 : OptionalPropertyList->getType(),
1055 1: NULL);
1056 1: std::vector<llvm::Constant*> Elements;
1057 : // The isa pointer must be set to a magic number so the runtime knows it's
1058 : // the correct layout.
1059 : int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
0: branch 2 not taken
1: branch 3 taken
1060 1: NonFragileProtocolVersion : ProtocolVersion;
1061 : Elements.push_back(llvm::ConstantExpr::getIntToPtr(
1062 1: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
1063 1: Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
1064 1: Elements.push_back(ProtocolList);
1065 1: Elements.push_back(InstanceMethodList);
1066 1: Elements.push_back(ClassMethodList);
1067 1: Elements.push_back(OptionalInstanceMethodList);
1068 1: Elements.push_back(OptionalClassMethodList);
1069 1: Elements.push_back(PropertyList);
1070 1: Elements.push_back(OptionalPropertyList);
1071 : ExistingProtocols[ProtocolName] =
1072 : llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
1073 1: ".objc_protocol"), IdTy);
1074 1: }
1075 7: void CGObjCGNU::GenerateProtocolHolderCategory(void) {
1076 : // Collect information about instance methods
1077 7: llvm::SmallVector<Selector, 1> MethodSels;
1078 7: llvm::SmallVector<llvm::Constant*, 1> MethodTypes;
1079 :
1080 7: std::vector<llvm::Constant*> Elements;
1081 7: const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
1082 7: const std::string CategoryName = "AnotherHack";
1083 7: Elements.push_back(MakeConstantString(CategoryName));
1084 7: Elements.push_back(MakeConstantString(ClassName));
1085 : // Instance method list
1086 : Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1087 7: ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
1088 : // Class method list
1089 : Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1090 7: ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
1091 : // Protocol list
1092 : llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
1093 7: ExistingProtocols.size());
1094 : llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
1095 : PtrTy, //Should be a recurisve pointer, but it's always NULL here.
1096 : LongTy,//FIXME: Should be size_t
1097 : ProtocolArrayTy,
1098 7: NULL);
1099 7: std::vector<llvm::Constant*> ProtocolElements;
1: branch 2 taken
7: branch 3 taken
1100 8: for (llvm::StringMapIterator<llvm::Constant*> iter =
1101 7: ExistingProtocols.begin(), endIter = ExistingProtocols.end();
1102 : iter != endIter ; iter++) {
1103 : llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
1104 1: PtrTy);
1105 1: ProtocolElements.push_back(Ptr);
1106 : }
1107 : llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
1108 7: ProtocolElements);
1109 7: ProtocolElements.clear();
1110 7: ProtocolElements.push_back(NULLPtr);
1111 : ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
1112 7: ExistingProtocols.size()));
1113 7: ProtocolElements.push_back(ProtocolArray);
1114 : Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
1115 7: ProtocolElements, ".objc_protocol_list"), PtrTy));
1116 : Categories.push_back(llvm::ConstantExpr::getBitCast(
1117 : MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
1118 7: PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
1119 7: }
1120 :
1121 1: void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
1122 1: std::string ClassName = OCD->getClassInterface()->getNameAsString();
1123 1: std::string CategoryName = OCD->getNameAsString();
1124 : // Collect information about instance methods
1125 1: llvm::SmallVector<Selector, 16> InstanceMethodSels;
1126 1: llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
0: branch 3 not taken
1: branch 4 taken
1127 1: for (ObjCCategoryImplDecl::instmeth_iterator
1128 1: iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end();
1129 : iter != endIter ; iter++) {
1130 0: InstanceMethodSels.push_back((*iter)->getSelector());
1131 0: std::string TypeStr;
1132 0: CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
1133 0: InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
1134 : }
1135 :
1136 : // Collect information about class methods
1137 1: llvm::SmallVector<Selector, 16> ClassMethodSels;
1138 1: llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
0: branch 3 not taken
1: branch 4 taken
1139 1: for (ObjCCategoryImplDecl::classmeth_iterator
1140 1: iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end();
1141 : iter != endIter ; iter++) {
1142 0: ClassMethodSels.push_back((*iter)->getSelector());
1143 0: std::string TypeStr;
1144 0: CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
1145 0: ClassMethodTypes.push_back(MakeConstantString(TypeStr));
1146 : }
1147 :
1148 : // Collect the names of referenced protocols
1149 1: llvm::SmallVector<std::string, 16> Protocols;
1150 1: const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
1151 1: const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
1: branch 1 taken
1: branch 2 taken
1152 3: for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
1153 1: E = Protos.end(); I != E; ++I)
1154 1: Protocols.push_back((*I)->getNameAsString());
1155 :
1156 1: std::vector<llvm::Constant*> Elements;
1157 1: Elements.push_back(MakeConstantString(CategoryName));
1158 1: Elements.push_back(MakeConstantString(ClassName));
1159 : // Instance method list
1160 : Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1161 : ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
1162 1: false), PtrTy));
1163 : // Class method list
1164 : Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1165 : ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
1166 1: PtrTy));
1167 : // Protocol list
1168 : Elements.push_back(llvm::ConstantExpr::getBitCast(
1169 1: GenerateProtocolList(Protocols), PtrTy));
1170 : Categories.push_back(llvm::ConstantExpr::getBitCast(
1171 : MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
1172 1: PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
1173 1: }
1174 :
1175 : llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
1176 : llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
1177 3: llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
1178 3: ASTContext &Context = CGM.getContext();
1179 : //
1180 : // Property metadata: name, attributes, isSynthesized, setter name, setter
1181 : // types, getter name, getter types.
1182 : llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
1183 : PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
1184 3: PtrToInt8Ty, NULL);
1185 3: std::vector<llvm::Constant*> Properties;
1186 :
1187 :
1188 : // Add all of the property methods need adding to the method list and to the
1189 : // property metadata list.
3: branch 3 taken
3: branch 4 taken
1190 6: for (ObjCImplDecl::propimpl_iterator
1191 3: iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
1192 : iter != endIter ; iter++) {
1193 3: std::vector<llvm::Constant*> Fields;
1194 3: ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
1195 :
1196 3: Fields.push_back(MakeConstantString(property->getNameAsString()));
1197 : Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1198 3: property->getPropertyAttributes()));
1199 : Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1200 : (*iter)->getPropertyImplementation() ==
1201 3: ObjCPropertyImplDecl::Synthesize));
3: branch 1 taken
0: branch 2 not taken
1202 3: if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
1203 3: InstanceMethodSels.push_back(getter->getSelector());
1204 3: std::string TypeStr;
1205 3: Context.getObjCEncodingForMethodDecl(getter,TypeStr);
1206 3: llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1207 3: InstanceMethodTypes.push_back(TypeEncoding);
1208 3: Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
1209 3: Fields.push_back(TypeEncoding);
1210 : } else {
1211 0: Fields.push_back(NULLPtr);
1212 0: Fields.push_back(NULLPtr);
1213 : }
2: branch 1 taken
1: branch 2 taken
1214 3: if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
1215 2: InstanceMethodSels.push_back(setter->getSelector());
1216 2: std::string TypeStr;
1217 2: Context.getObjCEncodingForMethodDecl(setter,TypeStr);
1218 2: llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1219 2: InstanceMethodTypes.push_back(TypeEncoding);
1220 2: Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
1221 2: Fields.push_back(TypeEncoding);
1222 : } else {
1223 1: Fields.push_back(NULLPtr);
1224 1: Fields.push_back(NULLPtr);
1225 : }
1226 3: Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1227 : }
1228 : llvm::ArrayType *PropertyArrayTy =
1229 3: llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
1230 : llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
1231 3: Properties);
1232 : llvm::Constant* PropertyListInitFields[] =
1233 3: {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
1234 :
1235 : llvm::Constant *PropertyListInit =
1236 3: llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
1237 : return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
1238 : llvm::GlobalValue::InternalLinkage, PropertyListInit,
1239 3: ".objc_property_list");
1240 : }
1241 :
1242 3: void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
1243 3: ASTContext &Context = CGM.getContext();
1244 :
1245 : // Get the superclass name.
1246 : const ObjCInterfaceDecl * SuperClassDecl =
1247 3: OID->getClassInterface()->getSuperClass();
1248 3: std::string SuperClassName;
2: branch 0 taken
1: branch 1 taken
1249 3: if (SuperClassDecl) {
1250 2: SuperClassName = SuperClassDecl->getNameAsString();
1251 2: EmitClassRef(SuperClassName);
1252 : }
1253 :
1254 : // Get the class name
1255 : ObjCInterfaceDecl *ClassDecl =
1256 3: const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
1257 3: std::string ClassName = ClassDecl->getNameAsString();
1258 : // Emit the symbol that is used to generate linker errors if this class is
1259 : // referenced in other modules but not declared.
1260 3: std::string classSymbolName = "__objc_class_name_" + ClassName;
0: branch 0 not taken
3: branch 1 taken
1261 3: if (llvm::GlobalVariable *symbol =
1262 3: TheModule.getGlobalVariable(classSymbolName)) {
1263 0: symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
1264 : } else {
1265 : new llvm::GlobalVariable(TheModule, LongTy, false,
1266 : llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0),
1267 3: classSymbolName);
1268 : }
1269 :
1270 : // Get the size of instances.
1271 3: int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
1272 :
1273 : // Collect information about instance variables.
1274 3: llvm::SmallVector<llvm::Constant*, 16> IvarNames;
1275 3: llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
1276 3: llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
1277 :
1278 3: std::vector<llvm::Constant*> IvarOffsetValues;
1279 :
1280 : int superInstanceSize = !SuperClassDecl ? 0 :
2: branch 0 taken
1: branch 1 taken
1281 3: Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8;
1282 : // For non-fragile ivars, set the instance size to 0 - {the size of just this
1283 : // class}. The runtime will then set this to the correct value on load.
0: branch 2 not taken
3: branch 3 taken
1284 3: if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
1285 0: instanceSize = 0 - (instanceSize - superInstanceSize);
1286 : }
3: branch 2 taken
3: branch 3 taken
1287 9: for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
1288 3: endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
1289 : // Store the name
1290 3: IvarNames.push_back(MakeConstantString((*iter)->getNameAsString()));
1291 : // Get the type encoding for this ivar
1292 3: std::string TypeStr;
1293 3: Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
1294 3: IvarTypes.push_back(MakeConstantString(TypeStr));
1295 : // Get the offset
1296 3: uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter);
1297 3: uint64_t Offset = BaseOffset;
0: branch 2 not taken
3: branch 3 taken
1298 3: if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
1299 0: Offset = BaseOffset - superInstanceSize;
1300 : }
1301 : IvarOffsets.push_back(
1302 3: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset));
1303 : IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy,
1304 : false, llvm::GlobalValue::ExternalLinkage,
1305 : llvm::ConstantInt::get(IntTy, BaseOffset),
1306 : "__objc_ivar_offset_value_" + ClassName +"." +
1307 3: (*iter)->getNameAsString()));
1308 : }
1309 : llvm::Constant *IvarOffsetArrayInit =
1310 : llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy,
1311 3: IvarOffsetValues.size()), IvarOffsetValues);
1312 : llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule,
1313 : IvarOffsetArrayInit->getType(), false,
1314 : llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit,
1315 3: ".ivar.offsets");
1316 :
1317 : // Collect information about instance methods
1318 3: llvm::SmallVector<Selector, 16> InstanceMethodSels;
1319 3: llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
2: branch 3 taken
3: branch 4 taken
1320 5: for (ObjCImplementationDecl::instmeth_iterator
1321 3: iter = OID->instmeth_begin(), endIter = OID->instmeth_end();
1322 : iter != endIter ; iter++) {
1323 2: InstanceMethodSels.push_back((*iter)->getSelector());
1324 2: std::string TypeStr;
1325 2: Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
1326 2: InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
1327 : }
1328 :
1329 : llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
1330 3: InstanceMethodTypes);
1331 :
1332 :
1333 : // Collect information about class methods
1334 3: llvm::SmallVector<Selector, 16> ClassMethodSels;
1335 3: llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
1: branch 3 taken
3: branch 4 taken
1336 4: for (ObjCImplementationDecl::classmeth_iterator
1337 3: iter = OID->classmeth_begin(), endIter = OID->classmeth_end();
1338 : iter != endIter ; iter++) {
1339 1: ClassMethodSels.push_back((*iter)->getSelector());
1340 1: std::string TypeStr;
1341 1: Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
1342 1: ClassMethodTypes.push_back(MakeConstantString(TypeStr));
1343 : }
1344 : // Collect the names of referenced protocols
1345 3: llvm::SmallVector<std::string, 16> Protocols;
1346 3: const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
2: branch 1 taken
3: branch 2 taken
1347 8: for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
1348 3: E = Protos.end(); I != E; ++I)
1349 2: Protocols.push_back((*I)->getNameAsString());
1350 :
1351 :
1352 :
1353 : // Get the superclass pointer.
1354 : llvm::Constant *SuperClass;
2: branch 1 taken
1: branch 2 taken
1355 3: if (!SuperClassName.empty()) {
1356 2: SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
1357 : } else {
1358 1: SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
1359 : }
1360 : // Empty vector used to construct empty method lists
1361 3: llvm::SmallVector<llvm::Constant*, 1> empty;
1362 : // Generate the method and instance variable lists
1363 : llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
1364 3: InstanceMethodSels, InstanceMethodTypes, false);
1365 : llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
1366 3: ClassMethodSels, ClassMethodTypes, true);
1367 : llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
1368 3: IvarOffsets);
1369 : // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
1370 : // we emit a symbol containing the offset for each ivar in the class. This
1371 : // allows code compiled for the non-Fragile ABI to inherit from code compiled
1372 : // for the legacy ABI, without causing problems. The converse is also
1373 : // possible, but causes all ivar accesses to be fragile.
1374 3: int i = 0;
1375 : // Offset pointer for getting at the correct field in the ivar list when
1376 : // setting up the alias. These are: The base address for the global, the
1377 : // ivar array (second field), the ivar in this list (set for each ivar), and
1378 : // the offset (third field in ivar structure)
1379 3: const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
1380 : llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
1381 : llvm::ConstantInt::get(IndexTy, 1), 0,
1382 3: llvm::ConstantInt::get(IndexTy, 2) };
1383 :
3: branch 2 taken
3: branch 3 taken
1384 9: for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
1385 3: endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
1386 : const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
1387 3: +(*iter)->getNameAsString();
1388 3: offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++);
1389 : // Get the correct ivar field
1390 : llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
1391 3: IvarList, offsetPointerIndexes, 4);
1392 : // Get the existing alias, if one exists.
1393 3: llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
0: branch 0 not taken
3: branch 1 taken
1394 3: if (offset) {
1395 0: offset->setInitializer(offsetValue);
1396 : // If this is the real definition, change its linkage type so that
1397 : // different modules will use this one, rather than their private
1398 : // copy.
1399 0: offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
1400 : } else {
1401 : // Add a new alias if there isn't one already.
1402 : offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
1403 3: false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
1404 : }
1405 : }
1406 : //Generate metaclass for class methods
1407 : llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
1408 : NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
1409 3: empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr);
1410 :
1411 : // Generate the class structure
1412 : llvm::Constant *ClassStruct =
1413 : GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L,
1414 : ClassName.c_str(), 0,
1415 : llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
1416 : MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
1417 3: Properties);
1418 :
1419 : // Resolve the class aliases, if they exist.
1: branch 0 taken
2: branch 1 taken
1420 3: if (ClassPtrAlias) {
1421 : ClassPtrAlias->setAliasee(
1422 1: llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
1423 1: ClassPtrAlias = 0;
1424 : }
1: branch 0 taken
2: branch 1 taken
1425 3: if (MetaClassPtrAlias) {
1426 : MetaClassPtrAlias->setAliasee(
1427 1: llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
1428 1: MetaClassPtrAlias = 0;
1429 : }
1430 :
1431 : // Add class structure to list to be added to the symtab later
1432 3: ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
1433 3: Classes.push_back(ClassStruct);
1434 3: }
1435 :
1436 :
1437 7: llvm::Function *CGObjCGNU::ModuleInitFunction() {
1438 : // Only emit an ObjC load function if no Objective-C stuff has been called
5: branch 1 taken
2: branch 2 taken
5: branch 4 taken
0: branch 5 not taken
2: branch 7 taken
3: branch 8 taken
2: branch 10 taken
0: branch 11 not taken
2: branch 13 taken
0: branch 14 not taken
0: branch 16 not taken
2: branch 17 taken
0: branch 18 not taken
7: branch 19 taken
1439 7: if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
1440 : ExistingProtocols.empty() && TypedSelectors.empty() &&
1441 : UntypedSelectors.empty())
1442 0: return NULL;
1443 :
1444 : // Add all referenced protocols to a category.
1445 7: GenerateProtocolHolderCategory();
1446 :
1447 : const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
1448 7: SelectorTy->getElementType());
1449 7: const llvm::Type *SelStructPtrTy = SelectorTy;
1450 7: bool isSelOpaque = false;
7: branch 0 taken
0: branch 1 not taken
1451 7: if (SelStructTy == 0) {
1452 : SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty,
1453 7: PtrToInt8Ty, NULL);
1454 7: SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
1455 7: isSelOpaque = true;
1456 : }
1457 :
1458 : // Name the ObjC types to make the IR a bit easier to read
1459 7: TheModule.addTypeName(".objc_selector", SelStructPtrTy);
1460 7: TheModule.addTypeName(".objc_id", IdTy);
1461 7: TheModule.addTypeName(".objc_imp", IMPTy);
1462 :
1463 7: std::vector<llvm::Constant*> Elements;
1464 7: llvm::Constant *Statics = NULLPtr;
1465 : // Generate statics list:
3: branch 1 taken
4: branch 2 taken
1466 7: if (ConstantStrings.size()) {
1467 : llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
1468 3: ConstantStrings.size() + 1);
1469 3: ConstantStrings.push_back(NULLPtr);
1470 :
1471 3: llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass;
2: branch 1 taken
1: branch 2 taken
1472 3: if (StringClass.empty()) StringClass = "NXConstantString";
1473 : Elements.push_back(MakeConstantString(StringClass,
1474 3: ".objc_static_class_name"));
1475 : Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
1476 3: ConstantStrings));
1477 : llvm::StructType *StaticsListTy =
1478 3: llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL);
1479 : llvm::Type *StaticsListPtrTy =
1480 3: llvm::PointerType::getUnqual(StaticsListTy);
1481 3: Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
1482 : llvm::ArrayType *StaticsListArrayTy =
1483 3: llvm::ArrayType::get(StaticsListPtrTy, 2);
1484 3: Elements.clear();
1485 3: Elements.push_back(Statics);
1486 3: Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
1487 3: Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
1488 3: Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
1489 : }
1490 : // Array of classes, categories, and constant objects
1491 : llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
1492 7: Classes.size() + Categories.size() + 2);
1493 : llvm::StructType *SymTabTy = llvm::StructType::get(VMContext,
1494 : LongTy, SelStructPtrTy,
1495 : llvm::Type::getInt16Ty(VMContext),
1496 : llvm::Type::getInt16Ty(VMContext),
1497 7: ClassListTy, NULL);
1498 :
1499 7: Elements.clear();
1500 : // Pointer to an array of selectors used in this module.
1501 7: std::vector<llvm::Constant*> Selectors;
0: branch 2 not taken
7: branch 3 taken
1502 7: for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
1503 7: iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
1504 : iter != iterEnd ; ++iter) {
1505 0: Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name"));
1506 : Elements.push_back(MakeConstantString(iter->first.second,
1507 0: ".objc_sel_types"));
1508 0: Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
1509 0: Elements.clear();
1510 : }
14: branch 2 taken
7: branch 3 taken
1511 21: for (llvm::StringMap<llvm::GlobalAlias*>::iterator
1512 7: iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
1513 : iter != iterEnd; ++iter) {
1514 : Elements.push_back(
1515 14: ExportUniqueString(iter->getKeyData(), ".objc_sel_name"));
1516 14: Elements.push_back(NULLPtr);
1517 14: Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
1518 14: Elements.clear();
1519 : }
1520 7: Elements.push_back(NULLPtr);
1521 7: Elements.push_back(NULLPtr);
1522 7: Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
1523 7: Elements.clear();
1524 : // Number of static selectors
1525 7: Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
1526 : llvm::Constant *SelectorList = MakeGlobal(
1527 : llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
1528 7: ".objc_selector_list");
1529 : Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
1530 7: SelStructPtrTy));
1531 :
1532 : // Now that all of the static selectors exist, create pointers to them.
1533 7: int index = 0;
0: branch 2 not taken
7: branch 3 taken
1534 7: for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
1535 7: iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
1536 : iter != iterEnd; ++iter) {
1537 : llvm::Constant *Idxs[] = {Zeros[0],
1538 0: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
1539 : llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
1540 : true, llvm::GlobalValue::InternalLinkage,
1541 : llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1542 0: ".objc_sel_ptr");
1543 : // If selectors are defined as an opaque type, cast the pointer to this
1544 : // type.
0: branch 0 not taken
0: branch 1 not taken
1545 0: if (isSelOpaque) {
1546 : SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1547 0: llvm::PointerType::getUnqual(SelectorTy));
1548 : }
1549 0: (*iter).second->setAliasee(SelPtr);
1550 : }
14: branch 2 taken
7: branch 3 taken
1551 21: for (llvm::StringMap<llvm::GlobalAlias*>::iterator
1552 7: iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
1553 : iter != iterEnd; iter++) {
1554 : llvm::Constant *Idxs[] = {Zeros[0],
1555 14: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
1556 : llvm::Constant *SelPtr = new llvm::GlobalVariable
1557 : (TheModule, SelStructPtrTy,
1558 : true, llvm::GlobalValue::InternalLinkage,
1559 : llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1560 14: ".objc_sel_ptr");
1561 : // If selectors are defined as an opaque type, cast the pointer to this
1562 : // type.
14: branch 0 taken
0: branch 1 not taken
1563 14: if (isSelOpaque) {
1564 : SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1565 14: llvm::PointerType::getUnqual(SelectorTy));
1566 : }
1567 14: (*iter).second->setAliasee(SelPtr);
1568 : }
1569 : // Number of classes defined.
1570 : Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
1571 7: Classes.size()));
1572 : // Number of categories defined
1573 : Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
1574 7: Categories.size()));
1575 : // Create an array of classes, then categories, then static object instances
1576 7: Classes.insert(Classes.end(), Categories.begin(), Categories.end());
1577 : // NULL-terminated list of static object instances (mainly constant strings)
1578 7: Classes.push_back(Statics);
1579 7: Classes.push_back(NULLPtr);
1580 7: llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
1581 7: Elements.push_back(ClassList);
1582 : // Construct the symbol table
1583 7: llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
1584 :
1585 : // The symbol table is contained in a module which has some version-checking
1586 : // constants
1587 : llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy,
1588 7: PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
1589 7: Elements.clear();
1590 : // Runtime version used for compatibility checking.
1: branch 2 taken
6: branch 3 taken
1591 7: if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
1592 : Elements.push_back(llvm::ConstantInt::get(LongTy,
1593 1: NonFragileRuntimeVersion));
1594 : } else {
1595 6: Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
1596 : }
1597 : // sizeof(ModuleTy)
1598 7: llvm::TargetData td(&TheModule);
1599 : Elements.push_back(llvm::ConstantInt::get(LongTy,
1600 7: td.getTypeSizeInBits(ModuleTy)/8));
1601 : //FIXME: Should be the path to the file where this module was declared
1602 7: Elements.push_back(NULLPtr);
1603 7: Elements.push_back(SymTab);
1604 7: llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
1605 :
1606 : // Create the load function calling the runtime entry point with the module
1607 : // structure
1608 : llvm::Function * LoadFunction = llvm::Function::Create(
1609 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
1610 : llvm::GlobalValue::InternalLinkage, ".objc_load_function",
1611 7: &TheModule);
1612 : llvm::BasicBlock *EntryBB =
1613 7: llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
1614 7: CGBuilderTy Builder(VMContext);
1615 7: Builder.SetInsertPoint(EntryBB);
1616 :
1617 : std::vector<const llvm::Type*> Params(1,
1618 7: llvm::PointerType::getUnqual(ModuleTy));
1619 : llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
1620 7: llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class");
1621 7: Builder.CreateCall(Register, Module);
1622 7: Builder.CreateRetVoid();
1623 :
1624 7: return LoadFunction;
1625 : }
1626 :
1627 : llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
1628 7: const ObjCContainerDecl *CD) {
1629 : const ObjCCategoryImplDecl *OCD =
1630 7: dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
0: branch 0 not taken
7: branch 1 taken
7: branch 5 taken
0: branch 6 not taken
1631 7: std::string CategoryName = OCD ? OCD->getNameAsString() : "";
1632 7: std::string ClassName = OMD->getClassInterface()->getNameAsString();
1633 7: std::string MethodName = OMD->getSelector().getAsString();
1634 7: bool isClassMethod = !OMD->isInstanceMethod();
1635 :
1636 7: CodeGenTypes &Types = CGM.getTypes();
1637 : const llvm::FunctionType *MethodTy =
1638 7: Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
1639 : std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
1640 7: MethodName, isClassMethod);
1641 :
1642 : llvm::Function *Method
1643 : = llvm::Function::Create(MethodTy,
1644 : llvm::GlobalValue::InternalLinkage,
1645 : FunctionName,
1646 7: &TheModule);
1647 7: return Method;
1648 : }
1649 :
1650 0: llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
1651 0: std::vector<const llvm::Type*> Params;
1652 : const llvm::Type *BoolTy =
1653 0: CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
1654 0: Params.push_back(IdTy);
1655 0: Params.push_back(SelectorTy);
1656 : // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64
1657 0: Params.push_back(LongTy);
1658 0: Params.push_back(BoolTy);
1659 : // void objc_getProperty (id, SEL, ptrdiff_t, bool)
1660 : const llvm::FunctionType *FTy =
1661 0: llvm::FunctionType::get(IdTy, Params, false);
1662 : return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
1663 0: "objc_getProperty"));
1664 : }
1665 :
1666 0: llvm::Function *CGObjCGNU::GetPropertySetFunction() {
1667 0: std::vector<const llvm::Type*> Params;
1668 : const llvm::Type *BoolTy =
1669 0: CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
1670 0: Params.push_back(IdTy);
1671 0: Params.push_back(SelectorTy);
1672 : // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64
1673 0: Params.push_back(LongTy);
1674 0: Params.push_back(IdTy);
1675 0: Params.push_back(BoolTy);
1676 0: Params.push_back(BoolTy);
1677 : // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
1678 : const llvm::FunctionType *FTy =
1679 0: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
1680 : return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
1681 0: "objc_setProperty"));
1682 : }
1683 :
1684 1: llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
1685 1: CodeGen::CodeGenTypes &Types = CGM.getTypes();
1686 1: ASTContext &Ctx = CGM.getContext();
1687 : // void objc_enumerationMutation (id)
1688 1: llvm::SmallVector<QualType,16> Params;
1689 1: Params.push_back(ASTIdTy);
1690 : const llvm::FunctionType *FTy =
1691 : Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
1692 1: CC_Default, false), false);
1693 1: return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
1694 : }
1695 :
1696 : void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1697 2: const Stmt &S) {
1698 : // Pointer to the personality function
1699 : llvm::Constant *Personality =
1700 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
1701 : true),
1702 2: "__gnu_objc_personality_v0");
1703 2: Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy);
1704 2: std::vector<const llvm::Type*> Params;
1705 2: Params.push_back(PtrTy);
1706 : llvm::Value *RethrowFn =
1707 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
1708 2: Params, false), "_Unwind_Resume");
1709 :
1710 2: bool isTry = isa<ObjCAtTryStmt>(S);
1711 2: llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
1712 2: llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
1713 2: llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
1714 2: llvm::BasicBlock *CatchInCatch = CGF.createBasicBlock("catch.rethrow");
1715 2: llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
1716 2: llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
1717 2: llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
1718 :
1719 : // @synchronized()
1: branch 0 taken
1: branch 1 taken
1720 2: if (!isTry) {
1721 1: std::vector<const llvm::Type*> Args(1, IdTy);
1722 : llvm::FunctionType *FTy =
1723 1: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1724 1: llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
1725 : llvm::Value *SyncArg =
1726 1: CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1727 1: SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1728 1: CGF.Builder.CreateCall(SyncEnter, SyncArg);
1729 : }
1730 :
1731 :
1732 : // Push an EH context entry, used for handling rethrows and jumps
1733 : // through finally.
1734 2: CGF.PushCleanupBlock(FinallyBlock);
1735 :
1736 : // Emit the statements in the @try {} block
1737 2: CGF.setInvokeDest(TryHandler);
1738 :
1739 2: CGF.EmitBlock(TryBlock);
1740 : CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
1: branch 0 taken
1: branch 1 taken
1741 2: : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
1742 :
1743 : // Jump to @finally if there is no exception
1744 2: CGF.EmitBranchThroughCleanup(FinallyEnd);
1745 :
1746 : // Emit the handlers
1747 2: CGF.EmitBlock(TryHandler);
1748 :
1749 : // Get the correct versions of the exception handling intrinsics
1750 : llvm::Value *llvm_eh_exception =
1751 2: CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
1752 : llvm::Value *llvm_eh_selector =
1753 2: CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
1754 : llvm::Value *llvm_eh_typeid_for =
1755 2: CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
1756 :
1757 : // Exception object
1758 2: llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
1759 2: llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
1760 :
1761 2: llvm::SmallVector<llvm::Value*, 8> ESelArgs;
1762 2: llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
1763 :
1764 2: ESelArgs.push_back(Exc);
1765 2: ESelArgs.push_back(Personality);
1766 :
1767 2: bool HasCatchAll = false;
1768 : // Only @try blocks are allowed @catch blocks, but both can have @finally
1: branch 0 taken
1: branch 1 taken
1769 2: if (isTry) {
1: branch 0 taken
0: branch 1 not taken
1770 1: if (const ObjCAtCatchStmt* CatchStmt =
1771 1: cast<ObjCAtTryStmt>(S).getCatchStmts()) {
1772 1: CGF.setInvokeDest(CatchInCatch);
1773 :
2: branch 1 taken
1: branch 2 taken
1774 3: for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
1775 2: const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
1776 : Handlers.push_back(std::make_pair(CatchDecl,
1777 2: CatchStmt->getCatchBody()));
1778 :
1779 : // @catch() and @catch(id) both catch any ObjC exception
2: branch 0 taken
0: branch 1 not taken
2: branch 5 taken
0: branch 6 not taken
0: branch 10 not taken
2: branch 11 taken
0: branch 12 not taken
2: branch 13 taken
1780 2: if (!CatchDecl || CatchDecl->getType()->isObjCIdType()
1781 : || CatchDecl->getType()->isObjCQualifiedIdType()) {
1782 : // Use i8* null here to signal this is a catch all, not a cleanup.
1783 0: ESelArgs.push_back(NULLPtr);
1784 0: HasCatchAll = true;
1785 : // No further catches after this one will ever by reached
1786 0: break;
1787 : }
1788 :
1789 : // All other types should be Objective-C interface pointer types.
1790 : const ObjCObjectPointerType *OPT =
1791 2: CatchDecl->getType()->getAs<ObjCObjectPointerType>();
0: branch 0 not taken
2: branch 1 taken
1792 2: assert(OPT && "Invalid @catch type.");
1793 : const ObjCInterfaceType *IT =
1794 2: OPT->getPointeeType()->getAs<ObjCInterfaceType>();
0: branch 0 not taken
2: branch 1 taken
1795 2: assert(IT && "Invalid @catch type.");
1796 : llvm::Value *EHType =
1797 2: MakeConstantString(IT->getDecl()->getNameAsString());
1798 2: ESelArgs.push_back(EHType);
1799 : }
1800 : }
1801 : }
1802 :
1803 : // We use a cleanup unless there was already a catch all.
2: branch 0 taken
0: branch 1 not taken
1804 2: if (!HasCatchAll) {
1805 2: ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
1806 2: Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
1807 : }
1808 :
1809 : // Find which handler was matched.
1810 : llvm::Value *ESelector = CGF.Builder.CreateCall(llvm_eh_selector,
1811 2: ESelArgs.begin(), ESelArgs.end(), "selector");
1812 :
4: branch 1 taken
2: branch 2 taken
1813 6: for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
1814 4: const ParmVarDecl *CatchParam = Handlers[i].first;
1815 4: const Stmt *CatchBody = Handlers[i].second;
1816 :
1817 4: llvm::BasicBlock *Next = 0;
1818 :
1819 : // The last handler always matches.
2: branch 0 taken
2: branch 1 taken
1820 4: if (i + 1 != e) {
0: branch 0 not taken
2: branch 1 taken
1821 2: assert(CatchParam && "Only last handler can be a catch all.");
1822 :
1823 : // Test whether this block matches the type for the selector and branch
1824 : // to Match if it does, or to the next BB if it doesn't.
1825 2: llvm::BasicBlock *Match = CGF.createBasicBlock("match");
1826 2: Next = CGF.createBasicBlock("catch.next");
1827 : llvm::Value *Id = CGF.Builder.CreateCall(llvm_eh_typeid_for,
1828 2: CGF.Builder.CreateBitCast(ESelArgs[i+2], PtrTy));
1829 : CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(ESelector, Id), Match,
1830 2: Next);
1831 :
1832 2: CGF.EmitBlock(Match);
1833 : }
1834 :
2: branch 0 taken
2: branch 1 taken
1835 4: if (CatchBody) {
1836 : llvm::Value *ExcObject = CGF.Builder.CreateBitCast(Exc,
1837 2: CGF.ConvertType(CatchParam->getType()));
1838 :
1839 : // Bind the catch parameter if it exists.
2: branch 0 taken
0: branch 1 not taken
1840 2: if (CatchParam) {
1841 : // CatchParam is a ParmVarDecl because of the grammar
1842 : // construction used to handle this, but for codegen purposes
1843 : // we treat this as a local decl.
1844 2: CGF.EmitLocalBlockVarDecl(*CatchParam);
1845 2: CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
1846 : }
1847 :
1848 2: CGF.ObjCEHValueStack.push_back(ExcObject);
1849 2: CGF.EmitStmt(CatchBody);
1850 2: CGF.ObjCEHValueStack.pop_back();
1851 :
1852 2: CGF.EmitBranchThroughCleanup(FinallyEnd);
1853 :
2: branch 0 taken
0: branch 1 not taken
1854 2: if (Next)
1855 2: CGF.EmitBlock(Next);
1856 : } else {
0: branch 0 not taken
2: branch 1 taken
1857 2: assert(!Next && "catchup should be last handler.");
1858 :
1859 2: CGF.Builder.CreateStore(Exc, RethrowPtr);
1860 2: CGF.EmitBranchThroughCleanup(FinallyRethrow);
1861 : }
1862 : }
1863 : // The @finally block is a secondary landing pad for any exceptions thrown in
1864 : // @catch() blocks
1865 2: CGF.EmitBlock(CatchInCatch);
1866 2: Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
1867 2: ESelArgs.clear();
1868 2: ESelArgs.push_back(Exc);
1869 2: ESelArgs.push_back(Personality);
1870 : // If there is a @catch or @finally clause in outside of this one then we
1871 : // need to make sure that we catch and rethrow it.
0: branch 0 not taken
2: branch 1 taken
1872 2: if (PrevLandingPad) {
1873 0: ESelArgs.push_back(NULLPtr);
1874 : } else {
1875 2: ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
1876 : }
1877 : CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(),
1878 2: "selector");
1879 : CGF.Builder.CreateCall(llvm_eh_typeid_for,
1880 2: CGF.Builder.CreateIntToPtr(ESelArgs[2], PtrTy));
1881 2: CGF.Builder.CreateStore(Exc, RethrowPtr);
1882 2: CGF.EmitBranchThroughCleanup(FinallyRethrow);
1883 :
1884 2: CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
1885 :
1886 2: CGF.setInvokeDest(PrevLandingPad);
1887 :
1888 2: CGF.EmitBlock(FinallyBlock);
1889 :
1890 :
1: branch 0 taken
1: branch 1 taken
1891 2: if (isTry) {
1: branch 0 taken
0: branch 1 not taken
1892 1: if (const ObjCAtFinallyStmt* FinallyStmt =
1893 1: cast<ObjCAtTryStmt>(S).getFinallyStmt())
1894 1: CGF.EmitStmt(FinallyStmt->getFinallyBody());
1895 : } else {
1896 : // Emit 'objc_sync_exit(expr)' as finally's sole statement for
1897 : // @synchronized.
1898 1: std::vector<const llvm::Type*> Args(1, IdTy);
1899 : llvm::FunctionType *FTy =
1900 1: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1901 1: llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
1902 : llvm::Value *SyncArg =
1903 1: CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1904 1: SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1905 1: CGF.Builder.CreateCall(SyncExit, SyncArg);
1906 : }
1907 :
2: branch 0 taken
0: branch 1 not taken
1908 2: if (Info.SwitchBlock)
1909 2: CGF.EmitBlock(Info.SwitchBlock);
2: branch 0 taken
0: branch 1 not taken
1910 2: if (Info.EndBlock)
1911 2: CGF.EmitBlock(Info.EndBlock);
1912 :
1913 : // Branch around the rethrow code.
1914 2: CGF.EmitBranch(FinallyEnd);
1915 :
1916 2: CGF.EmitBlock(FinallyRethrow);
1917 :
1918 2: llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr);
1919 2: llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
2: branch 0 taken
0: branch 1 not taken
1920 2: if (!UnwindBB) {
1921 2: CGF.Builder.CreateCall(RethrowFn, ExceptionObject);
1922 : // Exception always thrown, next instruction is never reached.
1923 2: CGF.Builder.CreateUnreachable();
1924 : } else {
1925 : // If there is a @catch block outside this scope, we invoke instead of
1926 : // calling because we may return to this function. This is very slow, but
1927 : // some people still do it. It would be nice to add an optimised path for
1928 : // this.
1929 : CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject,
1930 0: &ExceptionObject+1);
1931 : }
1932 :
1933 2: CGF.EmitBlock(FinallyEnd);
1934 2: }
1935 :
1936 : void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1937 2: const ObjCAtThrowStmt &S) {
1938 : llvm::Value *ExceptionAsObject;
1939 :
1940 2: std::vector<const llvm::Type*> Args(1, IdTy);
1941 : llvm::FunctionType *FTy =
1942 2: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1943 : llvm::Value *ThrowFn =
1944 2: CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
1945 :
1: branch 1 taken
1: branch 2 taken
1946 2: if (const Expr *ThrowExpr = S.getThrowExpr()) {
1947 1: llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
1948 1: ExceptionAsObject = Exception;
1949 : } else {
1950 : assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
1: branch 1 taken
0: branch 2 not taken
1: branch 4 taken
0: branch 5 not taken
1951 1: "Unexpected rethrow outside @catch block.");
1952 1: ExceptionAsObject = CGF.ObjCEHValueStack.back();
1953 : }
1954 : ExceptionAsObject =
1955 2: CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp");
1956 :
1957 : // Note: This may have to be an invoke, if we want to support constructs like:
1958 : // @try {
1959 : // @throw(obj);
1960 : // }
1961 : // @catch(id) ...
1962 : //
1963 : // This is effectively turning @throw into an incredibly-expensive goto, but
1964 : // it may happen as a result of inlining followed by missed optimizations, or
1965 : // as a result of stupidity.
1966 2: llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
0: branch 0 not taken
2: branch 1 taken
1967 2: if (!UnwindBB) {
1968 0: CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject);
1969 0: CGF.Builder.CreateUnreachable();
1970 : } else {
1971 : CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject,
1972 2: &ExceptionAsObject+1);
1973 : }
1974 : // Clear the insertion point to indicate we are in unreachable code.
1975 2: CGF.Builder.ClearInsertionPoint();
1976 2: }
1977 :
1978 : llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1979 0: llvm::Value *AddrWeakObj) {
1980 0: CGBuilderTy B = CGF.Builder;
1981 0: AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy);
1982 0: return B.CreateCall(WeakReadFn, AddrWeakObj);
1983 : }
1984 :
1985 : void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1986 0: llvm::Value *src, llvm::Value *dst) {
1987 0: CGBuilderTy B = CGF.Builder;
1988 0: src = EnforceType(B, src, IdTy);
1989 0: dst = EnforceType(B, dst, PtrToIdTy);
1990 0: B.CreateCall2(WeakAssignFn, src, dst);
1991 0: }
1992 :
1993 : void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1994 0: llvm::Value *src, llvm::Value *dst) {
1995 0: CGBuilderTy B = CGF.Builder;
1996 0: src = EnforceType(B, src, IdTy);
1997 0: dst = EnforceType(B, dst, PtrToIdTy);
1998 0: B.CreateCall2(GlobalAssignFn, src, dst);
1999 0: }
2000 :
2001 : void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2002 : llvm::Value *src, llvm::Value *dst,
2003 0: llvm::Value *ivarOffset) {
2004 0: CGBuilderTy B = CGF.Builder;
2005 0: src = EnforceType(B, src, IdTy);
2006 0: dst = EnforceType(B, dst, PtrToIdTy);
2007 0: B.CreateCall3(IvarAssignFn, src, dst, ivarOffset);
2008 0: }
2009 :
2010 : void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2011 0: llvm::Value *src, llvm::Value *dst) {
2012 0: CGBuilderTy B = CGF.Builder;
2013 0: src = EnforceType(B, src, IdTy);
2014 0: dst = EnforceType(B, dst, PtrToIdTy);
2015 0: B.CreateCall2(StrongCastAssignFn, src, dst);
2016 0: }
2017 :
2018 : void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
2019 : llvm::Value *DestPtr,
2020 : llvm::Value *SrcPtr,
2021 0: QualType Ty) {
2022 0: CGBuilderTy B = CGF.Builder;
2023 0: DestPtr = EnforceType(B, DestPtr, IdTy);
2024 0: SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy);
2025 :
2026 0: std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
2027 0: unsigned long size = TypeInfo.first/8;
2028 : // FIXME: size_t
2029 0: llvm::Value *N = llvm::ConstantInt::get(LongTy, size);
2030 :
2031 0: B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, N);
2032 0: }
2033 :
2034 : llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
2035 : const ObjCInterfaceDecl *ID,
2036 0: const ObjCIvarDecl *Ivar) {
2037 : const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
2038 0: + '.' + Ivar->getNameAsString();
2039 : // Emit the variable and initialize it with what we think the correct value
2040 : // is. This allows code compiled with non-fragile ivars to work correctly
2041 : // when linked against code which isn't (most of the time).
2042 0: llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
0: branch 0 not taken
0: branch 1 not taken
2043 0: if (!IvarOffsetPointer) {
2044 0: uint64_t Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
2045 : llvm::ConstantInt *OffsetGuess =
2046 0: llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset, "ivar");
2047 : // Don't emit the guess in non-PIC code because the linker will not be able
2048 : // to replace it with the real version for a library. In non-PIC code you
2049 : // must compile with the fragile ABI if you want to use ivars from a
2050 : // GCC-compiled class.
0: branch 1 not taken
0: branch 2 not taken
2051 0: if (CGM.getLangOptions().PICLevel) {
2052 : llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
2053 : llvm::Type::getInt32Ty(VMContext), false,
2054 0: llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
2055 : IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
2056 : IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
2057 0: IvarOffsetGV, Name);
2058 : } else {
2059 : IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
2060 : llvm::Type::getInt32PtrTy(VMContext), false,
2061 0: llvm::GlobalValue::ExternalLinkage, 0, Name);
2062 : }
2063 : }
2064 0: return IvarOffsetPointer;
2065 : }
2066 :
2067 : LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2068 : QualType ObjectTy,
2069 : llvm::Value *BaseValue,
2070 : const ObjCIvarDecl *Ivar,
2071 4: unsigned CVRQualifiers) {
2072 4: const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
2073 : return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
2074 4: EmitIvarOffset(CGF, ID, Ivar));
2075 : }
2076 :
2077 : static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
2078 : const ObjCInterfaceDecl *OID,
2079 0: const ObjCIvarDecl *OIVD) {
2080 0: llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
2081 0: Context.ShallowCollectObjCIvars(OID, Ivars);
0: branch 1 not taken
0: branch 2 not taken
2082 0: for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
0: branch 1 not taken
0: branch 2 not taken
2083 0: if (OIVD == Ivars[k])
2084 0: return OID;
2085 : }
2086 :
2087 : // Otherwise check in the super class.
0: branch 1 not taken
0: branch 2 not taken
2088 0: if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
2089 0: return FindIvarInterface(Context, Super, OIVD);
2090 :
2091 0: return 0;
2092 : }
2093 :
2094 : llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2095 : const ObjCInterfaceDecl *Interface,
2096 4: const ObjCIvarDecl *Ivar) {
0: branch 1 not taken
4: branch 2 taken
2097 4: if (CGM.getLangOptions().ObjCNonFragileABI) {
2098 0: Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
2099 : return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
2100 0: ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"));
2101 : }
2102 4: uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
2103 4: return llvm::ConstantInt::get(LongTy, Offset, "ivar");
2104 : }
2105 :
2106 : CodeGen::CGObjCRuntime *
2107 7: CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) {
2108 7: return new CGObjCGNU(CGM);
2109 : }
Generated: 2010-02-10 01:31 by zcov