[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
This revision was automatically updated to reflect the committed changes. Closed by commit rC354056: [CodeGenObjC] Emit [[X alloc] init] as objc_alloc_init(X) when available (authored by epilk, committed by ). Changed prior to commit: https://reviews.llvm.org/D57936?vs=186784=186894#toc Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 Files: include/clang/Basic/ObjCRuntime.h lib/CodeGen/CGObjC.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.h test/CodeGenObjC/objc-alloc-init.m Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -124,6 +124,9 @@ /// void objc_allocWithZone(id); llvm::FunctionCallee objc_allocWithZone; + /// void objc_alloc_init(id); + llvm::FunctionCallee objc_alloc_init; + /// void objc_autoreleasePoolPop(void*); llvm::FunctionCallee objc_autoreleasePoolPop; Index: lib/CodeGen/CGObjC.cpp === --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -422,6 +422,40 @@ return None; } +/// Instead of '[[MyClass alloc] init]', try to generate +/// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the +/// caller side, as well as the optimized objc_alloc. +static Optional +tryEmitSpecializedAllocInit(CodeGenFunction , const ObjCMessageExpr *OME) { + auto = CGF.getLangOpts().ObjCRuntime; + if (!Runtime.shouldUseRuntimeFunctionForCombinedAllocInit()) +return None; + + // Match the exact pattern '[[MyClass alloc] init]'. + Selector Sel = OME->getSelector(); + if (!OME->isInstanceMessage() || !OME->getType()->isObjCObjectPointerType() || + !Sel.isUnarySelector() || Sel.getNameForSlot(0) != "init") +return None; + + // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]'. + auto *SubOME = + dyn_cast(OME->getInstanceReceiver()->IgnoreParens()); + if (!SubOME) +return None; + Selector SubSel = SubOME->getSelector(); + if (SubOME->getReceiverKind() != ObjCMessageExpr::Class || + !SubOME->getType()->isObjCObjectPointerType() || + !SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc") +return None; + + QualType ReceiverType = SubOME->getClassReceiver(); + const ObjCObjectType *ObjTy = ReceiverType->getAs(); + const ObjCInterfaceDecl *ID = ObjTy->getInterface(); + assert(ID && "null interface should be impossible here"); + llvm::Value *Receiver = CGF.CGM.getObjCRuntime().GetClass(CGF, ID); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); +} + RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return) { // Only the lookup mechanism and first two arguments of the method @@ -443,6 +477,9 @@ } } + if (Optional Val = tryEmitSpecializedAllocInit(*this, E)) +return AdjustObjCObjectType(*this, E->getType(), RValue::get(*Val)); + // We don't retain the receiver in delegate init calls, and this is // safe because the receiver value is always loaded from 'self', // which we zero out. We don't want to Block_copy block receivers, @@ -2503,6 +2540,13 @@ "objc_allocWithZone", /*MayThrow=*/true); } +llvm::Value *CodeGenFunction::EmitObjCAllocInit(llvm::Value *value, +llvm::Type *resultType) { + return emitObjCValueOperation(*this, value, resultType, +CGM.getObjCEntrypoints().objc_alloc_init, +"objc_alloc_init", /*MayThrow=*/true); +} + /// Produce the code to do a primitive release. /// [tmp drain]; void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) { Index: lib/CodeGen/CodeGenFunction.h === --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -3831,6 +3831,8 @@ llvm::Type *returnType); llvm::Value *EmitObjCAllocWithZone(llvm::Value *value, llvm::Type *returnType); + llvm::Value *EmitObjCAllocInit(llvm::Value *value, llvm::Type *resultType); + llvm::Value *EmitObjCThrowOperand(const Expr *expr); llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); Index: include/clang/Basic/ObjCRuntime.h === --- include/clang/Basic/ObjCRuntime.h +++ include/clang/Basic/ObjCRuntime.h @@ -246,6 +246,22 @@ llvm_unreachable("bad kind"); } + /// Does this runtime provide the objc_alloc_init entrypoint? This can apply + /// the same optimization as objc_alloc, but also sends an -init message, + /// reducing code size on the
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
rjmccall accepted this revision. rjmccall added inline comments. This revision is now accepted and ready to land. Comment at: clang/lib/CodeGen/CGObjC.cpp:475-483 case ObjCMessageExpr::Class: { ReceiverType = E->getClassReceiver(); const ObjCObjectType *ObjTy = ReceiverType->getAs(); assert(ObjTy && "Invalid Objective-C class message send"); OID = ObjTy->getInterface(); assert(OID && "Invalid Objective-C class message send"); Receiver = Runtime.GetClass(*this, OID); erik.pilkington wrote: > > Also, I think getInterface() can return null here, although it might need > > to be contrived to fit the other requirements. Class, where > > that protocol declares +alloc? If there isn't a way to just emit the > > receiver pointer of a normal message send from an ObjCMessageExpr, that's > > really too bad. > > Are you sure? It looks like we unconditionally dereference getInterface() > here, and we would take this path if not for the new check above. It looks like `ObjCMessageExpr::Class` is only for messages to type names, and Sema rejects types in that case that aren't just an ObjC class, so you're right, I misunderstood. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
erik.pilkington marked 2 inline comments as done. erik.pilkington added inline comments. Comment at: clang/lib/CodeGen/CGObjC.cpp:459 + llvm::Value *Receiver = + CGF.CGM.getObjCRuntime().GetClass(CGF, ObjTy->getInterface()); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); gparker42 wrote: > gparker42 wrote: > > rjmccall wrote: > > > You might need to check for a `super` message send, which can be a class > > > message send in a class method. > > > > > > Also, I think `getInterface()` can return null here, although it might > > > need to be contrived to fit the other requirements. > > > `Class`, where that protocol declares `+alloc`? If there > > > isn't a way to just emit the receiver pointer of a normal message send > > > from an `ObjCMessageExpr`, that's really too bad. > > Should this be done inside `tryGenerateSpecializedMessageSend`, or from the > > same place that calls `tryGenerateSpecializedMessageSend`? That position > > already rejects `[super …]` call sites, and might make it more obvious how > > the `objc_alloc` and `objc_alloc_init` optimizations interact. (Currently > > it takes some digging to verify that the `objc_alloc_init` generator does > > not need to look for the pattern `[objc_alloc(cls) init]`). > (Never mind, that super check wouldn't help catch `[[super alloc] > init]`because it's checking `init`'s receiver.) > You might need to check for a super message send, which can be a class > message send in a class method. Ah, good catch. New patch only does this for class message sends. Comment at: clang/lib/CodeGen/CGObjC.cpp:475-483 case ObjCMessageExpr::Class: { ReceiverType = E->getClassReceiver(); const ObjCObjectType *ObjTy = ReceiverType->getAs(); assert(ObjTy && "Invalid Objective-C class message send"); OID = ObjTy->getInterface(); assert(OID && "Invalid Objective-C class message send"); Receiver = Runtime.GetClass(*this, OID); > Also, I think getInterface() can return null here, although it might need to > be contrived to fit the other requirements. Class, where that > protocol declares +alloc? If there isn't a way to just emit the receiver > pointer of a normal message send from an ObjCMessageExpr, that's really too > bad. Are you sure? It looks like we unconditionally dereference getInterface() here, and we would take this path if not for the new check above. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
erik.pilkington updated this revision to Diff 186784. erik.pilkington marked an inline comment as done. erik.pilkington added a comment. Address review comments. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 Files: clang/include/clang/Basic/ObjCRuntime.h clang/lib/CodeGen/CGObjC.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenModule.h clang/test/CodeGenObjC/objc-alloc-init.m Index: clang/test/CodeGenObjC/objc-alloc-init.m === --- /dev/null +++ clang/test/CodeGenObjC/objc-alloc-init.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 %s -fobjc-runtime=macosx-10.14.4 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=OPTIMIZED --check-prefix=EITHER +// RUN: %clang_cc1 %s -fobjc-runtime=macosx-10.14.3 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=NOT_OPTIMIZED --check-prefix=EITHER +// RUN: %clang_cc1 %s -fobjc-runtime=ios-12.2 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=OPTIMIZED --check-prefix=EITHER +// RUN: %clang_cc1 %s -fobjc-runtime=ios-12.1 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=NOT_OPTIMIZED --check-prefix=EITHER + +@interface X ++(X *)alloc; +-(X *)init; +@end + +void f() { + [[X alloc] init]; + // OPTIMIZED: call i8* @objc_alloc_init( + // NOT_OPTIMIZED: call i8* @objc_alloc( +} + +@interface Y : X ++(void)meth; +@end + +@implementation Y ++(void)meth { + [[self alloc] init]; + // EITHER-NOT: call i8* @objc_alloc + // EITHER: call {{.*}} @objc_msgSend + // EITHER: call {{.*}} @objc_msgSend +} +@end Index: clang/lib/CodeGen/CodeGenModule.h === --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -124,6 +124,9 @@ /// void objc_allocWithZone(id); llvm::FunctionCallee objc_allocWithZone; + /// void objc_alloc_init(id); + llvm::FunctionCallee objc_alloc_init; + /// void objc_autoreleasePoolPop(void*); llvm::FunctionCallee objc_autoreleasePoolPop; Index: clang/lib/CodeGen/CodeGenFunction.h === --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -3831,6 +3831,8 @@ llvm::Type *returnType); llvm::Value *EmitObjCAllocWithZone(llvm::Value *value, llvm::Type *returnType); + llvm::Value *EmitObjCAllocInit(llvm::Value *value, llvm::Type *resultType); + llvm::Value *EmitObjCThrowOperand(const Expr *expr); llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); Index: clang/lib/CodeGen/CGObjC.cpp === --- clang/lib/CodeGen/CGObjC.cpp +++ clang/lib/CodeGen/CGObjC.cpp @@ -422,6 +422,40 @@ return None; } +/// Instead of '[[MyClass alloc] init]', try to generate +/// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the +/// caller side, as well as the optimized objc_alloc. +static Optional +tryEmitSpecializedAllocInit(CodeGenFunction , const ObjCMessageExpr *OME) { + auto = CGF.getLangOpts().ObjCRuntime; + if (!Runtime.shouldUseRuntimeFunctionForCombinedAllocInit()) +return None; + + // Match the exact pattern '[[MyClass alloc] init]'. + Selector Sel = OME->getSelector(); + if (!OME->isInstanceMessage() || !OME->getType()->isObjCObjectPointerType() || + !Sel.isUnarySelector() || Sel.getNameForSlot(0) != "init") +return None; + + // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]'. + auto *SubOME = + dyn_cast(OME->getInstanceReceiver()->IgnoreParens()); + if (!SubOME) +return None; + Selector SubSel = SubOME->getSelector(); + if (SubOME->getReceiverKind() != ObjCMessageExpr::Class || + !SubOME->getType()->isObjCObjectPointerType() || + !SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc") +return None; + + QualType ReceiverType = SubOME->getClassReceiver(); + const ObjCObjectType *ObjTy = ReceiverType->getAs(); + const ObjCInterfaceDecl *ID = ObjTy->getInterface(); + assert(ID && "null interface should be impossible here"); + llvm::Value *Receiver = CGF.CGM.getObjCRuntime().GetClass(CGF, ID); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); +} + RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return) { // Only the lookup mechanism and first two arguments of the method @@ -443,6 +477,9 @@ } } + if (Optional Val = tryEmitSpecializedAllocInit(*this, E)) +return AdjustObjCObjectType(*this, E->getType(), RValue::get(*Val)); + // We don't retain the receiver in delegate init calls, and this is // safe because the receiver value is always loaded from 'self', // which we zero out. We don't want to
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
gparker42 added inline comments. Comment at: clang/lib/CodeGen/CGObjC.cpp:459 + llvm::Value *Receiver = + CGF.CGM.getObjCRuntime().GetClass(CGF, ObjTy->getInterface()); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); gparker42 wrote: > rjmccall wrote: > > You might need to check for a `super` message send, which can be a class > > message send in a class method. > > > > Also, I think `getInterface()` can return null here, although it might need > > to be contrived to fit the other requirements. `Class`, > > where that protocol declares `+alloc`? If there isn't a way to just emit > > the receiver pointer of a normal message send from an `ObjCMessageExpr`, > > that's really too bad. > Should this be done inside `tryGenerateSpecializedMessageSend`, or from the > same place that calls `tryGenerateSpecializedMessageSend`? That position > already rejects `[super …]` call sites, and might make it more obvious how > the `objc_alloc` and `objc_alloc_init` optimizations interact. (Currently it > takes some digging to verify that the `objc_alloc_init` generator does not > need to look for the pattern `[objc_alloc(cls) init]`). (Never mind, that super check wouldn't help catch `[[super alloc] init]`because it's checking `init`'s receiver.) Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
gparker42 added inline comments. Comment at: clang/lib/CodeGen/CGObjC.cpp:459 + llvm::Value *Receiver = + CGF.CGM.getObjCRuntime().GetClass(CGF, ObjTy->getInterface()); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); rjmccall wrote: > You might need to check for a `super` message send, which can be a class > message send in a class method. > > Also, I think `getInterface()` can return null here, although it might need > to be contrived to fit the other requirements. `Class`, where > that protocol declares `+alloc`? If there isn't a way to just emit the > receiver pointer of a normal message send from an `ObjCMessageExpr`, that's > really too bad. Should this be done inside `tryGenerateSpecializedMessageSend`, or from the same place that calls `tryGenerateSpecializedMessageSend`? That position already rejects `[super …]` call sites, and might make it more obvious how the `objc_alloc` and `objc_alloc_init` optimizations interact. (Currently it takes some digging to verify that the `objc_alloc_init` generator does not need to look for the pattern `[objc_alloc(cls) init]`). Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
rjmccall added inline comments. Comment at: clang/lib/CodeGen/CGObjC.cpp:459 + llvm::Value *Receiver = + CGF.CGM.getObjCRuntime().GetClass(CGF, ObjTy->getInterface()); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); You might need to check for a `super` message send, which can be a class message send in a class method. Also, I think `getInterface()` can return null here, although it might need to be contrived to fit the other requirements. `Class`, where that protocol declares `+alloc`? If there isn't a way to just emit the receiver pointer of a normal message send from an `ObjCMessageExpr`, that's really too bad. Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D57936/new/ https://reviews.llvm.org/D57936 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D57936: [CodeGenObjC] When available, emit a direct call to objc_alloc_init(cls) instead of [objc_alloc(cls) init]
erik.pilkington created this revision. erik.pilkington added reviewers: rjmccall, pete, ahatanak. Herald added subscribers: dexonsmith, jkorous. Herald added a project: clang. This provides a code size win on the caller side, since the `init` message send is done in the runtime function. rdar://44987038 Thanks! Erik Repository: rC Clang https://reviews.llvm.org/D57936 Files: clang/include/clang/Basic/ObjCRuntime.h clang/lib/CodeGen/CGObjC.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenModule.h clang/test/CodeGenObjC/objc-alloc-init.m Index: clang/test/CodeGenObjC/objc-alloc-init.m === --- /dev/null +++ clang/test/CodeGenObjC/objc-alloc-init.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -fobjc-runtime=macosx-10.14.4 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=OPTIMIZED +// RUN: %clang_cc1 %s -fobjc-runtime=macosx-10.14.3 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=NOT_OPTIMIZED +// RUN: %clang_cc1 %s -fobjc-runtime=ios-12.2 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=OPTIMIZED +// RUN: %clang_cc1 %s -fobjc-runtime=ios-12.1 -emit-llvm -O0 -o - | FileCheck %s --check-prefix=NOT_OPTIMIZED + +@interface X ++(X *)alloc; +-(X *)init; +@end + +void f() { + [[X alloc] init]; + // OPTIMIZED: call i8* @objc_alloc_init( + // NOT_OPTIMIZED: call i8* @objc_alloc( +} Index: clang/lib/CodeGen/CodeGenModule.h === --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -124,6 +124,9 @@ /// void objc_allocWithZone(id); llvm::FunctionCallee objc_allocWithZone; + /// void objc_alloc_init(id); + llvm::FunctionCallee objc_alloc_init; + /// void objc_autoreleasePoolPop(void*); llvm::FunctionCallee objc_autoreleasePoolPop; Index: clang/lib/CodeGen/CodeGenFunction.h === --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -3827,6 +3827,8 @@ llvm::Type *returnType); llvm::Value *EmitObjCAllocWithZone(llvm::Value *value, llvm::Type *returnType); + llvm::Value *EmitObjCAllocInit(llvm::Value *value, llvm::Type *resultType); + llvm::Value *EmitObjCThrowOperand(const Expr *expr); llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); Index: clang/lib/CodeGen/CGObjC.cpp === --- clang/lib/CodeGen/CGObjC.cpp +++ clang/lib/CodeGen/CGObjC.cpp @@ -425,6 +425,41 @@ return None; } +/// Instead of '[[MyClass alloc] init]', try to generate +/// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the +/// caller side, as well as the optimized objc_alloc. +static Optional +tryEmitSpecializedAllocInit(CodeGenFunction , const ObjCMessageExpr *OME) { + auto = CGF.getLangOpts().ObjCRuntime; + if (!Runtime.shouldUseRuntimeFunctionForCombinedAllocInit()) +return None; + + // Match the exact pattern '[[MyClass alloc] init]'. + Selector Sel = OME->getSelector(); + if (!OME->isInstanceMessage() || !OME->getType()->isObjCObjectPointerType() || + !Sel.isUnarySelector() || Sel.getNameForSlot(0) != "init") +return None; + + // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]'. + auto *SubOME = + dyn_cast(OME->getInstanceReceiver()->IgnoreParens()); + if (!SubOME) +return None; + Selector SubSel = SubOME->getSelector(); + if (!SubOME->isClassMessage() || + !SubOME->getType()->isObjCObjectPointerType() || + !SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc") +return None; + + QualType ReceiverType = SubOME->getClassReceiver(); + const ObjCObjectType *ObjTy = ReceiverType->getAs(); + if (!ObjTy) +return None; + llvm::Value *Receiver = + CGF.CGM.getObjCRuntime().GetClass(CGF, ObjTy->getInterface()); + return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); +} + RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return) { // Only the lookup mechanism and first two arguments of the method @@ -446,6 +481,9 @@ } } + if (Optional Val = tryEmitSpecializedAllocInit(*this, E)) +return AdjustObjCObjectType(*this, E->getType(), RValue::get(*Val)); + // We don't retain the receiver in delegate init calls, and this is // safe because the receiver value is always loaded from 'self', // which we zero out. We don't want to Block_copy block receivers, @@ -2506,6 +2544,13 @@ "objc_allocWithZone", /*MayThrow=*/true); } +llvm::Value *CodeGenFunction::EmitObjCAllocInit(llvm::Value *value, +llvm::Type *resultType) { + return