10b57cec5SDimitry Andric //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This provides Objective-C code generation targeting the Apple runtime.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "CGBlocks.h"
140b57cec5SDimitry Andric #include "CGCleanup.h"
150b57cec5SDimitry Andric #include "CGObjCRuntime.h"
160b57cec5SDimitry Andric #include "CGRecordLayout.h"
170b57cec5SDimitry Andric #include "CodeGenFunction.h"
180b57cec5SDimitry Andric #include "CodeGenModule.h"
190b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
20480093f4SDimitry Andric #include "clang/AST/Attr.h"
210b57cec5SDimitry Andric #include "clang/AST/Decl.h"
220b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
23e8d8bef9SDimitry Andric #include "clang/AST/Mangle.h"
240b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h"
250b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
260b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h"
270b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
280b57cec5SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h"
29480093f4SDimitry Andric #include "clang/CodeGen/ConstantInitBuilder.h"
300b57cec5SDimitry Andric #include "llvm/ADT/CachedHashString.h"
310b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
320b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
35e8d8bef9SDimitry Andric #include "llvm/ADT/UniqueVector.h"
360b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
370b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
380b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
390b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
400b57cec5SDimitry Andric #include "llvm/IR/Module.h"
410b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
420b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
430b57cec5SDimitry Andric #include <cstdio>
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric using namespace clang;
460b57cec5SDimitry Andric using namespace CodeGen;
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric namespace {
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric // FIXME: We should find a nicer way to make the labels for metadata, string
510b57cec5SDimitry Andric // concatenation is lame.
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric class ObjCCommonTypesHelper {
540b57cec5SDimitry Andric protected:
550b57cec5SDimitry Andric llvm::LLVMContext &VMContext;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric private:
580b57cec5SDimitry Andric // The types of these functions don't really matter because we
590b57cec5SDimitry Andric // should always bitcast before calling them.
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric /// id objc_msgSend (id, SEL, ...)
620b57cec5SDimitry Andric ///
630b57cec5SDimitry Andric /// The default messenger, used for sends whose ABI is unchanged from
640b57cec5SDimitry Andric /// the all-integer/pointer case.
getMessageSendFn() const650b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendFn() const {
660b57cec5SDimitry Andric // Add the non-lazy-bind attribute, since objc_msgSend is likely to
670b57cec5SDimitry Andric // be called a lot.
680b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
690b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
700b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend",
710b57cec5SDimitry Andric llvm::AttributeList::get(CGM.getLLVMContext(),
720b57cec5SDimitry Andric llvm::AttributeList::FunctionIndex,
730b57cec5SDimitry Andric llvm::Attribute::NonLazyBind));
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric /// void objc_msgSend_stret (id, SEL, ...)
770b57cec5SDimitry Andric ///
780b57cec5SDimitry Andric /// The messenger used when the return value is an aggregate returned
790b57cec5SDimitry Andric /// by indirect reference in the first argument, and therefore the
800b57cec5SDimitry Andric /// self and selector parameters are shifted over by one.
getMessageSendStretFn() const810b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendStretFn() const {
820b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
830b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
840b57cec5SDimitry Andric params, true),
850b57cec5SDimitry Andric "objc_msgSend_stret");
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
890b57cec5SDimitry Andric ///
900b57cec5SDimitry Andric /// The messenger used when the return value is returned on the x87
910b57cec5SDimitry Andric /// floating-point stack; without a special entrypoint, the nil case
920b57cec5SDimitry Andric /// would be unbalanced.
getMessageSendFpretFn() const930b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendFpretFn() const {
940b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
950b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
960b57cec5SDimitry Andric params, true),
970b57cec5SDimitry Andric "objc_msgSend_fpret");
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric
1000b57cec5SDimitry Andric /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
1010b57cec5SDimitry Andric ///
1020b57cec5SDimitry Andric /// The messenger used when the return value is returned in two values on the
1030b57cec5SDimitry Andric /// x87 floating point stack; without a special entrypoint, the nil case
1040b57cec5SDimitry Andric /// would be unbalanced. Only used on 64-bit X86.
getMessageSendFp2retFn() const1050b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendFp2retFn() const {
1060b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
1070b57cec5SDimitry Andric llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
1080b57cec5SDimitry Andric llvm::Type *resultType =
1090b57cec5SDimitry Andric llvm::StructType::get(longDoubleType, longDoubleType);
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
1120b57cec5SDimitry Andric params, true),
1130b57cec5SDimitry Andric "objc_msgSend_fp2ret");
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
1170b57cec5SDimitry Andric ///
1180b57cec5SDimitry Andric /// The messenger used for super calls, which have different dispatch
1190b57cec5SDimitry Andric /// semantics. The class passed is the superclass of the current
1200b57cec5SDimitry Andric /// class.
getMessageSendSuperFn() const1210b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperFn() const {
1220b57cec5SDimitry Andric llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
1230b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
1240b57cec5SDimitry Andric params, true),
1250b57cec5SDimitry Andric "objc_msgSendSuper");
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
1290b57cec5SDimitry Andric ///
1300b57cec5SDimitry Andric /// A slightly different messenger used for super calls. The class
1310b57cec5SDimitry Andric /// passed is the current class.
getMessageSendSuperFn2() const1320b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperFn2() const {
1330b57cec5SDimitry Andric llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
1340b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
1350b57cec5SDimitry Andric params, true),
1360b57cec5SDimitry Andric "objc_msgSendSuper2");
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
1400b57cec5SDimitry Andric /// SEL op, ...)
1410b57cec5SDimitry Andric ///
1420b57cec5SDimitry Andric /// The messenger used for super calls which return an aggregate indirectly.
getMessageSendSuperStretFn() const1430b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperStretFn() const {
1440b57cec5SDimitry Andric llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
1450b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
1460b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, params, true),
1470b57cec5SDimitry Andric "objc_msgSendSuper_stret");
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
1510b57cec5SDimitry Andric /// SEL op, ...)
1520b57cec5SDimitry Andric ///
1530b57cec5SDimitry Andric /// objc_msgSendSuper_stret with the super2 semantics.
getMessageSendSuperStretFn2() const1540b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperStretFn2() const {
1550b57cec5SDimitry Andric llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
1560b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
1570b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, params, true),
1580b57cec5SDimitry Andric "objc_msgSendSuper2_stret");
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
getMessageSendSuperFpretFn() const1610b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperFpretFn() const {
1620b57cec5SDimitry Andric // There is no objc_msgSendSuper_fpret? How can that work?
1630b57cec5SDimitry Andric return getMessageSendSuperFn();
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
getMessageSendSuperFpretFn2() const1660b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuperFpretFn2() const {
1670b57cec5SDimitry Andric // There is no objc_msgSendSuper_fpret? How can that work?
1680b57cec5SDimitry Andric return getMessageSendSuperFn2();
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric protected:
1720b57cec5SDimitry Andric CodeGen::CodeGenModule &CGM;
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric public:
1750b57cec5SDimitry Andric llvm::IntegerType *ShortTy, *IntTy, *LongTy;
1760b57cec5SDimitry Andric llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
177bdd1243dSDimitry Andric llvm::PointerType *Int8PtrProgramASTy;
1780b57cec5SDimitry Andric llvm::Type *IvarOffsetVarTy;
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric /// ObjectPtrTy - LLVM type for object handles (typeof(id))
1810b57cec5SDimitry Andric llvm::PointerType *ObjectPtrTy;
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric /// PtrObjectPtrTy - LLVM type for id *
1840b57cec5SDimitry Andric llvm::PointerType *PtrObjectPtrTy;
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
1870b57cec5SDimitry Andric llvm::PointerType *SelectorPtrTy;
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric private:
1900b57cec5SDimitry Andric /// ProtocolPtrTy - LLVM type for external protocol handles
1910b57cec5SDimitry Andric /// (typeof(Protocol))
1920b57cec5SDimitry Andric llvm::Type *ExternalProtocolPtrTy;
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric public:
getExternalProtocolPtrTy()1950b57cec5SDimitry Andric llvm::Type *getExternalProtocolPtrTy() {
1960b57cec5SDimitry Andric if (!ExternalProtocolPtrTy) {
1970b57cec5SDimitry Andric // FIXME: It would be nice to unify this with the opaque type, so that the
1980b57cec5SDimitry Andric // IR comes out a bit cleaner.
1990b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
2000b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
2010b57cec5SDimitry Andric llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
2020b57cec5SDimitry Andric ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric return ExternalProtocolPtrTy;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric // SuperCTy - clang type for struct objc_super.
2090b57cec5SDimitry Andric QualType SuperCTy;
2100b57cec5SDimitry Andric // SuperPtrCTy - clang type for struct objc_super *.
2110b57cec5SDimitry Andric QualType SuperPtrCTy;
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric /// SuperTy - LLVM type for struct objc_super.
2140b57cec5SDimitry Andric llvm::StructType *SuperTy;
2150b57cec5SDimitry Andric /// SuperPtrTy - LLVM type for struct objc_super *.
2160b57cec5SDimitry Andric llvm::PointerType *SuperPtrTy;
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
2190b57cec5SDimitry Andric /// in GCC parlance).
2200b57cec5SDimitry Andric llvm::StructType *PropertyTy;
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric /// PropertyListTy - LLVM type for struct objc_property_list
2230b57cec5SDimitry Andric /// (_prop_list_t in GCC parlance).
2240b57cec5SDimitry Andric llvm::StructType *PropertyListTy;
2250b57cec5SDimitry Andric /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
2260b57cec5SDimitry Andric llvm::PointerType *PropertyListPtrTy;
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric // MethodTy - LLVM type for struct objc_method.
2290b57cec5SDimitry Andric llvm::StructType *MethodTy;
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric /// CacheTy - LLVM type for struct objc_cache.
2320b57cec5SDimitry Andric llvm::Type *CacheTy;
2330b57cec5SDimitry Andric /// CachePtrTy - LLVM type for struct objc_cache *.
2340b57cec5SDimitry Andric llvm::PointerType *CachePtrTy;
2350b57cec5SDimitry Andric
getGetPropertyFn()2360b57cec5SDimitry Andric llvm::FunctionCallee getGetPropertyFn() {
2370b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
2380b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
2390b57cec5SDimitry Andric // id objc_getProperty (id, SEL, ptrdiff_t, bool)
2400b57cec5SDimitry Andric CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2410b57cec5SDimitry Andric CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2420b57cec5SDimitry Andric CanQualType Params[] = {
2430b57cec5SDimitry Andric IdType, SelType,
2440b57cec5SDimitry Andric Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
2450b57cec5SDimitry Andric llvm::FunctionType *FTy =
2460b57cec5SDimitry Andric Types.GetFunctionType(
2470b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
2480b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
getSetPropertyFn()2510b57cec5SDimitry Andric llvm::FunctionCallee getSetPropertyFn() {
2520b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
2530b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
2540b57cec5SDimitry Andric // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
2550b57cec5SDimitry Andric CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2560b57cec5SDimitry Andric CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2570b57cec5SDimitry Andric CanQualType Params[] = {
2580b57cec5SDimitry Andric IdType,
2590b57cec5SDimitry Andric SelType,
2600b57cec5SDimitry Andric Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
2610b57cec5SDimitry Andric IdType,
2620b57cec5SDimitry Andric Ctx.BoolTy,
2630b57cec5SDimitry Andric Ctx.BoolTy};
2640b57cec5SDimitry Andric llvm::FunctionType *FTy =
2650b57cec5SDimitry Andric Types.GetFunctionType(
2660b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
2670b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric
getOptimizedSetPropertyFn(bool atomic,bool copy)2700b57cec5SDimitry Andric llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) {
2710b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
2720b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
2730b57cec5SDimitry Andric // void objc_setProperty_atomic(id self, SEL _cmd,
2740b57cec5SDimitry Andric // id newValue, ptrdiff_t offset);
2750b57cec5SDimitry Andric // void objc_setProperty_nonatomic(id self, SEL _cmd,
2760b57cec5SDimitry Andric // id newValue, ptrdiff_t offset);
2770b57cec5SDimitry Andric // void objc_setProperty_atomic_copy(id self, SEL _cmd,
2780b57cec5SDimitry Andric // id newValue, ptrdiff_t offset);
2790b57cec5SDimitry Andric // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
2800b57cec5SDimitry Andric // id newValue, ptrdiff_t offset);
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric SmallVector<CanQualType,4> Params;
2830b57cec5SDimitry Andric CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2840b57cec5SDimitry Andric CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2850b57cec5SDimitry Andric Params.push_back(IdType);
2860b57cec5SDimitry Andric Params.push_back(SelType);
2870b57cec5SDimitry Andric Params.push_back(IdType);
2880b57cec5SDimitry Andric Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
2890b57cec5SDimitry Andric llvm::FunctionType *FTy =
2900b57cec5SDimitry Andric Types.GetFunctionType(
2910b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
2920b57cec5SDimitry Andric const char *name;
2930b57cec5SDimitry Andric if (atomic && copy)
2940b57cec5SDimitry Andric name = "objc_setProperty_atomic_copy";
2950b57cec5SDimitry Andric else if (atomic && !copy)
2960b57cec5SDimitry Andric name = "objc_setProperty_atomic";
2970b57cec5SDimitry Andric else if (!atomic && copy)
2980b57cec5SDimitry Andric name = "objc_setProperty_nonatomic_copy";
2990b57cec5SDimitry Andric else
3000b57cec5SDimitry Andric name = "objc_setProperty_nonatomic";
3010b57cec5SDimitry Andric
3020b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, name);
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric
getCopyStructFn()3050b57cec5SDimitry Andric llvm::FunctionCallee getCopyStructFn() {
3060b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
3070b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
3080b57cec5SDimitry Andric // void objc_copyStruct (void *, const void *, size_t, bool, bool)
3090b57cec5SDimitry Andric SmallVector<CanQualType,5> Params;
3100b57cec5SDimitry Andric Params.push_back(Ctx.VoidPtrTy);
3110b57cec5SDimitry Andric Params.push_back(Ctx.VoidPtrTy);
3120b57cec5SDimitry Andric Params.push_back(Ctx.getSizeType());
3130b57cec5SDimitry Andric Params.push_back(Ctx.BoolTy);
3140b57cec5SDimitry Andric Params.push_back(Ctx.BoolTy);
3150b57cec5SDimitry Andric llvm::FunctionType *FTy =
3160b57cec5SDimitry Andric Types.GetFunctionType(
3170b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3180b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric /// This routine declares and returns address of:
3220b57cec5SDimitry Andric /// void objc_copyCppObjectAtomic(
3230b57cec5SDimitry Andric /// void *dest, const void *src,
3240b57cec5SDimitry Andric /// void (*copyHelper) (void *dest, const void *source));
getCppAtomicObjectFunction()3250b57cec5SDimitry Andric llvm::FunctionCallee getCppAtomicObjectFunction() {
3260b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
3270b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
3280b57cec5SDimitry Andric /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
3290b57cec5SDimitry Andric SmallVector<CanQualType,3> Params;
3300b57cec5SDimitry Andric Params.push_back(Ctx.VoidPtrTy);
3310b57cec5SDimitry Andric Params.push_back(Ctx.VoidPtrTy);
3320b57cec5SDimitry Andric Params.push_back(Ctx.VoidPtrTy);
3330b57cec5SDimitry Andric llvm::FunctionType *FTy =
3340b57cec5SDimitry Andric Types.GetFunctionType(
3350b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3360b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric
getEnumerationMutationFn()3390b57cec5SDimitry Andric llvm::FunctionCallee getEnumerationMutationFn() {
3400b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
3410b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
3420b57cec5SDimitry Andric // void objc_enumerationMutation (id)
3430b57cec5SDimitry Andric SmallVector<CanQualType,1> Params;
3440b57cec5SDimitry Andric Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
3450b57cec5SDimitry Andric llvm::FunctionType *FTy =
3460b57cec5SDimitry Andric Types.GetFunctionType(
3470b57cec5SDimitry Andric Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3480b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric
getLookUpClassFn()3510b57cec5SDimitry Andric llvm::FunctionCallee getLookUpClassFn() {
3520b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
3530b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
3540b57cec5SDimitry Andric // Class objc_lookUpClass (const char *)
3550b57cec5SDimitry Andric SmallVector<CanQualType,1> Params;
3560b57cec5SDimitry Andric Params.push_back(
3570b57cec5SDimitry Andric Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
3580b57cec5SDimitry Andric llvm::FunctionType *FTy =
3590b57cec5SDimitry Andric Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
3600b57cec5SDimitry Andric Ctx.getCanonicalType(Ctx.getObjCClassType()),
3610b57cec5SDimitry Andric Params));
3620b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
getGcReadWeakFn()3660b57cec5SDimitry Andric llvm::FunctionCallee getGcReadWeakFn() {
3670b57cec5SDimitry Andric // id objc_read_weak (id *)
3680b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
3690b57cec5SDimitry Andric llvm::FunctionType *FTy =
3700b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
3710b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric /// GcAssignWeakFn -- LLVM objc_assign_weak function.
getGcAssignWeakFn()3750b57cec5SDimitry Andric llvm::FunctionCallee getGcAssignWeakFn() {
3760b57cec5SDimitry Andric // id objc_assign_weak (id, id *)
3770b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3780b57cec5SDimitry Andric llvm::FunctionType *FTy =
3790b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
3800b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric /// GcAssignGlobalFn -- LLVM objc_assign_global function.
getGcAssignGlobalFn()3840b57cec5SDimitry Andric llvm::FunctionCallee getGcAssignGlobalFn() {
3850b57cec5SDimitry Andric // id objc_assign_global(id, id *)
3860b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3870b57cec5SDimitry Andric llvm::FunctionType *FTy =
3880b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
3890b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric
3920b57cec5SDimitry Andric /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
getGcAssignThreadLocalFn()3930b57cec5SDimitry Andric llvm::FunctionCallee getGcAssignThreadLocalFn() {
3940b57cec5SDimitry Andric // id objc_assign_threadlocal(id src, id * dest)
3950b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3960b57cec5SDimitry Andric llvm::FunctionType *FTy =
3970b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
3980b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
getGcAssignIvarFn()4020b57cec5SDimitry Andric llvm::FunctionCallee getGcAssignIvarFn() {
4030b57cec5SDimitry Andric // id objc_assign_ivar(id, id *, ptrdiff_t)
4040b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
4050b57cec5SDimitry Andric CGM.PtrDiffTy };
4060b57cec5SDimitry Andric llvm::FunctionType *FTy =
4070b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
4080b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
4110b57cec5SDimitry Andric /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
GcMemmoveCollectableFn()4120b57cec5SDimitry Andric llvm::FunctionCallee GcMemmoveCollectableFn() {
4130b57cec5SDimitry Andric // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
4140b57cec5SDimitry Andric llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
4150b57cec5SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
4160b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
getGcAssignStrongCastFn()4200b57cec5SDimitry Andric llvm::FunctionCallee getGcAssignStrongCastFn() {
4210b57cec5SDimitry Andric // id objc_assign_strongCast(id, id *)
4220b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
4230b57cec5SDimitry Andric llvm::FunctionType *FTy =
4240b57cec5SDimitry Andric llvm::FunctionType::get(ObjectPtrTy, args, false);
4250b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric /// ExceptionThrowFn - LLVM objc_exception_throw function.
getExceptionThrowFn()4290b57cec5SDimitry Andric llvm::FunctionCallee getExceptionThrowFn() {
4300b57cec5SDimitry Andric // void objc_exception_throw(id)
4310b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy };
4320b57cec5SDimitry Andric llvm::FunctionType *FTy =
4330b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, args, false);
4340b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
getExceptionRethrowFn()4380b57cec5SDimitry Andric llvm::FunctionCallee getExceptionRethrowFn() {
4390b57cec5SDimitry Andric // void objc_exception_rethrow(void)
4400b57cec5SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
4410b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric /// SyncEnterFn - LLVM object_sync_enter function.
getSyncEnterFn()4450b57cec5SDimitry Andric llvm::FunctionCallee getSyncEnterFn() {
4460b57cec5SDimitry Andric // int objc_sync_enter (id)
4470b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy };
4480b57cec5SDimitry Andric llvm::FunctionType *FTy =
4490b57cec5SDimitry Andric llvm::FunctionType::get(CGM.IntTy, args, false);
4500b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric
4530b57cec5SDimitry Andric /// SyncExitFn - LLVM object_sync_exit function.
getSyncExitFn()4540b57cec5SDimitry Andric llvm::FunctionCallee getSyncExitFn() {
4550b57cec5SDimitry Andric // int objc_sync_exit (id)
4560b57cec5SDimitry Andric llvm::Type *args[] = { ObjectPtrTy };
4570b57cec5SDimitry Andric llvm::FunctionType *FTy =
4580b57cec5SDimitry Andric llvm::FunctionType::get(CGM.IntTy, args, false);
4590b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric
getSendFn(bool IsSuper) const4620b57cec5SDimitry Andric llvm::FunctionCallee getSendFn(bool IsSuper) const {
4630b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric
getSendFn2(bool IsSuper) const4660b57cec5SDimitry Andric llvm::FunctionCallee getSendFn2(bool IsSuper) const {
4670b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric
getSendStretFn(bool IsSuper) const4700b57cec5SDimitry Andric llvm::FunctionCallee getSendStretFn(bool IsSuper) const {
4710b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
getSendStretFn2(bool IsSuper) const4740b57cec5SDimitry Andric llvm::FunctionCallee getSendStretFn2(bool IsSuper) const {
4750b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric
getSendFpretFn(bool IsSuper) const4780b57cec5SDimitry Andric llvm::FunctionCallee getSendFpretFn(bool IsSuper) const {
4790b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric
getSendFpretFn2(bool IsSuper) const4820b57cec5SDimitry Andric llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const {
4830b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric
getSendFp2retFn(bool IsSuper) const4860b57cec5SDimitry Andric llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const {
4870b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric
getSendFp2RetFn2(bool IsSuper) const4900b57cec5SDimitry Andric llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const {
4910b57cec5SDimitry Andric return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andric ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
4950b57cec5SDimitry Andric };
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric /// ObjCTypesHelper - Helper class that encapsulates lazy
4980b57cec5SDimitry Andric /// construction of varies types used during ObjC generation.
4990b57cec5SDimitry Andric class ObjCTypesHelper : public ObjCCommonTypesHelper {
5000b57cec5SDimitry Andric public:
5010b57cec5SDimitry Andric /// SymtabTy - LLVM type for struct objc_symtab.
5020b57cec5SDimitry Andric llvm::StructType *SymtabTy;
5030b57cec5SDimitry Andric /// SymtabPtrTy - LLVM type for struct objc_symtab *.
5040b57cec5SDimitry Andric llvm::PointerType *SymtabPtrTy;
5050b57cec5SDimitry Andric /// ModuleTy - LLVM type for struct objc_module.
5060b57cec5SDimitry Andric llvm::StructType *ModuleTy;
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andric /// ProtocolTy - LLVM type for struct objc_protocol.
5090b57cec5SDimitry Andric llvm::StructType *ProtocolTy;
5100b57cec5SDimitry Andric /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
5110b57cec5SDimitry Andric llvm::PointerType *ProtocolPtrTy;
5120b57cec5SDimitry Andric /// ProtocolExtensionTy - LLVM type for struct
5130b57cec5SDimitry Andric /// objc_protocol_extension.
5140b57cec5SDimitry Andric llvm::StructType *ProtocolExtensionTy;
5150b57cec5SDimitry Andric /// ProtocolExtensionTy - LLVM type for struct
5160b57cec5SDimitry Andric /// objc_protocol_extension *.
5170b57cec5SDimitry Andric llvm::PointerType *ProtocolExtensionPtrTy;
5180b57cec5SDimitry Andric /// MethodDescriptionTy - LLVM type for struct
5190b57cec5SDimitry Andric /// objc_method_description.
5200b57cec5SDimitry Andric llvm::StructType *MethodDescriptionTy;
5210b57cec5SDimitry Andric /// MethodDescriptionListTy - LLVM type for struct
5220b57cec5SDimitry Andric /// objc_method_description_list.
5230b57cec5SDimitry Andric llvm::StructType *MethodDescriptionListTy;
5240b57cec5SDimitry Andric /// MethodDescriptionListPtrTy - LLVM type for struct
5250b57cec5SDimitry Andric /// objc_method_description_list *.
5260b57cec5SDimitry Andric llvm::PointerType *MethodDescriptionListPtrTy;
5270b57cec5SDimitry Andric /// ProtocolListTy - LLVM type for struct objc_property_list.
5280b57cec5SDimitry Andric llvm::StructType *ProtocolListTy;
5290b57cec5SDimitry Andric /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
5300b57cec5SDimitry Andric llvm::PointerType *ProtocolListPtrTy;
5310b57cec5SDimitry Andric /// CategoryTy - LLVM type for struct objc_category.
5320b57cec5SDimitry Andric llvm::StructType *CategoryTy;
5330b57cec5SDimitry Andric /// ClassTy - LLVM type for struct objc_class.
5340b57cec5SDimitry Andric llvm::StructType *ClassTy;
5350b57cec5SDimitry Andric /// ClassPtrTy - LLVM type for struct objc_class *.
5360b57cec5SDimitry Andric llvm::PointerType *ClassPtrTy;
5370b57cec5SDimitry Andric /// ClassExtensionTy - LLVM type for struct objc_class_ext.
5380b57cec5SDimitry Andric llvm::StructType *ClassExtensionTy;
5390b57cec5SDimitry Andric /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
5400b57cec5SDimitry Andric llvm::PointerType *ClassExtensionPtrTy;
5410b57cec5SDimitry Andric // IvarTy - LLVM type for struct objc_ivar.
5420b57cec5SDimitry Andric llvm::StructType *IvarTy;
5430b57cec5SDimitry Andric /// IvarListTy - LLVM type for struct objc_ivar_list.
5440b57cec5SDimitry Andric llvm::StructType *IvarListTy;
5450b57cec5SDimitry Andric /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
5460b57cec5SDimitry Andric llvm::PointerType *IvarListPtrTy;
5470b57cec5SDimitry Andric /// MethodListTy - LLVM type for struct objc_method_list.
5480b57cec5SDimitry Andric llvm::StructType *MethodListTy;
5490b57cec5SDimitry Andric /// MethodListPtrTy - LLVM type for struct objc_method_list *.
5500b57cec5SDimitry Andric llvm::PointerType *MethodListPtrTy;
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
5530b57cec5SDimitry Andric llvm::StructType *ExceptionDataTy;
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
getExceptionTryEnterFn()5560b57cec5SDimitry Andric llvm::FunctionCallee getExceptionTryEnterFn() {
5570b57cec5SDimitry Andric llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5580b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
5590b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, params, false),
5600b57cec5SDimitry Andric "objc_exception_try_enter");
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
getExceptionTryExitFn()5640b57cec5SDimitry Andric llvm::FunctionCallee getExceptionTryExitFn() {
5650b57cec5SDimitry Andric llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5660b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
5670b57cec5SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, params, false),
5680b57cec5SDimitry Andric "objc_exception_try_exit");
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric /// ExceptionExtractFn - LLVM objc_exception_extract function.
getExceptionExtractFn()5720b57cec5SDimitry Andric llvm::FunctionCallee getExceptionExtractFn() {
5730b57cec5SDimitry Andric llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5740b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
5750b57cec5SDimitry Andric params, false),
5760b57cec5SDimitry Andric "objc_exception_extract");
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric /// ExceptionMatchFn - LLVM objc_exception_match function.
getExceptionMatchFn()5800b57cec5SDimitry Andric llvm::FunctionCallee getExceptionMatchFn() {
5810b57cec5SDimitry Andric llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
5820b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
5830b57cec5SDimitry Andric llvm::FunctionType::get(CGM.Int32Ty, params, false),
5840b57cec5SDimitry Andric "objc_exception_match");
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric /// SetJmpFn - LLVM _setjmp function.
getSetJmpFn()5880b57cec5SDimitry Andric llvm::FunctionCallee getSetJmpFn() {
5890b57cec5SDimitry Andric // This is specifically the prototype for x86.
5900b57cec5SDimitry Andric llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
5910b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(
5920b57cec5SDimitry Andric llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
5930b57cec5SDimitry Andric llvm::AttributeList::get(CGM.getLLVMContext(),
5940b57cec5SDimitry Andric llvm::AttributeList::FunctionIndex,
5950b57cec5SDimitry Andric llvm::Attribute::NonLazyBind));
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric
5980b57cec5SDimitry Andric public:
5990b57cec5SDimitry Andric ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
6000b57cec5SDimitry Andric };
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric /// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
6030b57cec5SDimitry Andric /// modern abi
6040b57cec5SDimitry Andric class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
6050b57cec5SDimitry Andric public:
6060b57cec5SDimitry Andric // MethodListnfABITy - LLVM for struct _method_list_t
6070b57cec5SDimitry Andric llvm::StructType *MethodListnfABITy;
6080b57cec5SDimitry Andric
6090b57cec5SDimitry Andric // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
6100b57cec5SDimitry Andric llvm::PointerType *MethodListnfABIPtrTy;
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric // ProtocolnfABITy = LLVM for struct _protocol_t
6130b57cec5SDimitry Andric llvm::StructType *ProtocolnfABITy;
6140b57cec5SDimitry Andric
6150b57cec5SDimitry Andric // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
6160b57cec5SDimitry Andric llvm::PointerType *ProtocolnfABIPtrTy;
6170b57cec5SDimitry Andric
6180b57cec5SDimitry Andric // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
6190b57cec5SDimitry Andric llvm::StructType *ProtocolListnfABITy;
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
6220b57cec5SDimitry Andric llvm::PointerType *ProtocolListnfABIPtrTy;
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andric // ClassnfABITy - LLVM for struct _class_t
6250b57cec5SDimitry Andric llvm::StructType *ClassnfABITy;
6260b57cec5SDimitry Andric
6270b57cec5SDimitry Andric // ClassnfABIPtrTy - LLVM for struct _class_t*
6280b57cec5SDimitry Andric llvm::PointerType *ClassnfABIPtrTy;
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andric // IvarnfABITy - LLVM for struct _ivar_t
6310b57cec5SDimitry Andric llvm::StructType *IvarnfABITy;
6320b57cec5SDimitry Andric
6330b57cec5SDimitry Andric // IvarListnfABITy - LLVM for struct _ivar_list_t
6340b57cec5SDimitry Andric llvm::StructType *IvarListnfABITy;
6350b57cec5SDimitry Andric
6360b57cec5SDimitry Andric // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
6370b57cec5SDimitry Andric llvm::PointerType *IvarListnfABIPtrTy;
6380b57cec5SDimitry Andric
6390b57cec5SDimitry Andric // ClassRonfABITy - LLVM for struct _class_ro_t
6400b57cec5SDimitry Andric llvm::StructType *ClassRonfABITy;
6410b57cec5SDimitry Andric
6420b57cec5SDimitry Andric // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6430b57cec5SDimitry Andric llvm::PointerType *ImpnfABITy;
6440b57cec5SDimitry Andric
6450b57cec5SDimitry Andric // CategorynfABITy - LLVM for struct _category_t
6460b57cec5SDimitry Andric llvm::StructType *CategorynfABITy;
6470b57cec5SDimitry Andric
6480b57cec5SDimitry Andric // New types for nonfragile abi messaging.
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric // MessageRefTy - LLVM for:
6510b57cec5SDimitry Andric // struct _message_ref_t {
6520b57cec5SDimitry Andric // IMP messenger;
6530b57cec5SDimitry Andric // SEL name;
6540b57cec5SDimitry Andric // };
6550b57cec5SDimitry Andric llvm::StructType *MessageRefTy;
6560b57cec5SDimitry Andric // MessageRefCTy - clang type for struct _message_ref_t
6570b57cec5SDimitry Andric QualType MessageRefCTy;
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andric // MessageRefPtrTy - LLVM for struct _message_ref_t*
6600b57cec5SDimitry Andric llvm::Type *MessageRefPtrTy;
6610b57cec5SDimitry Andric // MessageRefCPtrTy - clang type for struct _message_ref_t*
6620b57cec5SDimitry Andric QualType MessageRefCPtrTy;
6630b57cec5SDimitry Andric
6640b57cec5SDimitry Andric // SuperMessageRefTy - LLVM for:
6650b57cec5SDimitry Andric // struct _super_message_ref_t {
6660b57cec5SDimitry Andric // SUPER_IMP messenger;
6670b57cec5SDimitry Andric // SEL name;
6680b57cec5SDimitry Andric // };
6690b57cec5SDimitry Andric llvm::StructType *SuperMessageRefTy;
6700b57cec5SDimitry Andric
6710b57cec5SDimitry Andric // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6720b57cec5SDimitry Andric llvm::PointerType *SuperMessageRefPtrTy;
6730b57cec5SDimitry Andric
getMessageSendFixupFn()6740b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendFixupFn() {
6750b57cec5SDimitry Andric // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
6760b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6770b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6780b57cec5SDimitry Andric params, true),
6790b57cec5SDimitry Andric "objc_msgSend_fixup");
6800b57cec5SDimitry Andric }
6810b57cec5SDimitry Andric
getMessageSendFpretFixupFn()6820b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendFpretFixupFn() {
6830b57cec5SDimitry Andric // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
6840b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6850b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6860b57cec5SDimitry Andric params, true),
6870b57cec5SDimitry Andric "objc_msgSend_fpret_fixup");
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric
getMessageSendStretFixupFn()6900b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendStretFixupFn() {
6910b57cec5SDimitry Andric // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
6920b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6930b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6940b57cec5SDimitry Andric params, true),
6950b57cec5SDimitry Andric "objc_msgSend_stret_fixup");
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric
getMessageSendSuper2FixupFn()6980b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuper2FixupFn() {
6990b57cec5SDimitry Andric // id objc_msgSendSuper2_fixup (struct objc_super *,
7000b57cec5SDimitry Andric // struct _super_message_ref_t*, ...)
7010b57cec5SDimitry Andric llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
7020b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
7030b57cec5SDimitry Andric params, true),
7040b57cec5SDimitry Andric "objc_msgSendSuper2_fixup");
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric
getMessageSendSuper2StretFixupFn()7070b57cec5SDimitry Andric llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
7080b57cec5SDimitry Andric // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
7090b57cec5SDimitry Andric // struct _super_message_ref_t*, ...)
7100b57cec5SDimitry Andric llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
7110b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
7120b57cec5SDimitry Andric params, true),
7130b57cec5SDimitry Andric "objc_msgSendSuper2_stret_fixup");
7140b57cec5SDimitry Andric }
7150b57cec5SDimitry Andric
getObjCEndCatchFn()7160b57cec5SDimitry Andric llvm::FunctionCallee getObjCEndCatchFn() {
7170b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
7180b57cec5SDimitry Andric "objc_end_catch");
7190b57cec5SDimitry Andric }
7200b57cec5SDimitry Andric
getObjCBeginCatchFn()7210b57cec5SDimitry Andric llvm::FunctionCallee getObjCBeginCatchFn() {
7220b57cec5SDimitry Andric llvm::Type *params[] = { Int8PtrTy };
7230b57cec5SDimitry Andric return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
7240b57cec5SDimitry Andric params, false),
7250b57cec5SDimitry Andric "objc_begin_catch");
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andric /// Class objc_loadClassref (void *)
7290b57cec5SDimitry Andric ///
7300b57cec5SDimitry Andric /// Loads from a classref. For Objective-C stub classes, this invokes the
7310b57cec5SDimitry Andric /// initialization callback stored inside the stub. For all other classes
7320b57cec5SDimitry Andric /// this simply dereferences the pointer.
getLoadClassrefFn() const7330b57cec5SDimitry Andric llvm::FunctionCallee getLoadClassrefFn() const {
7340b57cec5SDimitry Andric // Add the non-lazy-bind attribute, since objc_loadClassref is likely to
7350b57cec5SDimitry Andric // be called a lot.
7360b57cec5SDimitry Andric //
7370b57cec5SDimitry Andric // Also it is safe to make it readnone, since we never load or store the
7380b57cec5SDimitry Andric // classref except by calling this function.
7390b57cec5SDimitry Andric llvm::Type *params[] = { Int8PtrPtrTy };
740bdd1243dSDimitry Andric llvm::LLVMContext &C = CGM.getLLVMContext();
741bdd1243dSDimitry Andric llvm::AttributeSet AS = llvm::AttributeSet::get(C, {
742bdd1243dSDimitry Andric llvm::Attribute::get(C, llvm::Attribute::NonLazyBind),
743bdd1243dSDimitry Andric llvm::Attribute::getWithMemoryEffects(C, llvm::MemoryEffects::none()),
744bdd1243dSDimitry Andric llvm::Attribute::get(C, llvm::Attribute::NoUnwind),
745bdd1243dSDimitry Andric });
7460b57cec5SDimitry Andric llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
7470b57cec5SDimitry Andric llvm::FunctionType::get(ClassnfABIPtrTy, params, false),
7480b57cec5SDimitry Andric "objc_loadClassref",
7490b57cec5SDimitry Andric llvm::AttributeList::get(CGM.getLLVMContext(),
750bdd1243dSDimitry Andric llvm::AttributeList::FunctionIndex, AS));
7510b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatCOFF())
7520b57cec5SDimitry Andric cast<llvm::Function>(F.getCallee())->setLinkage(
7530b57cec5SDimitry Andric llvm::Function::ExternalWeakLinkage);
7540b57cec5SDimitry Andric
7550b57cec5SDimitry Andric return F;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric llvm::StructType *EHTypeTy;
7590b57cec5SDimitry Andric llvm::Type *EHTypePtrTy;
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
7620b57cec5SDimitry Andric };
7630b57cec5SDimitry Andric
7640b57cec5SDimitry Andric enum class ObjCLabelType {
7650b57cec5SDimitry Andric ClassName,
7660b57cec5SDimitry Andric MethodVarName,
7670b57cec5SDimitry Andric MethodVarType,
7680b57cec5SDimitry Andric PropertyName,
7690b57cec5SDimitry Andric };
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
7720b57cec5SDimitry Andric public:
7730b57cec5SDimitry Andric class SKIP_SCAN {
7740b57cec5SDimitry Andric public:
7750b57cec5SDimitry Andric unsigned skip;
7760b57cec5SDimitry Andric unsigned scan;
SKIP_SCAN(unsigned _skip=0,unsigned _scan=0)7770b57cec5SDimitry Andric SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
7780b57cec5SDimitry Andric : skip(_skip), scan(_scan) {}
7790b57cec5SDimitry Andric };
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric /// opcode for captured block variables layout 'instructions'.
7820b57cec5SDimitry Andric /// In the following descriptions, 'I' is the value of the immediate field.
7830b57cec5SDimitry Andric /// (field following the opcode).
7840b57cec5SDimitry Andric ///
7850b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE {
7860b57cec5SDimitry Andric /// An operator which affects how the following layout should be
7870b57cec5SDimitry Andric /// interpreted.
7880b57cec5SDimitry Andric /// I == 0: Halt interpretation and treat everything else as
7890b57cec5SDimitry Andric /// a non-pointer. Note that this instruction is equal
7900b57cec5SDimitry Andric /// to '\0'.
7910b57cec5SDimitry Andric /// I != 0: Currently unused.
7920b57cec5SDimitry Andric BLOCK_LAYOUT_OPERATOR = 0,
7930b57cec5SDimitry Andric
7940b57cec5SDimitry Andric /// The next I+1 bytes do not contain a value of object pointer type.
7950b57cec5SDimitry Andric /// Note that this can leave the stream unaligned, meaning that
7960b57cec5SDimitry Andric /// subsequent word-size instructions do not begin at a multiple of
7970b57cec5SDimitry Andric /// the pointer size.
7980b57cec5SDimitry Andric BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric /// The next I+1 words do not contain a value of object pointer type.
8010b57cec5SDimitry Andric /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
8020b57cec5SDimitry Andric /// when the required skip quantity is a multiple of the pointer size.
8030b57cec5SDimitry Andric BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
8040b57cec5SDimitry Andric
8050b57cec5SDimitry Andric /// The next I+1 words are __strong pointers to Objective-C
8060b57cec5SDimitry Andric /// objects or blocks.
8070b57cec5SDimitry Andric BLOCK_LAYOUT_STRONG = 3,
8080b57cec5SDimitry Andric
8090b57cec5SDimitry Andric /// The next I+1 words are pointers to __block variables.
8100b57cec5SDimitry Andric BLOCK_LAYOUT_BYREF = 4,
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric /// The next I+1 words are __weak pointers to Objective-C
8130b57cec5SDimitry Andric /// objects or blocks.
8140b57cec5SDimitry Andric BLOCK_LAYOUT_WEAK = 5,
8150b57cec5SDimitry Andric
8160b57cec5SDimitry Andric /// The next I+1 words are __unsafe_unretained pointers to
8170b57cec5SDimitry Andric /// Objective-C objects or blocks.
8180b57cec5SDimitry Andric BLOCK_LAYOUT_UNRETAINED = 6
8190b57cec5SDimitry Andric
8200b57cec5SDimitry Andric /// The next I+1 words are block or object pointers with some
8210b57cec5SDimitry Andric /// as-yet-unspecified ownership semantics. If we add more
8220b57cec5SDimitry Andric /// flavors of ownership semantics, values will be taken from
8230b57cec5SDimitry Andric /// this range.
8240b57cec5SDimitry Andric ///
8250b57cec5SDimitry Andric /// This is included so that older tools can at least continue
8260b57cec5SDimitry Andric /// processing the layout past such things.
8270b57cec5SDimitry Andric //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
8280b57cec5SDimitry Andric
8290b57cec5SDimitry Andric /// All other opcodes are reserved. Halt interpretation and
8300b57cec5SDimitry Andric /// treat everything else as opaque.
8310b57cec5SDimitry Andric };
8320b57cec5SDimitry Andric
8330b57cec5SDimitry Andric class RUN_SKIP {
8340b57cec5SDimitry Andric public:
8350b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE opcode;
8360b57cec5SDimitry Andric CharUnits block_var_bytepos;
8370b57cec5SDimitry Andric CharUnits block_var_size;
RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode=BLOCK_LAYOUT_OPERATOR,CharUnits BytePos=CharUnits::Zero (),CharUnits Size=CharUnits::Zero ())8380b57cec5SDimitry Andric RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
8390b57cec5SDimitry Andric CharUnits BytePos = CharUnits::Zero(),
8400b57cec5SDimitry Andric CharUnits Size = CharUnits::Zero())
8410b57cec5SDimitry Andric : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric // Allow sorting based on byte pos.
operator <(const RUN_SKIP & b) const8440b57cec5SDimitry Andric bool operator<(const RUN_SKIP &b) const {
8450b57cec5SDimitry Andric return block_var_bytepos < b.block_var_bytepos;
8460b57cec5SDimitry Andric }
8470b57cec5SDimitry Andric };
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric protected:
8500b57cec5SDimitry Andric llvm::LLVMContext &VMContext;
8510b57cec5SDimitry Andric // FIXME! May not be needing this after all.
8520b57cec5SDimitry Andric unsigned ObjCABI;
8530b57cec5SDimitry Andric
8540b57cec5SDimitry Andric // arc/mrr layout of captured block literal variables.
8550b57cec5SDimitry Andric SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
8560b57cec5SDimitry Andric
8570b57cec5SDimitry Andric /// LazySymbols - Symbols to generate a lazy reference for. See
8580b57cec5SDimitry Andric /// DefinedSymbols and FinishModule().
8590b57cec5SDimitry Andric llvm::SetVector<IdentifierInfo*> LazySymbols;
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric /// DefinedSymbols - External symbols which are defined by this
8620b57cec5SDimitry Andric /// module. The symbols in this list and LazySymbols are used to add
8630b57cec5SDimitry Andric /// special linker symbols which ensure that Objective-C modules are
8640b57cec5SDimitry Andric /// linked properly.
8650b57cec5SDimitry Andric llvm::SetVector<IdentifierInfo*> DefinedSymbols;
8660b57cec5SDimitry Andric
8670b57cec5SDimitry Andric /// ClassNames - uniqued class names.
8680b57cec5SDimitry Andric llvm::StringMap<llvm::GlobalVariable*> ClassNames;
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric /// MethodVarNames - uniqued method variable names.
8710b57cec5SDimitry Andric llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
8720b57cec5SDimitry Andric
8730b57cec5SDimitry Andric /// DefinedCategoryNames - list of category names in form Class_Category.
8740b57cec5SDimitry Andric llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andric /// MethodVarTypes - uniqued method type signatures. We have to use
8770b57cec5SDimitry Andric /// a StringMap here because have no other unique reference.
8780b57cec5SDimitry Andric llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andric /// MethodDefinitions - map of methods which have been defined in
8810b57cec5SDimitry Andric /// this translation unit.
8820b57cec5SDimitry Andric llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
8830b57cec5SDimitry Andric
884480093f4SDimitry Andric /// DirectMethodDefinitions - map of direct methods which have been defined in
885480093f4SDimitry Andric /// this translation unit.
886480093f4SDimitry Andric llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
887480093f4SDimitry Andric
8880b57cec5SDimitry Andric /// PropertyNames - uniqued method variable names.
8890b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andric /// ClassReferences - uniqued class references.
8920b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric /// SelectorReferences - uniqued selector references.
8950b57cec5SDimitry Andric llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric /// Protocols - Protocols for which an objc_protocol structure has
8980b57cec5SDimitry Andric /// been emitted. Forward declarations are handled by creating an
8990b57cec5SDimitry Andric /// empty structure whose initializer is filled in when/if defined.
9000b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric /// DefinedProtocols - Protocols which have actually been
9030b57cec5SDimitry Andric /// defined. We should not need this, see FIXME in GenerateProtocol.
9040b57cec5SDimitry Andric llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andric /// DefinedClasses - List of defined classes.
9070b57cec5SDimitry Andric SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric /// ImplementedClasses - List of @implemented classes.
9100b57cec5SDimitry Andric SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andric /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
9130b57cec5SDimitry Andric SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
9140b57cec5SDimitry Andric
9150b57cec5SDimitry Andric /// DefinedCategories - List of defined categories.
9160b57cec5SDimitry Andric SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
9170b57cec5SDimitry Andric
9180b57cec5SDimitry Andric /// DefinedStubCategories - List of defined categories on class stubs.
9190b57cec5SDimitry Andric SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories;
9200b57cec5SDimitry Andric
9210b57cec5SDimitry Andric /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
9220b57cec5SDimitry Andric SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
9230b57cec5SDimitry Andric
9240b57cec5SDimitry Andric /// Cached reference to the class for constant strings. This value has type
9250b57cec5SDimitry Andric /// int * but is actually an Obj-C class pointer.
9260b57cec5SDimitry Andric llvm::WeakTrackingVH ConstantStringClassRef;
9270b57cec5SDimitry Andric
9280b57cec5SDimitry Andric /// The LLVM type corresponding to NSConstantString.
9290b57cec5SDimitry Andric llvm::StructType *NSConstantStringType = nullptr;
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
9320b57cec5SDimitry Andric
9330b57cec5SDimitry Andric /// GetMethodVarName - Return a unique constant for the given
9340b57cec5SDimitry Andric /// selector's name. The return value has type char *.
9350b57cec5SDimitry Andric llvm::Constant *GetMethodVarName(Selector Sel);
9360b57cec5SDimitry Andric llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric /// GetMethodVarType - Return a unique constant for the given
9390b57cec5SDimitry Andric /// method's type encoding string. The return value has type char *.
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric // FIXME: This is a horrible name.
9420b57cec5SDimitry Andric llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
9430b57cec5SDimitry Andric bool Extended = false);
9440b57cec5SDimitry Andric llvm::Constant *GetMethodVarType(const FieldDecl *D);
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric /// GetPropertyName - Return a unique constant for the given
9470b57cec5SDimitry Andric /// name. The return value has type char *.
9480b57cec5SDimitry Andric llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric // FIXME: This can be dropped once string functions are unified.
9510b57cec5SDimitry Andric llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
9520b57cec5SDimitry Andric const Decl *Container);
9530b57cec5SDimitry Andric
9540b57cec5SDimitry Andric /// GetClassName - Return a unique constant for the given selector's
9550b57cec5SDimitry Andric /// runtime name (which may change via use of objc_runtime_name attribute on
9560b57cec5SDimitry Andric /// class or protocol definition. The return value has type char *.
9570b57cec5SDimitry Andric llvm::Constant *GetClassName(StringRef RuntimeName);
9580b57cec5SDimitry Andric
9590b57cec5SDimitry Andric llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric /// BuildIvarLayout - Builds ivar layout bitmap for the class
9620b57cec5SDimitry Andric /// implementation for the __strong or __weak case.
9630b57cec5SDimitry Andric ///
9640b57cec5SDimitry Andric /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
9650b57cec5SDimitry Andric /// are any weak ivars defined directly in the class. Meaningless unless
9660b57cec5SDimitry Andric /// building a weak layout. Does not guarantee that the layout will
9670b57cec5SDimitry Andric /// actually have any entries, because the ivar might be under-aligned.
9680b57cec5SDimitry Andric llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
9690b57cec5SDimitry Andric CharUnits beginOffset,
9700b57cec5SDimitry Andric CharUnits endOffset,
9710b57cec5SDimitry Andric bool forStrongLayout,
9720b57cec5SDimitry Andric bool hasMRCWeakIvars);
9730b57cec5SDimitry Andric
BuildStrongIvarLayout(const ObjCImplementationDecl * OI,CharUnits beginOffset,CharUnits endOffset)9740b57cec5SDimitry Andric llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
9750b57cec5SDimitry Andric CharUnits beginOffset,
9760b57cec5SDimitry Andric CharUnits endOffset) {
9770b57cec5SDimitry Andric return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
9780b57cec5SDimitry Andric }
9790b57cec5SDimitry Andric
BuildWeakIvarLayout(const ObjCImplementationDecl * OI,CharUnits beginOffset,CharUnits endOffset,bool hasMRCWeakIvars)9800b57cec5SDimitry Andric llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
9810b57cec5SDimitry Andric CharUnits beginOffset,
9820b57cec5SDimitry Andric CharUnits endOffset,
9830b57cec5SDimitry Andric bool hasMRCWeakIvars) {
9840b57cec5SDimitry Andric return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andric void UpdateRunSkipBlockVars(bool IsByref,
9900b57cec5SDimitry Andric Qualifiers::ObjCLifetime LifeTime,
9910b57cec5SDimitry Andric CharUnits FieldOffset,
9920b57cec5SDimitry Andric CharUnits FieldSize);
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric void BuildRCBlockVarRecordLayout(const RecordType *RT,
9950b57cec5SDimitry Andric CharUnits BytePos, bool &HasUnion,
9960b57cec5SDimitry Andric bool ByrefLayout=false);
9970b57cec5SDimitry Andric
9980b57cec5SDimitry Andric void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
9990b57cec5SDimitry Andric const RecordDecl *RD,
10000b57cec5SDimitry Andric ArrayRef<const FieldDecl*> RecFields,
10010b57cec5SDimitry Andric CharUnits BytePos, bool &HasUnion,
10020b57cec5SDimitry Andric bool ByrefLayout);
10030b57cec5SDimitry Andric
10040b57cec5SDimitry Andric uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
10050b57cec5SDimitry Andric
10060b57cec5SDimitry Andric llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
10070b57cec5SDimitry Andric
10080b57cec5SDimitry Andric /// GetIvarLayoutName - Returns a unique constant for the given
10090b57cec5SDimitry Andric /// ivar layout bitmap.
10100b57cec5SDimitry Andric llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
10110b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes);
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andric /// EmitPropertyList - Emit the given property list. The return
10140b57cec5SDimitry Andric /// value has type PropertyListPtrTy.
10150b57cec5SDimitry Andric llvm::Constant *EmitPropertyList(Twine Name,
10160b57cec5SDimitry Andric const Decl *Container,
10170b57cec5SDimitry Andric const ObjCContainerDecl *OCD,
10180b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes,
10190b57cec5SDimitry Andric bool IsClassProperty);
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andric /// EmitProtocolMethodTypes - Generate the array of extended method type
10220b57cec5SDimitry Andric /// strings. The return value has type Int8PtrPtrTy.
10230b57cec5SDimitry Andric llvm::Constant *EmitProtocolMethodTypes(Twine Name,
10240b57cec5SDimitry Andric ArrayRef<llvm::Constant*> MethodTypes,
10250b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes);
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric /// GetProtocolRef - Return a reference to the internal protocol
10280b57cec5SDimitry Andric /// description, creating an empty one if it has not been
10290b57cec5SDimitry Andric /// defined. The return value has type ProtocolPtrTy.
10300b57cec5SDimitry Andric llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
10310b57cec5SDimitry Andric
10320b57cec5SDimitry Andric /// Return a reference to the given Class using runtime calls rather than
10330b57cec5SDimitry Andric /// by a symbol reference.
10340b57cec5SDimitry Andric llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
10350b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
10360b57cec5SDimitry Andric ObjCCommonTypesHelper &ObjCTypes);
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
10390b57cec5SDimitry Andric
10400b57cec5SDimitry Andric public:
10410b57cec5SDimitry Andric /// CreateMetadataVar - Create a global variable with internal
10420b57cec5SDimitry Andric /// linkage for use by the Objective-C runtime.
10430b57cec5SDimitry Andric ///
10440b57cec5SDimitry Andric /// This is a convenience wrapper which not only creates the
10450b57cec5SDimitry Andric /// variable, but also sets the section and alignment and adds the
10460b57cec5SDimitry Andric /// global to the "llvm.used" list.
10470b57cec5SDimitry Andric ///
10480b57cec5SDimitry Andric /// \param Name - The variable name.
10490b57cec5SDimitry Andric /// \param Init - The variable initializer; this is also used to
10500b57cec5SDimitry Andric /// define the type of the variable.
10510b57cec5SDimitry Andric /// \param Section - The section the variable should go into, or empty.
10520b57cec5SDimitry Andric /// \param Align - The alignment for the variable, or 0.
10530b57cec5SDimitry Andric /// \param AddToUsed - Whether the variable should be added to
10540b57cec5SDimitry Andric /// "llvm.used".
10550b57cec5SDimitry Andric llvm::GlobalVariable *CreateMetadataVar(Twine Name,
10560b57cec5SDimitry Andric ConstantStructBuilder &Init,
10570b57cec5SDimitry Andric StringRef Section, CharUnits Align,
10580b57cec5SDimitry Andric bool AddToUsed);
10590b57cec5SDimitry Andric llvm::GlobalVariable *CreateMetadataVar(Twine Name,
10600b57cec5SDimitry Andric llvm::Constant *Init,
10610b57cec5SDimitry Andric StringRef Section, CharUnits Align,
10620b57cec5SDimitry Andric bool AddToUsed);
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
10650b57cec5SDimitry Andric ObjCLabelType LabelType,
10660b57cec5SDimitry Andric bool ForceNonFragileABI = false,
10670b57cec5SDimitry Andric bool NullTerminate = true);
10680b57cec5SDimitry Andric
10690b57cec5SDimitry Andric protected:
10700b57cec5SDimitry Andric CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
10710b57cec5SDimitry Andric ReturnValueSlot Return,
10720b57cec5SDimitry Andric QualType ResultType,
1073480093f4SDimitry Andric Selector Sel,
10740b57cec5SDimitry Andric llvm::Value *Arg0,
10750b57cec5SDimitry Andric QualType Arg0Ty,
10760b57cec5SDimitry Andric bool IsSuper,
10770b57cec5SDimitry Andric const CallArgList &CallArgs,
10780b57cec5SDimitry Andric const ObjCMethodDecl *OMD,
10790b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassReceiver,
10800b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes);
10810b57cec5SDimitry Andric
10820b57cec5SDimitry Andric /// EmitImageInfo - Emit the image info marker used to encode some module
10830b57cec5SDimitry Andric /// level information.
10840b57cec5SDimitry Andric void EmitImageInfo();
10850b57cec5SDimitry Andric
10860b57cec5SDimitry Andric public:
CGObjCCommonMac(CodeGen::CodeGenModule & cgm)1087e8d8bef9SDimitry Andric CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
1088e8d8bef9SDimitry Andric : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}
10890b57cec5SDimitry Andric
isNonFragileABI() const10900b57cec5SDimitry Andric bool isNonFragileABI() const {
10910b57cec5SDimitry Andric return ObjCABI == 2;
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric
10940b57cec5SDimitry Andric ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
10950b57cec5SDimitry Andric ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
10960b57cec5SDimitry Andric
10970b57cec5SDimitry Andric llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
10980b57cec5SDimitry Andric const ObjCContainerDecl *CD=nullptr) override;
10990b57cec5SDimitry Andric
1100480093f4SDimitry Andric llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD,
1101480093f4SDimitry Andric const ObjCContainerDecl *CD);
1102480093f4SDimitry Andric
1103480093f4SDimitry Andric void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1104480093f4SDimitry Andric const ObjCMethodDecl *OMD,
1105480093f4SDimitry Andric const ObjCContainerDecl *CD) override;
1106480093f4SDimitry Andric
11070b57cec5SDimitry Andric void GenerateProtocol(const ObjCProtocolDecl *PD) override;
11080b57cec5SDimitry Andric
11090b57cec5SDimitry Andric /// GetOrEmitProtocolRef - Get a forward reference to the protocol
11100b57cec5SDimitry Andric /// object for the given declaration, emitting it if needed. These
11110b57cec5SDimitry Andric /// forward references will be filled in with empty bodies if no
11120b57cec5SDimitry Andric /// definition is seen. The return value has type ProtocolPtrTy.
11130b57cec5SDimitry Andric virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
11140b57cec5SDimitry Andric
11150b57cec5SDimitry Andric virtual llvm::Constant *getNSConstantStringClassRef() = 0;
11160b57cec5SDimitry Andric
11170b57cec5SDimitry Andric llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
11180b57cec5SDimitry Andric const CGBlockInfo &blockInfo) override;
11190b57cec5SDimitry Andric llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
11200b57cec5SDimitry Andric const CGBlockInfo &blockInfo) override;
11210b57cec5SDimitry Andric std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
11220b57cec5SDimitry Andric const CGBlockInfo &blockInfo) override;
11230b57cec5SDimitry Andric
11240b57cec5SDimitry Andric llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
11250b57cec5SDimitry Andric QualType T) override;
11260b57cec5SDimitry Andric
11270b57cec5SDimitry Andric private:
11280b57cec5SDimitry Andric void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
11290b57cec5SDimitry Andric };
11300b57cec5SDimitry Andric
11310b57cec5SDimitry Andric namespace {
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andric enum class MethodListType {
11340b57cec5SDimitry Andric CategoryInstanceMethods,
11350b57cec5SDimitry Andric CategoryClassMethods,
11360b57cec5SDimitry Andric InstanceMethods,
11370b57cec5SDimitry Andric ClassMethods,
11380b57cec5SDimitry Andric ProtocolInstanceMethods,
11390b57cec5SDimitry Andric ProtocolClassMethods,
11400b57cec5SDimitry Andric OptionalProtocolInstanceMethods,
11410b57cec5SDimitry Andric OptionalProtocolClassMethods,
11420b57cec5SDimitry Andric };
11430b57cec5SDimitry Andric
11440b57cec5SDimitry Andric /// A convenience class for splitting the methods of a protocol into
11450b57cec5SDimitry Andric /// the four interesting groups.
11460b57cec5SDimitry Andric class ProtocolMethodLists {
11470b57cec5SDimitry Andric public:
11480b57cec5SDimitry Andric enum Kind {
11490b57cec5SDimitry Andric RequiredInstanceMethods,
11500b57cec5SDimitry Andric RequiredClassMethods,
11510b57cec5SDimitry Andric OptionalInstanceMethods,
11520b57cec5SDimitry Andric OptionalClassMethods
11530b57cec5SDimitry Andric };
11540b57cec5SDimitry Andric enum {
11550b57cec5SDimitry Andric NumProtocolMethodLists = 4
11560b57cec5SDimitry Andric };
11570b57cec5SDimitry Andric
getMethodListKind(Kind kind)11580b57cec5SDimitry Andric static MethodListType getMethodListKind(Kind kind) {
11590b57cec5SDimitry Andric switch (kind) {
11600b57cec5SDimitry Andric case RequiredInstanceMethods:
11610b57cec5SDimitry Andric return MethodListType::ProtocolInstanceMethods;
11620b57cec5SDimitry Andric case RequiredClassMethods:
11630b57cec5SDimitry Andric return MethodListType::ProtocolClassMethods;
11640b57cec5SDimitry Andric case OptionalInstanceMethods:
11650b57cec5SDimitry Andric return MethodListType::OptionalProtocolInstanceMethods;
11660b57cec5SDimitry Andric case OptionalClassMethods:
11670b57cec5SDimitry Andric return MethodListType::OptionalProtocolClassMethods;
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric llvm_unreachable("bad kind");
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric
11720b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
11730b57cec5SDimitry Andric
get(const ObjCProtocolDecl * PD)11740b57cec5SDimitry Andric static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
11750b57cec5SDimitry Andric ProtocolMethodLists result;
11760b57cec5SDimitry Andric
1177bdd1243dSDimitry Andric for (auto *MD : PD->methods()) {
11780b57cec5SDimitry Andric size_t index = (2 * size_t(MD->isOptional()))
11790b57cec5SDimitry Andric + (size_t(MD->isClassMethod()));
11800b57cec5SDimitry Andric result.Methods[index].push_back(MD);
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric
11830b57cec5SDimitry Andric return result;
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric
11860b57cec5SDimitry Andric template <class Self>
emitExtendedTypesArray(Self * self) const11870b57cec5SDimitry Andric SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
11880b57cec5SDimitry Andric // In both ABIs, the method types list is parallel with the
11890b57cec5SDimitry Andric // concatenation of the methods arrays in the following order:
11900b57cec5SDimitry Andric // instance methods
11910b57cec5SDimitry Andric // class methods
11920b57cec5SDimitry Andric // optional instance methods
11930b57cec5SDimitry Andric // optional class methods
11940b57cec5SDimitry Andric SmallVector<llvm::Constant*, 8> result;
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric // Methods is already in the correct order for both ABIs.
11970b57cec5SDimitry Andric for (auto &list : Methods) {
11980b57cec5SDimitry Andric for (auto MD : list) {
11990b57cec5SDimitry Andric result.push_back(self->GetMethodVarType(MD, true));
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric
12030b57cec5SDimitry Andric return result;
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andric template <class Self>
emitMethodList(Self * self,const ObjCProtocolDecl * PD,Kind kind) const12070b57cec5SDimitry Andric llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
12080b57cec5SDimitry Andric Kind kind) const {
12090b57cec5SDimitry Andric return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
12100b57cec5SDimitry Andric getMethodListKind(kind), Methods[kind]);
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric };
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andric } // end anonymous namespace
12150b57cec5SDimitry Andric
12160b57cec5SDimitry Andric class CGObjCMac : public CGObjCCommonMac {
12170b57cec5SDimitry Andric private:
12180b57cec5SDimitry Andric friend ProtocolMethodLists;
12190b57cec5SDimitry Andric
12200b57cec5SDimitry Andric ObjCTypesHelper ObjCTypes;
12210b57cec5SDimitry Andric
12220b57cec5SDimitry Andric /// EmitModuleInfo - Another marker encoding module level
12230b57cec5SDimitry Andric /// information.
12240b57cec5SDimitry Andric void EmitModuleInfo();
12250b57cec5SDimitry Andric
12260b57cec5SDimitry Andric /// EmitModuleSymols - Emit module symbols, the list of defined
12270b57cec5SDimitry Andric /// classes and categories. The result has type SymtabPtrTy.
12280b57cec5SDimitry Andric llvm::Constant *EmitModuleSymbols();
12290b57cec5SDimitry Andric
12300b57cec5SDimitry Andric /// FinishModule - Write out global data structures at the end of
12310b57cec5SDimitry Andric /// processing a translation unit.
12320b57cec5SDimitry Andric void FinishModule();
12330b57cec5SDimitry Andric
12340b57cec5SDimitry Andric /// EmitClassExtension - Generate the class extension structure used
12350b57cec5SDimitry Andric /// to store the weak ivar layout and properties. The return value
12360b57cec5SDimitry Andric /// has type ClassExtensionPtrTy.
12370b57cec5SDimitry Andric llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
12380b57cec5SDimitry Andric CharUnits instanceSize,
12390b57cec5SDimitry Andric bool hasMRCWeakIvars,
12400b57cec5SDimitry Andric bool isMetaclass);
12410b57cec5SDimitry Andric
12420b57cec5SDimitry Andric /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
12430b57cec5SDimitry Andric /// for the given class.
12440b57cec5SDimitry Andric llvm::Value *EmitClassRef(CodeGenFunction &CGF,
12450b57cec5SDimitry Andric const ObjCInterfaceDecl *ID);
12460b57cec5SDimitry Andric
12470b57cec5SDimitry Andric llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
12480b57cec5SDimitry Andric IdentifierInfo *II);
12490b57cec5SDimitry Andric
12500b57cec5SDimitry Andric llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric /// EmitSuperClassRef - Emits reference to class's main metadata class.
12530b57cec5SDimitry Andric llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
12540b57cec5SDimitry Andric
12550b57cec5SDimitry Andric /// EmitIvarList - Emit the ivar list for the given
12560b57cec5SDimitry Andric /// implementation. If ForClass is true the list of class ivars
12570b57cec5SDimitry Andric /// (i.e. metaclass ivars) is emitted, otherwise the list of
12580b57cec5SDimitry Andric /// interface ivars will be emitted. The return value has type
12590b57cec5SDimitry Andric /// IvarListPtrTy.
12600b57cec5SDimitry Andric llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
12610b57cec5SDimitry Andric bool ForClass);
12620b57cec5SDimitry Andric
12630b57cec5SDimitry Andric /// EmitMetaClass - Emit a forward reference to the class structure
12640b57cec5SDimitry Andric /// for the metaclass of the given interface. The return value has
12650b57cec5SDimitry Andric /// type ClassPtrTy.
12660b57cec5SDimitry Andric llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
12670b57cec5SDimitry Andric
12680b57cec5SDimitry Andric /// EmitMetaClass - Emit a class structure for the metaclass of the
12690b57cec5SDimitry Andric /// given implementation. The return value has type ClassPtrTy.
12700b57cec5SDimitry Andric llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
12710b57cec5SDimitry Andric llvm::Constant *Protocols,
12720b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl *> Methods);
12730b57cec5SDimitry Andric
12740b57cec5SDimitry Andric void emitMethodConstant(ConstantArrayBuilder &builder,
12750b57cec5SDimitry Andric const ObjCMethodDecl *MD);
12760b57cec5SDimitry Andric
12770b57cec5SDimitry Andric void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
12780b57cec5SDimitry Andric const ObjCMethodDecl *MD);
12790b57cec5SDimitry Andric
12800b57cec5SDimitry Andric /// EmitMethodList - Emit the method list for the given
12810b57cec5SDimitry Andric /// implementation. The return value has type MethodListPtrTy.
12820b57cec5SDimitry Andric llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
12830b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl *> Methods);
12840b57cec5SDimitry Andric
12850b57cec5SDimitry Andric /// GetOrEmitProtocol - Get the protocol object for the given
12860b57cec5SDimitry Andric /// declaration, emitting it if necessary. The return value has type
12870b57cec5SDimitry Andric /// ProtocolPtrTy.
12880b57cec5SDimitry Andric llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
12890b57cec5SDimitry Andric
12900b57cec5SDimitry Andric /// GetOrEmitProtocolRef - Get a forward reference to the protocol
12910b57cec5SDimitry Andric /// object for the given declaration, emitting it if needed. These
12920b57cec5SDimitry Andric /// forward references will be filled in with empty bodies if no
12930b57cec5SDimitry Andric /// definition is seen. The return value has type ProtocolPtrTy.
12940b57cec5SDimitry Andric llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
12950b57cec5SDimitry Andric
12960b57cec5SDimitry Andric /// EmitProtocolExtension - Generate the protocol extension
12970b57cec5SDimitry Andric /// structure used to store optional instance and class methods, and
12980b57cec5SDimitry Andric /// protocol properties. The return value has type
12990b57cec5SDimitry Andric /// ProtocolExtensionPtrTy.
13000b57cec5SDimitry Andric llvm::Constant *
13010b57cec5SDimitry Andric EmitProtocolExtension(const ObjCProtocolDecl *PD,
13020b57cec5SDimitry Andric const ProtocolMethodLists &methodLists);
13030b57cec5SDimitry Andric
13040b57cec5SDimitry Andric /// EmitProtocolList - Generate the list of referenced
13050b57cec5SDimitry Andric /// protocols. The return value has type ProtocolListPtrTy.
13060b57cec5SDimitry Andric llvm::Constant *EmitProtocolList(Twine Name,
13070b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator begin,
13080b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator end);
13090b57cec5SDimitry Andric
13100b57cec5SDimitry Andric /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
13110b57cec5SDimitry Andric /// for the given selector.
13120b57cec5SDimitry Andric llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1313*0fca6ea1SDimitry Andric ConstantAddress EmitSelectorAddr(Selector Sel);
13140b57cec5SDimitry Andric
13150b57cec5SDimitry Andric public:
13160b57cec5SDimitry Andric CGObjCMac(CodeGen::CodeGenModule &cgm);
13170b57cec5SDimitry Andric
13180b57cec5SDimitry Andric llvm::Constant *getNSConstantStringClassRef() override;
13190b57cec5SDimitry Andric
13200b57cec5SDimitry Andric llvm::Function *ModuleInitFunction() override;
13210b57cec5SDimitry Andric
13220b57cec5SDimitry Andric CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
13230b57cec5SDimitry Andric ReturnValueSlot Return,
13240b57cec5SDimitry Andric QualType ResultType,
13250b57cec5SDimitry Andric Selector Sel, llvm::Value *Receiver,
13260b57cec5SDimitry Andric const CallArgList &CallArgs,
13270b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
13280b57cec5SDimitry Andric const ObjCMethodDecl *Method) override;
13290b57cec5SDimitry Andric
13300b57cec5SDimitry Andric CodeGen::RValue
13310b57cec5SDimitry Andric GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
13320b57cec5SDimitry Andric ReturnValueSlot Return, QualType ResultType,
13330b57cec5SDimitry Andric Selector Sel, const ObjCInterfaceDecl *Class,
13340b57cec5SDimitry Andric bool isCategoryImpl, llvm::Value *Receiver,
13350b57cec5SDimitry Andric bool IsClassMessage, const CallArgList &CallArgs,
13360b57cec5SDimitry Andric const ObjCMethodDecl *Method) override;
13370b57cec5SDimitry Andric
13380b57cec5SDimitry Andric llvm::Value *GetClass(CodeGenFunction &CGF,
13390b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) override;
13400b57cec5SDimitry Andric
13410b57cec5SDimitry Andric llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
13420b57cec5SDimitry Andric Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
13430b57cec5SDimitry Andric
13440b57cec5SDimitry Andric /// The NeXT/Apple runtimes do not support typed selectors; just emit an
13450b57cec5SDimitry Andric /// untyped one.
13460b57cec5SDimitry Andric llvm::Value *GetSelector(CodeGenFunction &CGF,
13470b57cec5SDimitry Andric const ObjCMethodDecl *Method) override;
13480b57cec5SDimitry Andric
13490b57cec5SDimitry Andric llvm::Constant *GetEHType(QualType T) override;
13500b57cec5SDimitry Andric
13510b57cec5SDimitry Andric void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
13520b57cec5SDimitry Andric
13530b57cec5SDimitry Andric void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
13540b57cec5SDimitry Andric
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)13550b57cec5SDimitry Andric void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
13560b57cec5SDimitry Andric
13570b57cec5SDimitry Andric llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
13580b57cec5SDimitry Andric const ObjCProtocolDecl *PD) override;
13590b57cec5SDimitry Andric
13600b57cec5SDimitry Andric llvm::FunctionCallee GetPropertyGetFunction() override;
13610b57cec5SDimitry Andric llvm::FunctionCallee GetPropertySetFunction() override;
13620b57cec5SDimitry Andric llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
13630b57cec5SDimitry Andric bool copy) override;
13640b57cec5SDimitry Andric llvm::FunctionCallee GetGetStructFunction() override;
13650b57cec5SDimitry Andric llvm::FunctionCallee GetSetStructFunction() override;
13660b57cec5SDimitry Andric llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
13670b57cec5SDimitry Andric llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
13680b57cec5SDimitry Andric llvm::FunctionCallee EnumerationMutationFunction() override;
13690b57cec5SDimitry Andric
13700b57cec5SDimitry Andric void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
13710b57cec5SDimitry Andric const ObjCAtTryStmt &S) override;
13720b57cec5SDimitry Andric void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
13730b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S) override;
13740b57cec5SDimitry Andric void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
13750b57cec5SDimitry Andric void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
13760b57cec5SDimitry Andric bool ClearInsertionPoint=true) override;
13770b57cec5SDimitry Andric llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
13780b57cec5SDimitry Andric Address AddrWeakObj) override;
13790b57cec5SDimitry Andric void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
13800b57cec5SDimitry Andric llvm::Value *src, Address dst) override;
13810b57cec5SDimitry Andric void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
13820b57cec5SDimitry Andric llvm::Value *src, Address dest,
13830b57cec5SDimitry Andric bool threadlocal = false) override;
13840b57cec5SDimitry Andric void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
13850b57cec5SDimitry Andric llvm::Value *src, Address dest,
13860b57cec5SDimitry Andric llvm::Value *ivarOffset) override;
13870b57cec5SDimitry Andric void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
13880b57cec5SDimitry Andric llvm::Value *src, Address dest) override;
13890b57cec5SDimitry Andric void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
13900b57cec5SDimitry Andric Address dest, Address src,
13910b57cec5SDimitry Andric llvm::Value *size) override;
13920b57cec5SDimitry Andric
13930b57cec5SDimitry Andric LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
13940b57cec5SDimitry Andric llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
13950b57cec5SDimitry Andric unsigned CVRQualifiers) override;
13960b57cec5SDimitry Andric llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
13970b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface,
13980b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) override;
13990b57cec5SDimitry Andric };
14000b57cec5SDimitry Andric
14010b57cec5SDimitry Andric class CGObjCNonFragileABIMac : public CGObjCCommonMac {
14020b57cec5SDimitry Andric private:
14030b57cec5SDimitry Andric friend ProtocolMethodLists;
14040b57cec5SDimitry Andric ObjCNonFragileABITypesHelper ObjCTypes;
14050b57cec5SDimitry Andric llvm::GlobalVariable* ObjCEmptyCacheVar;
14060b57cec5SDimitry Andric llvm::Constant* ObjCEmptyVtableVar;
14070b57cec5SDimitry Andric
14080b57cec5SDimitry Andric /// SuperClassReferences - uniqued super class references.
14090b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
14100b57cec5SDimitry Andric
14110b57cec5SDimitry Andric /// MetaClassReferences - uniqued meta class references.
14120b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
14130b57cec5SDimitry Andric
14140b57cec5SDimitry Andric /// EHTypeReferences - uniqued class ehtype references.
14150b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
14160b57cec5SDimitry Andric
14170b57cec5SDimitry Andric /// VTableDispatchMethods - List of methods for which we generate
14180b57cec5SDimitry Andric /// vtable-based message dispatch.
14190b57cec5SDimitry Andric llvm::DenseSet<Selector> VTableDispatchMethods;
14200b57cec5SDimitry Andric
14210b57cec5SDimitry Andric /// DefinedMetaClasses - List of defined meta-classes.
14220b57cec5SDimitry Andric std::vector<llvm::GlobalValue*> DefinedMetaClasses;
14230b57cec5SDimitry Andric
14240b57cec5SDimitry Andric /// isVTableDispatchedSelector - Returns true if SEL is a
14250b57cec5SDimitry Andric /// vtable-based selector.
14260b57cec5SDimitry Andric bool isVTableDispatchedSelector(Selector Sel);
14270b57cec5SDimitry Andric
14280b57cec5SDimitry Andric /// FinishNonFragileABIModule - Write out global data structures at the end of
14290b57cec5SDimitry Andric /// processing a translation unit.
14300b57cec5SDimitry Andric void FinishNonFragileABIModule();
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andric /// AddModuleClassList - Add the given list of class pointers to the
14330b57cec5SDimitry Andric /// module with the provided symbol and section names.
14340b57cec5SDimitry Andric void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
14350b57cec5SDimitry Andric StringRef SymbolName, StringRef SectionName);
14360b57cec5SDimitry Andric
14370b57cec5SDimitry Andric llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
14380b57cec5SDimitry Andric unsigned InstanceStart,
14390b57cec5SDimitry Andric unsigned InstanceSize,
14400b57cec5SDimitry Andric const ObjCImplementationDecl *ID);
14410b57cec5SDimitry Andric llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
14420b57cec5SDimitry Andric bool isMetaclass,
14430b57cec5SDimitry Andric llvm::Constant *IsAGV,
14440b57cec5SDimitry Andric llvm::Constant *SuperClassGV,
14450b57cec5SDimitry Andric llvm::Constant *ClassRoGV,
14460b57cec5SDimitry Andric bool HiddenVisibility);
14470b57cec5SDimitry Andric
14480b57cec5SDimitry Andric void emitMethodConstant(ConstantArrayBuilder &builder,
14490b57cec5SDimitry Andric const ObjCMethodDecl *MD,
14500b57cec5SDimitry Andric bool forProtocol);
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric /// Emit the method list for the given implementation. The return value
14530b57cec5SDimitry Andric /// has type MethodListnfABITy.
14540b57cec5SDimitry Andric llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
14550b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl *> Methods);
14560b57cec5SDimitry Andric
14570b57cec5SDimitry Andric /// EmitIvarList - Emit the ivar list for the given
14580b57cec5SDimitry Andric /// implementation. If ForClass is true the list of class ivars
14590b57cec5SDimitry Andric /// (i.e. metaclass ivars) is emitted, otherwise the list of
14600b57cec5SDimitry Andric /// interface ivars will be emitted. The return value has type
14610b57cec5SDimitry Andric /// IvarListnfABIPtrTy.
14620b57cec5SDimitry Andric llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
14630b57cec5SDimitry Andric
14640b57cec5SDimitry Andric llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
14650b57cec5SDimitry Andric const ObjCIvarDecl *Ivar,
14660b57cec5SDimitry Andric unsigned long int offset);
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric /// GetOrEmitProtocol - Get the protocol object for the given
14690b57cec5SDimitry Andric /// declaration, emitting it if necessary. The return value has type
14700b57cec5SDimitry Andric /// ProtocolPtrTy.
14710b57cec5SDimitry Andric llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
14720b57cec5SDimitry Andric
14730b57cec5SDimitry Andric /// GetOrEmitProtocolRef - Get a forward reference to the protocol
14740b57cec5SDimitry Andric /// object for the given declaration, emitting it if needed. These
14750b57cec5SDimitry Andric /// forward references will be filled in with empty bodies if no
14760b57cec5SDimitry Andric /// definition is seen. The return value has type ProtocolPtrTy.
14770b57cec5SDimitry Andric llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
14780b57cec5SDimitry Andric
14790b57cec5SDimitry Andric /// EmitProtocolList - Generate the list of referenced
14800b57cec5SDimitry Andric /// protocols. The return value has type ProtocolListPtrTy.
14810b57cec5SDimitry Andric llvm::Constant *EmitProtocolList(Twine Name,
14820b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator begin,
14830b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator end);
14840b57cec5SDimitry Andric
14850b57cec5SDimitry Andric CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
14860b57cec5SDimitry Andric ReturnValueSlot Return,
14870b57cec5SDimitry Andric QualType ResultType,
14880b57cec5SDimitry Andric Selector Sel,
14890b57cec5SDimitry Andric llvm::Value *Receiver,
14900b57cec5SDimitry Andric QualType Arg0Ty,
14910b57cec5SDimitry Andric bool IsSuper,
14920b57cec5SDimitry Andric const CallArgList &CallArgs,
14930b57cec5SDimitry Andric const ObjCMethodDecl *Method);
14940b57cec5SDimitry Andric
14950b57cec5SDimitry Andric /// GetClassGlobal - Return the global variable for the Objective-C
14960b57cec5SDimitry Andric /// class of the given name.
14970b57cec5SDimitry Andric llvm::Constant *GetClassGlobal(StringRef Name,
14980b57cec5SDimitry Andric ForDefinition_t IsForDefinition,
14990b57cec5SDimitry Andric bool Weak = false, bool DLLImport = false);
15000b57cec5SDimitry Andric llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
15010b57cec5SDimitry Andric bool isMetaclass,
15020b57cec5SDimitry Andric ForDefinition_t isForDefinition);
15030b57cec5SDimitry Andric
15040b57cec5SDimitry Andric llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);
15050b57cec5SDimitry Andric
15060b57cec5SDimitry Andric llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
15070b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
15080b57cec5SDimitry Andric llvm::GlobalVariable *Entry);
15090b57cec5SDimitry Andric
15100b57cec5SDimitry Andric /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
15110b57cec5SDimitry Andric /// for the given class reference.
15120b57cec5SDimitry Andric llvm::Value *EmitClassRef(CodeGenFunction &CGF,
15130b57cec5SDimitry Andric const ObjCInterfaceDecl *ID);
15140b57cec5SDimitry Andric
15150b57cec5SDimitry Andric llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
15160b57cec5SDimitry Andric IdentifierInfo *II,
15170b57cec5SDimitry Andric const ObjCInterfaceDecl *ID);
15180b57cec5SDimitry Andric
15190b57cec5SDimitry Andric llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
15200b57cec5SDimitry Andric
15210b57cec5SDimitry Andric /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
15220b57cec5SDimitry Andric /// for the given super class reference.
15230b57cec5SDimitry Andric llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
15240b57cec5SDimitry Andric const ObjCInterfaceDecl *ID);
15250b57cec5SDimitry Andric
15260b57cec5SDimitry Andric /// EmitMetaClassRef - Return a Value * of the address of _class_t
15270b57cec5SDimitry Andric /// meta-data
15280b57cec5SDimitry Andric llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
15290b57cec5SDimitry Andric const ObjCInterfaceDecl *ID, bool Weak);
15300b57cec5SDimitry Andric
15310b57cec5SDimitry Andric /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
15320b57cec5SDimitry Andric /// the given ivar.
15330b57cec5SDimitry Andric ///
15340b57cec5SDimitry Andric llvm::GlobalVariable * ObjCIvarOffsetVariable(
15350b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
15360b57cec5SDimitry Andric const ObjCIvarDecl *Ivar);
15370b57cec5SDimitry Andric
15380b57cec5SDimitry Andric /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
15390b57cec5SDimitry Andric /// for the given selector.
15400b57cec5SDimitry Andric llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1541*0fca6ea1SDimitry Andric ConstantAddress EmitSelectorAddr(Selector Sel);
15420b57cec5SDimitry Andric
15430b57cec5SDimitry Andric /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
15440b57cec5SDimitry Andric /// interface. The return value has type EHTypePtrTy.
15450b57cec5SDimitry Andric llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
15460b57cec5SDimitry Andric ForDefinition_t IsForDefinition);
15470b57cec5SDimitry Andric
getMetaclassSymbolPrefix() const15480b57cec5SDimitry Andric StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
15490b57cec5SDimitry Andric
getClassSymbolPrefix() const15500b57cec5SDimitry Andric StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
15510b57cec5SDimitry Andric
15520b57cec5SDimitry Andric void GetClassSizeInfo(const ObjCImplementationDecl *OID,
15530b57cec5SDimitry Andric uint32_t &InstanceStart,
15540b57cec5SDimitry Andric uint32_t &InstanceSize);
15550b57cec5SDimitry Andric
15560b57cec5SDimitry Andric // Shamelessly stolen from Analysis/CFRefCount.cpp
GetNullarySelector(const char * name) const15570b57cec5SDimitry Andric Selector GetNullarySelector(const char* name) const {
1558*0fca6ea1SDimitry Andric const IdentifierInfo *II = &CGM.getContext().Idents.get(name);
15590b57cec5SDimitry Andric return CGM.getContext().Selectors.getSelector(0, &II);
15600b57cec5SDimitry Andric }
15610b57cec5SDimitry Andric
GetUnarySelector(const char * name) const15620b57cec5SDimitry Andric Selector GetUnarySelector(const char* name) const {
1563*0fca6ea1SDimitry Andric const IdentifierInfo *II = &CGM.getContext().Idents.get(name);
15640b57cec5SDimitry Andric return CGM.getContext().Selectors.getSelector(1, &II);
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric
15670b57cec5SDimitry Andric /// ImplementationIsNonLazy - Check whether the given category or
15680b57cec5SDimitry Andric /// class implementation is "non-lazy".
15690b57cec5SDimitry Andric bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
15700b57cec5SDimitry Andric
IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction & CGF,const ObjCIvarDecl * IV)15710b57cec5SDimitry Andric bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
15720b57cec5SDimitry Andric const ObjCIvarDecl *IV) {
15730b57cec5SDimitry Andric // Annotate the load as an invariant load iff inside an instance method
15740b57cec5SDimitry Andric // and ivar belongs to instance method's class and one of its super class.
15750b57cec5SDimitry Andric // This check is needed because the ivar offset is a lazily
15760b57cec5SDimitry Andric // initialised value that may depend on objc_msgSend to perform a fixup on
15770b57cec5SDimitry Andric // the first message dispatch.
15780b57cec5SDimitry Andric //
15790b57cec5SDimitry Andric // An additional opportunity to mark the load as invariant arises when the
15800b57cec5SDimitry Andric // base of the ivar access is a parameter to an Objective C method.
15810b57cec5SDimitry Andric // However, because the parameters are not available in the current
15820b57cec5SDimitry Andric // interface, we cannot perform this check.
1583480093f4SDimitry Andric //
1584480093f4SDimitry Andric // Note that for direct methods, because objc_msgSend is skipped,
1585480093f4SDimitry Andric // and that the method may be inlined, this optimization actually
1586480093f4SDimitry Andric // can't be performed.
15870b57cec5SDimitry Andric if (const ObjCMethodDecl *MD =
15880b57cec5SDimitry Andric dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
1589480093f4SDimitry Andric if (MD->isInstanceMethod() && !MD->isDirectMethod())
15900b57cec5SDimitry Andric if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
15910b57cec5SDimitry Andric return IV->getContainingInterface()->isSuperClassOf(ID);
15920b57cec5SDimitry Andric return false;
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric
isClassLayoutKnownStatically(const ObjCInterfaceDecl * ID)15950b57cec5SDimitry Andric bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
1596*0fca6ea1SDimitry Andric // Test a class by checking its superclasses up to
1597*0fca6ea1SDimitry Andric // its base class if it has one.
1598*0fca6ea1SDimitry Andric for (; ID; ID = ID->getSuperClass()) {
1599*0fca6ea1SDimitry Andric // The layout of base class NSObject
1600*0fca6ea1SDimitry Andric // is guaranteed to be statically known
1601*0fca6ea1SDimitry Andric if (ID->getIdentifier()->getName() == "NSObject")
1602*0fca6ea1SDimitry Andric return true;
1603*0fca6ea1SDimitry Andric
1604*0fca6ea1SDimitry Andric // If we cannot see the @implementation of a class,
1605*0fca6ea1SDimitry Andric // we cannot statically know the class layout.
1606*0fca6ea1SDimitry Andric if (!ID->getImplementation())
1607*0fca6ea1SDimitry Andric return false;
1608*0fca6ea1SDimitry Andric }
1609*0fca6ea1SDimitry Andric return false;
16100b57cec5SDimitry Andric }
16110b57cec5SDimitry Andric
16120b57cec5SDimitry Andric public:
16130b57cec5SDimitry Andric CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
16140b57cec5SDimitry Andric
16150b57cec5SDimitry Andric llvm::Constant *getNSConstantStringClassRef() override;
16160b57cec5SDimitry Andric
16170b57cec5SDimitry Andric llvm::Function *ModuleInitFunction() override;
16180b57cec5SDimitry Andric
16190b57cec5SDimitry Andric CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
16200b57cec5SDimitry Andric ReturnValueSlot Return,
16210b57cec5SDimitry Andric QualType ResultType, Selector Sel,
16220b57cec5SDimitry Andric llvm::Value *Receiver,
16230b57cec5SDimitry Andric const CallArgList &CallArgs,
16240b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
16250b57cec5SDimitry Andric const ObjCMethodDecl *Method) override;
16260b57cec5SDimitry Andric
16270b57cec5SDimitry Andric CodeGen::RValue
16280b57cec5SDimitry Andric GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
16290b57cec5SDimitry Andric ReturnValueSlot Return, QualType ResultType,
16300b57cec5SDimitry Andric Selector Sel, const ObjCInterfaceDecl *Class,
16310b57cec5SDimitry Andric bool isCategoryImpl, llvm::Value *Receiver,
16320b57cec5SDimitry Andric bool IsClassMessage, const CallArgList &CallArgs,
16330b57cec5SDimitry Andric const ObjCMethodDecl *Method) override;
16340b57cec5SDimitry Andric
16350b57cec5SDimitry Andric llvm::Value *GetClass(CodeGenFunction &CGF,
16360b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) override;
16370b57cec5SDimitry Andric
GetSelector(CodeGenFunction & CGF,Selector Sel)16380b57cec5SDimitry Andric llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
16390b57cec5SDimitry Andric { return EmitSelector(CGF, Sel); }
GetAddrOfSelector(CodeGenFunction & CGF,Selector Sel)16400b57cec5SDimitry Andric Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1641480093f4SDimitry Andric { return EmitSelectorAddr(Sel); }
16420b57cec5SDimitry Andric
16430b57cec5SDimitry Andric /// The NeXT/Apple runtimes do not support typed selectors; just emit an
16440b57cec5SDimitry Andric /// untyped one.
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)16450b57cec5SDimitry Andric llvm::Value *GetSelector(CodeGenFunction &CGF,
16460b57cec5SDimitry Andric const ObjCMethodDecl *Method) override
16470b57cec5SDimitry Andric { return EmitSelector(CGF, Method->getSelector()); }
16480b57cec5SDimitry Andric
16490b57cec5SDimitry Andric void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
16500b57cec5SDimitry Andric
16510b57cec5SDimitry Andric void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
16520b57cec5SDimitry Andric
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)16530b57cec5SDimitry Andric void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
16540b57cec5SDimitry Andric
16550b57cec5SDimitry Andric llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
16560b57cec5SDimitry Andric const ObjCProtocolDecl *PD) override;
16570b57cec5SDimitry Andric
16580b57cec5SDimitry Andric llvm::Constant *GetEHType(QualType T) override;
16590b57cec5SDimitry Andric
GetPropertyGetFunction()16600b57cec5SDimitry Andric llvm::FunctionCallee GetPropertyGetFunction() override {
16610b57cec5SDimitry Andric return ObjCTypes.getGetPropertyFn();
16620b57cec5SDimitry Andric }
GetPropertySetFunction()16630b57cec5SDimitry Andric llvm::FunctionCallee GetPropertySetFunction() override {
16640b57cec5SDimitry Andric return ObjCTypes.getSetPropertyFn();
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric
GetOptimizedPropertySetFunction(bool atomic,bool copy)16670b57cec5SDimitry Andric llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
16680b57cec5SDimitry Andric bool copy) override {
16690b57cec5SDimitry Andric return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
16700b57cec5SDimitry Andric }
16710b57cec5SDimitry Andric
GetSetStructFunction()16720b57cec5SDimitry Andric llvm::FunctionCallee GetSetStructFunction() override {
16730b57cec5SDimitry Andric return ObjCTypes.getCopyStructFn();
16740b57cec5SDimitry Andric }
16750b57cec5SDimitry Andric
GetGetStructFunction()16760b57cec5SDimitry Andric llvm::FunctionCallee GetGetStructFunction() override {
16770b57cec5SDimitry Andric return ObjCTypes.getCopyStructFn();
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric
GetCppAtomicObjectSetFunction()16800b57cec5SDimitry Andric llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
16810b57cec5SDimitry Andric return ObjCTypes.getCppAtomicObjectFunction();
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric
GetCppAtomicObjectGetFunction()16840b57cec5SDimitry Andric llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
16850b57cec5SDimitry Andric return ObjCTypes.getCppAtomicObjectFunction();
16860b57cec5SDimitry Andric }
16870b57cec5SDimitry Andric
EnumerationMutationFunction()16880b57cec5SDimitry Andric llvm::FunctionCallee EnumerationMutationFunction() override {
16890b57cec5SDimitry Andric return ObjCTypes.getEnumerationMutationFn();
16900b57cec5SDimitry Andric }
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andric void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
16930b57cec5SDimitry Andric const ObjCAtTryStmt &S) override;
16940b57cec5SDimitry Andric void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
16950b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S) override;
16960b57cec5SDimitry Andric void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
16970b57cec5SDimitry Andric bool ClearInsertionPoint=true) override;
16980b57cec5SDimitry Andric llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
16990b57cec5SDimitry Andric Address AddrWeakObj) override;
17000b57cec5SDimitry Andric void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
17010b57cec5SDimitry Andric llvm::Value *src, Address edst) override;
17020b57cec5SDimitry Andric void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
17030b57cec5SDimitry Andric llvm::Value *src, Address dest,
17040b57cec5SDimitry Andric bool threadlocal = false) override;
17050b57cec5SDimitry Andric void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
17060b57cec5SDimitry Andric llvm::Value *src, Address dest,
17070b57cec5SDimitry Andric llvm::Value *ivarOffset) override;
17080b57cec5SDimitry Andric void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
17090b57cec5SDimitry Andric llvm::Value *src, Address dest) override;
17100b57cec5SDimitry Andric void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
17110b57cec5SDimitry Andric Address dest, Address src,
17120b57cec5SDimitry Andric llvm::Value *size) override;
17130b57cec5SDimitry Andric LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
17140b57cec5SDimitry Andric llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
17150b57cec5SDimitry Andric unsigned CVRQualifiers) override;
17160b57cec5SDimitry Andric llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
17170b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface,
17180b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) override;
17190b57cec5SDimitry Andric };
17200b57cec5SDimitry Andric
17210b57cec5SDimitry Andric /// A helper class for performing the null-initialization of a return
17220b57cec5SDimitry Andric /// value.
17230b57cec5SDimitry Andric struct NullReturnState {
17245f757f3fSDimitry Andric llvm::BasicBlock *NullBB = nullptr;
17255f757f3fSDimitry Andric NullReturnState() = default;
17260b57cec5SDimitry Andric
17270b57cec5SDimitry Andric /// Perform a null-check of the given receiver.
init__anonb5e682970111::NullReturnState17280b57cec5SDimitry Andric void init(CodeGenFunction &CGF, llvm::Value *receiver) {
17290b57cec5SDimitry Andric // Make blocks for the null-receiver and call edges.
17300b57cec5SDimitry Andric NullBB = CGF.createBasicBlock("msgSend.null-receiver");
17310b57cec5SDimitry Andric llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
17320b57cec5SDimitry Andric
17330b57cec5SDimitry Andric // Check for a null receiver and, if there is one, jump to the
17340b57cec5SDimitry Andric // null-receiver block. There's no point in trying to avoid it:
17350b57cec5SDimitry Andric // we're always going to put *something* there, because otherwise
17360b57cec5SDimitry Andric // we shouldn't have done this null-check in the first place.
17370b57cec5SDimitry Andric llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
17380b57cec5SDimitry Andric CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
17390b57cec5SDimitry Andric
17400b57cec5SDimitry Andric // Otherwise, start performing the call.
17410b57cec5SDimitry Andric CGF.EmitBlock(callBB);
17420b57cec5SDimitry Andric }
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andric /// Complete the null-return operation. It is valid to call this
17450b57cec5SDimitry Andric /// regardless of whether 'init' has been called.
complete__anonb5e682970111::NullReturnState17460b57cec5SDimitry Andric RValue complete(CodeGenFunction &CGF,
17470b57cec5SDimitry Andric ReturnValueSlot returnSlot,
17480b57cec5SDimitry Andric RValue result,
17490b57cec5SDimitry Andric QualType resultType,
17500b57cec5SDimitry Andric const CallArgList &CallArgs,
17510b57cec5SDimitry Andric const ObjCMethodDecl *Method) {
17520b57cec5SDimitry Andric // If we never had to do a null-check, just use the raw result.
17530b57cec5SDimitry Andric if (!NullBB) return result;
17540b57cec5SDimitry Andric
17550b57cec5SDimitry Andric // The continuation block. This will be left null if we don't have an
17560b57cec5SDimitry Andric // IP, which can happen if the method we're calling is marked noreturn.
17570b57cec5SDimitry Andric llvm::BasicBlock *contBB = nullptr;
17580b57cec5SDimitry Andric
17590b57cec5SDimitry Andric // Finish the call path.
17600b57cec5SDimitry Andric llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
17610b57cec5SDimitry Andric if (callBB) {
17620b57cec5SDimitry Andric contBB = CGF.createBasicBlock("msgSend.cont");
17630b57cec5SDimitry Andric CGF.Builder.CreateBr(contBB);
17640b57cec5SDimitry Andric }
17650b57cec5SDimitry Andric
17660b57cec5SDimitry Andric // Okay, start emitting the null-receiver block.
17670b57cec5SDimitry Andric CGF.EmitBlock(NullBB);
17680b57cec5SDimitry Andric
1769349cc55cSDimitry Andric // Destroy any consumed arguments we've got.
17700b57cec5SDimitry Andric if (Method) {
1771349cc55cSDimitry Andric CGObjCRuntime::destroyCalleeDestroyedArguments(CGF, Method, CallArgs);
17720b57cec5SDimitry Andric }
17730b57cec5SDimitry Andric
17740b57cec5SDimitry Andric // The phi code below assumes that we haven't needed any control flow yet.
17750b57cec5SDimitry Andric assert(CGF.Builder.GetInsertBlock() == NullBB);
17760b57cec5SDimitry Andric
17770b57cec5SDimitry Andric // If we've got a void return, just jump to the continuation block.
17780b57cec5SDimitry Andric if (result.isScalar() && resultType->isVoidType()) {
17790b57cec5SDimitry Andric // No jumps required if the message-send was noreturn.
17800b57cec5SDimitry Andric if (contBB) CGF.EmitBlock(contBB);
17810b57cec5SDimitry Andric return result;
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric
17840b57cec5SDimitry Andric // If we've got a scalar return, build a phi.
17850b57cec5SDimitry Andric if (result.isScalar()) {
17860b57cec5SDimitry Andric // Derive the null-initialization value.
1787e8d8bef9SDimitry Andric llvm::Value *null =
1788e8d8bef9SDimitry Andric CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(resultType), resultType);
17890b57cec5SDimitry Andric
17900b57cec5SDimitry Andric // If no join is necessary, just flow out.
17910b57cec5SDimitry Andric if (!contBB) return RValue::get(null);
17920b57cec5SDimitry Andric
17930b57cec5SDimitry Andric // Otherwise, build a phi.
17940b57cec5SDimitry Andric CGF.EmitBlock(contBB);
17950b57cec5SDimitry Andric llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
17960b57cec5SDimitry Andric phi->addIncoming(result.getScalarVal(), callBB);
17970b57cec5SDimitry Andric phi->addIncoming(null, NullBB);
17980b57cec5SDimitry Andric return RValue::get(phi);
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric
18010b57cec5SDimitry Andric // If we've got an aggregate return, null the buffer out.
18020b57cec5SDimitry Andric // FIXME: maybe we should be doing things differently for all the
18030b57cec5SDimitry Andric // cases where the ABI has us returning (1) non-agg values in
18040b57cec5SDimitry Andric // memory or (2) agg values in registers.
18050b57cec5SDimitry Andric if (result.isAggregate()) {
18060b57cec5SDimitry Andric assert(result.isAggregate() && "null init of non-aggregate result?");
18070b57cec5SDimitry Andric if (!returnSlot.isUnused())
18080b57cec5SDimitry Andric CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
18090b57cec5SDimitry Andric if (contBB) CGF.EmitBlock(contBB);
18100b57cec5SDimitry Andric return result;
18110b57cec5SDimitry Andric }
18120b57cec5SDimitry Andric
18130b57cec5SDimitry Andric // Complex types.
18140b57cec5SDimitry Andric CGF.EmitBlock(contBB);
18150b57cec5SDimitry Andric CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
18160b57cec5SDimitry Andric
18170b57cec5SDimitry Andric // Find the scalar type and its zero value.
18180b57cec5SDimitry Andric llvm::Type *scalarTy = callResult.first->getType();
18190b57cec5SDimitry Andric llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
18200b57cec5SDimitry Andric
18210b57cec5SDimitry Andric // Build phis for both coordinates.
18220b57cec5SDimitry Andric llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
18230b57cec5SDimitry Andric real->addIncoming(callResult.first, callBB);
18240b57cec5SDimitry Andric real->addIncoming(scalarZero, NullBB);
18250b57cec5SDimitry Andric llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
18260b57cec5SDimitry Andric imag->addIncoming(callResult.second, callBB);
18270b57cec5SDimitry Andric imag->addIncoming(scalarZero, NullBB);
18280b57cec5SDimitry Andric return RValue::getComplex(real, imag);
18290b57cec5SDimitry Andric }
18300b57cec5SDimitry Andric };
18310b57cec5SDimitry Andric
18320b57cec5SDimitry Andric } // end anonymous namespace
18330b57cec5SDimitry Andric
18340b57cec5SDimitry Andric /* *** Helper Functions *** */
18350b57cec5SDimitry Andric
18360b57cec5SDimitry Andric /// getConstantGEP() - Help routine to construct simple GEPs.
getConstantGEP(llvm::LLVMContext & VMContext,llvm::GlobalVariable * C,unsigned idx0,unsigned idx1)18370b57cec5SDimitry Andric static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
18380b57cec5SDimitry Andric llvm::GlobalVariable *C, unsigned idx0,
18390b57cec5SDimitry Andric unsigned idx1) {
18400b57cec5SDimitry Andric llvm::Value *Idxs[] = {
18410b57cec5SDimitry Andric llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
18420b57cec5SDimitry Andric llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
18430b57cec5SDimitry Andric };
18440b57cec5SDimitry Andric return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
18450b57cec5SDimitry Andric }
18460b57cec5SDimitry Andric
18470b57cec5SDimitry Andric /// hasObjCExceptionAttribute - Return true if this class or any super
18480b57cec5SDimitry Andric /// class has the __objc_exception__ attribute.
hasObjCExceptionAttribute(ASTContext & Context,const ObjCInterfaceDecl * OID)18490b57cec5SDimitry Andric static bool hasObjCExceptionAttribute(ASTContext &Context,
18500b57cec5SDimitry Andric const ObjCInterfaceDecl *OID) {
18510b57cec5SDimitry Andric if (OID->hasAttr<ObjCExceptionAttr>())
18520b57cec5SDimitry Andric return true;
18530b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
18540b57cec5SDimitry Andric return hasObjCExceptionAttribute(Context, Super);
18550b57cec5SDimitry Andric return false;
18560b57cec5SDimitry Andric }
18570b57cec5SDimitry Andric
18580b57cec5SDimitry Andric static llvm::GlobalValue::LinkageTypes
getLinkageTypeForObjCMetadata(CodeGenModule & CGM,StringRef Section)18590b57cec5SDimitry Andric getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
18600b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO() &&
18615f757f3fSDimitry Andric (Section.empty() || Section.starts_with("__DATA")))
18620b57cec5SDimitry Andric return llvm::GlobalValue::InternalLinkage;
18630b57cec5SDimitry Andric return llvm::GlobalValue::PrivateLinkage;
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric
18660b57cec5SDimitry Andric /// A helper function to create an internal or private global variable.
18670b57cec5SDimitry Andric static llvm::GlobalVariable *
finishAndCreateGlobal(ConstantInitBuilder::StructBuilder & Builder,const llvm::Twine & Name,CodeGenModule & CGM)18680b57cec5SDimitry Andric finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
18690b57cec5SDimitry Andric const llvm::Twine &Name, CodeGenModule &CGM) {
18700b57cec5SDimitry Andric std::string SectionName;
18710b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
18720b57cec5SDimitry Andric SectionName = "__DATA, __objc_const";
18730b57cec5SDimitry Andric auto *GV = Builder.finishAndCreateGlobal(
18740b57cec5SDimitry Andric Name, CGM.getPointerAlign(), /*constant*/ false,
18750b57cec5SDimitry Andric getLinkageTypeForObjCMetadata(CGM, SectionName));
18760b57cec5SDimitry Andric GV->setSection(SectionName);
18770b57cec5SDimitry Andric return GV;
18780b57cec5SDimitry Andric }
18790b57cec5SDimitry Andric
18800b57cec5SDimitry Andric /* *** CGObjCMac Public Interface *** */
18810b57cec5SDimitry Andric
CGObjCMac(CodeGen::CodeGenModule & cgm)18820b57cec5SDimitry Andric CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
18830b57cec5SDimitry Andric ObjCTypes(cgm) {
18840b57cec5SDimitry Andric ObjCABI = 1;
18850b57cec5SDimitry Andric EmitImageInfo();
18860b57cec5SDimitry Andric }
18870b57cec5SDimitry Andric
18880b57cec5SDimitry Andric /// GetClass - Return a reference to the class for the given interface
18890b57cec5SDimitry Andric /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)18900b57cec5SDimitry Andric llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
18910b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
18920b57cec5SDimitry Andric return EmitClassRef(CGF, ID);
18930b57cec5SDimitry Andric }
18940b57cec5SDimitry Andric
18950b57cec5SDimitry Andric /// GetSelector - Return the pointer to the unique'd string for this selector.
GetSelector(CodeGenFunction & CGF,Selector Sel)18960b57cec5SDimitry Andric llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
18970b57cec5SDimitry Andric return EmitSelector(CGF, Sel);
18980b57cec5SDimitry Andric }
GetAddrOfSelector(CodeGenFunction & CGF,Selector Sel)18990b57cec5SDimitry Andric Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1900480093f4SDimitry Andric return EmitSelectorAddr(Sel);
19010b57cec5SDimitry Andric }
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)19020b57cec5SDimitry Andric llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
19030b57cec5SDimitry Andric *Method) {
19040b57cec5SDimitry Andric return EmitSelector(CGF, Method->getSelector());
19050b57cec5SDimitry Andric }
19060b57cec5SDimitry Andric
GetEHType(QualType T)19070b57cec5SDimitry Andric llvm::Constant *CGObjCMac::GetEHType(QualType T) {
19080b57cec5SDimitry Andric if (T->isObjCIdType() ||
19090b57cec5SDimitry Andric T->isObjCQualifiedIdType()) {
19100b57cec5SDimitry Andric return CGM.GetAddrOfRTTIDescriptor(
19110b57cec5SDimitry Andric CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
19120b57cec5SDimitry Andric }
19130b57cec5SDimitry Andric if (T->isObjCClassType() ||
19140b57cec5SDimitry Andric T->isObjCQualifiedClassType()) {
19150b57cec5SDimitry Andric return CGM.GetAddrOfRTTIDescriptor(
19160b57cec5SDimitry Andric CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
19170b57cec5SDimitry Andric }
19180b57cec5SDimitry Andric if (T->isObjCObjectPointerType())
19190b57cec5SDimitry Andric return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
19200b57cec5SDimitry Andric
19210b57cec5SDimitry Andric llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
19220b57cec5SDimitry Andric }
19230b57cec5SDimitry Andric
19240b57cec5SDimitry Andric /// Generate a constant CFString object.
19250b57cec5SDimitry Andric /*
19260b57cec5SDimitry Andric struct __builtin_CFString {
19270b57cec5SDimitry Andric const int *isa; // point to __CFConstantStringClassReference
19280b57cec5SDimitry Andric int flags;
19290b57cec5SDimitry Andric const char *str;
19300b57cec5SDimitry Andric long length;
19310b57cec5SDimitry Andric };
19320b57cec5SDimitry Andric */
19330b57cec5SDimitry Andric
19340b57cec5SDimitry Andric /// or Generate a constant NSString object.
19350b57cec5SDimitry Andric /*
19360b57cec5SDimitry Andric struct __builtin_NSString {
19370b57cec5SDimitry Andric const int *isa; // point to __NSConstantStringClassReference
19380b57cec5SDimitry Andric const char *str;
19390b57cec5SDimitry Andric unsigned int length;
19400b57cec5SDimitry Andric };
19410b57cec5SDimitry Andric */
19420b57cec5SDimitry Andric
19430b57cec5SDimitry Andric ConstantAddress
GenerateConstantString(const StringLiteral * SL)19440b57cec5SDimitry Andric CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
19450b57cec5SDimitry Andric return (!CGM.getLangOpts().NoConstantCFStrings
19460b57cec5SDimitry Andric ? CGM.GetAddrOfConstantCFString(SL)
19470b57cec5SDimitry Andric : GenerateConstantNSString(SL));
19480b57cec5SDimitry Andric }
19490b57cec5SDimitry Andric
19500b57cec5SDimitry Andric static llvm::StringMapEntry<llvm::GlobalVariable *> &
GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable * > & Map,const StringLiteral * Literal,unsigned & StringLength)19510b57cec5SDimitry Andric GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
19520b57cec5SDimitry Andric const StringLiteral *Literal, unsigned &StringLength) {
19530b57cec5SDimitry Andric StringRef String = Literal->getString();
19540b57cec5SDimitry Andric StringLength = String.size();
19550b57cec5SDimitry Andric return *Map.insert(std::make_pair(String, nullptr)).first;
19560b57cec5SDimitry Andric }
19570b57cec5SDimitry Andric
getNSConstantStringClassRef()19580b57cec5SDimitry Andric llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
19590b57cec5SDimitry Andric if (llvm::Value *V = ConstantStringClassRef)
19600b57cec5SDimitry Andric return cast<llvm::Constant>(V);
19610b57cec5SDimitry Andric
19620b57cec5SDimitry Andric auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
19630b57cec5SDimitry Andric std::string str =
19640b57cec5SDimitry Andric StringClass.empty() ? "_NSConstantStringClassReference"
19650b57cec5SDimitry Andric : "_" + StringClass + "ClassReference";
19660b57cec5SDimitry Andric
19670b57cec5SDimitry Andric llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
19680b57cec5SDimitry Andric auto GV = CGM.CreateRuntimeVariable(PTy, str);
19695f757f3fSDimitry Andric ConstantStringClassRef = GV;
19705f757f3fSDimitry Andric return GV;
19710b57cec5SDimitry Andric }
19720b57cec5SDimitry Andric
getNSConstantStringClassRef()19730b57cec5SDimitry Andric llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
19740b57cec5SDimitry Andric if (llvm::Value *V = ConstantStringClassRef)
19750b57cec5SDimitry Andric return cast<llvm::Constant>(V);
19760b57cec5SDimitry Andric
19770b57cec5SDimitry Andric auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
19780b57cec5SDimitry Andric std::string str =
19790b57cec5SDimitry Andric StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
19800b57cec5SDimitry Andric : "OBJC_CLASS_$_" + StringClass;
19810b57cec5SDimitry Andric llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
19825f757f3fSDimitry Andric ConstantStringClassRef = GV;
19835f757f3fSDimitry Andric return GV;
19840b57cec5SDimitry Andric }
19850b57cec5SDimitry Andric
19860b57cec5SDimitry Andric ConstantAddress
GenerateConstantNSString(const StringLiteral * Literal)19870b57cec5SDimitry Andric CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
19880b57cec5SDimitry Andric unsigned StringLength = 0;
19890b57cec5SDimitry Andric llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
19900b57cec5SDimitry Andric GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
19910b57cec5SDimitry Andric
19920b57cec5SDimitry Andric if (auto *C = Entry.second)
19930eae32dcSDimitry Andric return ConstantAddress(
19940eae32dcSDimitry Andric C, C->getValueType(), CharUnits::fromQuantity(C->getAlignment()));
19950b57cec5SDimitry Andric
19960b57cec5SDimitry Andric // If we don't already have it, get _NSConstantStringClassReference.
19970b57cec5SDimitry Andric llvm::Constant *Class = getNSConstantStringClassRef();
19980b57cec5SDimitry Andric
19990b57cec5SDimitry Andric // If we don't already have it, construct the type for a constant NSString.
20000b57cec5SDimitry Andric if (!NSConstantStringType) {
20010b57cec5SDimitry Andric NSConstantStringType =
20025f757f3fSDimitry Andric llvm::StructType::create({CGM.UnqualPtrTy, CGM.Int8PtrTy, CGM.IntTy},
20035f757f3fSDimitry Andric "struct.__builtin_NSString");
20040b57cec5SDimitry Andric }
20050b57cec5SDimitry Andric
20060b57cec5SDimitry Andric ConstantInitBuilder Builder(CGM);
20070b57cec5SDimitry Andric auto Fields = Builder.beginStruct(NSConstantStringType);
20080b57cec5SDimitry Andric
20090b57cec5SDimitry Andric // Class pointer.
20100b57cec5SDimitry Andric Fields.add(Class);
20110b57cec5SDimitry Andric
20120b57cec5SDimitry Andric // String pointer.
20130b57cec5SDimitry Andric llvm::Constant *C =
20140b57cec5SDimitry Andric llvm::ConstantDataArray::getString(VMContext, Entry.first());
20150b57cec5SDimitry Andric
20160b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
20170b57cec5SDimitry Andric bool isConstant = !CGM.getLangOpts().WritableStrings;
20180b57cec5SDimitry Andric
20190b57cec5SDimitry Andric auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
20200b57cec5SDimitry Andric Linkage, C, ".str");
20210b57cec5SDimitry Andric GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
20220b57cec5SDimitry Andric // Don't enforce the target's minimum global alignment, since the only use
20230b57cec5SDimitry Andric // of the string is via this class initializer.
20245ffd83dbSDimitry Andric GV->setAlignment(llvm::Align(1));
20255f757f3fSDimitry Andric Fields.add(GV);
20260b57cec5SDimitry Andric
20270b57cec5SDimitry Andric // String length.
20280b57cec5SDimitry Andric Fields.addInt(CGM.IntTy, StringLength);
20290b57cec5SDimitry Andric
20300b57cec5SDimitry Andric // The struct.
20310b57cec5SDimitry Andric CharUnits Alignment = CGM.getPointerAlign();
20320b57cec5SDimitry Andric GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
20330b57cec5SDimitry Andric /*constant*/ true,
20340b57cec5SDimitry Andric llvm::GlobalVariable::PrivateLinkage);
20350b57cec5SDimitry Andric const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
20360b57cec5SDimitry Andric const char *NSStringNonFragileABISection =
20370b57cec5SDimitry Andric "__DATA,__objc_stringobj,regular,no_dead_strip";
20380b57cec5SDimitry Andric // FIXME. Fix section.
20390b57cec5SDimitry Andric GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
20400b57cec5SDimitry Andric ? NSStringNonFragileABISection
20410b57cec5SDimitry Andric : NSStringSection);
20420b57cec5SDimitry Andric Entry.second = GV;
20430b57cec5SDimitry Andric
20440eae32dcSDimitry Andric return ConstantAddress(GV, GV->getValueType(), Alignment);
20450b57cec5SDimitry Andric }
20460b57cec5SDimitry Andric
20470b57cec5SDimitry Andric enum {
20480b57cec5SDimitry Andric kCFTaggedObjectID_Integer = (1 << 1) + 1
20490b57cec5SDimitry Andric };
20500b57cec5SDimitry Andric
20510b57cec5SDimitry Andric /// Generates a message send where the super is the receiver. This is
20520b57cec5SDimitry Andric /// a message send to self with special delivery semantics indicating
20530b57cec5SDimitry Andric /// which class's method should be called.
20540b57cec5SDimitry Andric CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,const ObjCInterfaceDecl * Class,bool isCategoryImpl,llvm::Value * Receiver,bool IsClassMessage,const CodeGen::CallArgList & CallArgs,const ObjCMethodDecl * Method)20550b57cec5SDimitry Andric CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
20560b57cec5SDimitry Andric ReturnValueSlot Return,
20570b57cec5SDimitry Andric QualType ResultType,
20580b57cec5SDimitry Andric Selector Sel,
20590b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
20600b57cec5SDimitry Andric bool isCategoryImpl,
20610b57cec5SDimitry Andric llvm::Value *Receiver,
20620b57cec5SDimitry Andric bool IsClassMessage,
20630b57cec5SDimitry Andric const CodeGen::CallArgList &CallArgs,
20640b57cec5SDimitry Andric const ObjCMethodDecl *Method) {
20650b57cec5SDimitry Andric // Create and init a super structure; this is a (receiver, class)
20660b57cec5SDimitry Andric // pair we will pass to objc_msgSendSuper.
2067*0fca6ea1SDimitry Andric RawAddress ObjCSuper = CGF.CreateTempAlloca(
2068*0fca6ea1SDimitry Andric ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super");
20690b57cec5SDimitry Andric llvm::Value *ReceiverAsObject =
20700b57cec5SDimitry Andric CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
20710b57cec5SDimitry Andric CGF.Builder.CreateStore(ReceiverAsObject,
20720b57cec5SDimitry Andric CGF.Builder.CreateStructGEP(ObjCSuper, 0));
20730b57cec5SDimitry Andric
20740b57cec5SDimitry Andric // If this is a class message the metaclass is passed as the target.
2075fe6060f1SDimitry Andric llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
20760b57cec5SDimitry Andric llvm::Value *Target;
20770b57cec5SDimitry Andric if (IsClassMessage) {
20780b57cec5SDimitry Andric if (isCategoryImpl) {
20790b57cec5SDimitry Andric // Message sent to 'super' in a class method defined in a category
20800b57cec5SDimitry Andric // implementation requires an odd treatment.
20810b57cec5SDimitry Andric // If we are in a class method, we must retrieve the
20820b57cec5SDimitry Andric // _metaclass_ for the current class, pointed at by
20830b57cec5SDimitry Andric // the class's "isa" pointer. The following assumes that
20840b57cec5SDimitry Andric // isa" is the first ivar in a class (which it must be).
20850b57cec5SDimitry Andric Target = EmitClassRef(CGF, Class->getSuperClass());
20860b57cec5SDimitry Andric Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
2087fe6060f1SDimitry Andric Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, Target,
2088fe6060f1SDimitry Andric CGF.getPointerAlign());
20890b57cec5SDimitry Andric } else {
20900b57cec5SDimitry Andric llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
20910b57cec5SDimitry Andric llvm::Value *SuperPtr =
20920b57cec5SDimitry Andric CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
2093fe6060f1SDimitry Andric llvm::Value *Super = CGF.Builder.CreateAlignedLoad(ClassTyPtr, SuperPtr,
2094fe6060f1SDimitry Andric CGF.getPointerAlign());
20950b57cec5SDimitry Andric Target = Super;
20960b57cec5SDimitry Andric }
20970b57cec5SDimitry Andric } else if (isCategoryImpl)
20980b57cec5SDimitry Andric Target = EmitClassRef(CGF, Class->getSuperClass());
20990b57cec5SDimitry Andric else {
21000b57cec5SDimitry Andric llvm::Value *ClassPtr = EmitSuperClassRef(Class);
21010b57cec5SDimitry Andric ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
2102fe6060f1SDimitry Andric Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, ClassPtr,
2103fe6060f1SDimitry Andric CGF.getPointerAlign());
21040b57cec5SDimitry Andric }
21050b57cec5SDimitry Andric // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
21060b57cec5SDimitry Andric // ObjCTypes types.
21070b57cec5SDimitry Andric llvm::Type *ClassTy =
21080b57cec5SDimitry Andric CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
21090b57cec5SDimitry Andric Target = CGF.Builder.CreateBitCast(Target, ClassTy);
21100b57cec5SDimitry Andric CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
2111480093f4SDimitry Andric return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
2112480093f4SDimitry Andric ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class,
2113480093f4SDimitry Andric ObjCTypes);
21140b57cec5SDimitry Andric }
21150b57cec5SDimitry Andric
21160b57cec5SDimitry Andric /// Generate code for a message send expression.
GenerateMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)21170b57cec5SDimitry Andric CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
21180b57cec5SDimitry Andric ReturnValueSlot Return,
21190b57cec5SDimitry Andric QualType ResultType,
21200b57cec5SDimitry Andric Selector Sel,
21210b57cec5SDimitry Andric llvm::Value *Receiver,
21220b57cec5SDimitry Andric const CallArgList &CallArgs,
21230b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
21240b57cec5SDimitry Andric const ObjCMethodDecl *Method) {
2125480093f4SDimitry Andric return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2126480093f4SDimitry Andric CGF.getContext().getObjCIdType(), false, CallArgs,
2127480093f4SDimitry Andric Method, Class, ObjCTypes);
21280b57cec5SDimitry Andric }
21290b57cec5SDimitry Andric
21300b57cec5SDimitry Andric CodeGen::RValue
EmitMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Arg0,QualType Arg0Ty,bool IsSuper,const CallArgList & CallArgs,const ObjCMethodDecl * Method,const ObjCInterfaceDecl * ClassReceiver,const ObjCCommonTypesHelper & ObjCTypes)21310b57cec5SDimitry Andric CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
21320b57cec5SDimitry Andric ReturnValueSlot Return,
21330b57cec5SDimitry Andric QualType ResultType,
2134480093f4SDimitry Andric Selector Sel,
21350b57cec5SDimitry Andric llvm::Value *Arg0,
21360b57cec5SDimitry Andric QualType Arg0Ty,
21370b57cec5SDimitry Andric bool IsSuper,
21380b57cec5SDimitry Andric const CallArgList &CallArgs,
21390b57cec5SDimitry Andric const ObjCMethodDecl *Method,
21400b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassReceiver,
21410b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes) {
2142480093f4SDimitry Andric CodeGenTypes &Types = CGM.getTypes();
2143480093f4SDimitry Andric auto selTy = CGF.getContext().getObjCSelType();
214404eeddc0SDimitry Andric llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2145480093f4SDimitry Andric
21460b57cec5SDimitry Andric CallArgList ActualArgs;
21470b57cec5SDimitry Andric if (!IsSuper)
21480b57cec5SDimitry Andric Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
21490b57cec5SDimitry Andric ActualArgs.add(RValue::get(Arg0), Arg0Ty);
2150bdd1243dSDimitry Andric if (!Method || !Method->isDirectMethod())
2151480093f4SDimitry Andric ActualArgs.add(RValue::get(SelValue), selTy);
21520b57cec5SDimitry Andric ActualArgs.addFrom(CallArgs);
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric // If we're calling a method, use the formal signature.
21550b57cec5SDimitry Andric MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
21560b57cec5SDimitry Andric
21570b57cec5SDimitry Andric if (Method)
21580b57cec5SDimitry Andric assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
21590b57cec5SDimitry Andric CGM.getContext().getCanonicalType(ResultType) &&
21600b57cec5SDimitry Andric "Result type mismatch!");
21610b57cec5SDimitry Andric
2162349cc55cSDimitry Andric bool ReceiverCanBeNull =
2163349cc55cSDimitry Andric canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
21640b57cec5SDimitry Andric
21650b57cec5SDimitry Andric bool RequiresNullCheck = false;
216604eeddc0SDimitry Andric bool RequiresSelValue = true;
21670b57cec5SDimitry Andric
21680b57cec5SDimitry Andric llvm::FunctionCallee Fn = nullptr;
2169480093f4SDimitry Andric if (Method && Method->isDirectMethod()) {
217004eeddc0SDimitry Andric assert(!IsSuper);
2171480093f4SDimitry Andric Fn = GenerateDirectMethod(Method, Method->getClassInterface());
217204eeddc0SDimitry Andric // Direct methods will synthesize the proper `_cmd` internally,
217304eeddc0SDimitry Andric // so just don't bother with setting the `_cmd` argument.
217404eeddc0SDimitry Andric RequiresSelValue = false;
2175480093f4SDimitry Andric } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
21760b57cec5SDimitry Andric if (ReceiverCanBeNull) RequiresNullCheck = true;
21770b57cec5SDimitry Andric Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
21780b57cec5SDimitry Andric : ObjCTypes.getSendStretFn(IsSuper);
21790b57cec5SDimitry Andric } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
21800b57cec5SDimitry Andric Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
21810b57cec5SDimitry Andric : ObjCTypes.getSendFpretFn(IsSuper);
21820b57cec5SDimitry Andric } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
21830b57cec5SDimitry Andric Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
21840b57cec5SDimitry Andric : ObjCTypes.getSendFp2retFn(IsSuper);
21850b57cec5SDimitry Andric } else {
21860b57cec5SDimitry Andric // arm64 uses objc_msgSend for stret methods and yet null receiver check
21870b57cec5SDimitry Andric // must be made for it.
21880b57cec5SDimitry Andric if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
21890b57cec5SDimitry Andric RequiresNullCheck = true;
21900b57cec5SDimitry Andric Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
21910b57cec5SDimitry Andric : ObjCTypes.getSendFn(IsSuper);
21920b57cec5SDimitry Andric }
21930b57cec5SDimitry Andric
21940b57cec5SDimitry Andric // Cast function to proper signature
21950b57cec5SDimitry Andric llvm::Constant *BitcastFn = cast<llvm::Constant>(
21960b57cec5SDimitry Andric CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
21970b57cec5SDimitry Andric
21980b57cec5SDimitry Andric // We don't need to emit a null check to zero out an indirect result if the
21990b57cec5SDimitry Andric // result is ignored.
22000b57cec5SDimitry Andric if (Return.isUnused())
22010b57cec5SDimitry Andric RequiresNullCheck = false;
22020b57cec5SDimitry Andric
22030b57cec5SDimitry Andric // Emit a null-check if there's a consumed argument other than the receiver.
2204349cc55cSDimitry Andric if (!RequiresNullCheck && Method && Method->hasParamDestroyedInCallee())
22050b57cec5SDimitry Andric RequiresNullCheck = true;
22060b57cec5SDimitry Andric
22070b57cec5SDimitry Andric NullReturnState nullReturn;
22080b57cec5SDimitry Andric if (RequiresNullCheck) {
22090b57cec5SDimitry Andric nullReturn.init(CGF, Arg0);
22100b57cec5SDimitry Andric }
22110b57cec5SDimitry Andric
221204eeddc0SDimitry Andric // If a selector value needs to be passed, emit the load before the call.
221304eeddc0SDimitry Andric if (RequiresSelValue) {
221404eeddc0SDimitry Andric SelValue = GetSelector(CGF, Sel);
221504eeddc0SDimitry Andric ActualArgs[1] = CallArg(RValue::get(SelValue), selTy);
221604eeddc0SDimitry Andric }
221704eeddc0SDimitry Andric
22180b57cec5SDimitry Andric llvm::CallBase *CallSite;
22190b57cec5SDimitry Andric CGCallee Callee = CGCallee::forDirect(BitcastFn);
22200b57cec5SDimitry Andric RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
22210b57cec5SDimitry Andric &CallSite);
22220b57cec5SDimitry Andric
22230b57cec5SDimitry Andric // Mark the call as noreturn if the method is marked noreturn and the
22240b57cec5SDimitry Andric // receiver cannot be null.
22250b57cec5SDimitry Andric if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
22260b57cec5SDimitry Andric CallSite->setDoesNotReturn();
22270b57cec5SDimitry Andric }
22280b57cec5SDimitry Andric
22290b57cec5SDimitry Andric return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
22300b57cec5SDimitry Andric RequiresNullCheck ? Method : nullptr);
22310b57cec5SDimitry Andric }
22320b57cec5SDimitry Andric
GetGCAttrTypeForType(ASTContext & Ctx,QualType FQT,bool pointee=false)22330b57cec5SDimitry Andric static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
22340b57cec5SDimitry Andric bool pointee = false) {
22350b57cec5SDimitry Andric // Note that GC qualification applies recursively to C pointer types
22360b57cec5SDimitry Andric // that aren't otherwise decorated. This is weird, but it's probably
22370b57cec5SDimitry Andric // an intentional workaround to the unreliable placement of GC qualifiers.
22380b57cec5SDimitry Andric if (FQT.isObjCGCStrong())
22390b57cec5SDimitry Andric return Qualifiers::Strong;
22400b57cec5SDimitry Andric
22410b57cec5SDimitry Andric if (FQT.isObjCGCWeak())
22420b57cec5SDimitry Andric return Qualifiers::Weak;
22430b57cec5SDimitry Andric
22440b57cec5SDimitry Andric if (auto ownership = FQT.getObjCLifetime()) {
22450b57cec5SDimitry Andric // Ownership does not apply recursively to C pointer types.
22460b57cec5SDimitry Andric if (pointee) return Qualifiers::GCNone;
22470b57cec5SDimitry Andric switch (ownership) {
22480b57cec5SDimitry Andric case Qualifiers::OCL_Weak: return Qualifiers::Weak;
22490b57cec5SDimitry Andric case Qualifiers::OCL_Strong: return Qualifiers::Strong;
22500b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
22510b57cec5SDimitry Andric case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
22520b57cec5SDimitry Andric case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
22530b57cec5SDimitry Andric }
22540b57cec5SDimitry Andric llvm_unreachable("bad objc ownership");
22550b57cec5SDimitry Andric }
22560b57cec5SDimitry Andric
22570b57cec5SDimitry Andric // Treat unqualified retainable pointers as strong.
22580b57cec5SDimitry Andric if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
22590b57cec5SDimitry Andric return Qualifiers::Strong;
22600b57cec5SDimitry Andric
22610b57cec5SDimitry Andric // Walk into C pointer types, but only in GC.
22620b57cec5SDimitry Andric if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
22630b57cec5SDimitry Andric if (const PointerType *PT = FQT->getAs<PointerType>())
22640b57cec5SDimitry Andric return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
22650b57cec5SDimitry Andric }
22660b57cec5SDimitry Andric
22670b57cec5SDimitry Andric return Qualifiers::GCNone;
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric
22700b57cec5SDimitry Andric namespace {
22710b57cec5SDimitry Andric struct IvarInfo {
22720b57cec5SDimitry Andric CharUnits Offset;
22730b57cec5SDimitry Andric uint64_t SizeInWords;
IvarInfo__anonb5e682970511::IvarInfo22740b57cec5SDimitry Andric IvarInfo(CharUnits offset, uint64_t sizeInWords)
22750b57cec5SDimitry Andric : Offset(offset), SizeInWords(sizeInWords) {}
22760b57cec5SDimitry Andric
22770b57cec5SDimitry Andric // Allow sorting based on byte pos.
operator <__anonb5e682970511::IvarInfo22780b57cec5SDimitry Andric bool operator<(const IvarInfo &other) const {
22790b57cec5SDimitry Andric return Offset < other.Offset;
22800b57cec5SDimitry Andric }
22810b57cec5SDimitry Andric };
22820b57cec5SDimitry Andric
22830b57cec5SDimitry Andric /// A helper class for building GC layout strings.
22840b57cec5SDimitry Andric class IvarLayoutBuilder {
22850b57cec5SDimitry Andric CodeGenModule &CGM;
22860b57cec5SDimitry Andric
22870b57cec5SDimitry Andric /// The start of the layout. Offsets will be relative to this value,
22880b57cec5SDimitry Andric /// and entries less than this value will be silently discarded.
22890b57cec5SDimitry Andric CharUnits InstanceBegin;
22900b57cec5SDimitry Andric
22910b57cec5SDimitry Andric /// The end of the layout. Offsets will never exceed this value.
22920b57cec5SDimitry Andric CharUnits InstanceEnd;
22930b57cec5SDimitry Andric
22940b57cec5SDimitry Andric /// Whether we're generating the strong layout or the weak layout.
22950b57cec5SDimitry Andric bool ForStrongLayout;
22960b57cec5SDimitry Andric
22970b57cec5SDimitry Andric /// Whether the offsets in IvarsInfo might be out-of-order.
22980b57cec5SDimitry Andric bool IsDisordered = false;
22990b57cec5SDimitry Andric
23000b57cec5SDimitry Andric llvm::SmallVector<IvarInfo, 8> IvarsInfo;
23010b57cec5SDimitry Andric
23020b57cec5SDimitry Andric public:
IvarLayoutBuilder(CodeGenModule & CGM,CharUnits instanceBegin,CharUnits instanceEnd,bool forStrongLayout)23030b57cec5SDimitry Andric IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
23040b57cec5SDimitry Andric CharUnits instanceEnd, bool forStrongLayout)
23050b57cec5SDimitry Andric : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
23060b57cec5SDimitry Andric ForStrongLayout(forStrongLayout) {
23070b57cec5SDimitry Andric }
23080b57cec5SDimitry Andric
23090b57cec5SDimitry Andric void visitRecord(const RecordType *RT, CharUnits offset);
23100b57cec5SDimitry Andric
23110b57cec5SDimitry Andric template <class Iterator, class GetOffsetFn>
23120b57cec5SDimitry Andric void visitAggregate(Iterator begin, Iterator end,
23130b57cec5SDimitry Andric CharUnits aggrOffset,
23140b57cec5SDimitry Andric const GetOffsetFn &getOffset);
23150b57cec5SDimitry Andric
23160b57cec5SDimitry Andric void visitField(const FieldDecl *field, CharUnits offset);
23170b57cec5SDimitry Andric
23180b57cec5SDimitry Andric /// Add the layout of a block implementation.
23190b57cec5SDimitry Andric void visitBlock(const CGBlockInfo &blockInfo);
23200b57cec5SDimitry Andric
23210b57cec5SDimitry Andric /// Is there any information for an interesting bitmap?
hasBitmapData() const23220b57cec5SDimitry Andric bool hasBitmapData() const { return !IvarsInfo.empty(); }
23230b57cec5SDimitry Andric
23240b57cec5SDimitry Andric llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
23250b57cec5SDimitry Andric llvm::SmallVectorImpl<unsigned char> &buffer);
23260b57cec5SDimitry Andric
dump(ArrayRef<unsigned char> buffer)23270b57cec5SDimitry Andric static void dump(ArrayRef<unsigned char> buffer) {
23280b57cec5SDimitry Andric const unsigned char *s = buffer.data();
23290b57cec5SDimitry Andric for (unsigned i = 0, e = buffer.size(); i < e; i++)
23300b57cec5SDimitry Andric if (!(s[i] & 0xf0))
23310b57cec5SDimitry Andric printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
23320b57cec5SDimitry Andric else
23330b57cec5SDimitry Andric printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
23340b57cec5SDimitry Andric printf("\n");
23350b57cec5SDimitry Andric }
23360b57cec5SDimitry Andric };
23370b57cec5SDimitry Andric } // end anonymous namespace
23380b57cec5SDimitry Andric
BuildGCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)23390b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
23400b57cec5SDimitry Andric const CGBlockInfo &blockInfo) {
23410b57cec5SDimitry Andric
23420b57cec5SDimitry Andric llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
23430b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
23440b57cec5SDimitry Andric return nullPtr;
23450b57cec5SDimitry Andric
23460b57cec5SDimitry Andric IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
23470b57cec5SDimitry Andric /*for strong layout*/ true);
23480b57cec5SDimitry Andric
23490b57cec5SDimitry Andric builder.visitBlock(blockInfo);
23500b57cec5SDimitry Andric
23510b57cec5SDimitry Andric if (!builder.hasBitmapData())
23520b57cec5SDimitry Andric return nullPtr;
23530b57cec5SDimitry Andric
23540b57cec5SDimitry Andric llvm::SmallVector<unsigned char, 32> buffer;
23550b57cec5SDimitry Andric llvm::Constant *C = builder.buildBitmap(*this, buffer);
23560b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
23570b57cec5SDimitry Andric printf("\n block variable layout for block: ");
23580b57cec5SDimitry Andric builder.dump(buffer);
23590b57cec5SDimitry Andric }
23600b57cec5SDimitry Andric
23610b57cec5SDimitry Andric return C;
23620b57cec5SDimitry Andric }
23630b57cec5SDimitry Andric
visitBlock(const CGBlockInfo & blockInfo)23640b57cec5SDimitry Andric void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
23650b57cec5SDimitry Andric // __isa is the first field in block descriptor and must assume by runtime's
23660b57cec5SDimitry Andric // convention that it is GC'able.
23670b57cec5SDimitry Andric IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
23680b57cec5SDimitry Andric
23690b57cec5SDimitry Andric const BlockDecl *blockDecl = blockInfo.getBlockDecl();
23700b57cec5SDimitry Andric
23710b57cec5SDimitry Andric // Ignore the optional 'this' capture: C++ objects are not assumed
23720b57cec5SDimitry Andric // to be GC'ed.
23730b57cec5SDimitry Andric
23740b57cec5SDimitry Andric CharUnits lastFieldOffset;
23750b57cec5SDimitry Andric
23760b57cec5SDimitry Andric // Walk the captured variables.
23770b57cec5SDimitry Andric for (const auto &CI : blockDecl->captures()) {
23780b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable();
23790b57cec5SDimitry Andric QualType type = variable->getType();
23800b57cec5SDimitry Andric
23810b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
23820b57cec5SDimitry Andric
23830b57cec5SDimitry Andric // Ignore constant captures.
23840b57cec5SDimitry Andric if (capture.isConstant()) continue;
23850b57cec5SDimitry Andric
23860b57cec5SDimitry Andric CharUnits fieldOffset = capture.getOffset();
23870b57cec5SDimitry Andric
23880b57cec5SDimitry Andric // Block fields are not necessarily ordered; if we detect that we're
23890b57cec5SDimitry Andric // adding them out-of-order, make sure we sort later.
23900b57cec5SDimitry Andric if (fieldOffset < lastFieldOffset)
23910b57cec5SDimitry Andric IsDisordered = true;
23920b57cec5SDimitry Andric lastFieldOffset = fieldOffset;
23930b57cec5SDimitry Andric
23940b57cec5SDimitry Andric // __block variables are passed by their descriptor address.
23950b57cec5SDimitry Andric if (CI.isByRef()) {
23960b57cec5SDimitry Andric IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
23970b57cec5SDimitry Andric continue;
23980b57cec5SDimitry Andric }
23990b57cec5SDimitry Andric
24000b57cec5SDimitry Andric assert(!type->isArrayType() && "array variable should not be caught");
24010b57cec5SDimitry Andric if (const RecordType *record = type->getAs<RecordType>()) {
24020b57cec5SDimitry Andric visitRecord(record, fieldOffset);
24030b57cec5SDimitry Andric continue;
24040b57cec5SDimitry Andric }
24050b57cec5SDimitry Andric
24060b57cec5SDimitry Andric Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
24070b57cec5SDimitry Andric
24080b57cec5SDimitry Andric if (GCAttr == Qualifiers::Strong) {
2409bdd1243dSDimitry Andric assert(CGM.getContext().getTypeSize(type) ==
2410bdd1243dSDimitry Andric CGM.getTarget().getPointerWidth(LangAS::Default));
24110b57cec5SDimitry Andric IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
24120b57cec5SDimitry Andric }
24130b57cec5SDimitry Andric }
24140b57cec5SDimitry Andric }
24150b57cec5SDimitry Andric
24160b57cec5SDimitry Andric /// getBlockCaptureLifetime - This routine returns life time of the captured
24170b57cec5SDimitry Andric /// block variable for the purpose of block layout meta-data generation. FQT is
24180b57cec5SDimitry Andric /// the type of the variable captured in the block.
getBlockCaptureLifetime(QualType FQT,bool ByrefLayout)24190b57cec5SDimitry Andric Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
24200b57cec5SDimitry Andric bool ByrefLayout) {
24210b57cec5SDimitry Andric // If it has an ownership qualifier, we're done.
24220b57cec5SDimitry Andric if (auto lifetime = FQT.getObjCLifetime())
24230b57cec5SDimitry Andric return lifetime;
24240b57cec5SDimitry Andric
24250b57cec5SDimitry Andric // If it doesn't, and this is ARC, it has no ownership.
24260b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount)
24270b57cec5SDimitry Andric return Qualifiers::OCL_None;
24280b57cec5SDimitry Andric
24290b57cec5SDimitry Andric // In MRC, retainable pointers are owned by non-__block variables.
24300b57cec5SDimitry Andric if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
24310b57cec5SDimitry Andric return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
24320b57cec5SDimitry Andric
24330b57cec5SDimitry Andric return Qualifiers::OCL_None;
24340b57cec5SDimitry Andric }
24350b57cec5SDimitry Andric
UpdateRunSkipBlockVars(bool IsByref,Qualifiers::ObjCLifetime LifeTime,CharUnits FieldOffset,CharUnits FieldSize)24360b57cec5SDimitry Andric void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
24370b57cec5SDimitry Andric Qualifiers::ObjCLifetime LifeTime,
24380b57cec5SDimitry Andric CharUnits FieldOffset,
24390b57cec5SDimitry Andric CharUnits FieldSize) {
24400b57cec5SDimitry Andric // __block variables are passed by their descriptor address.
24410b57cec5SDimitry Andric if (IsByref)
24420b57cec5SDimitry Andric RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
24430b57cec5SDimitry Andric FieldSize));
24440b57cec5SDimitry Andric else if (LifeTime == Qualifiers::OCL_Strong)
24450b57cec5SDimitry Andric RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
24460b57cec5SDimitry Andric FieldSize));
24470b57cec5SDimitry Andric else if (LifeTime == Qualifiers::OCL_Weak)
24480b57cec5SDimitry Andric RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
24490b57cec5SDimitry Andric FieldSize));
24500b57cec5SDimitry Andric else if (LifeTime == Qualifiers::OCL_ExplicitNone)
24510b57cec5SDimitry Andric RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
24520b57cec5SDimitry Andric FieldSize));
24530b57cec5SDimitry Andric else
24540b57cec5SDimitry Andric RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
24550b57cec5SDimitry Andric FieldOffset,
24560b57cec5SDimitry Andric FieldSize));
24570b57cec5SDimitry Andric }
24580b57cec5SDimitry Andric
BuildRCRecordLayout(const llvm::StructLayout * RecLayout,const RecordDecl * RD,ArrayRef<const FieldDecl * > RecFields,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)24590b57cec5SDimitry Andric void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
24600b57cec5SDimitry Andric const RecordDecl *RD,
24610b57cec5SDimitry Andric ArrayRef<const FieldDecl*> RecFields,
24620b57cec5SDimitry Andric CharUnits BytePos, bool &HasUnion,
24630b57cec5SDimitry Andric bool ByrefLayout) {
24640b57cec5SDimitry Andric bool IsUnion = (RD && RD->isUnion());
24650b57cec5SDimitry Andric CharUnits MaxUnionSize = CharUnits::Zero();
24660b57cec5SDimitry Andric const FieldDecl *MaxField = nullptr;
24670b57cec5SDimitry Andric const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
24680b57cec5SDimitry Andric CharUnits MaxFieldOffset = CharUnits::Zero();
24690b57cec5SDimitry Andric CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
24700b57cec5SDimitry Andric
24710b57cec5SDimitry Andric if (RecFields.empty())
24720b57cec5SDimitry Andric return;
24730b57cec5SDimitry Andric unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
24740b57cec5SDimitry Andric
24750b57cec5SDimitry Andric for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
24760b57cec5SDimitry Andric const FieldDecl *Field = RecFields[i];
24770b57cec5SDimitry Andric // Note that 'i' here is actually the field index inside RD of Field,
24780b57cec5SDimitry Andric // although this dependency is hidden.
24790b57cec5SDimitry Andric const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
24800b57cec5SDimitry Andric CharUnits FieldOffset =
24810b57cec5SDimitry Andric CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
24820b57cec5SDimitry Andric
24830b57cec5SDimitry Andric // Skip over unnamed or bitfields
24840b57cec5SDimitry Andric if (!Field->getIdentifier() || Field->isBitField()) {
24850b57cec5SDimitry Andric LastFieldBitfieldOrUnnamed = Field;
24860b57cec5SDimitry Andric LastBitfieldOrUnnamedOffset = FieldOffset;
24870b57cec5SDimitry Andric continue;
24880b57cec5SDimitry Andric }
24890b57cec5SDimitry Andric
24900b57cec5SDimitry Andric LastFieldBitfieldOrUnnamed = nullptr;
24910b57cec5SDimitry Andric QualType FQT = Field->getType();
24920b57cec5SDimitry Andric if (FQT->isRecordType() || FQT->isUnionType()) {
24930b57cec5SDimitry Andric if (FQT->isUnionType())
24940b57cec5SDimitry Andric HasUnion = true;
24950b57cec5SDimitry Andric
249604eeddc0SDimitry Andric BuildRCBlockVarRecordLayout(FQT->castAs<RecordType>(),
24970b57cec5SDimitry Andric BytePos + FieldOffset, HasUnion);
24980b57cec5SDimitry Andric continue;
24990b57cec5SDimitry Andric }
25000b57cec5SDimitry Andric
25010b57cec5SDimitry Andric if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2502a7dea167SDimitry Andric auto *CArray = cast<ConstantArrayType>(Array);
2503*0fca6ea1SDimitry Andric uint64_t ElCount = CArray->getZExtSize();
25040b57cec5SDimitry Andric assert(CArray && "only array with known element size is supported");
25050b57cec5SDimitry Andric FQT = CArray->getElementType();
25060b57cec5SDimitry Andric while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2507a7dea167SDimitry Andric auto *CArray = cast<ConstantArrayType>(Array);
2508*0fca6ea1SDimitry Andric ElCount *= CArray->getZExtSize();
25090b57cec5SDimitry Andric FQT = CArray->getElementType();
25100b57cec5SDimitry Andric }
25110b57cec5SDimitry Andric if (FQT->isRecordType() && ElCount) {
25120b57cec5SDimitry Andric int OldIndex = RunSkipBlockVars.size() - 1;
25135ffd83dbSDimitry Andric auto *RT = FQT->castAs<RecordType>();
25145ffd83dbSDimitry Andric BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
25150b57cec5SDimitry Andric
25160b57cec5SDimitry Andric // Replicate layout information for each array element. Note that
25170b57cec5SDimitry Andric // one element is already done.
25180b57cec5SDimitry Andric uint64_t ElIx = 1;
25190b57cec5SDimitry Andric for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
25200b57cec5SDimitry Andric CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
25210b57cec5SDimitry Andric for (int i = OldIndex+1; i <= FirstIndex; ++i)
25220b57cec5SDimitry Andric RunSkipBlockVars.push_back(
25230b57cec5SDimitry Andric RUN_SKIP(RunSkipBlockVars[i].opcode,
25240b57cec5SDimitry Andric RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
25250b57cec5SDimitry Andric RunSkipBlockVars[i].block_var_size));
25260b57cec5SDimitry Andric }
25270b57cec5SDimitry Andric continue;
25280b57cec5SDimitry Andric }
25290b57cec5SDimitry Andric }
25300b57cec5SDimitry Andric CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
25310b57cec5SDimitry Andric if (IsUnion) {
25320b57cec5SDimitry Andric CharUnits UnionIvarSize = FieldSize;
25330b57cec5SDimitry Andric if (UnionIvarSize > MaxUnionSize) {
25340b57cec5SDimitry Andric MaxUnionSize = UnionIvarSize;
25350b57cec5SDimitry Andric MaxField = Field;
25360b57cec5SDimitry Andric MaxFieldOffset = FieldOffset;
25370b57cec5SDimitry Andric }
25380b57cec5SDimitry Andric } else {
25390b57cec5SDimitry Andric UpdateRunSkipBlockVars(false,
25400b57cec5SDimitry Andric getBlockCaptureLifetime(FQT, ByrefLayout),
25410b57cec5SDimitry Andric BytePos + FieldOffset,
25420b57cec5SDimitry Andric FieldSize);
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric }
25450b57cec5SDimitry Andric
25460b57cec5SDimitry Andric if (LastFieldBitfieldOrUnnamed) {
25470b57cec5SDimitry Andric if (LastFieldBitfieldOrUnnamed->isBitField()) {
25480b57cec5SDimitry Andric // Last field was a bitfield. Must update the info.
25490b57cec5SDimitry Andric uint64_t BitFieldSize
25500b57cec5SDimitry Andric = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
25510b57cec5SDimitry Andric unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
25520b57cec5SDimitry Andric ((BitFieldSize % ByteSizeInBits) != 0);
25530b57cec5SDimitry Andric CharUnits Size = CharUnits::fromQuantity(UnsSize);
25540b57cec5SDimitry Andric Size += LastBitfieldOrUnnamedOffset;
25550b57cec5SDimitry Andric UpdateRunSkipBlockVars(false,
25560b57cec5SDimitry Andric getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
25570b57cec5SDimitry Andric ByrefLayout),
25580b57cec5SDimitry Andric BytePos + LastBitfieldOrUnnamedOffset,
25590b57cec5SDimitry Andric Size);
25600b57cec5SDimitry Andric } else {
25610b57cec5SDimitry Andric assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
25620b57cec5SDimitry Andric // Last field was unnamed. Must update skip info.
25630b57cec5SDimitry Andric CharUnits FieldSize
25640b57cec5SDimitry Andric = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
25650b57cec5SDimitry Andric UpdateRunSkipBlockVars(false,
25660b57cec5SDimitry Andric getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
25670b57cec5SDimitry Andric ByrefLayout),
25680b57cec5SDimitry Andric BytePos + LastBitfieldOrUnnamedOffset,
25690b57cec5SDimitry Andric FieldSize);
25700b57cec5SDimitry Andric }
25710b57cec5SDimitry Andric }
25720b57cec5SDimitry Andric
25730b57cec5SDimitry Andric if (MaxField)
25740b57cec5SDimitry Andric UpdateRunSkipBlockVars(false,
25750b57cec5SDimitry Andric getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
25760b57cec5SDimitry Andric BytePos + MaxFieldOffset,
25770b57cec5SDimitry Andric MaxUnionSize);
25780b57cec5SDimitry Andric }
25790b57cec5SDimitry Andric
BuildRCBlockVarRecordLayout(const RecordType * RT,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)25800b57cec5SDimitry Andric void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
25810b57cec5SDimitry Andric CharUnits BytePos,
25820b57cec5SDimitry Andric bool &HasUnion,
25830b57cec5SDimitry Andric bool ByrefLayout) {
25840b57cec5SDimitry Andric const RecordDecl *RD = RT->getDecl();
25850b57cec5SDimitry Andric SmallVector<const FieldDecl*, 16> Fields(RD->fields());
25860b57cec5SDimitry Andric llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
25870b57cec5SDimitry Andric const llvm::StructLayout *RecLayout =
25880b57cec5SDimitry Andric CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
25890b57cec5SDimitry Andric
25900b57cec5SDimitry Andric BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
25910b57cec5SDimitry Andric }
25920b57cec5SDimitry Andric
25930b57cec5SDimitry Andric /// InlineLayoutInstruction - This routine produce an inline instruction for the
25940b57cec5SDimitry Andric /// block variable layout if it can. If not, it returns 0. Rules are as follow:
25950b57cec5SDimitry Andric /// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
25960b57cec5SDimitry Andric /// an inline layout of value 0x0000000000000xyz is interpreted as follows:
25970b57cec5SDimitry Andric /// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
25980b57cec5SDimitry Andric /// y captured object of BLOCK_LAYOUT_BYREF. Followed by
25990b57cec5SDimitry Andric /// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
26000b57cec5SDimitry Andric /// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
26010b57cec5SDimitry Andric /// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
InlineLayoutInstruction(SmallVectorImpl<unsigned char> & Layout)26020b57cec5SDimitry Andric uint64_t CGObjCCommonMac::InlineLayoutInstruction(
26030b57cec5SDimitry Andric SmallVectorImpl<unsigned char> &Layout) {
26040b57cec5SDimitry Andric uint64_t Result = 0;
26050b57cec5SDimitry Andric if (Layout.size() <= 3) {
26060b57cec5SDimitry Andric unsigned size = Layout.size();
26070b57cec5SDimitry Andric unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
26080b57cec5SDimitry Andric unsigned char inst;
26090b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE opcode ;
26100b57cec5SDimitry Andric switch (size) {
26110b57cec5SDimitry Andric case 3:
26120b57cec5SDimitry Andric inst = Layout[0];
26130b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26140b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_STRONG)
26150b57cec5SDimitry Andric strong_word_count = (inst & 0xF)+1;
26160b57cec5SDimitry Andric else
26170b57cec5SDimitry Andric return 0;
26180b57cec5SDimitry Andric inst = Layout[1];
26190b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26200b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_BYREF)
26210b57cec5SDimitry Andric byref_word_count = (inst & 0xF)+1;
26220b57cec5SDimitry Andric else
26230b57cec5SDimitry Andric return 0;
26240b57cec5SDimitry Andric inst = Layout[2];
26250b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26260b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_WEAK)
26270b57cec5SDimitry Andric weak_word_count = (inst & 0xF)+1;
26280b57cec5SDimitry Andric else
26290b57cec5SDimitry Andric return 0;
26300b57cec5SDimitry Andric break;
26310b57cec5SDimitry Andric
26320b57cec5SDimitry Andric case 2:
26330b57cec5SDimitry Andric inst = Layout[0];
26340b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26350b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_STRONG) {
26360b57cec5SDimitry Andric strong_word_count = (inst & 0xF)+1;
26370b57cec5SDimitry Andric inst = Layout[1];
26380b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26390b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_BYREF)
26400b57cec5SDimitry Andric byref_word_count = (inst & 0xF)+1;
26410b57cec5SDimitry Andric else if (opcode == BLOCK_LAYOUT_WEAK)
26420b57cec5SDimitry Andric weak_word_count = (inst & 0xF)+1;
26430b57cec5SDimitry Andric else
26440b57cec5SDimitry Andric return 0;
26450b57cec5SDimitry Andric }
26460b57cec5SDimitry Andric else if (opcode == BLOCK_LAYOUT_BYREF) {
26470b57cec5SDimitry Andric byref_word_count = (inst & 0xF)+1;
26480b57cec5SDimitry Andric inst = Layout[1];
26490b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26500b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_WEAK)
26510b57cec5SDimitry Andric weak_word_count = (inst & 0xF)+1;
26520b57cec5SDimitry Andric else
26530b57cec5SDimitry Andric return 0;
26540b57cec5SDimitry Andric }
26550b57cec5SDimitry Andric else
26560b57cec5SDimitry Andric return 0;
26570b57cec5SDimitry Andric break;
26580b57cec5SDimitry Andric
26590b57cec5SDimitry Andric case 1:
26600b57cec5SDimitry Andric inst = Layout[0];
26610b57cec5SDimitry Andric opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26620b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_STRONG)
26630b57cec5SDimitry Andric strong_word_count = (inst & 0xF)+1;
26640b57cec5SDimitry Andric else if (opcode == BLOCK_LAYOUT_BYREF)
26650b57cec5SDimitry Andric byref_word_count = (inst & 0xF)+1;
26660b57cec5SDimitry Andric else if (opcode == BLOCK_LAYOUT_WEAK)
26670b57cec5SDimitry Andric weak_word_count = (inst & 0xF)+1;
26680b57cec5SDimitry Andric else
26690b57cec5SDimitry Andric return 0;
26700b57cec5SDimitry Andric break;
26710b57cec5SDimitry Andric
26720b57cec5SDimitry Andric default:
26730b57cec5SDimitry Andric return 0;
26740b57cec5SDimitry Andric }
26750b57cec5SDimitry Andric
26760b57cec5SDimitry Andric // Cannot inline when any of the word counts is 15. Because this is one less
26770b57cec5SDimitry Andric // than the actual work count (so 15 means 16 actual word counts),
26780b57cec5SDimitry Andric // and we can only display 0 thru 15 word counts.
26790b57cec5SDimitry Andric if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
26800b57cec5SDimitry Andric return 0;
26810b57cec5SDimitry Andric
26820b57cec5SDimitry Andric unsigned count =
26830b57cec5SDimitry Andric (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
26840b57cec5SDimitry Andric
26850b57cec5SDimitry Andric if (size == count) {
26860b57cec5SDimitry Andric if (strong_word_count)
26870b57cec5SDimitry Andric Result = strong_word_count;
26880b57cec5SDimitry Andric Result <<= 4;
26890b57cec5SDimitry Andric if (byref_word_count)
26900b57cec5SDimitry Andric Result += byref_word_count;
26910b57cec5SDimitry Andric Result <<= 4;
26920b57cec5SDimitry Andric if (weak_word_count)
26930b57cec5SDimitry Andric Result += weak_word_count;
26940b57cec5SDimitry Andric }
26950b57cec5SDimitry Andric }
26960b57cec5SDimitry Andric return Result;
26970b57cec5SDimitry Andric }
26980b57cec5SDimitry Andric
getBitmapBlockLayout(bool ComputeByrefLayout)26990b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
27000b57cec5SDimitry Andric llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
27010b57cec5SDimitry Andric if (RunSkipBlockVars.empty())
27020b57cec5SDimitry Andric return nullPtr;
2703bdd1243dSDimitry Andric unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default);
27040b57cec5SDimitry Andric unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
27050b57cec5SDimitry Andric unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
27060b57cec5SDimitry Andric
27070b57cec5SDimitry Andric // Sort on byte position; captures might not be allocated in order,
27080b57cec5SDimitry Andric // and unions can do funny things.
27090b57cec5SDimitry Andric llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
27100b57cec5SDimitry Andric SmallVector<unsigned char, 16> Layout;
27110b57cec5SDimitry Andric
27120b57cec5SDimitry Andric unsigned size = RunSkipBlockVars.size();
27130b57cec5SDimitry Andric for (unsigned i = 0; i < size; i++) {
27140b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
27150b57cec5SDimitry Andric CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
27160b57cec5SDimitry Andric CharUnits end_byte_pos = start_byte_pos;
27170b57cec5SDimitry Andric unsigned j = i+1;
27180b57cec5SDimitry Andric while (j < size) {
27190b57cec5SDimitry Andric if (opcode == RunSkipBlockVars[j].opcode) {
27200b57cec5SDimitry Andric end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
27210b57cec5SDimitry Andric i++;
27220b57cec5SDimitry Andric }
27230b57cec5SDimitry Andric else
27240b57cec5SDimitry Andric break;
27250b57cec5SDimitry Andric }
27260b57cec5SDimitry Andric CharUnits size_in_bytes =
27270b57cec5SDimitry Andric end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
27280b57cec5SDimitry Andric if (j < size) {
27290b57cec5SDimitry Andric CharUnits gap =
27300b57cec5SDimitry Andric RunSkipBlockVars[j].block_var_bytepos -
27310b57cec5SDimitry Andric RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
27320b57cec5SDimitry Andric size_in_bytes += gap;
27330b57cec5SDimitry Andric }
27340b57cec5SDimitry Andric CharUnits residue_in_bytes = CharUnits::Zero();
27350b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
27360b57cec5SDimitry Andric residue_in_bytes = size_in_bytes % WordSizeInBytes;
27370b57cec5SDimitry Andric size_in_bytes -= residue_in_bytes;
27380b57cec5SDimitry Andric opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
27390b57cec5SDimitry Andric }
27400b57cec5SDimitry Andric
27410b57cec5SDimitry Andric unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
27420b57cec5SDimitry Andric while (size_in_words >= 16) {
27430b57cec5SDimitry Andric // Note that value in imm. is one less that the actual
27440b57cec5SDimitry Andric // value. So, 0xf means 16 words follow!
27450b57cec5SDimitry Andric unsigned char inst = (opcode << 4) | 0xf;
27460b57cec5SDimitry Andric Layout.push_back(inst);
27470b57cec5SDimitry Andric size_in_words -= 16;
27480b57cec5SDimitry Andric }
27490b57cec5SDimitry Andric if (size_in_words > 0) {
27500b57cec5SDimitry Andric // Note that value in imm. is one less that the actual
27510b57cec5SDimitry Andric // value. So, we subtract 1 away!
27520b57cec5SDimitry Andric unsigned char inst = (opcode << 4) | (size_in_words-1);
27530b57cec5SDimitry Andric Layout.push_back(inst);
27540b57cec5SDimitry Andric }
27550b57cec5SDimitry Andric if (residue_in_bytes > CharUnits::Zero()) {
27560b57cec5SDimitry Andric unsigned char inst =
27570b57cec5SDimitry Andric (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
27580b57cec5SDimitry Andric Layout.push_back(inst);
27590b57cec5SDimitry Andric }
27600b57cec5SDimitry Andric }
27610b57cec5SDimitry Andric
27620b57cec5SDimitry Andric while (!Layout.empty()) {
27630b57cec5SDimitry Andric unsigned char inst = Layout.back();
27640b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
27650b57cec5SDimitry Andric if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
27660b57cec5SDimitry Andric Layout.pop_back();
27670b57cec5SDimitry Andric else
27680b57cec5SDimitry Andric break;
27690b57cec5SDimitry Andric }
27700b57cec5SDimitry Andric
27710b57cec5SDimitry Andric uint64_t Result = InlineLayoutInstruction(Layout);
27720b57cec5SDimitry Andric if (Result != 0) {
27730b57cec5SDimitry Andric // Block variable layout instruction has been inlined.
27740b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCGCBitmapPrint) {
27750b57cec5SDimitry Andric if (ComputeByrefLayout)
27760b57cec5SDimitry Andric printf("\n Inline BYREF variable layout: ");
27770b57cec5SDimitry Andric else
27780b57cec5SDimitry Andric printf("\n Inline block variable layout: ");
27790b57cec5SDimitry Andric printf("0x0%" PRIx64 "", Result);
27800b57cec5SDimitry Andric if (auto numStrong = (Result & 0xF00) >> 8)
27810b57cec5SDimitry Andric printf(", BL_STRONG:%d", (int) numStrong);
27820b57cec5SDimitry Andric if (auto numByref = (Result & 0x0F0) >> 4)
27830b57cec5SDimitry Andric printf(", BL_BYREF:%d", (int) numByref);
27840b57cec5SDimitry Andric if (auto numWeak = (Result & 0x00F) >> 0)
27850b57cec5SDimitry Andric printf(", BL_WEAK:%d", (int) numWeak);
27860b57cec5SDimitry Andric printf(", BL_OPERATOR:0\n");
27870b57cec5SDimitry Andric }
27880b57cec5SDimitry Andric return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
27890b57cec5SDimitry Andric }
27900b57cec5SDimitry Andric
27910b57cec5SDimitry Andric unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
27920b57cec5SDimitry Andric Layout.push_back(inst);
27930b57cec5SDimitry Andric std::string BitMap;
27940b57cec5SDimitry Andric for (unsigned i = 0, e = Layout.size(); i != e; i++)
27950b57cec5SDimitry Andric BitMap += Layout[i];
27960b57cec5SDimitry Andric
27970b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCGCBitmapPrint) {
27980b57cec5SDimitry Andric if (ComputeByrefLayout)
27990b57cec5SDimitry Andric printf("\n Byref variable layout: ");
28000b57cec5SDimitry Andric else
28010b57cec5SDimitry Andric printf("\n Block variable layout: ");
28020b57cec5SDimitry Andric for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
28030b57cec5SDimitry Andric unsigned char inst = BitMap[i];
28040b57cec5SDimitry Andric enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
28050b57cec5SDimitry Andric unsigned delta = 1;
28060b57cec5SDimitry Andric switch (opcode) {
28070b57cec5SDimitry Andric case BLOCK_LAYOUT_OPERATOR:
28080b57cec5SDimitry Andric printf("BL_OPERATOR:");
28090b57cec5SDimitry Andric delta = 0;
28100b57cec5SDimitry Andric break;
28110b57cec5SDimitry Andric case BLOCK_LAYOUT_NON_OBJECT_BYTES:
28120b57cec5SDimitry Andric printf("BL_NON_OBJECT_BYTES:");
28130b57cec5SDimitry Andric break;
28140b57cec5SDimitry Andric case BLOCK_LAYOUT_NON_OBJECT_WORDS:
28150b57cec5SDimitry Andric printf("BL_NON_OBJECT_WORD:");
28160b57cec5SDimitry Andric break;
28170b57cec5SDimitry Andric case BLOCK_LAYOUT_STRONG:
28180b57cec5SDimitry Andric printf("BL_STRONG:");
28190b57cec5SDimitry Andric break;
28200b57cec5SDimitry Andric case BLOCK_LAYOUT_BYREF:
28210b57cec5SDimitry Andric printf("BL_BYREF:");
28220b57cec5SDimitry Andric break;
28230b57cec5SDimitry Andric case BLOCK_LAYOUT_WEAK:
28240b57cec5SDimitry Andric printf("BL_WEAK:");
28250b57cec5SDimitry Andric break;
28260b57cec5SDimitry Andric case BLOCK_LAYOUT_UNRETAINED:
28270b57cec5SDimitry Andric printf("BL_UNRETAINED:");
28280b57cec5SDimitry Andric break;
28290b57cec5SDimitry Andric }
28300b57cec5SDimitry Andric // Actual value of word count is one more that what is in the imm.
28310b57cec5SDimitry Andric // field of the instruction
28320b57cec5SDimitry Andric printf("%d", (inst & 0xf) + delta);
28330b57cec5SDimitry Andric if (i < e-1)
28340b57cec5SDimitry Andric printf(", ");
28350b57cec5SDimitry Andric else
28360b57cec5SDimitry Andric printf("\n");
28370b57cec5SDimitry Andric }
28380b57cec5SDimitry Andric }
28390b57cec5SDimitry Andric
28400b57cec5SDimitry Andric auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
28410b57cec5SDimitry Andric /*ForceNonFragileABI=*/true,
28420b57cec5SDimitry Andric /*NullTerminate=*/false);
28430b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
28440b57cec5SDimitry Andric }
28450b57cec5SDimitry Andric
getBlockLayoutInfoString(const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> & RunSkipBlockVars,bool HasCopyDisposeHelpers)28460b57cec5SDimitry Andric static std::string getBlockLayoutInfoString(
28470b57cec5SDimitry Andric const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
28480b57cec5SDimitry Andric bool HasCopyDisposeHelpers) {
28490b57cec5SDimitry Andric std::string Str;
28500b57cec5SDimitry Andric for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
28510b57cec5SDimitry Andric if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
28520b57cec5SDimitry Andric // Copy/dispose helpers don't have any information about
28530b57cec5SDimitry Andric // __unsafe_unretained captures, so unconditionally concatenate a string.
28540b57cec5SDimitry Andric Str += "u";
28550b57cec5SDimitry Andric } else if (HasCopyDisposeHelpers) {
28560b57cec5SDimitry Andric // Information about __strong, __weak, or byref captures has already been
28570b57cec5SDimitry Andric // encoded into the names of the copy/dispose helpers. We have to add a
28580b57cec5SDimitry Andric // string here only when the copy/dispose helpers aren't generated (which
28590b57cec5SDimitry Andric // happens when the block is non-escaping).
28600b57cec5SDimitry Andric continue;
28610b57cec5SDimitry Andric } else {
28620b57cec5SDimitry Andric switch (R.opcode) {
28630b57cec5SDimitry Andric case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
28640b57cec5SDimitry Andric Str += "s";
28650b57cec5SDimitry Andric break;
28660b57cec5SDimitry Andric case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
28670b57cec5SDimitry Andric Str += "r";
28680b57cec5SDimitry Andric break;
28690b57cec5SDimitry Andric case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
28700b57cec5SDimitry Andric Str += "w";
28710b57cec5SDimitry Andric break;
28720b57cec5SDimitry Andric default:
28730b57cec5SDimitry Andric continue;
28740b57cec5SDimitry Andric }
28750b57cec5SDimitry Andric }
28760b57cec5SDimitry Andric Str += llvm::to_string(R.block_var_bytepos.getQuantity());
28770b57cec5SDimitry Andric Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
28780b57cec5SDimitry Andric }
28790b57cec5SDimitry Andric return Str;
28800b57cec5SDimitry Andric }
28810b57cec5SDimitry Andric
fillRunSkipBlockVars(CodeGenModule & CGM,const CGBlockInfo & blockInfo)28820b57cec5SDimitry Andric void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
28830b57cec5SDimitry Andric const CGBlockInfo &blockInfo) {
28840b57cec5SDimitry Andric assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
28850b57cec5SDimitry Andric
28860b57cec5SDimitry Andric RunSkipBlockVars.clear();
28870b57cec5SDimitry Andric bool hasUnion = false;
28880b57cec5SDimitry Andric
2889bdd1243dSDimitry Andric unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default);
28900b57cec5SDimitry Andric unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
28910b57cec5SDimitry Andric unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
28920b57cec5SDimitry Andric
28930b57cec5SDimitry Andric const BlockDecl *blockDecl = blockInfo.getBlockDecl();
28940b57cec5SDimitry Andric
28950b57cec5SDimitry Andric // Calculate the basic layout of the block structure.
28960b57cec5SDimitry Andric const llvm::StructLayout *layout =
28970b57cec5SDimitry Andric CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
28980b57cec5SDimitry Andric
28990b57cec5SDimitry Andric // Ignore the optional 'this' capture: C++ objects are not assumed
29000b57cec5SDimitry Andric // to be GC'ed.
29010b57cec5SDimitry Andric if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
29020b57cec5SDimitry Andric UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
29030b57cec5SDimitry Andric blockInfo.BlockHeaderForcedGapOffset,
29040b57cec5SDimitry Andric blockInfo.BlockHeaderForcedGapSize);
29050b57cec5SDimitry Andric // Walk the captured variables.
29060b57cec5SDimitry Andric for (const auto &CI : blockDecl->captures()) {
29070b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable();
29080b57cec5SDimitry Andric QualType type = variable->getType();
29090b57cec5SDimitry Andric
29100b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
29110b57cec5SDimitry Andric
29120b57cec5SDimitry Andric // Ignore constant captures.
29130b57cec5SDimitry Andric if (capture.isConstant()) continue;
29140b57cec5SDimitry Andric
29150b57cec5SDimitry Andric CharUnits fieldOffset =
29160b57cec5SDimitry Andric CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
29170b57cec5SDimitry Andric
29180b57cec5SDimitry Andric assert(!type->isArrayType() && "array variable should not be caught");
29190b57cec5SDimitry Andric if (!CI.isByRef())
29200b57cec5SDimitry Andric if (const RecordType *record = type->getAs<RecordType>()) {
29210b57cec5SDimitry Andric BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
29220b57cec5SDimitry Andric continue;
29230b57cec5SDimitry Andric }
29240b57cec5SDimitry Andric CharUnits fieldSize;
29250b57cec5SDimitry Andric if (CI.isByRef())
29260b57cec5SDimitry Andric fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
29270b57cec5SDimitry Andric else
29280b57cec5SDimitry Andric fieldSize = CGM.getContext().getTypeSizeInChars(type);
29290b57cec5SDimitry Andric UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
29300b57cec5SDimitry Andric fieldOffset, fieldSize);
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric }
29330b57cec5SDimitry Andric
29340b57cec5SDimitry Andric llvm::Constant *
BuildRCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)29350b57cec5SDimitry Andric CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
29360b57cec5SDimitry Andric const CGBlockInfo &blockInfo) {
29370b57cec5SDimitry Andric fillRunSkipBlockVars(CGM, blockInfo);
29380b57cec5SDimitry Andric return getBitmapBlockLayout(false);
29390b57cec5SDimitry Andric }
29400b57cec5SDimitry Andric
getRCBlockLayoutStr(CodeGenModule & CGM,const CGBlockInfo & blockInfo)29410b57cec5SDimitry Andric std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
29420b57cec5SDimitry Andric const CGBlockInfo &blockInfo) {
29430b57cec5SDimitry Andric fillRunSkipBlockVars(CGM, blockInfo);
294404eeddc0SDimitry Andric return getBlockLayoutInfoString(RunSkipBlockVars, blockInfo.NeedsCopyDispose);
29450b57cec5SDimitry Andric }
29460b57cec5SDimitry Andric
BuildByrefLayout(CodeGen::CodeGenModule & CGM,QualType T)29470b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
29480b57cec5SDimitry Andric QualType T) {
29490b57cec5SDimitry Andric assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
29500b57cec5SDimitry Andric assert(!T->isArrayType() && "__block array variable should not be caught");
29510b57cec5SDimitry Andric CharUnits fieldOffset;
29520b57cec5SDimitry Andric RunSkipBlockVars.clear();
29530b57cec5SDimitry Andric bool hasUnion = false;
29540b57cec5SDimitry Andric if (const RecordType *record = T->getAs<RecordType>()) {
29550b57cec5SDimitry Andric BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
29560b57cec5SDimitry Andric llvm::Constant *Result = getBitmapBlockLayout(true);
29570b57cec5SDimitry Andric if (isa<llvm::ConstantInt>(Result))
29580b57cec5SDimitry Andric Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
29590b57cec5SDimitry Andric return Result;
29600b57cec5SDimitry Andric }
29610b57cec5SDimitry Andric llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
29620b57cec5SDimitry Andric return nullPtr;
29630b57cec5SDimitry Andric }
29640b57cec5SDimitry Andric
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)29650b57cec5SDimitry Andric llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
29660b57cec5SDimitry Andric const ObjCProtocolDecl *PD) {
29670b57cec5SDimitry Andric // FIXME: I don't understand why gcc generates this, or where it is
29680b57cec5SDimitry Andric // resolved. Investigate. Its also wasteful to look this up over and over.
29690b57cec5SDimitry Andric LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
29700b57cec5SDimitry Andric
29715f757f3fSDimitry Andric return GetProtocolRef(PD);
29720b57cec5SDimitry Andric }
29730b57cec5SDimitry Andric
GenerateProtocol(const ObjCProtocolDecl * PD)29740b57cec5SDimitry Andric void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
29750b57cec5SDimitry Andric // FIXME: We shouldn't need this, the protocol decl should contain enough
29760b57cec5SDimitry Andric // information to tell us whether this was a declaration or a definition.
29770b57cec5SDimitry Andric DefinedProtocols.insert(PD->getIdentifier());
29780b57cec5SDimitry Andric
29790b57cec5SDimitry Andric // If we have generated a forward reference to this protocol, emit
29800b57cec5SDimitry Andric // it now. Otherwise do nothing, the protocol objects are lazily
29810b57cec5SDimitry Andric // emitted.
29820b57cec5SDimitry Andric if (Protocols.count(PD->getIdentifier()))
29830b57cec5SDimitry Andric GetOrEmitProtocol(PD);
29840b57cec5SDimitry Andric }
29850b57cec5SDimitry Andric
GetProtocolRef(const ObjCProtocolDecl * PD)29860b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
29870b57cec5SDimitry Andric if (DefinedProtocols.count(PD->getIdentifier()))
29880b57cec5SDimitry Andric return GetOrEmitProtocol(PD);
29890b57cec5SDimitry Andric
29900b57cec5SDimitry Andric return GetOrEmitProtocolRef(PD);
29910b57cec5SDimitry Andric }
29920b57cec5SDimitry Andric
EmitClassRefViaRuntime(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,ObjCCommonTypesHelper & ObjCTypes)29930b57cec5SDimitry Andric llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
29940b57cec5SDimitry Andric CodeGenFunction &CGF,
29950b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
29960b57cec5SDimitry Andric ObjCCommonTypesHelper &ObjCTypes) {
29970b57cec5SDimitry Andric llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
29980b57cec5SDimitry Andric
29995ffd83dbSDimitry Andric llvm::Value *className = CGF.CGM
30005ffd83dbSDimitry Andric .GetAddrOfConstantCString(std::string(
30015ffd83dbSDimitry Andric ID->getObjCRuntimeNameAsString()))
30020b57cec5SDimitry Andric .getPointer();
30030b57cec5SDimitry Andric ASTContext &ctx = CGF.CGM.getContext();
30040b57cec5SDimitry Andric className =
30050b57cec5SDimitry Andric CGF.Builder.CreateBitCast(className,
30060b57cec5SDimitry Andric CGF.ConvertType(
30070b57cec5SDimitry Andric ctx.getPointerType(ctx.CharTy.withConst())));
30080b57cec5SDimitry Andric llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
30090b57cec5SDimitry Andric call->setDoesNotThrow();
30100b57cec5SDimitry Andric return call;
30110b57cec5SDimitry Andric }
30120b57cec5SDimitry Andric
30130b57cec5SDimitry Andric /*
30140b57cec5SDimitry Andric // Objective-C 1.0 extensions
30150b57cec5SDimitry Andric struct _objc_protocol {
30160b57cec5SDimitry Andric struct _objc_protocol_extension *isa;
30170b57cec5SDimitry Andric char *protocol_name;
30180b57cec5SDimitry Andric struct _objc_protocol_list *protocol_list;
30190b57cec5SDimitry Andric struct _objc__method_prototype_list *instance_methods;
30200b57cec5SDimitry Andric struct _objc__method_prototype_list *class_methods
30210b57cec5SDimitry Andric };
30220b57cec5SDimitry Andric
30230b57cec5SDimitry Andric See EmitProtocolExtension().
30240b57cec5SDimitry Andric */
GetOrEmitProtocol(const ObjCProtocolDecl * PD)30250b57cec5SDimitry Andric llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
30260b57cec5SDimitry Andric llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
30270b57cec5SDimitry Andric
30280b57cec5SDimitry Andric // Early exit if a defining object has already been generated.
30290b57cec5SDimitry Andric if (Entry && Entry->hasInitializer())
30300b57cec5SDimitry Andric return Entry;
30310b57cec5SDimitry Andric
30320b57cec5SDimitry Andric // Use the protocol definition, if there is one.
30330b57cec5SDimitry Andric if (const ObjCProtocolDecl *Def = PD->getDefinition())
30340b57cec5SDimitry Andric PD = Def;
30350b57cec5SDimitry Andric
30360b57cec5SDimitry Andric // FIXME: I don't understand why gcc generates this, or where it is
30370b57cec5SDimitry Andric // resolved. Investigate. Its also wasteful to look this up over and over.
30380b57cec5SDimitry Andric LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
30390b57cec5SDimitry Andric
30400b57cec5SDimitry Andric // Construct method lists.
30410b57cec5SDimitry Andric auto methodLists = ProtocolMethodLists::get(PD);
30420b57cec5SDimitry Andric
30430b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
30440b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
30450b57cec5SDimitry Andric values.add(EmitProtocolExtension(PD, methodLists));
30460b57cec5SDimitry Andric values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
30470b57cec5SDimitry Andric values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
30480b57cec5SDimitry Andric PD->protocol_begin(), PD->protocol_end()));
30490b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
30500b57cec5SDimitry Andric ProtocolMethodLists::RequiredInstanceMethods));
30510b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
30520b57cec5SDimitry Andric ProtocolMethodLists::RequiredClassMethods));
30530b57cec5SDimitry Andric
30540b57cec5SDimitry Andric if (Entry) {
30550b57cec5SDimitry Andric // Already created, update the initializer.
30560b57cec5SDimitry Andric assert(Entry->hasPrivateLinkage());
30570b57cec5SDimitry Andric values.finishAndSetAsInitializer(Entry);
30580b57cec5SDimitry Andric } else {
30590b57cec5SDimitry Andric Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
30600b57cec5SDimitry Andric CGM.getPointerAlign(),
30610b57cec5SDimitry Andric /*constant*/ false,
30620b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage);
30630b57cec5SDimitry Andric Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
30640b57cec5SDimitry Andric
30650b57cec5SDimitry Andric Protocols[PD->getIdentifier()] = Entry;
30660b57cec5SDimitry Andric }
30670b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(Entry);
30680b57cec5SDimitry Andric
30690b57cec5SDimitry Andric return Entry;
30700b57cec5SDimitry Andric }
30710b57cec5SDimitry Andric
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)30720b57cec5SDimitry Andric llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
30730b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
30740b57cec5SDimitry Andric
30750b57cec5SDimitry Andric if (!Entry) {
30760b57cec5SDimitry Andric // We use the initializer as a marker of whether this is a forward
30770b57cec5SDimitry Andric // reference or not. At module finalization we add the empty
30780b57cec5SDimitry Andric // contents for protocols which were referenced but never defined.
30790b57cec5SDimitry Andric Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
30800b57cec5SDimitry Andric false, llvm::GlobalValue::PrivateLinkage,
30810b57cec5SDimitry Andric nullptr, "OBJC_PROTOCOL_" + PD->getName());
30820b57cec5SDimitry Andric Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
30830b57cec5SDimitry Andric // FIXME: Is this necessary? Why only for protocol?
3084a7dea167SDimitry Andric Entry->setAlignment(llvm::Align(4));
30850b57cec5SDimitry Andric }
30860b57cec5SDimitry Andric
30870b57cec5SDimitry Andric return Entry;
30880b57cec5SDimitry Andric }
30890b57cec5SDimitry Andric
30900b57cec5SDimitry Andric /*
30910b57cec5SDimitry Andric struct _objc_protocol_extension {
30920b57cec5SDimitry Andric uint32_t size;
30930b57cec5SDimitry Andric struct objc_method_description_list *optional_instance_methods;
30940b57cec5SDimitry Andric struct objc_method_description_list *optional_class_methods;
30950b57cec5SDimitry Andric struct objc_property_list *instance_properties;
30960b57cec5SDimitry Andric const char ** extendedMethodTypes;
30970b57cec5SDimitry Andric struct objc_property_list *class_properties;
30980b57cec5SDimitry Andric };
30990b57cec5SDimitry Andric */
31000b57cec5SDimitry Andric llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl * PD,const ProtocolMethodLists & methodLists)31010b57cec5SDimitry Andric CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
31020b57cec5SDimitry Andric const ProtocolMethodLists &methodLists) {
31030b57cec5SDimitry Andric auto optInstanceMethods =
31040b57cec5SDimitry Andric methodLists.emitMethodList(this, PD,
31050b57cec5SDimitry Andric ProtocolMethodLists::OptionalInstanceMethods);
31060b57cec5SDimitry Andric auto optClassMethods =
31070b57cec5SDimitry Andric methodLists.emitMethodList(this, PD,
31080b57cec5SDimitry Andric ProtocolMethodLists::OptionalClassMethods);
31090b57cec5SDimitry Andric
31100b57cec5SDimitry Andric auto extendedMethodTypes =
31110b57cec5SDimitry Andric EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
31120b57cec5SDimitry Andric methodLists.emitExtendedTypesArray(this),
31130b57cec5SDimitry Andric ObjCTypes);
31140b57cec5SDimitry Andric
31150b57cec5SDimitry Andric auto instanceProperties =
31160b57cec5SDimitry Andric EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
31170b57cec5SDimitry Andric ObjCTypes, false);
31180b57cec5SDimitry Andric auto classProperties =
31190b57cec5SDimitry Andric EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
31200b57cec5SDimitry Andric PD, ObjCTypes, true);
31210b57cec5SDimitry Andric
31220b57cec5SDimitry Andric // Return null if no extension bits are used.
31230b57cec5SDimitry Andric if (optInstanceMethods->isNullValue() &&
31240b57cec5SDimitry Andric optClassMethods->isNullValue() &&
31250b57cec5SDimitry Andric extendedMethodTypes->isNullValue() &&
31260b57cec5SDimitry Andric instanceProperties->isNullValue() &&
31270b57cec5SDimitry Andric classProperties->isNullValue()) {
31280b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
31290b57cec5SDimitry Andric }
31300b57cec5SDimitry Andric
31310b57cec5SDimitry Andric uint64_t size =
31320b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
31330b57cec5SDimitry Andric
31340b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
31350b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
31360b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, size);
31370b57cec5SDimitry Andric values.add(optInstanceMethods);
31380b57cec5SDimitry Andric values.add(optClassMethods);
31390b57cec5SDimitry Andric values.add(instanceProperties);
31400b57cec5SDimitry Andric values.add(extendedMethodTypes);
31410b57cec5SDimitry Andric values.add(classProperties);
31420b57cec5SDimitry Andric
31430b57cec5SDimitry Andric // No special section, but goes in llvm.used
31440b57cec5SDimitry Andric return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
31450b57cec5SDimitry Andric StringRef(), CGM.getPointerAlign(), true);
31460b57cec5SDimitry Andric }
31470b57cec5SDimitry Andric
31480b57cec5SDimitry Andric /*
31490b57cec5SDimitry Andric struct objc_protocol_list {
31500b57cec5SDimitry Andric struct objc_protocol_list *next;
31510b57cec5SDimitry Andric long count;
31520b57cec5SDimitry Andric Protocol *list[];
31530b57cec5SDimitry Andric };
31540b57cec5SDimitry Andric */
31550b57cec5SDimitry Andric llvm::Constant *
EmitProtocolList(Twine name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)31560b57cec5SDimitry Andric CGObjCMac::EmitProtocolList(Twine name,
31570b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator begin,
31580b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator end) {
31590b57cec5SDimitry Andric // Just return null for empty protocol lists
3160e8d8bef9SDimitry Andric auto PDs = GetRuntimeProtocolList(begin, end);
3161e8d8bef9SDimitry Andric if (PDs.empty())
31620b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
31630b57cec5SDimitry Andric
31640b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
31650b57cec5SDimitry Andric auto values = builder.beginStruct();
31660b57cec5SDimitry Andric
31670b57cec5SDimitry Andric // This field is only used by the runtime.
31680b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
31690b57cec5SDimitry Andric
31700b57cec5SDimitry Andric // Reserve a slot for the count.
31710b57cec5SDimitry Andric auto countSlot = values.addPlaceholder();
31720b57cec5SDimitry Andric
31730b57cec5SDimitry Andric auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3174e8d8bef9SDimitry Andric for (const auto *Proto : PDs)
3175e8d8bef9SDimitry Andric refsArray.add(GetProtocolRef(Proto));
3176e8d8bef9SDimitry Andric
31770b57cec5SDimitry Andric auto count = refsArray.size();
31780b57cec5SDimitry Andric
31790b57cec5SDimitry Andric // This list is null terminated.
31800b57cec5SDimitry Andric refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
31810b57cec5SDimitry Andric
31820b57cec5SDimitry Andric refsArray.finishAndAddTo(values);
31830b57cec5SDimitry Andric values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
31840b57cec5SDimitry Andric
31850b57cec5SDimitry Andric StringRef section;
31860b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
31870b57cec5SDimitry Andric section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
31880b57cec5SDimitry Andric
31890b57cec5SDimitry Andric llvm::GlobalVariable *GV =
31900b57cec5SDimitry Andric CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
31915f757f3fSDimitry Andric return GV;
31920b57cec5SDimitry Andric }
31930b57cec5SDimitry Andric
31940b57cec5SDimitry Andric static void
PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo *,16> & PropertySet,SmallVectorImpl<const ObjCPropertyDecl * > & Properties,const ObjCProtocolDecl * Proto,bool IsClassProperty)31950b57cec5SDimitry Andric PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
31960b57cec5SDimitry Andric SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
31970b57cec5SDimitry Andric const ObjCProtocolDecl *Proto,
31980b57cec5SDimitry Andric bool IsClassProperty) {
31990b57cec5SDimitry Andric for (const auto *PD : Proto->properties()) {
32000b57cec5SDimitry Andric if (IsClassProperty != PD->isClassProperty())
32010b57cec5SDimitry Andric continue;
32020b57cec5SDimitry Andric if (!PropertySet.insert(PD->getIdentifier()).second)
32030b57cec5SDimitry Andric continue;
32040b57cec5SDimitry Andric Properties.push_back(PD);
32050b57cec5SDimitry Andric }
3206480093f4SDimitry Andric
3207480093f4SDimitry Andric for (const auto *P : Proto->protocols())
3208480093f4SDimitry Andric PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
32090b57cec5SDimitry Andric }
32100b57cec5SDimitry Andric
32110b57cec5SDimitry Andric /*
32120b57cec5SDimitry Andric struct _objc_property {
32130b57cec5SDimitry Andric const char * const name;
32140b57cec5SDimitry Andric const char * const attributes;
32150b57cec5SDimitry Andric };
32160b57cec5SDimitry Andric
32170b57cec5SDimitry Andric struct _objc_property_list {
32180b57cec5SDimitry Andric uint32_t entsize; // sizeof (struct _objc_property)
32190b57cec5SDimitry Andric uint32_t prop_count;
32200b57cec5SDimitry Andric struct _objc_property[prop_count];
32210b57cec5SDimitry Andric };
32220b57cec5SDimitry Andric */
EmitPropertyList(Twine Name,const Decl * Container,const ObjCContainerDecl * OCD,const ObjCCommonTypesHelper & ObjCTypes,bool IsClassProperty)32230b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
32240b57cec5SDimitry Andric const Decl *Container,
32250b57cec5SDimitry Andric const ObjCContainerDecl *OCD,
32260b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes,
32270b57cec5SDimitry Andric bool IsClassProperty) {
32280b57cec5SDimitry Andric if (IsClassProperty) {
32290b57cec5SDimitry Andric // Make this entry NULL for OS X with deployment target < 10.11, for iOS
32300b57cec5SDimitry Andric // with deployment target < 9.0.
32310b57cec5SDimitry Andric const llvm::Triple &Triple = CGM.getTarget().getTriple();
32320b57cec5SDimitry Andric if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
32330b57cec5SDimitry Andric (Triple.isiOS() && Triple.isOSVersionLT(9)))
32340b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
32350b57cec5SDimitry Andric }
32360b57cec5SDimitry Andric
32370b57cec5SDimitry Andric SmallVector<const ObjCPropertyDecl *, 16> Properties;
32380b57cec5SDimitry Andric llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
32390b57cec5SDimitry Andric
32400b57cec5SDimitry Andric if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
32410b57cec5SDimitry Andric for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
32420b57cec5SDimitry Andric for (auto *PD : ClassExt->properties()) {
32430b57cec5SDimitry Andric if (IsClassProperty != PD->isClassProperty())
32440b57cec5SDimitry Andric continue;
32455ffd83dbSDimitry Andric if (PD->isDirectProperty())
32465ffd83dbSDimitry Andric continue;
32470b57cec5SDimitry Andric PropertySet.insert(PD->getIdentifier());
32480b57cec5SDimitry Andric Properties.push_back(PD);
32490b57cec5SDimitry Andric }
32500b57cec5SDimitry Andric
32510b57cec5SDimitry Andric for (const auto *PD : OCD->properties()) {
32520b57cec5SDimitry Andric if (IsClassProperty != PD->isClassProperty())
32530b57cec5SDimitry Andric continue;
32540b57cec5SDimitry Andric // Don't emit duplicate metadata for properties that were already in a
32550b57cec5SDimitry Andric // class extension.
32560b57cec5SDimitry Andric if (!PropertySet.insert(PD->getIdentifier()).second)
32570b57cec5SDimitry Andric continue;
32585ffd83dbSDimitry Andric if (PD->isDirectProperty())
32595ffd83dbSDimitry Andric continue;
32600b57cec5SDimitry Andric Properties.push_back(PD);
32610b57cec5SDimitry Andric }
32620b57cec5SDimitry Andric
32630b57cec5SDimitry Andric if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
32640b57cec5SDimitry Andric for (const auto *P : OID->all_referenced_protocols())
32650b57cec5SDimitry Andric PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
32660b57cec5SDimitry Andric }
32670b57cec5SDimitry Andric else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
32680b57cec5SDimitry Andric for (const auto *P : CD->protocols())
32690b57cec5SDimitry Andric PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
32700b57cec5SDimitry Andric }
32710b57cec5SDimitry Andric
32720b57cec5SDimitry Andric // Return null for empty list.
32730b57cec5SDimitry Andric if (Properties.empty())
32740b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
32750b57cec5SDimitry Andric
32760b57cec5SDimitry Andric unsigned propertySize =
32770b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
32780b57cec5SDimitry Andric
32790b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
32800b57cec5SDimitry Andric auto values = builder.beginStruct();
32810b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, propertySize);
32820b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, Properties.size());
32830b57cec5SDimitry Andric auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
32840b57cec5SDimitry Andric for (auto PD : Properties) {
32850b57cec5SDimitry Andric auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
32860b57cec5SDimitry Andric property.add(GetPropertyName(PD->getIdentifier()));
32870b57cec5SDimitry Andric property.add(GetPropertyTypeString(PD, Container));
32880b57cec5SDimitry Andric property.finishAndAddTo(propertiesArray);
32890b57cec5SDimitry Andric }
32900b57cec5SDimitry Andric propertiesArray.finishAndAddTo(values);
32910b57cec5SDimitry Andric
32920b57cec5SDimitry Andric StringRef Section;
32930b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
32940b57cec5SDimitry Andric Section = (ObjCABI == 2) ? "__DATA, __objc_const"
32950b57cec5SDimitry Andric : "__OBJC,__property,regular,no_dead_strip";
32960b57cec5SDimitry Andric
32970b57cec5SDimitry Andric llvm::GlobalVariable *GV =
32980b57cec5SDimitry Andric CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
32995f757f3fSDimitry Andric return GV;
33000b57cec5SDimitry Andric }
33010b57cec5SDimitry Andric
33020b57cec5SDimitry Andric llvm::Constant *
EmitProtocolMethodTypes(Twine Name,ArrayRef<llvm::Constant * > MethodTypes,const ObjCCommonTypesHelper & ObjCTypes)33030b57cec5SDimitry Andric CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
33040b57cec5SDimitry Andric ArrayRef<llvm::Constant*> MethodTypes,
33050b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes) {
33060b57cec5SDimitry Andric // Return null for empty list.
33070b57cec5SDimitry Andric if (MethodTypes.empty())
33080b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
33090b57cec5SDimitry Andric
33100b57cec5SDimitry Andric llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
33110b57cec5SDimitry Andric MethodTypes.size());
33120b57cec5SDimitry Andric llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
33130b57cec5SDimitry Andric
33140b57cec5SDimitry Andric StringRef Section;
33150b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
33160b57cec5SDimitry Andric Section = "__DATA, __objc_const";
33170b57cec5SDimitry Andric
33180b57cec5SDimitry Andric llvm::GlobalVariable *GV =
33190b57cec5SDimitry Andric CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
33205f757f3fSDimitry Andric return GV;
33210b57cec5SDimitry Andric }
33220b57cec5SDimitry Andric
33230b57cec5SDimitry Andric /*
33240b57cec5SDimitry Andric struct _objc_category {
33250b57cec5SDimitry Andric char *category_name;
33260b57cec5SDimitry Andric char *class_name;
33270b57cec5SDimitry Andric struct _objc_method_list *instance_methods;
33280b57cec5SDimitry Andric struct _objc_method_list *class_methods;
33290b57cec5SDimitry Andric struct _objc_protocol_list *protocols;
33305f757f3fSDimitry Andric uint32_t size; // sizeof(struct _objc_category)
33310b57cec5SDimitry Andric struct _objc_property_list *instance_properties;
33320b57cec5SDimitry Andric struct _objc_property_list *class_properties;
33330b57cec5SDimitry Andric };
33340b57cec5SDimitry Andric */
GenerateCategory(const ObjCCategoryImplDecl * OCD)33350b57cec5SDimitry Andric void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
33360b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
33370b57cec5SDimitry Andric
33380b57cec5SDimitry Andric // FIXME: This is poor design, the OCD should have a pointer to the category
33390b57cec5SDimitry Andric // decl. Additionally, note that Category can be null for the @implementation
33400b57cec5SDimitry Andric // w/o an @interface case. Sema should just create one for us as it does for
33410b57cec5SDimitry Andric // @implementation so everyone else can live life under a clear blue sky.
33420b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
33430b57cec5SDimitry Andric const ObjCCategoryDecl *Category =
33440b57cec5SDimitry Andric Interface->FindCategoryDeclaration(OCD->getIdentifier());
33450b57cec5SDimitry Andric
33460b57cec5SDimitry Andric SmallString<256> ExtName;
33470b57cec5SDimitry Andric llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
33480b57cec5SDimitry Andric << OCD->getName();
33490b57cec5SDimitry Andric
33500b57cec5SDimitry Andric ConstantInitBuilder Builder(CGM);
33510b57cec5SDimitry Andric auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
33520b57cec5SDimitry Andric
33530b57cec5SDimitry Andric enum {
33540b57cec5SDimitry Andric InstanceMethods,
33550b57cec5SDimitry Andric ClassMethods,
33560b57cec5SDimitry Andric NumMethodLists
33570b57cec5SDimitry Andric };
33580b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
33590b57cec5SDimitry Andric for (const auto *MD : OCD->methods()) {
3360480093f4SDimitry Andric if (!MD->isDirectMethod())
33610b57cec5SDimitry Andric Methods[unsigned(MD->isClassMethod())].push_back(MD);
33620b57cec5SDimitry Andric }
33630b57cec5SDimitry Andric
33640b57cec5SDimitry Andric Values.add(GetClassName(OCD->getName()));
33650b57cec5SDimitry Andric Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
33660b57cec5SDimitry Andric LazySymbols.insert(Interface->getIdentifier());
33670b57cec5SDimitry Andric
33680b57cec5SDimitry Andric Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
33690b57cec5SDimitry Andric Methods[InstanceMethods]));
33700b57cec5SDimitry Andric Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
33710b57cec5SDimitry Andric Methods[ClassMethods]));
33720b57cec5SDimitry Andric if (Category) {
33730b57cec5SDimitry Andric Values.add(
33740b57cec5SDimitry Andric EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
33750b57cec5SDimitry Andric Category->protocol_begin(), Category->protocol_end()));
33760b57cec5SDimitry Andric } else {
33770b57cec5SDimitry Andric Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
33780b57cec5SDimitry Andric }
33790b57cec5SDimitry Andric Values.addInt(ObjCTypes.IntTy, Size);
33800b57cec5SDimitry Andric
33810b57cec5SDimitry Andric // If there is no category @interface then there can be no properties.
33820b57cec5SDimitry Andric if (Category) {
33830b57cec5SDimitry Andric Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
33840b57cec5SDimitry Andric OCD, Category, ObjCTypes, false));
33850b57cec5SDimitry Andric Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
33860b57cec5SDimitry Andric OCD, Category, ObjCTypes, true));
33870b57cec5SDimitry Andric } else {
33880b57cec5SDimitry Andric Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
33890b57cec5SDimitry Andric Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
33900b57cec5SDimitry Andric }
33910b57cec5SDimitry Andric
33920b57cec5SDimitry Andric llvm::GlobalVariable *GV =
33930b57cec5SDimitry Andric CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
33940b57cec5SDimitry Andric "__OBJC,__category,regular,no_dead_strip",
33950b57cec5SDimitry Andric CGM.getPointerAlign(), true);
33960b57cec5SDimitry Andric DefinedCategories.push_back(GV);
33970b57cec5SDimitry Andric DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
33980b57cec5SDimitry Andric // method definition entries must be clear for next implementation.
33990b57cec5SDimitry Andric MethodDefinitions.clear();
34000b57cec5SDimitry Andric }
34010b57cec5SDimitry Andric
34020b57cec5SDimitry Andric enum FragileClassFlags {
34030b57cec5SDimitry Andric /// Apparently: is not a meta-class.
34040b57cec5SDimitry Andric FragileABI_Class_Factory = 0x00001,
34050b57cec5SDimitry Andric
34060b57cec5SDimitry Andric /// Is a meta-class.
34070b57cec5SDimitry Andric FragileABI_Class_Meta = 0x00002,
34080b57cec5SDimitry Andric
34090b57cec5SDimitry Andric /// Has a non-trivial constructor or destructor.
34100b57cec5SDimitry Andric FragileABI_Class_HasCXXStructors = 0x02000,
34110b57cec5SDimitry Andric
34120b57cec5SDimitry Andric /// Has hidden visibility.
34130b57cec5SDimitry Andric FragileABI_Class_Hidden = 0x20000,
34140b57cec5SDimitry Andric
34150b57cec5SDimitry Andric /// Class implementation was compiled under ARC.
34160b57cec5SDimitry Andric FragileABI_Class_CompiledByARC = 0x04000000,
34170b57cec5SDimitry Andric
34180b57cec5SDimitry Andric /// Class implementation was compiled under MRC and has MRC weak ivars.
34190b57cec5SDimitry Andric /// Exclusive with CompiledByARC.
34200b57cec5SDimitry Andric FragileABI_Class_HasMRCWeakIvars = 0x08000000,
34210b57cec5SDimitry Andric };
34220b57cec5SDimitry Andric
34230b57cec5SDimitry Andric enum NonFragileClassFlags {
34240b57cec5SDimitry Andric /// Is a meta-class.
34250b57cec5SDimitry Andric NonFragileABI_Class_Meta = 0x00001,
34260b57cec5SDimitry Andric
34270b57cec5SDimitry Andric /// Is a root class.
34280b57cec5SDimitry Andric NonFragileABI_Class_Root = 0x00002,
34290b57cec5SDimitry Andric
34300b57cec5SDimitry Andric /// Has a non-trivial constructor or destructor.
34310b57cec5SDimitry Andric NonFragileABI_Class_HasCXXStructors = 0x00004,
34320b57cec5SDimitry Andric
34330b57cec5SDimitry Andric /// Has hidden visibility.
34340b57cec5SDimitry Andric NonFragileABI_Class_Hidden = 0x00010,
34350b57cec5SDimitry Andric
34360b57cec5SDimitry Andric /// Has the exception attribute.
34370b57cec5SDimitry Andric NonFragileABI_Class_Exception = 0x00020,
34380b57cec5SDimitry Andric
34390b57cec5SDimitry Andric /// (Obsolete) ARC-specific: this class has a .release_ivars method
34400b57cec5SDimitry Andric NonFragileABI_Class_HasIvarReleaser = 0x00040,
34410b57cec5SDimitry Andric
34420b57cec5SDimitry Andric /// Class implementation was compiled under ARC.
34430b57cec5SDimitry Andric NonFragileABI_Class_CompiledByARC = 0x00080,
34440b57cec5SDimitry Andric
34450b57cec5SDimitry Andric /// Class has non-trivial destructors, but zero-initialization is okay.
34460b57cec5SDimitry Andric NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
34470b57cec5SDimitry Andric
34480b57cec5SDimitry Andric /// Class implementation was compiled under MRC and has MRC weak ivars.
34490b57cec5SDimitry Andric /// Exclusive with CompiledByARC.
34500b57cec5SDimitry Andric NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
34510b57cec5SDimitry Andric };
34520b57cec5SDimitry Andric
hasWeakMember(QualType type)34530b57cec5SDimitry Andric static bool hasWeakMember(QualType type) {
34540b57cec5SDimitry Andric if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
34550b57cec5SDimitry Andric return true;
34560b57cec5SDimitry Andric }
34570b57cec5SDimitry Andric
34580b57cec5SDimitry Andric if (auto recType = type->getAs<RecordType>()) {
3459bdd1243dSDimitry Andric for (auto *field : recType->getDecl()->fields()) {
34600b57cec5SDimitry Andric if (hasWeakMember(field->getType()))
34610b57cec5SDimitry Andric return true;
34620b57cec5SDimitry Andric }
34630b57cec5SDimitry Andric }
34640b57cec5SDimitry Andric
34650b57cec5SDimitry Andric return false;
34660b57cec5SDimitry Andric }
34670b57cec5SDimitry Andric
34680b57cec5SDimitry Andric /// For compatibility, we only want to set the "HasMRCWeakIvars" flag
34690b57cec5SDimitry Andric /// (and actually fill in a layout string) if we really do have any
34700b57cec5SDimitry Andric /// __weak ivars.
hasMRCWeakIvars(CodeGenModule & CGM,const ObjCImplementationDecl * ID)34710b57cec5SDimitry Andric static bool hasMRCWeakIvars(CodeGenModule &CGM,
34720b57cec5SDimitry Andric const ObjCImplementationDecl *ID) {
34730b57cec5SDimitry Andric if (!CGM.getLangOpts().ObjCWeak) return false;
34740b57cec5SDimitry Andric assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
34750b57cec5SDimitry Andric
34760b57cec5SDimitry Andric for (const ObjCIvarDecl *ivar =
34770b57cec5SDimitry Andric ID->getClassInterface()->all_declared_ivar_begin();
34780b57cec5SDimitry Andric ivar; ivar = ivar->getNextIvar()) {
34790b57cec5SDimitry Andric if (hasWeakMember(ivar->getType()))
34800b57cec5SDimitry Andric return true;
34810b57cec5SDimitry Andric }
34820b57cec5SDimitry Andric
34830b57cec5SDimitry Andric return false;
34840b57cec5SDimitry Andric }
34850b57cec5SDimitry Andric
34860b57cec5SDimitry Andric /*
34870b57cec5SDimitry Andric struct _objc_class {
34880b57cec5SDimitry Andric Class isa;
34890b57cec5SDimitry Andric Class super_class;
34900b57cec5SDimitry Andric const char *name;
34910b57cec5SDimitry Andric long version;
34920b57cec5SDimitry Andric long info;
34930b57cec5SDimitry Andric long instance_size;
34940b57cec5SDimitry Andric struct _objc_ivar_list *ivars;
34950b57cec5SDimitry Andric struct _objc_method_list *methods;
34960b57cec5SDimitry Andric struct _objc_cache *cache;
34970b57cec5SDimitry Andric struct _objc_protocol_list *protocols;
34980b57cec5SDimitry Andric // Objective-C 1.0 extensions (<rdr://4585769>)
34990b57cec5SDimitry Andric const char *ivar_layout;
35000b57cec5SDimitry Andric struct _objc_class_ext *ext;
35010b57cec5SDimitry Andric };
35020b57cec5SDimitry Andric
35030b57cec5SDimitry Andric See EmitClassExtension();
35040b57cec5SDimitry Andric */
GenerateClass(const ObjCImplementationDecl * ID)35050b57cec5SDimitry Andric void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
35060b57cec5SDimitry Andric IdentifierInfo *RuntimeName =
35070b57cec5SDimitry Andric &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
35080b57cec5SDimitry Andric DefinedSymbols.insert(RuntimeName);
35090b57cec5SDimitry Andric
35100b57cec5SDimitry Andric std::string ClassName = ID->getNameAsString();
35110b57cec5SDimitry Andric // FIXME: Gross
35120b57cec5SDimitry Andric ObjCInterfaceDecl *Interface =
35130b57cec5SDimitry Andric const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
35140b57cec5SDimitry Andric llvm::Constant *Protocols =
35150b57cec5SDimitry Andric EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
35160b57cec5SDimitry Andric Interface->all_referenced_protocol_begin(),
35170b57cec5SDimitry Andric Interface->all_referenced_protocol_end());
35180b57cec5SDimitry Andric unsigned Flags = FragileABI_Class_Factory;
35190b57cec5SDimitry Andric if (ID->hasNonZeroConstructors() || ID->hasDestructors())
35200b57cec5SDimitry Andric Flags |= FragileABI_Class_HasCXXStructors;
35210b57cec5SDimitry Andric
35220b57cec5SDimitry Andric bool hasMRCWeak = false;
35230b57cec5SDimitry Andric
35240b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount)
35250b57cec5SDimitry Andric Flags |= FragileABI_Class_CompiledByARC;
35260b57cec5SDimitry Andric else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
35270b57cec5SDimitry Andric Flags |= FragileABI_Class_HasMRCWeakIvars;
35280b57cec5SDimitry Andric
35290b57cec5SDimitry Andric CharUnits Size =
35300b57cec5SDimitry Andric CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
35310b57cec5SDimitry Andric
35320b57cec5SDimitry Andric // FIXME: Set CXX-structors flag.
35330b57cec5SDimitry Andric if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
35340b57cec5SDimitry Andric Flags |= FragileABI_Class_Hidden;
35350b57cec5SDimitry Andric
35360b57cec5SDimitry Andric enum {
35370b57cec5SDimitry Andric InstanceMethods,
35380b57cec5SDimitry Andric ClassMethods,
35390b57cec5SDimitry Andric NumMethodLists
35400b57cec5SDimitry Andric };
35410b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
35420b57cec5SDimitry Andric for (const auto *MD : ID->methods()) {
3543480093f4SDimitry Andric if (!MD->isDirectMethod())
35440b57cec5SDimitry Andric Methods[unsigned(MD->isClassMethod())].push_back(MD);
35450b57cec5SDimitry Andric }
35460b57cec5SDimitry Andric
35470b57cec5SDimitry Andric for (const auto *PID : ID->property_impls()) {
35480b57cec5SDimitry Andric if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3549480093f4SDimitry Andric if (PID->getPropertyDecl()->isDirectProperty())
3550480093f4SDimitry Andric continue;
3551480093f4SDimitry Andric if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
35520b57cec5SDimitry Andric if (GetMethodDefinition(MD))
35530b57cec5SDimitry Andric Methods[InstanceMethods].push_back(MD);
3554480093f4SDimitry Andric if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
35550b57cec5SDimitry Andric if (GetMethodDefinition(MD))
35560b57cec5SDimitry Andric Methods[InstanceMethods].push_back(MD);
35570b57cec5SDimitry Andric }
35580b57cec5SDimitry Andric }
35590b57cec5SDimitry Andric
35600b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
35610b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ClassTy);
35620b57cec5SDimitry Andric values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
35630b57cec5SDimitry Andric if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
35640b57cec5SDimitry Andric // Record a reference to the super class.
35650b57cec5SDimitry Andric LazySymbols.insert(Super->getIdentifier());
35660b57cec5SDimitry Andric
35675f757f3fSDimitry Andric values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
35680b57cec5SDimitry Andric } else {
35690b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ClassPtrTy);
35700b57cec5SDimitry Andric }
35710b57cec5SDimitry Andric values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
35720b57cec5SDimitry Andric // Version is always 0.
35730b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, 0);
35740b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, Flags);
35750b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, Size.getQuantity());
35760b57cec5SDimitry Andric values.add(EmitIvarList(ID, false));
35770b57cec5SDimitry Andric values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
35780b57cec5SDimitry Andric Methods[InstanceMethods]));
35790b57cec5SDimitry Andric // cache is always NULL.
35800b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.CachePtrTy);
35810b57cec5SDimitry Andric values.add(Protocols);
35820b57cec5SDimitry Andric values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
35830b57cec5SDimitry Andric values.add(EmitClassExtension(ID, Size, hasMRCWeak,
35840b57cec5SDimitry Andric /*isMetaclass*/ false));
35850b57cec5SDimitry Andric
35860b57cec5SDimitry Andric std::string Name("OBJC_CLASS_");
35870b57cec5SDimitry Andric Name += ClassName;
35880b57cec5SDimitry Andric const char *Section = "__OBJC,__class,regular,no_dead_strip";
35890b57cec5SDimitry Andric // Check for a forward reference.
35900b57cec5SDimitry Andric llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
35910b57cec5SDimitry Andric if (GV) {
35925ffd83dbSDimitry Andric assert(GV->getValueType() == ObjCTypes.ClassTy &&
35930b57cec5SDimitry Andric "Forward metaclass reference has incorrect type.");
35940b57cec5SDimitry Andric values.finishAndSetAsInitializer(GV);
35950b57cec5SDimitry Andric GV->setSection(Section);
3596a7dea167SDimitry Andric GV->setAlignment(CGM.getPointerAlign().getAsAlign());
35970b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
35980b57cec5SDimitry Andric } else
35990b57cec5SDimitry Andric GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
36000b57cec5SDimitry Andric DefinedClasses.push_back(GV);
36010b57cec5SDimitry Andric ImplementedClasses.push_back(Interface);
36020b57cec5SDimitry Andric // method definition entries must be clear for next implementation.
36030b57cec5SDimitry Andric MethodDefinitions.clear();
36040b57cec5SDimitry Andric }
36050b57cec5SDimitry Andric
EmitMetaClass(const ObjCImplementationDecl * ID,llvm::Constant * Protocols,ArrayRef<const ObjCMethodDecl * > Methods)36060b57cec5SDimitry Andric llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
36070b57cec5SDimitry Andric llvm::Constant *Protocols,
36080b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl*> Methods) {
36090b57cec5SDimitry Andric unsigned Flags = FragileABI_Class_Meta;
36100b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
36110b57cec5SDimitry Andric
36120b57cec5SDimitry Andric if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
36130b57cec5SDimitry Andric Flags |= FragileABI_Class_Hidden;
36140b57cec5SDimitry Andric
36150b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
36160b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ClassTy);
36170b57cec5SDimitry Andric // The isa for the metaclass is the root of the hierarchy.
36180b57cec5SDimitry Andric const ObjCInterfaceDecl *Root = ID->getClassInterface();
36190b57cec5SDimitry Andric while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
36200b57cec5SDimitry Andric Root = Super;
36215f757f3fSDimitry Andric values.add(GetClassName(Root->getObjCRuntimeNameAsString()));
36220b57cec5SDimitry Andric // The super class for the metaclass is emitted as the name of the
36230b57cec5SDimitry Andric // super class. The runtime fixes this up to point to the
36240b57cec5SDimitry Andric // *metaclass* for the super class.
36250b57cec5SDimitry Andric if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
36265f757f3fSDimitry Andric values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
36270b57cec5SDimitry Andric } else {
36280b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ClassPtrTy);
36290b57cec5SDimitry Andric }
36300b57cec5SDimitry Andric values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
36310b57cec5SDimitry Andric // Version is always 0.
36320b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, 0);
36330b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, Flags);
36340b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, Size);
36350b57cec5SDimitry Andric values.add(EmitIvarList(ID, true));
36360b57cec5SDimitry Andric values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
36370b57cec5SDimitry Andric Methods));
36380b57cec5SDimitry Andric // cache is always NULL.
36390b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.CachePtrTy);
36400b57cec5SDimitry Andric values.add(Protocols);
36410b57cec5SDimitry Andric // ivar_layout for metaclass is always NULL.
36420b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.Int8PtrTy);
36430b57cec5SDimitry Andric // The class extension is used to store class properties for metaclasses.
36440b57cec5SDimitry Andric values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
36450b57cec5SDimitry Andric /*isMetaclass*/true));
36460b57cec5SDimitry Andric
36470b57cec5SDimitry Andric std::string Name("OBJC_METACLASS_");
36480b57cec5SDimitry Andric Name += ID->getName();
36490b57cec5SDimitry Andric
36500b57cec5SDimitry Andric // Check for a forward reference.
36510b57cec5SDimitry Andric llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
36520b57cec5SDimitry Andric if (GV) {
36535ffd83dbSDimitry Andric assert(GV->getValueType() == ObjCTypes.ClassTy &&
36540b57cec5SDimitry Andric "Forward metaclass reference has incorrect type.");
36550b57cec5SDimitry Andric values.finishAndSetAsInitializer(GV);
36560b57cec5SDimitry Andric } else {
36570b57cec5SDimitry Andric GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
36580b57cec5SDimitry Andric /*constant*/ false,
36590b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage);
36600b57cec5SDimitry Andric }
36610b57cec5SDimitry Andric GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
36620b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
36630b57cec5SDimitry Andric
36640b57cec5SDimitry Andric return GV;
36650b57cec5SDimitry Andric }
36660b57cec5SDimitry Andric
EmitMetaClassRef(const ObjCInterfaceDecl * ID)36670b57cec5SDimitry Andric llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
36680b57cec5SDimitry Andric std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
36690b57cec5SDimitry Andric
36700b57cec5SDimitry Andric // FIXME: Should we look these up somewhere other than the module. Its a bit
36710b57cec5SDimitry Andric // silly since we only generate these while processing an implementation, so
36720b57cec5SDimitry Andric // exactly one pointer would work if know when we entered/exitted an
36730b57cec5SDimitry Andric // implementation block.
36740b57cec5SDimitry Andric
36750b57cec5SDimitry Andric // Check for an existing forward reference.
36760b57cec5SDimitry Andric // Previously, metaclass with internal linkage may have been defined.
36770b57cec5SDimitry Andric // pass 'true' as 2nd argument so it is returned.
36780b57cec5SDimitry Andric llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
36790b57cec5SDimitry Andric if (!GV)
36800b57cec5SDimitry Andric GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
36810b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage, nullptr,
36820b57cec5SDimitry Andric Name);
36830b57cec5SDimitry Andric
36845ffd83dbSDimitry Andric assert(GV->getValueType() == ObjCTypes.ClassTy &&
36850b57cec5SDimitry Andric "Forward metaclass reference has incorrect type.");
36860b57cec5SDimitry Andric return GV;
36870b57cec5SDimitry Andric }
36880b57cec5SDimitry Andric
EmitSuperClassRef(const ObjCInterfaceDecl * ID)36890b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
36900b57cec5SDimitry Andric std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
36910b57cec5SDimitry Andric llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
36920b57cec5SDimitry Andric
36930b57cec5SDimitry Andric if (!GV)
36940b57cec5SDimitry Andric GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
36950b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage, nullptr,
36960b57cec5SDimitry Andric Name);
36970b57cec5SDimitry Andric
36985ffd83dbSDimitry Andric assert(GV->getValueType() == ObjCTypes.ClassTy &&
36990b57cec5SDimitry Andric "Forward class metadata reference has incorrect type.");
37000b57cec5SDimitry Andric return GV;
37010b57cec5SDimitry Andric }
37020b57cec5SDimitry Andric
37030b57cec5SDimitry Andric /*
37040b57cec5SDimitry Andric Emit a "class extension", which in this specific context means extra
37050b57cec5SDimitry Andric data that doesn't fit in the normal fragile-ABI class structure, and
37060b57cec5SDimitry Andric has nothing to do with the language concept of a class extension.
37070b57cec5SDimitry Andric
37080b57cec5SDimitry Andric struct objc_class_ext {
37090b57cec5SDimitry Andric uint32_t size;
37100b57cec5SDimitry Andric const char *weak_ivar_layout;
37110b57cec5SDimitry Andric struct _objc_property_list *properties;
37120b57cec5SDimitry Andric };
37130b57cec5SDimitry Andric */
37140b57cec5SDimitry Andric llvm::Constant *
EmitClassExtension(const ObjCImplementationDecl * ID,CharUnits InstanceSize,bool hasMRCWeakIvars,bool isMetaclass)37150b57cec5SDimitry Andric CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
37160b57cec5SDimitry Andric CharUnits InstanceSize, bool hasMRCWeakIvars,
37170b57cec5SDimitry Andric bool isMetaclass) {
37180b57cec5SDimitry Andric // Weak ivar layout.
37190b57cec5SDimitry Andric llvm::Constant *layout;
37200b57cec5SDimitry Andric if (isMetaclass) {
37210b57cec5SDimitry Andric layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
37220b57cec5SDimitry Andric } else {
37230b57cec5SDimitry Andric layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
37240b57cec5SDimitry Andric hasMRCWeakIvars);
37250b57cec5SDimitry Andric }
37260b57cec5SDimitry Andric
37270b57cec5SDimitry Andric // Properties.
37280b57cec5SDimitry Andric llvm::Constant *propertyList =
37290b57cec5SDimitry Andric EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
37300b57cec5SDimitry Andric : Twine("_OBJC_$_PROP_LIST_"))
37310b57cec5SDimitry Andric + ID->getName(),
37320b57cec5SDimitry Andric ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
37330b57cec5SDimitry Andric
37340b57cec5SDimitry Andric // Return null if no extension bits are used.
37350b57cec5SDimitry Andric if (layout->isNullValue() && propertyList->isNullValue()) {
37360b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
37370b57cec5SDimitry Andric }
37380b57cec5SDimitry Andric
37390b57cec5SDimitry Andric uint64_t size =
37400b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
37410b57cec5SDimitry Andric
37420b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
37430b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
37440b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, size);
37450b57cec5SDimitry Andric values.add(layout);
37460b57cec5SDimitry Andric values.add(propertyList);
37470b57cec5SDimitry Andric
37480b57cec5SDimitry Andric return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
37490b57cec5SDimitry Andric "__OBJC,__class_ext,regular,no_dead_strip",
37500b57cec5SDimitry Andric CGM.getPointerAlign(), true);
37510b57cec5SDimitry Andric }
37520b57cec5SDimitry Andric
37530b57cec5SDimitry Andric /*
37540b57cec5SDimitry Andric struct objc_ivar {
37550b57cec5SDimitry Andric char *ivar_name;
37560b57cec5SDimitry Andric char *ivar_type;
37570b57cec5SDimitry Andric int ivar_offset;
37580b57cec5SDimitry Andric };
37590b57cec5SDimitry Andric
37600b57cec5SDimitry Andric struct objc_ivar_list {
37610b57cec5SDimitry Andric int ivar_count;
37620b57cec5SDimitry Andric struct objc_ivar list[count];
37630b57cec5SDimitry Andric };
37640b57cec5SDimitry Andric */
EmitIvarList(const ObjCImplementationDecl * ID,bool ForClass)37650b57cec5SDimitry Andric llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
37660b57cec5SDimitry Andric bool ForClass) {
37670b57cec5SDimitry Andric // When emitting the root class GCC emits ivar entries for the
37680b57cec5SDimitry Andric // actual class structure. It is not clear if we need to follow this
37690b57cec5SDimitry Andric // behavior; for now lets try and get away with not doing it. If so,
37700b57cec5SDimitry Andric // the cleanest solution would be to make up an ObjCInterfaceDecl
37710b57cec5SDimitry Andric // for the class.
37720b57cec5SDimitry Andric if (ForClass)
37730b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
37740b57cec5SDimitry Andric
37750b57cec5SDimitry Andric const ObjCInterfaceDecl *OID = ID->getClassInterface();
37760b57cec5SDimitry Andric
37770b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
37780b57cec5SDimitry Andric auto ivarList = builder.beginStruct();
37790b57cec5SDimitry Andric auto countSlot = ivarList.addPlaceholder();
37800b57cec5SDimitry Andric auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
37810b57cec5SDimitry Andric
37820b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
37830b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) {
37840b57cec5SDimitry Andric // Ignore unnamed bit-fields.
37850b57cec5SDimitry Andric if (!IVD->getDeclName())
37860b57cec5SDimitry Andric continue;
37870b57cec5SDimitry Andric
37880b57cec5SDimitry Andric auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
37890b57cec5SDimitry Andric ivar.add(GetMethodVarName(IVD->getIdentifier()));
37900b57cec5SDimitry Andric ivar.add(GetMethodVarType(IVD));
37910b57cec5SDimitry Andric ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
37920b57cec5SDimitry Andric ivar.finishAndAddTo(ivars);
37930b57cec5SDimitry Andric }
37940b57cec5SDimitry Andric
37950b57cec5SDimitry Andric // Return null for empty list.
37960b57cec5SDimitry Andric auto count = ivars.size();
37970b57cec5SDimitry Andric if (count == 0) {
37980b57cec5SDimitry Andric ivars.abandon();
37990b57cec5SDimitry Andric ivarList.abandon();
38000b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
38010b57cec5SDimitry Andric }
38020b57cec5SDimitry Andric
38030b57cec5SDimitry Andric ivars.finishAndAddTo(ivarList);
38040b57cec5SDimitry Andric ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
38050b57cec5SDimitry Andric
38060b57cec5SDimitry Andric llvm::GlobalVariable *GV;
38070b57cec5SDimitry Andric GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
38080b57cec5SDimitry Andric "__OBJC,__instance_vars,regular,no_dead_strip",
38090b57cec5SDimitry Andric CGM.getPointerAlign(), true);
38105f757f3fSDimitry Andric return GV;
38110b57cec5SDimitry Andric }
38120b57cec5SDimitry Andric
38130b57cec5SDimitry Andric /// Build a struct objc_method_description constant for the given method.
38140b57cec5SDimitry Andric ///
38150b57cec5SDimitry Andric /// struct objc_method_description {
38160b57cec5SDimitry Andric /// SEL method_name;
38170b57cec5SDimitry Andric /// char *method_types;
38180b57cec5SDimitry Andric /// };
emitMethodDescriptionConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD)38190b57cec5SDimitry Andric void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
38200b57cec5SDimitry Andric const ObjCMethodDecl *MD) {
38210b57cec5SDimitry Andric auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
38225f757f3fSDimitry Andric description.add(GetMethodVarName(MD->getSelector()));
38230b57cec5SDimitry Andric description.add(GetMethodVarType(MD));
38240b57cec5SDimitry Andric description.finishAndAddTo(builder);
38250b57cec5SDimitry Andric }
38260b57cec5SDimitry Andric
38270b57cec5SDimitry Andric /// Build a struct objc_method constant for the given method.
38280b57cec5SDimitry Andric ///
38290b57cec5SDimitry Andric /// struct objc_method {
38300b57cec5SDimitry Andric /// SEL method_name;
38310b57cec5SDimitry Andric /// char *method_types;
38320b57cec5SDimitry Andric /// void *method;
38330b57cec5SDimitry Andric /// };
emitMethodConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD)38340b57cec5SDimitry Andric void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
38350b57cec5SDimitry Andric const ObjCMethodDecl *MD) {
38360b57cec5SDimitry Andric llvm::Function *fn = GetMethodDefinition(MD);
38370b57cec5SDimitry Andric assert(fn && "no definition registered for method");
38380b57cec5SDimitry Andric
38390b57cec5SDimitry Andric auto method = builder.beginStruct(ObjCTypes.MethodTy);
38405f757f3fSDimitry Andric method.add(GetMethodVarName(MD->getSelector()));
38410b57cec5SDimitry Andric method.add(GetMethodVarType(MD));
38425f757f3fSDimitry Andric method.add(fn);
38430b57cec5SDimitry Andric method.finishAndAddTo(builder);
38440b57cec5SDimitry Andric }
38450b57cec5SDimitry Andric
38460b57cec5SDimitry Andric /// Build a struct objc_method_list or struct objc_method_description_list,
38470b57cec5SDimitry Andric /// as appropriate.
38480b57cec5SDimitry Andric ///
38490b57cec5SDimitry Andric /// struct objc_method_list {
38500b57cec5SDimitry Andric /// struct objc_method_list *obsolete;
38510b57cec5SDimitry Andric /// int count;
38520b57cec5SDimitry Andric /// struct objc_method methods_list[count];
38530b57cec5SDimitry Andric /// };
38540b57cec5SDimitry Andric ///
38550b57cec5SDimitry Andric /// struct objc_method_description_list {
38560b57cec5SDimitry Andric /// int count;
38570b57cec5SDimitry Andric /// struct objc_method_description list[count];
38580b57cec5SDimitry Andric /// };
emitMethodList(Twine name,MethodListType MLT,ArrayRef<const ObjCMethodDecl * > methods)38590b57cec5SDimitry Andric llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
38600b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl *> methods) {
38610b57cec5SDimitry Andric StringRef prefix;
38620b57cec5SDimitry Andric StringRef section;
38630b57cec5SDimitry Andric bool forProtocol = false;
38640b57cec5SDimitry Andric switch (MLT) {
38650b57cec5SDimitry Andric case MethodListType::CategoryInstanceMethods:
38660b57cec5SDimitry Andric prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
38670b57cec5SDimitry Andric section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
38680b57cec5SDimitry Andric forProtocol = false;
38690b57cec5SDimitry Andric break;
38700b57cec5SDimitry Andric case MethodListType::CategoryClassMethods:
38710b57cec5SDimitry Andric prefix = "OBJC_CATEGORY_CLASS_METHODS_";
38720b57cec5SDimitry Andric section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
38730b57cec5SDimitry Andric forProtocol = false;
38740b57cec5SDimitry Andric break;
38750b57cec5SDimitry Andric case MethodListType::InstanceMethods:
38760b57cec5SDimitry Andric prefix = "OBJC_INSTANCE_METHODS_";
38770b57cec5SDimitry Andric section = "__OBJC,__inst_meth,regular,no_dead_strip";
38780b57cec5SDimitry Andric forProtocol = false;
38790b57cec5SDimitry Andric break;
38800b57cec5SDimitry Andric case MethodListType::ClassMethods:
38810b57cec5SDimitry Andric prefix = "OBJC_CLASS_METHODS_";
38820b57cec5SDimitry Andric section = "__OBJC,__cls_meth,regular,no_dead_strip";
38830b57cec5SDimitry Andric forProtocol = false;
38840b57cec5SDimitry Andric break;
38850b57cec5SDimitry Andric case MethodListType::ProtocolInstanceMethods:
38860b57cec5SDimitry Andric prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
38870b57cec5SDimitry Andric section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
38880b57cec5SDimitry Andric forProtocol = true;
38890b57cec5SDimitry Andric break;
38900b57cec5SDimitry Andric case MethodListType::ProtocolClassMethods:
38910b57cec5SDimitry Andric prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
38920b57cec5SDimitry Andric section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
38930b57cec5SDimitry Andric forProtocol = true;
38940b57cec5SDimitry Andric break;
38950b57cec5SDimitry Andric case MethodListType::OptionalProtocolInstanceMethods:
38960b57cec5SDimitry Andric prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
38970b57cec5SDimitry Andric section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
38980b57cec5SDimitry Andric forProtocol = true;
38990b57cec5SDimitry Andric break;
39000b57cec5SDimitry Andric case MethodListType::OptionalProtocolClassMethods:
39010b57cec5SDimitry Andric prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
39020b57cec5SDimitry Andric section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
39030b57cec5SDimitry Andric forProtocol = true;
39040b57cec5SDimitry Andric break;
39050b57cec5SDimitry Andric }
39060b57cec5SDimitry Andric
39070b57cec5SDimitry Andric // Return null for empty list.
39080b57cec5SDimitry Andric if (methods.empty())
39090b57cec5SDimitry Andric return llvm::Constant::getNullValue(forProtocol
39100b57cec5SDimitry Andric ? ObjCTypes.MethodDescriptionListPtrTy
39110b57cec5SDimitry Andric : ObjCTypes.MethodListPtrTy);
39120b57cec5SDimitry Andric
39130b57cec5SDimitry Andric // For protocols, this is an objc_method_description_list, which has
39140b57cec5SDimitry Andric // a slightly different structure.
39150b57cec5SDimitry Andric if (forProtocol) {
39160b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
39170b57cec5SDimitry Andric auto values = builder.beginStruct();
39180b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, methods.size());
39190b57cec5SDimitry Andric auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
39200b57cec5SDimitry Andric for (auto MD : methods) {
39210b57cec5SDimitry Andric emitMethodDescriptionConstant(methodArray, MD);
39220b57cec5SDimitry Andric }
39230b57cec5SDimitry Andric methodArray.finishAndAddTo(values);
39240b57cec5SDimitry Andric
39250b57cec5SDimitry Andric llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
39260b57cec5SDimitry Andric CGM.getPointerAlign(), true);
39275f757f3fSDimitry Andric return GV;
39280b57cec5SDimitry Andric }
39290b57cec5SDimitry Andric
39300b57cec5SDimitry Andric // Otherwise, it's an objc_method_list.
39310b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
39320b57cec5SDimitry Andric auto values = builder.beginStruct();
39330b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.Int8PtrTy);
39340b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, methods.size());
39350b57cec5SDimitry Andric auto methodArray = values.beginArray(ObjCTypes.MethodTy);
39360b57cec5SDimitry Andric for (auto MD : methods) {
3937480093f4SDimitry Andric if (!MD->isDirectMethod())
39380b57cec5SDimitry Andric emitMethodConstant(methodArray, MD);
39390b57cec5SDimitry Andric }
39400b57cec5SDimitry Andric methodArray.finishAndAddTo(values);
39410b57cec5SDimitry Andric
39420b57cec5SDimitry Andric llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
39430b57cec5SDimitry Andric CGM.getPointerAlign(), true);
39445f757f3fSDimitry Andric return GV;
39450b57cec5SDimitry Andric }
39460b57cec5SDimitry Andric
GenerateMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)39470b57cec5SDimitry Andric llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
39480b57cec5SDimitry Andric const ObjCContainerDecl *CD) {
3949480093f4SDimitry Andric llvm::Function *Method;
3950480093f4SDimitry Andric
3951480093f4SDimitry Andric if (OMD->isDirectMethod()) {
3952480093f4SDimitry Andric Method = GenerateDirectMethod(OMD, CD);
3953480093f4SDimitry Andric } else {
3954e8d8bef9SDimitry Andric auto Name = getSymbolNameForMethod(OMD);
39550b57cec5SDimitry Andric
39560b57cec5SDimitry Andric CodeGenTypes &Types = CGM.getTypes();
39570b57cec5SDimitry Andric llvm::FunctionType *MethodTy =
39580b57cec5SDimitry Andric Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3959480093f4SDimitry Andric Method =
3960480093f4SDimitry Andric llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3961e8d8bef9SDimitry Andric Name, &CGM.getModule());
3962480093f4SDimitry Andric }
3963480093f4SDimitry Andric
39640b57cec5SDimitry Andric MethodDefinitions.insert(std::make_pair(OMD, Method));
39650b57cec5SDimitry Andric
39660b57cec5SDimitry Andric return Method;
39670b57cec5SDimitry Andric }
39680b57cec5SDimitry Andric
3969480093f4SDimitry Andric llvm::Function *
GenerateDirectMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)3970480093f4SDimitry Andric CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
3971480093f4SDimitry Andric const ObjCContainerDecl *CD) {
39725ffd83dbSDimitry Andric auto *COMD = OMD->getCanonicalDecl();
39735ffd83dbSDimitry Andric auto I = DirectMethodDefinitions.find(COMD);
39745ffd83dbSDimitry Andric llvm::Function *OldFn = nullptr, *Fn = nullptr;
3975480093f4SDimitry Andric
39765ffd83dbSDimitry Andric if (I != DirectMethodDefinitions.end()) {
39775ffd83dbSDimitry Andric // Objective-C allows for the declaration and implementation types
39785ffd83dbSDimitry Andric // to differ slightly.
39795ffd83dbSDimitry Andric //
39805ffd83dbSDimitry Andric // If we're being asked for the Function associated for a method
39815ffd83dbSDimitry Andric // implementation, a previous value might have been cached
39825ffd83dbSDimitry Andric // based on the type of the canonical declaration.
39835ffd83dbSDimitry Andric //
39845ffd83dbSDimitry Andric // If these do not match, then we'll replace this function with
39855ffd83dbSDimitry Andric // a new one that has the proper type below.
39865ffd83dbSDimitry Andric if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
39875ffd83dbSDimitry Andric return I->second;
39885ffd83dbSDimitry Andric OldFn = I->second;
39895ffd83dbSDimitry Andric }
3990480093f4SDimitry Andric
3991480093f4SDimitry Andric CodeGenTypes &Types = CGM.getTypes();
3992480093f4SDimitry Andric llvm::FunctionType *MethodTy =
3993480093f4SDimitry Andric Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3994480093f4SDimitry Andric
39955ffd83dbSDimitry Andric if (OldFn) {
39965ffd83dbSDimitry Andric Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
39975ffd83dbSDimitry Andric "", &CGM.getModule());
39985ffd83dbSDimitry Andric Fn->takeName(OldFn);
39995f757f3fSDimitry Andric OldFn->replaceAllUsesWith(Fn);
40005ffd83dbSDimitry Andric OldFn->eraseFromParent();
40015ffd83dbSDimitry Andric
40025ffd83dbSDimitry Andric // Replace the cached function in the map.
40035ffd83dbSDimitry Andric I->second = Fn;
40045ffd83dbSDimitry Andric } else {
4005e8d8bef9SDimitry Andric auto Name = getSymbolNameForMethod(OMD, /*include category*/ false);
40065ffd83dbSDimitry Andric
40075ffd83dbSDimitry Andric Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4008e8d8bef9SDimitry Andric Name, &CGM.getModule());
40095ffd83dbSDimitry Andric DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
40105ffd83dbSDimitry Andric }
40115ffd83dbSDimitry Andric
40125ffd83dbSDimitry Andric return Fn;
4013480093f4SDimitry Andric }
4014480093f4SDimitry Andric
GenerateDirectMethodPrologue(CodeGenFunction & CGF,llvm::Function * Fn,const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)4015480093f4SDimitry Andric void CGObjCCommonMac::GenerateDirectMethodPrologue(
4016480093f4SDimitry Andric CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
4017480093f4SDimitry Andric const ObjCContainerDecl *CD) {
4018480093f4SDimitry Andric auto &Builder = CGF.Builder;
4019480093f4SDimitry Andric bool ReceiverCanBeNull = true;
4020480093f4SDimitry Andric auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
4021480093f4SDimitry Andric auto selfValue = Builder.CreateLoad(selfAddr);
4022480093f4SDimitry Andric
4023480093f4SDimitry Andric // Generate:
4024480093f4SDimitry Andric //
4025480093f4SDimitry Andric // /* for class methods only to force class lazy initialization */
4026480093f4SDimitry Andric // self = [self self];
4027480093f4SDimitry Andric //
4028480093f4SDimitry Andric // /* unless the receiver is never NULL */
4029480093f4SDimitry Andric // if (self == nil) {
4030480093f4SDimitry Andric // return (ReturnType){ };
4031480093f4SDimitry Andric // }
4032480093f4SDimitry Andric //
4033480093f4SDimitry Andric // _cmd = @selector(...)
4034480093f4SDimitry Andric // ...
4035480093f4SDimitry Andric
4036480093f4SDimitry Andric if (OMD->isClassMethod()) {
4037480093f4SDimitry Andric const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
4038480093f4SDimitry Andric assert(OID &&
4039480093f4SDimitry Andric "GenerateDirectMethod() should be called with the Class Interface");
4040480093f4SDimitry Andric Selector SelfSel = GetNullarySelector("self", CGM.getContext());
4041480093f4SDimitry Andric auto ResultType = CGF.getContext().getObjCIdType();
4042480093f4SDimitry Andric RValue result;
4043480093f4SDimitry Andric CallArgList Args;
4044480093f4SDimitry Andric
4045480093f4SDimitry Andric // TODO: If this method is inlined, the caller might know that `self` is
4046480093f4SDimitry Andric // already initialized; for example, it might be an ordinary Objective-C
4047480093f4SDimitry Andric // method which always receives an initialized `self`, or it might have just
4048480093f4SDimitry Andric // forced initialization on its own.
4049480093f4SDimitry Andric //
4050480093f4SDimitry Andric // We should find a way to eliminate this unnecessary initialization in such
4051480093f4SDimitry Andric // cases in LLVM.
4052480093f4SDimitry Andric result = GeneratePossiblySpecializedMessageSend(
4053480093f4SDimitry Andric CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
4054480093f4SDimitry Andric nullptr, true);
4055480093f4SDimitry Andric Builder.CreateStore(result.getScalarVal(), selfAddr);
4056480093f4SDimitry Andric
4057480093f4SDimitry Andric // Nullable `Class` expressions cannot be messaged with a direct method
4058480093f4SDimitry Andric // so the only reason why the receive can be null would be because
4059480093f4SDimitry Andric // of weak linking.
4060480093f4SDimitry Andric ReceiverCanBeNull = isWeakLinkedClass(OID);
4061480093f4SDimitry Andric }
4062480093f4SDimitry Andric
4063480093f4SDimitry Andric if (ReceiverCanBeNull) {
4064480093f4SDimitry Andric llvm::BasicBlock *SelfIsNilBlock =
4065480093f4SDimitry Andric CGF.createBasicBlock("objc_direct_method.self_is_nil");
4066480093f4SDimitry Andric llvm::BasicBlock *ContBlock =
4067480093f4SDimitry Andric CGF.createBasicBlock("objc_direct_method.cont");
4068480093f4SDimitry Andric
4069480093f4SDimitry Andric // if (self == nil) {
4070480093f4SDimitry Andric auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4071480093f4SDimitry Andric auto Zero = llvm::ConstantPointerNull::get(selfTy);
4072480093f4SDimitry Andric
4073480093f4SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext());
4074480093f4SDimitry Andric Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4075*0fca6ea1SDimitry Andric ContBlock, MDHelper.createUnlikelyBranchWeights());
4076480093f4SDimitry Andric
4077480093f4SDimitry Andric CGF.EmitBlock(SelfIsNilBlock);
4078480093f4SDimitry Andric
4079480093f4SDimitry Andric // return (ReturnType){ };
4080480093f4SDimitry Andric auto retTy = OMD->getReturnType();
4081480093f4SDimitry Andric Builder.SetInsertPoint(SelfIsNilBlock);
4082480093f4SDimitry Andric if (!retTy->isVoidType()) {
4083480093f4SDimitry Andric CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
4084480093f4SDimitry Andric }
4085480093f4SDimitry Andric CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
4086480093f4SDimitry Andric // }
4087480093f4SDimitry Andric
4088480093f4SDimitry Andric // rest of the body
4089480093f4SDimitry Andric CGF.EmitBlock(ContBlock);
4090480093f4SDimitry Andric Builder.SetInsertPoint(ContBlock);
4091480093f4SDimitry Andric }
4092480093f4SDimitry Andric
4093480093f4SDimitry Andric // only synthesize _cmd if it's referenced
4094480093f4SDimitry Andric if (OMD->getCmdDecl()->isUsed()) {
4095bdd1243dSDimitry Andric // `_cmd` is not a parameter to direct methods, so storage must be
4096bdd1243dSDimitry Andric // explicitly declared for it.
4097bdd1243dSDimitry Andric CGF.EmitVarDecl(*OMD->getCmdDecl());
4098480093f4SDimitry Andric Builder.CreateStore(GetSelector(CGF, OMD),
4099480093f4SDimitry Andric CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
4100480093f4SDimitry Andric }
4101480093f4SDimitry Andric }
4102480093f4SDimitry Andric
CreateMetadataVar(Twine Name,ConstantStructBuilder & Init,StringRef Section,CharUnits Align,bool AddToUsed)41030b57cec5SDimitry Andric llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
41040b57cec5SDimitry Andric ConstantStructBuilder &Init,
41050b57cec5SDimitry Andric StringRef Section,
41060b57cec5SDimitry Andric CharUnits Align,
41070b57cec5SDimitry Andric bool AddToUsed) {
41080b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes LT =
41090b57cec5SDimitry Andric getLinkageTypeForObjCMetadata(CGM, Section);
41100b57cec5SDimitry Andric llvm::GlobalVariable *GV =
41110b57cec5SDimitry Andric Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
41120b57cec5SDimitry Andric if (!Section.empty())
41130b57cec5SDimitry Andric GV->setSection(Section);
41140b57cec5SDimitry Andric if (AddToUsed)
41150b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
41160b57cec5SDimitry Andric return GV;
41170b57cec5SDimitry Andric }
41180b57cec5SDimitry Andric
CreateMetadataVar(Twine Name,llvm::Constant * Init,StringRef Section,CharUnits Align,bool AddToUsed)41190b57cec5SDimitry Andric llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
41200b57cec5SDimitry Andric llvm::Constant *Init,
41210b57cec5SDimitry Andric StringRef Section,
41220b57cec5SDimitry Andric CharUnits Align,
41230b57cec5SDimitry Andric bool AddToUsed) {
41240b57cec5SDimitry Andric llvm::Type *Ty = Init->getType();
41250b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes LT =
41260b57cec5SDimitry Andric getLinkageTypeForObjCMetadata(CGM, Section);
41270b57cec5SDimitry Andric llvm::GlobalVariable *GV =
41280b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
41290b57cec5SDimitry Andric if (!Section.empty())
41300b57cec5SDimitry Andric GV->setSection(Section);
4131a7dea167SDimitry Andric GV->setAlignment(Align.getAsAlign());
41320b57cec5SDimitry Andric if (AddToUsed)
41330b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
41340b57cec5SDimitry Andric return GV;
41350b57cec5SDimitry Andric }
41360b57cec5SDimitry Andric
41370b57cec5SDimitry Andric llvm::GlobalVariable *
CreateCStringLiteral(StringRef Name,ObjCLabelType Type,bool ForceNonFragileABI,bool NullTerminate)41380b57cec5SDimitry Andric CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
41390b57cec5SDimitry Andric bool ForceNonFragileABI,
41400b57cec5SDimitry Andric bool NullTerminate) {
41410b57cec5SDimitry Andric StringRef Label;
41420b57cec5SDimitry Andric switch (Type) {
41430b57cec5SDimitry Andric case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
41440b57cec5SDimitry Andric case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
41450b57cec5SDimitry Andric case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
41460b57cec5SDimitry Andric case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
41470b57cec5SDimitry Andric }
41480b57cec5SDimitry Andric
41490b57cec5SDimitry Andric bool NonFragile = ForceNonFragileABI || isNonFragileABI();
41500b57cec5SDimitry Andric
41510b57cec5SDimitry Andric StringRef Section;
41520b57cec5SDimitry Andric switch (Type) {
41530b57cec5SDimitry Andric case ObjCLabelType::ClassName:
41540b57cec5SDimitry Andric Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
41550b57cec5SDimitry Andric : "__TEXT,__cstring,cstring_literals";
41560b57cec5SDimitry Andric break;
41570b57cec5SDimitry Andric case ObjCLabelType::MethodVarName:
41580b57cec5SDimitry Andric Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
41590b57cec5SDimitry Andric : "__TEXT,__cstring,cstring_literals";
41600b57cec5SDimitry Andric break;
41610b57cec5SDimitry Andric case ObjCLabelType::MethodVarType:
41620b57cec5SDimitry Andric Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
41630b57cec5SDimitry Andric : "__TEXT,__cstring,cstring_literals";
41640b57cec5SDimitry Andric break;
41650b57cec5SDimitry Andric case ObjCLabelType::PropertyName:
41665ffd83dbSDimitry Andric Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
41675ffd83dbSDimitry Andric : "__TEXT,__cstring,cstring_literals";
41680b57cec5SDimitry Andric break;
41690b57cec5SDimitry Andric }
41700b57cec5SDimitry Andric
41710b57cec5SDimitry Andric llvm::Constant *Value =
41720b57cec5SDimitry Andric llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
41730b57cec5SDimitry Andric llvm::GlobalVariable *GV =
41740b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
41750b57cec5SDimitry Andric /*isConstant=*/true,
41760b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage, Value, Label);
41770b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
41780b57cec5SDimitry Andric GV->setSection(Section);
41790b57cec5SDimitry Andric GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4180a7dea167SDimitry Andric GV->setAlignment(CharUnits::One().getAsAlign());
41810b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
41820b57cec5SDimitry Andric
41830b57cec5SDimitry Andric return GV;
41840b57cec5SDimitry Andric }
41850b57cec5SDimitry Andric
ModuleInitFunction()41860b57cec5SDimitry Andric llvm::Function *CGObjCMac::ModuleInitFunction() {
41870b57cec5SDimitry Andric // Abuse this interface function as a place to finalize.
41880b57cec5SDimitry Andric FinishModule();
41890b57cec5SDimitry Andric return nullptr;
41900b57cec5SDimitry Andric }
41910b57cec5SDimitry Andric
GetPropertyGetFunction()41920b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
41930b57cec5SDimitry Andric return ObjCTypes.getGetPropertyFn();
41940b57cec5SDimitry Andric }
41950b57cec5SDimitry Andric
GetPropertySetFunction()41960b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
41970b57cec5SDimitry Andric return ObjCTypes.getSetPropertyFn();
41980b57cec5SDimitry Andric }
41990b57cec5SDimitry Andric
GetOptimizedPropertySetFunction(bool atomic,bool copy)42000b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
42010b57cec5SDimitry Andric bool copy) {
42020b57cec5SDimitry Andric return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
42030b57cec5SDimitry Andric }
42040b57cec5SDimitry Andric
GetGetStructFunction()42050b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
42060b57cec5SDimitry Andric return ObjCTypes.getCopyStructFn();
42070b57cec5SDimitry Andric }
42080b57cec5SDimitry Andric
GetSetStructFunction()42090b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
42100b57cec5SDimitry Andric return ObjCTypes.getCopyStructFn();
42110b57cec5SDimitry Andric }
42120b57cec5SDimitry Andric
GetCppAtomicObjectGetFunction()42130b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
42140b57cec5SDimitry Andric return ObjCTypes.getCppAtomicObjectFunction();
42150b57cec5SDimitry Andric }
42160b57cec5SDimitry Andric
GetCppAtomicObjectSetFunction()42170b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
42180b57cec5SDimitry Andric return ObjCTypes.getCppAtomicObjectFunction();
42190b57cec5SDimitry Andric }
42200b57cec5SDimitry Andric
EnumerationMutationFunction()42210b57cec5SDimitry Andric llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
42220b57cec5SDimitry Andric return ObjCTypes.getEnumerationMutationFn();
42230b57cec5SDimitry Andric }
42240b57cec5SDimitry Andric
EmitTryStmt(CodeGenFunction & CGF,const ObjCAtTryStmt & S)42250b57cec5SDimitry Andric void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
42260b57cec5SDimitry Andric return EmitTryOrSynchronizedStmt(CGF, S);
42270b57cec5SDimitry Andric }
42280b57cec5SDimitry Andric
EmitSynchronizedStmt(CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)42290b57cec5SDimitry Andric void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
42300b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S) {
42310b57cec5SDimitry Andric return EmitTryOrSynchronizedStmt(CGF, S);
42320b57cec5SDimitry Andric }
42330b57cec5SDimitry Andric
42340b57cec5SDimitry Andric namespace {
42350b57cec5SDimitry Andric struct PerformFragileFinally final : EHScopeStack::Cleanup {
42360b57cec5SDimitry Andric const Stmt &S;
42370b57cec5SDimitry Andric Address SyncArgSlot;
42380b57cec5SDimitry Andric Address CallTryExitVar;
42390b57cec5SDimitry Andric Address ExceptionData;
42400b57cec5SDimitry Andric ObjCTypesHelper &ObjCTypes;
PerformFragileFinally__anonb5e682970811::PerformFragileFinally42410b57cec5SDimitry Andric PerformFragileFinally(const Stmt *S,
42420b57cec5SDimitry Andric Address SyncArgSlot,
42430b57cec5SDimitry Andric Address CallTryExitVar,
42440b57cec5SDimitry Andric Address ExceptionData,
42450b57cec5SDimitry Andric ObjCTypesHelper *ObjCTypes)
42460b57cec5SDimitry Andric : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
42470b57cec5SDimitry Andric ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
42480b57cec5SDimitry Andric
Emit__anonb5e682970811::PerformFragileFinally42490b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
42500b57cec5SDimitry Andric // Check whether we need to call objc_exception_try_exit.
42510b57cec5SDimitry Andric // In optimized code, this branch will always be folded.
42520b57cec5SDimitry Andric llvm::BasicBlock *FinallyCallExit =
42530b57cec5SDimitry Andric CGF.createBasicBlock("finally.call_exit");
42540b57cec5SDimitry Andric llvm::BasicBlock *FinallyNoCallExit =
42550b57cec5SDimitry Andric CGF.createBasicBlock("finally.no_call_exit");
42560b57cec5SDimitry Andric CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
42570b57cec5SDimitry Andric FinallyCallExit, FinallyNoCallExit);
42580b57cec5SDimitry Andric
42590b57cec5SDimitry Andric CGF.EmitBlock(FinallyCallExit);
42600b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
4261*0fca6ea1SDimitry Andric ExceptionData.emitRawPointer(CGF));
42620b57cec5SDimitry Andric
42630b57cec5SDimitry Andric CGF.EmitBlock(FinallyNoCallExit);
42640b57cec5SDimitry Andric
42650b57cec5SDimitry Andric if (isa<ObjCAtTryStmt>(S)) {
42660b57cec5SDimitry Andric if (const ObjCAtFinallyStmt* FinallyStmt =
42670b57cec5SDimitry Andric cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
42680b57cec5SDimitry Andric // Don't try to do the @finally if this is an EH cleanup.
42690b57cec5SDimitry Andric if (flags.isForEHCleanup()) return;
42700b57cec5SDimitry Andric
42710b57cec5SDimitry Andric // Save the current cleanup destination in case there's
42720b57cec5SDimitry Andric // control flow inside the finally statement.
42730b57cec5SDimitry Andric llvm::Value *CurCleanupDest =
42740b57cec5SDimitry Andric CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
42750b57cec5SDimitry Andric
42760b57cec5SDimitry Andric CGF.EmitStmt(FinallyStmt->getFinallyBody());
42770b57cec5SDimitry Andric
42780b57cec5SDimitry Andric if (CGF.HaveInsertPoint()) {
42790b57cec5SDimitry Andric CGF.Builder.CreateStore(CurCleanupDest,
42800b57cec5SDimitry Andric CGF.getNormalCleanupDestSlot());
42810b57cec5SDimitry Andric } else {
42820b57cec5SDimitry Andric // Currently, the end of the cleanup must always exist.
42830b57cec5SDimitry Andric CGF.EnsureInsertPoint();
42840b57cec5SDimitry Andric }
42850b57cec5SDimitry Andric }
42860b57cec5SDimitry Andric } else {
42870b57cec5SDimitry Andric // Emit objc_sync_exit(expr); as finally's sole statement for
42880b57cec5SDimitry Andric // @synchronized.
42890b57cec5SDimitry Andric llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
42900b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
42910b57cec5SDimitry Andric }
42920b57cec5SDimitry Andric }
42930b57cec5SDimitry Andric };
42940b57cec5SDimitry Andric
42950b57cec5SDimitry Andric class FragileHazards {
42960b57cec5SDimitry Andric CodeGenFunction &CGF;
42970b57cec5SDimitry Andric SmallVector<llvm::Value*, 20> Locals;
42980b57cec5SDimitry Andric llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
42990b57cec5SDimitry Andric
43000b57cec5SDimitry Andric llvm::InlineAsm *ReadHazard;
43010b57cec5SDimitry Andric llvm::InlineAsm *WriteHazard;
43020b57cec5SDimitry Andric
43030b57cec5SDimitry Andric llvm::FunctionType *GetAsmFnType();
43040b57cec5SDimitry Andric
43050b57cec5SDimitry Andric void collectLocals();
43060b57cec5SDimitry Andric void emitReadHazard(CGBuilderTy &Builder);
43070b57cec5SDimitry Andric
43080b57cec5SDimitry Andric public:
43090b57cec5SDimitry Andric FragileHazards(CodeGenFunction &CGF);
43100b57cec5SDimitry Andric
43110b57cec5SDimitry Andric void emitWriteHazard();
43120b57cec5SDimitry Andric void emitHazardsInNewBlocks();
43130b57cec5SDimitry Andric };
43140b57cec5SDimitry Andric } // end anonymous namespace
43150b57cec5SDimitry Andric
43160b57cec5SDimitry Andric /// Create the fragile-ABI read and write hazards based on the current
43170b57cec5SDimitry Andric /// state of the function, which is presumed to be immediately prior
43180b57cec5SDimitry Andric /// to a @try block. These hazards are used to maintain correct
43190b57cec5SDimitry Andric /// semantics in the face of optimization and the fragile ABI's
43200b57cec5SDimitry Andric /// cavalier use of setjmp/longjmp.
FragileHazards(CodeGenFunction & CGF)43210b57cec5SDimitry Andric FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
43220b57cec5SDimitry Andric collectLocals();
43230b57cec5SDimitry Andric
43240b57cec5SDimitry Andric if (Locals.empty()) return;
43250b57cec5SDimitry Andric
43260b57cec5SDimitry Andric // Collect all the blocks in the function.
43270b57cec5SDimitry Andric for (llvm::Function::iterator
43280b57cec5SDimitry Andric I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
43290b57cec5SDimitry Andric BlocksBeforeTry.insert(&*I);
43300b57cec5SDimitry Andric
43310b57cec5SDimitry Andric llvm::FunctionType *AsmFnTy = GetAsmFnType();
43320b57cec5SDimitry Andric
43330b57cec5SDimitry Andric // Create a read hazard for the allocas. This inhibits dead-store
43340b57cec5SDimitry Andric // optimizations and forces the values to memory. This hazard is
43350b57cec5SDimitry Andric // inserted before any 'throwing' calls in the protected scope to
43360b57cec5SDimitry Andric // reflect the possibility that the variables might be read from the
43370b57cec5SDimitry Andric // catch block if the call throws.
43380b57cec5SDimitry Andric {
43390b57cec5SDimitry Andric std::string Constraint;
43400b57cec5SDimitry Andric for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
43410b57cec5SDimitry Andric if (I) Constraint += ',';
43420b57cec5SDimitry Andric Constraint += "*m";
43430b57cec5SDimitry Andric }
43440b57cec5SDimitry Andric
43450b57cec5SDimitry Andric ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
43460b57cec5SDimitry Andric }
43470b57cec5SDimitry Andric
43480b57cec5SDimitry Andric // Create a write hazard for the allocas. This inhibits folding
43490b57cec5SDimitry Andric // loads across the hazard. This hazard is inserted at the
43500b57cec5SDimitry Andric // beginning of the catch path to reflect the possibility that the
43510b57cec5SDimitry Andric // variables might have been written within the protected scope.
43520b57cec5SDimitry Andric {
43530b57cec5SDimitry Andric std::string Constraint;
43540b57cec5SDimitry Andric for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
43550b57cec5SDimitry Andric if (I) Constraint += ',';
43560b57cec5SDimitry Andric Constraint += "=*m";
43570b57cec5SDimitry Andric }
43580b57cec5SDimitry Andric
43590b57cec5SDimitry Andric WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
43600b57cec5SDimitry Andric }
43610b57cec5SDimitry Andric }
43620b57cec5SDimitry Andric
43630b57cec5SDimitry Andric /// Emit a write hazard at the current location.
emitWriteHazard()43640b57cec5SDimitry Andric void FragileHazards::emitWriteHazard() {
43650b57cec5SDimitry Andric if (Locals.empty()) return;
43660b57cec5SDimitry Andric
436704eeddc0SDimitry Andric llvm::CallInst *Call = CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
436804eeddc0SDimitry Andric for (auto Pair : llvm::enumerate(Locals))
436904eeddc0SDimitry Andric Call->addParamAttr(Pair.index(), llvm::Attribute::get(
437004eeddc0SDimitry Andric CGF.getLLVMContext(), llvm::Attribute::ElementType,
437104eeddc0SDimitry Andric cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
43720b57cec5SDimitry Andric }
43730b57cec5SDimitry Andric
emitReadHazard(CGBuilderTy & Builder)43740b57cec5SDimitry Andric void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
43750b57cec5SDimitry Andric assert(!Locals.empty());
43760b57cec5SDimitry Andric llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
43770b57cec5SDimitry Andric call->setDoesNotThrow();
43780b57cec5SDimitry Andric call->setCallingConv(CGF.getRuntimeCC());
437904eeddc0SDimitry Andric for (auto Pair : llvm::enumerate(Locals))
438004eeddc0SDimitry Andric call->addParamAttr(Pair.index(), llvm::Attribute::get(
438104eeddc0SDimitry Andric Builder.getContext(), llvm::Attribute::ElementType,
438204eeddc0SDimitry Andric cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
43830b57cec5SDimitry Andric }
43840b57cec5SDimitry Andric
43850b57cec5SDimitry Andric /// Emit read hazards in all the protected blocks, i.e. all the blocks
43860b57cec5SDimitry Andric /// which have been inserted since the beginning of the try.
emitHazardsInNewBlocks()43870b57cec5SDimitry Andric void FragileHazards::emitHazardsInNewBlocks() {
43880b57cec5SDimitry Andric if (Locals.empty()) return;
43890b57cec5SDimitry Andric
43900b57cec5SDimitry Andric CGBuilderTy Builder(CGF, CGF.getLLVMContext());
43910b57cec5SDimitry Andric
43920b57cec5SDimitry Andric // Iterate through all blocks, skipping those prior to the try.
43930b57cec5SDimitry Andric for (llvm::Function::iterator
43940b57cec5SDimitry Andric FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
43950b57cec5SDimitry Andric llvm::BasicBlock &BB = *FI;
43960b57cec5SDimitry Andric if (BlocksBeforeTry.count(&BB)) continue;
43970b57cec5SDimitry Andric
43980b57cec5SDimitry Andric // Walk through all the calls in the block.
43990b57cec5SDimitry Andric for (llvm::BasicBlock::iterator
44000b57cec5SDimitry Andric BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
44010b57cec5SDimitry Andric llvm::Instruction &I = *BI;
44020b57cec5SDimitry Andric
44030b57cec5SDimitry Andric // Ignore instructions that aren't non-intrinsic calls.
44040b57cec5SDimitry Andric // These are the only calls that can possibly call longjmp.
44050b57cec5SDimitry Andric if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
44060b57cec5SDimitry Andric continue;
44070b57cec5SDimitry Andric if (isa<llvm::IntrinsicInst>(I))
44080b57cec5SDimitry Andric continue;
44090b57cec5SDimitry Andric
44100b57cec5SDimitry Andric // Ignore call sites marked nounwind. This may be questionable,
44110b57cec5SDimitry Andric // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
44120b57cec5SDimitry Andric if (cast<llvm::CallBase>(I).doesNotThrow())
44130b57cec5SDimitry Andric continue;
44140b57cec5SDimitry Andric
44150b57cec5SDimitry Andric // Insert a read hazard before the call. This will ensure that
44160b57cec5SDimitry Andric // any writes to the locals are performed before making the
44170b57cec5SDimitry Andric // call. If the call throws, then this is sufficient to
44180b57cec5SDimitry Andric // guarantee correctness as long as it doesn't also write to any
44190b57cec5SDimitry Andric // locals.
44200b57cec5SDimitry Andric Builder.SetInsertPoint(&BB, BI);
44210b57cec5SDimitry Andric emitReadHazard(Builder);
44220b57cec5SDimitry Andric }
44230b57cec5SDimitry Andric }
44240b57cec5SDimitry Andric }
44250b57cec5SDimitry Andric
addIfPresent(llvm::DenseSet<llvm::Value * > & S,Address V)44260b57cec5SDimitry Andric static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4427*0fca6ea1SDimitry Andric if (V.isValid())
4428*0fca6ea1SDimitry Andric if (llvm::Value *Ptr = V.getBasePointer())
4429*0fca6ea1SDimitry Andric S.insert(Ptr);
44300b57cec5SDimitry Andric }
44310b57cec5SDimitry Andric
collectLocals()44320b57cec5SDimitry Andric void FragileHazards::collectLocals() {
44330b57cec5SDimitry Andric // Compute a set of allocas to ignore.
44340b57cec5SDimitry Andric llvm::DenseSet<llvm::Value*> AllocasToIgnore;
44350b57cec5SDimitry Andric addIfPresent(AllocasToIgnore, CGF.ReturnValue);
44360b57cec5SDimitry Andric addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
44370b57cec5SDimitry Andric
44380b57cec5SDimitry Andric // Collect all the allocas currently in the function. This is
44390b57cec5SDimitry Andric // probably way too aggressive.
44400b57cec5SDimitry Andric llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
44410b57cec5SDimitry Andric for (llvm::BasicBlock::iterator
44420b57cec5SDimitry Andric I = Entry.begin(), E = Entry.end(); I != E; ++I)
44430b57cec5SDimitry Andric if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
44440b57cec5SDimitry Andric Locals.push_back(&*I);
44450b57cec5SDimitry Andric }
44460b57cec5SDimitry Andric
GetAsmFnType()44470b57cec5SDimitry Andric llvm::FunctionType *FragileHazards::GetAsmFnType() {
44480b57cec5SDimitry Andric SmallVector<llvm::Type *, 16> tys(Locals.size());
44490b57cec5SDimitry Andric for (unsigned i = 0, e = Locals.size(); i != e; ++i)
44500b57cec5SDimitry Andric tys[i] = Locals[i]->getType();
44510b57cec5SDimitry Andric return llvm::FunctionType::get(CGF.VoidTy, tys, false);
44520b57cec5SDimitry Andric }
44530b57cec5SDimitry Andric
44540b57cec5SDimitry Andric /*
44550b57cec5SDimitry Andric
44560b57cec5SDimitry Andric Objective-C setjmp-longjmp (sjlj) Exception Handling
44570b57cec5SDimitry Andric --
44580b57cec5SDimitry Andric
44590b57cec5SDimitry Andric A catch buffer is a setjmp buffer plus:
44600b57cec5SDimitry Andric - a pointer to the exception that was caught
44610b57cec5SDimitry Andric - a pointer to the previous exception data buffer
44620b57cec5SDimitry Andric - two pointers of reserved storage
44630b57cec5SDimitry Andric Therefore catch buffers form a stack, with a pointer to the top
44640b57cec5SDimitry Andric of the stack kept in thread-local storage.
44650b57cec5SDimitry Andric
44660b57cec5SDimitry Andric objc_exception_try_enter pushes a catch buffer onto the EH stack.
44670b57cec5SDimitry Andric objc_exception_try_exit pops the given catch buffer, which is
44680b57cec5SDimitry Andric required to be the top of the EH stack.
44690b57cec5SDimitry Andric objc_exception_throw pops the top of the EH stack, writes the
44700b57cec5SDimitry Andric thrown exception into the appropriate field, and longjmps
44710b57cec5SDimitry Andric to the setjmp buffer. It crashes the process (with a printf
44720b57cec5SDimitry Andric and an abort()) if there are no catch buffers on the stack.
44730b57cec5SDimitry Andric objc_exception_extract just reads the exception pointer out of the
44740b57cec5SDimitry Andric catch buffer.
44750b57cec5SDimitry Andric
44760b57cec5SDimitry Andric There's no reason an implementation couldn't use a light-weight
44770b57cec5SDimitry Andric setjmp here --- something like __builtin_setjmp, but API-compatible
44780b57cec5SDimitry Andric with the heavyweight setjmp. This will be more important if we ever
44790b57cec5SDimitry Andric want to implement correct ObjC/C++ exception interactions for the
44800b57cec5SDimitry Andric fragile ABI.
44810b57cec5SDimitry Andric
44825f757f3fSDimitry Andric Note that for this use of setjmp/longjmp to be correct in the presence of
44835f757f3fSDimitry Andric optimization, we use inline assembly on the set of local variables to force
44845f757f3fSDimitry Andric flushing locals to memory immediately before any protected calls and to
44855f757f3fSDimitry Andric inhibit optimizing locals across the setjmp->catch edge.
44860b57cec5SDimitry Andric
44870b57cec5SDimitry Andric The basic framework for a @try-catch-finally is as follows:
44880b57cec5SDimitry Andric {
44890b57cec5SDimitry Andric objc_exception_data d;
44900b57cec5SDimitry Andric id _rethrow = null;
44910b57cec5SDimitry Andric bool _call_try_exit = true;
44920b57cec5SDimitry Andric
44930b57cec5SDimitry Andric objc_exception_try_enter(&d);
44940b57cec5SDimitry Andric if (!setjmp(d.jmp_buf)) {
44950b57cec5SDimitry Andric ... try body ...
44960b57cec5SDimitry Andric } else {
44970b57cec5SDimitry Andric // exception path
44980b57cec5SDimitry Andric id _caught = objc_exception_extract(&d);
44990b57cec5SDimitry Andric
45000b57cec5SDimitry Andric // enter new try scope for handlers
45010b57cec5SDimitry Andric if (!setjmp(d.jmp_buf)) {
45020b57cec5SDimitry Andric ... match exception and execute catch blocks ...
45030b57cec5SDimitry Andric
45040b57cec5SDimitry Andric // fell off end, rethrow.
45050b57cec5SDimitry Andric _rethrow = _caught;
45060b57cec5SDimitry Andric ... jump-through-finally to finally_rethrow ...
45070b57cec5SDimitry Andric } else {
45080b57cec5SDimitry Andric // exception in catch block
45090b57cec5SDimitry Andric _rethrow = objc_exception_extract(&d);
45100b57cec5SDimitry Andric _call_try_exit = false;
45110b57cec5SDimitry Andric ... jump-through-finally to finally_rethrow ...
45120b57cec5SDimitry Andric }
45130b57cec5SDimitry Andric }
45140b57cec5SDimitry Andric ... jump-through-finally to finally_end ...
45150b57cec5SDimitry Andric
45160b57cec5SDimitry Andric finally:
45170b57cec5SDimitry Andric if (_call_try_exit)
45180b57cec5SDimitry Andric objc_exception_try_exit(&d);
45190b57cec5SDimitry Andric
45200b57cec5SDimitry Andric ... finally block ....
45210b57cec5SDimitry Andric ... dispatch to finally destination ...
45220b57cec5SDimitry Andric
45230b57cec5SDimitry Andric finally_rethrow:
45240b57cec5SDimitry Andric objc_exception_throw(_rethrow);
45250b57cec5SDimitry Andric
45260b57cec5SDimitry Andric finally_end:
45270b57cec5SDimitry Andric }
45280b57cec5SDimitry Andric
45290b57cec5SDimitry Andric This framework differs slightly from the one gcc uses, in that gcc
45300b57cec5SDimitry Andric uses _rethrow to determine if objc_exception_try_exit should be called
45310b57cec5SDimitry Andric and if the object should be rethrown. This breaks in the face of
45320b57cec5SDimitry Andric throwing nil and introduces unnecessary branches.
45330b57cec5SDimitry Andric
45340b57cec5SDimitry Andric We specialize this framework for a few particular circumstances:
45350b57cec5SDimitry Andric
45360b57cec5SDimitry Andric - If there are no catch blocks, then we avoid emitting the second
45370b57cec5SDimitry Andric exception handling context.
45380b57cec5SDimitry Andric
45390b57cec5SDimitry Andric - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
45400b57cec5SDimitry Andric e)) we avoid emitting the code to rethrow an uncaught exception.
45410b57cec5SDimitry Andric
45420b57cec5SDimitry Andric - FIXME: If there is no @finally block we can do a few more
45430b57cec5SDimitry Andric simplifications.
45440b57cec5SDimitry Andric
45450b57cec5SDimitry Andric Rethrows and Jumps-Through-Finally
45460b57cec5SDimitry Andric --
45470b57cec5SDimitry Andric
45480b57cec5SDimitry Andric '@throw;' is supported by pushing the currently-caught exception
45490b57cec5SDimitry Andric onto ObjCEHStack while the @catch blocks are emitted.
45500b57cec5SDimitry Andric
45510b57cec5SDimitry Andric Branches through the @finally block are handled with an ordinary
45520b57cec5SDimitry Andric normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
45530b57cec5SDimitry Andric exceptions are not compatible with C++ exceptions, and this is
45540b57cec5SDimitry Andric hardly the only place where this will go wrong.
45550b57cec5SDimitry Andric
45560b57cec5SDimitry Andric @synchronized(expr) { stmt; } is emitted as if it were:
45570b57cec5SDimitry Andric id synch_value = expr;
45580b57cec5SDimitry Andric objc_sync_enter(synch_value);
45590b57cec5SDimitry Andric @try { stmt; } @finally { objc_sync_exit(synch_value); }
45600b57cec5SDimitry Andric */
45610b57cec5SDimitry Andric
EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const Stmt & S)45620b57cec5SDimitry Andric void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
45630b57cec5SDimitry Andric const Stmt &S) {
45640b57cec5SDimitry Andric bool isTry = isa<ObjCAtTryStmt>(S);
45650b57cec5SDimitry Andric
45660b57cec5SDimitry Andric // A destination for the fall-through edges of the catch handlers to
45670b57cec5SDimitry Andric // jump to.
45680b57cec5SDimitry Andric CodeGenFunction::JumpDest FinallyEnd =
45690b57cec5SDimitry Andric CGF.getJumpDestInCurrentScope("finally.end");
45700b57cec5SDimitry Andric
45710b57cec5SDimitry Andric // A destination for the rethrow edge of the catch handlers to jump
45720b57cec5SDimitry Andric // to.
45730b57cec5SDimitry Andric CodeGenFunction::JumpDest FinallyRethrow =
45740b57cec5SDimitry Andric CGF.getJumpDestInCurrentScope("finally.rethrow");
45750b57cec5SDimitry Andric
45760b57cec5SDimitry Andric // For @synchronized, call objc_sync_enter(sync.expr). The
45770b57cec5SDimitry Andric // evaluation of the expression must occur before we enter the
45780b57cec5SDimitry Andric // @synchronized. We can't avoid a temp here because we need the
45790b57cec5SDimitry Andric // value to be preserved. If the backend ever does liveness
45800b57cec5SDimitry Andric // correctly after setjmp, this will be unnecessary.
45810b57cec5SDimitry Andric Address SyncArgSlot = Address::invalid();
45820b57cec5SDimitry Andric if (!isTry) {
45830b57cec5SDimitry Andric llvm::Value *SyncArg =
45840b57cec5SDimitry Andric CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
45850b57cec5SDimitry Andric SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
45860b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
45870b57cec5SDimitry Andric
45880b57cec5SDimitry Andric SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
45890b57cec5SDimitry Andric CGF.getPointerAlign(), "sync.arg");
45900b57cec5SDimitry Andric CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
45910b57cec5SDimitry Andric }
45920b57cec5SDimitry Andric
45930b57cec5SDimitry Andric // Allocate memory for the setjmp buffer. This needs to be kept
45940b57cec5SDimitry Andric // live throughout the try and catch blocks.
45950b57cec5SDimitry Andric Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
45960b57cec5SDimitry Andric CGF.getPointerAlign(),
45970b57cec5SDimitry Andric "exceptiondata.ptr");
45980b57cec5SDimitry Andric
45990b57cec5SDimitry Andric // Create the fragile hazards. Note that this will not capture any
46000b57cec5SDimitry Andric // of the allocas required for exception processing, but will
46010b57cec5SDimitry Andric // capture the current basic block (which extends all the way to the
46020b57cec5SDimitry Andric // setjmp call) as "before the @try".
46030b57cec5SDimitry Andric FragileHazards Hazards(CGF);
46040b57cec5SDimitry Andric
46050b57cec5SDimitry Andric // Create a flag indicating whether the cleanup needs to call
46060b57cec5SDimitry Andric // objc_exception_try_exit. This is true except when
46070b57cec5SDimitry Andric // - no catches match and we're branching through the cleanup
46080b57cec5SDimitry Andric // just to rethrow the exception, or
46090b57cec5SDimitry Andric // - a catch matched and we're falling out of the catch handler.
46100b57cec5SDimitry Andric // The setjmp-safety rule here is that we should always store to this
46110b57cec5SDimitry Andric // variable in a place that dominates the branch through the cleanup
46120b57cec5SDimitry Andric // without passing through any setjmps.
46130b57cec5SDimitry Andric Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
46140b57cec5SDimitry Andric CharUnits::One(),
46150b57cec5SDimitry Andric "_call_try_exit");
46160b57cec5SDimitry Andric
46170b57cec5SDimitry Andric // A slot containing the exception to rethrow. Only needed when we
46180b57cec5SDimitry Andric // have both a @catch and a @finally.
46190b57cec5SDimitry Andric Address PropagatingExnVar = Address::invalid();
46200b57cec5SDimitry Andric
46210b57cec5SDimitry Andric // Push a normal cleanup to leave the try scope.
46220b57cec5SDimitry Andric CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
46230b57cec5SDimitry Andric SyncArgSlot,
46240b57cec5SDimitry Andric CallTryExitVar,
46250b57cec5SDimitry Andric ExceptionData,
46260b57cec5SDimitry Andric &ObjCTypes);
46270b57cec5SDimitry Andric
46280b57cec5SDimitry Andric // Enter a try block:
46290b57cec5SDimitry Andric // - Call objc_exception_try_enter to push ExceptionData on top of
46300b57cec5SDimitry Andric // the EH stack.
46310b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
4632*0fca6ea1SDimitry Andric ExceptionData.emitRawPointer(CGF));
46330b57cec5SDimitry Andric
46340b57cec5SDimitry Andric // - Call setjmp on the exception data buffer.
46350b57cec5SDimitry Andric llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
46360b57cec5SDimitry Andric llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
46370b57cec5SDimitry Andric llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
4638*0fca6ea1SDimitry Andric ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
46390b57cec5SDimitry Andric "setjmp_buffer");
46400b57cec5SDimitry Andric llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
46410b57cec5SDimitry Andric ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
46420b57cec5SDimitry Andric SetJmpResult->setCanReturnTwice();
46430b57cec5SDimitry Andric
46440b57cec5SDimitry Andric // If setjmp returned 0, enter the protected block; otherwise,
46450b57cec5SDimitry Andric // branch to the handler.
46460b57cec5SDimitry Andric llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
46470b57cec5SDimitry Andric llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
46480b57cec5SDimitry Andric llvm::Value *DidCatch =
46490b57cec5SDimitry Andric CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
46500b57cec5SDimitry Andric CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
46510b57cec5SDimitry Andric
46520b57cec5SDimitry Andric // Emit the protected block.
46530b57cec5SDimitry Andric CGF.EmitBlock(TryBlock);
46540b57cec5SDimitry Andric CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
46550b57cec5SDimitry Andric CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
46560b57cec5SDimitry Andric : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
46570b57cec5SDimitry Andric
46580b57cec5SDimitry Andric CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
46590b57cec5SDimitry Andric
46600b57cec5SDimitry Andric // Emit the exception handler block.
46610b57cec5SDimitry Andric CGF.EmitBlock(TryHandler);
46620b57cec5SDimitry Andric
46630b57cec5SDimitry Andric // Don't optimize loads of the in-scope locals across this point.
46640b57cec5SDimitry Andric Hazards.emitWriteHazard();
46650b57cec5SDimitry Andric
46660b57cec5SDimitry Andric // For a @synchronized (or a @try with no catches), just branch
46670b57cec5SDimitry Andric // through the cleanup to the rethrow block.
46680b57cec5SDimitry Andric if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
46690b57cec5SDimitry Andric // Tell the cleanup not to re-pop the exit.
46700b57cec5SDimitry Andric CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
46710b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(FinallyRethrow);
46720b57cec5SDimitry Andric
46730b57cec5SDimitry Andric // Otherwise, we have to match against the caught exceptions.
46740b57cec5SDimitry Andric } else {
46750b57cec5SDimitry Andric // Retrieve the exception object. We may emit multiple blocks but
46760b57cec5SDimitry Andric // nothing can cross this so the value is already in SSA form.
4677*0fca6ea1SDimitry Andric llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall(
4678*0fca6ea1SDimitry Andric ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4679*0fca6ea1SDimitry Andric "caught");
46800b57cec5SDimitry Andric
46810b57cec5SDimitry Andric // Push the exception to rethrow onto the EH value stack for the
46820b57cec5SDimitry Andric // benefit of any @throws in the handlers.
46830b57cec5SDimitry Andric CGF.ObjCEHValueStack.push_back(Caught);
46840b57cec5SDimitry Andric
46850b57cec5SDimitry Andric const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
46860b57cec5SDimitry Andric
46870b57cec5SDimitry Andric bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
46880b57cec5SDimitry Andric
46890b57cec5SDimitry Andric llvm::BasicBlock *CatchBlock = nullptr;
46900b57cec5SDimitry Andric llvm::BasicBlock *CatchHandler = nullptr;
46910b57cec5SDimitry Andric if (HasFinally) {
46920b57cec5SDimitry Andric // Save the currently-propagating exception before
46930b57cec5SDimitry Andric // objc_exception_try_enter clears the exception slot.
46940b57cec5SDimitry Andric PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
46950b57cec5SDimitry Andric CGF.getPointerAlign(),
46960b57cec5SDimitry Andric "propagating_exception");
46970b57cec5SDimitry Andric CGF.Builder.CreateStore(Caught, PropagatingExnVar);
46980b57cec5SDimitry Andric
46990b57cec5SDimitry Andric // Enter a new exception try block (in case a @catch block
47000b57cec5SDimitry Andric // throws an exception).
47010b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
4702*0fca6ea1SDimitry Andric ExceptionData.emitRawPointer(CGF));
47030b57cec5SDimitry Andric
47040b57cec5SDimitry Andric llvm::CallInst *SetJmpResult =
47050b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
47060b57cec5SDimitry Andric SetJmpBuffer, "setjmp.result");
47070b57cec5SDimitry Andric SetJmpResult->setCanReturnTwice();
47080b57cec5SDimitry Andric
47090b57cec5SDimitry Andric llvm::Value *Threw =
47100b57cec5SDimitry Andric CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
47110b57cec5SDimitry Andric
47120b57cec5SDimitry Andric CatchBlock = CGF.createBasicBlock("catch");
47130b57cec5SDimitry Andric CatchHandler = CGF.createBasicBlock("catch_for_catch");
47140b57cec5SDimitry Andric CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
47150b57cec5SDimitry Andric
47160b57cec5SDimitry Andric CGF.EmitBlock(CatchBlock);
47170b57cec5SDimitry Andric }
47180b57cec5SDimitry Andric
47190b57cec5SDimitry Andric CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
47200b57cec5SDimitry Andric
47210b57cec5SDimitry Andric // Handle catch list. As a special case we check if everything is
47220b57cec5SDimitry Andric // matched and avoid generating code for falling off the end if
47230b57cec5SDimitry Andric // so.
47240b57cec5SDimitry Andric bool AllMatched = false;
4725349cc55cSDimitry Andric for (const ObjCAtCatchStmt *CatchStmt : AtTryStmt->catch_stmts()) {
47260b57cec5SDimitry Andric const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
47270b57cec5SDimitry Andric const ObjCObjectPointerType *OPT = nullptr;
47280b57cec5SDimitry Andric
47290b57cec5SDimitry Andric // catch(...) always matches.
47300b57cec5SDimitry Andric if (!CatchParam) {
47310b57cec5SDimitry Andric AllMatched = true;
47320b57cec5SDimitry Andric } else {
47330b57cec5SDimitry Andric OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
47340b57cec5SDimitry Andric
47350b57cec5SDimitry Andric // catch(id e) always matches under this ABI, since only
47360b57cec5SDimitry Andric // ObjC exceptions end up here in the first place.
47370b57cec5SDimitry Andric // FIXME: For the time being we also match id<X>; this should
47380b57cec5SDimitry Andric // be rejected by Sema instead.
47390b57cec5SDimitry Andric if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
47400b57cec5SDimitry Andric AllMatched = true;
47410b57cec5SDimitry Andric }
47420b57cec5SDimitry Andric
47430b57cec5SDimitry Andric // If this is a catch-all, we don't need to test anything.
47440b57cec5SDimitry Andric if (AllMatched) {
47450b57cec5SDimitry Andric CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
47460b57cec5SDimitry Andric
47470b57cec5SDimitry Andric if (CatchParam) {
47480b57cec5SDimitry Andric CGF.EmitAutoVarDecl(*CatchParam);
47490b57cec5SDimitry Andric assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
47500b57cec5SDimitry Andric
47510b57cec5SDimitry Andric // These types work out because ConvertType(id) == i8*.
47520b57cec5SDimitry Andric EmitInitOfCatchParam(CGF, Caught, CatchParam);
47530b57cec5SDimitry Andric }
47540b57cec5SDimitry Andric
47550b57cec5SDimitry Andric CGF.EmitStmt(CatchStmt->getCatchBody());
47560b57cec5SDimitry Andric
47570b57cec5SDimitry Andric // The scope of the catch variable ends right here.
47580b57cec5SDimitry Andric CatchVarCleanups.ForceCleanup();
47590b57cec5SDimitry Andric
47600b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(FinallyEnd);
47610b57cec5SDimitry Andric break;
47620b57cec5SDimitry Andric }
47630b57cec5SDimitry Andric
47640b57cec5SDimitry Andric assert(OPT && "Unexpected non-object pointer type in @catch");
47650b57cec5SDimitry Andric const ObjCObjectType *ObjTy = OPT->getObjectType();
47660b57cec5SDimitry Andric
47670b57cec5SDimitry Andric // FIXME: @catch (Class c) ?
47680b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
47690b57cec5SDimitry Andric assert(IDecl && "Catch parameter must have Objective-C type!");
47700b57cec5SDimitry Andric
47710b57cec5SDimitry Andric // Check if the @catch block matches the exception object.
47720b57cec5SDimitry Andric llvm::Value *Class = EmitClassRef(CGF, IDecl);
47730b57cec5SDimitry Andric
47740b57cec5SDimitry Andric llvm::Value *matchArgs[] = { Class, Caught };
47750b57cec5SDimitry Andric llvm::CallInst *Match =
47760b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
47770b57cec5SDimitry Andric matchArgs, "match");
47780b57cec5SDimitry Andric
47790b57cec5SDimitry Andric llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
47800b57cec5SDimitry Andric llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
47810b57cec5SDimitry Andric
47820b57cec5SDimitry Andric CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
47830b57cec5SDimitry Andric MatchedBlock, NextCatchBlock);
47840b57cec5SDimitry Andric
47850b57cec5SDimitry Andric // Emit the @catch block.
47860b57cec5SDimitry Andric CGF.EmitBlock(MatchedBlock);
47870b57cec5SDimitry Andric
47880b57cec5SDimitry Andric // Collect any cleanups for the catch variable. The scope lasts until
47890b57cec5SDimitry Andric // the end of the catch body.
47900b57cec5SDimitry Andric CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
47910b57cec5SDimitry Andric
47920b57cec5SDimitry Andric CGF.EmitAutoVarDecl(*CatchParam);
47930b57cec5SDimitry Andric assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
47940b57cec5SDimitry Andric
47950b57cec5SDimitry Andric // Initialize the catch variable.
47960b57cec5SDimitry Andric llvm::Value *Tmp =
47970b57cec5SDimitry Andric CGF.Builder.CreateBitCast(Caught,
47980b57cec5SDimitry Andric CGF.ConvertType(CatchParam->getType()));
47990b57cec5SDimitry Andric EmitInitOfCatchParam(CGF, Tmp, CatchParam);
48000b57cec5SDimitry Andric
48010b57cec5SDimitry Andric CGF.EmitStmt(CatchStmt->getCatchBody());
48020b57cec5SDimitry Andric
48030b57cec5SDimitry Andric // We're done with the catch variable.
48040b57cec5SDimitry Andric CatchVarCleanups.ForceCleanup();
48050b57cec5SDimitry Andric
48060b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(FinallyEnd);
48070b57cec5SDimitry Andric
48080b57cec5SDimitry Andric CGF.EmitBlock(NextCatchBlock);
48090b57cec5SDimitry Andric }
48100b57cec5SDimitry Andric
48110b57cec5SDimitry Andric CGF.ObjCEHValueStack.pop_back();
48120b57cec5SDimitry Andric
48130b57cec5SDimitry Andric // If nothing wanted anything to do with the caught exception,
48140b57cec5SDimitry Andric // kill the extract call.
48150b57cec5SDimitry Andric if (Caught->use_empty())
48160b57cec5SDimitry Andric Caught->eraseFromParent();
48170b57cec5SDimitry Andric
48180b57cec5SDimitry Andric if (!AllMatched)
48190b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(FinallyRethrow);
48200b57cec5SDimitry Andric
48210b57cec5SDimitry Andric if (HasFinally) {
48220b57cec5SDimitry Andric // Emit the exception handler for the @catch blocks.
48230b57cec5SDimitry Andric CGF.EmitBlock(CatchHandler);
48240b57cec5SDimitry Andric
48250b57cec5SDimitry Andric // In theory we might now need a write hazard, but actually it's
48260b57cec5SDimitry Andric // unnecessary because there's no local-accessing code between
48270b57cec5SDimitry Andric // the try's write hazard and here.
48280b57cec5SDimitry Andric //Hazards.emitWriteHazard();
48290b57cec5SDimitry Andric
48300b57cec5SDimitry Andric // Extract the new exception and save it to the
48310b57cec5SDimitry Andric // propagating-exception slot.
48320b57cec5SDimitry Andric assert(PropagatingExnVar.isValid());
4833*0fca6ea1SDimitry Andric llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall(
4834*0fca6ea1SDimitry Andric ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4835*0fca6ea1SDimitry Andric "caught");
48360b57cec5SDimitry Andric CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
48370b57cec5SDimitry Andric
48380b57cec5SDimitry Andric // Don't pop the catch handler; the throw already did.
48390b57cec5SDimitry Andric CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
48400b57cec5SDimitry Andric CGF.EmitBranchThroughCleanup(FinallyRethrow);
48410b57cec5SDimitry Andric }
48420b57cec5SDimitry Andric }
48430b57cec5SDimitry Andric
48440b57cec5SDimitry Andric // Insert read hazards as required in the new blocks.
48450b57cec5SDimitry Andric Hazards.emitHazardsInNewBlocks();
48460b57cec5SDimitry Andric
48470b57cec5SDimitry Andric // Pop the cleanup.
48480b57cec5SDimitry Andric CGF.Builder.restoreIP(TryFallthroughIP);
48490b57cec5SDimitry Andric if (CGF.HaveInsertPoint())
48500b57cec5SDimitry Andric CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
48510b57cec5SDimitry Andric CGF.PopCleanupBlock();
48520b57cec5SDimitry Andric CGF.EmitBlock(FinallyEnd.getBlock(), true);
48530b57cec5SDimitry Andric
48540b57cec5SDimitry Andric // Emit the rethrow block.
48550b57cec5SDimitry Andric CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
48560b57cec5SDimitry Andric CGF.EmitBlock(FinallyRethrow.getBlock(), true);
48570b57cec5SDimitry Andric if (CGF.HaveInsertPoint()) {
48580b57cec5SDimitry Andric // If we have a propagating-exception variable, check it.
48590b57cec5SDimitry Andric llvm::Value *PropagatingExn;
48600b57cec5SDimitry Andric if (PropagatingExnVar.isValid()) {
48610b57cec5SDimitry Andric PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
48620b57cec5SDimitry Andric
48630b57cec5SDimitry Andric // Otherwise, just look in the buffer for the exception to throw.
48640b57cec5SDimitry Andric } else {
4865*0fca6ea1SDimitry Andric llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall(
4866*0fca6ea1SDimitry Andric ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
48670b57cec5SDimitry Andric PropagatingExn = Caught;
48680b57cec5SDimitry Andric }
48690b57cec5SDimitry Andric
48700b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
48710b57cec5SDimitry Andric PropagatingExn);
48720b57cec5SDimitry Andric CGF.Builder.CreateUnreachable();
48730b57cec5SDimitry Andric }
48740b57cec5SDimitry Andric
48750b57cec5SDimitry Andric CGF.Builder.restoreIP(SavedIP);
48760b57cec5SDimitry Andric }
48770b57cec5SDimitry Andric
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)48780b57cec5SDimitry Andric void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
48790b57cec5SDimitry Andric const ObjCAtThrowStmt &S,
48800b57cec5SDimitry Andric bool ClearInsertionPoint) {
48810b57cec5SDimitry Andric llvm::Value *ExceptionAsObject;
48820b57cec5SDimitry Andric
48830b57cec5SDimitry Andric if (const Expr *ThrowExpr = S.getThrowExpr()) {
48840b57cec5SDimitry Andric llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
48850b57cec5SDimitry Andric ExceptionAsObject =
48860b57cec5SDimitry Andric CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
48870b57cec5SDimitry Andric } else {
48880b57cec5SDimitry Andric assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
48890b57cec5SDimitry Andric "Unexpected rethrow outside @catch block.");
48900b57cec5SDimitry Andric ExceptionAsObject = CGF.ObjCEHValueStack.back();
48910b57cec5SDimitry Andric }
48920b57cec5SDimitry Andric
48930b57cec5SDimitry Andric CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
48940b57cec5SDimitry Andric ->setDoesNotReturn();
48950b57cec5SDimitry Andric CGF.Builder.CreateUnreachable();
48960b57cec5SDimitry Andric
48970b57cec5SDimitry Andric // Clear the insertion point to indicate we are in unreachable code.
48980b57cec5SDimitry Andric if (ClearInsertionPoint)
48990b57cec5SDimitry Andric CGF.Builder.ClearInsertionPoint();
49000b57cec5SDimitry Andric }
49010b57cec5SDimitry Andric
49020b57cec5SDimitry Andric /// EmitObjCWeakRead - Code gen for loading value of a __weak
49030b57cec5SDimitry Andric /// object: objc_read_weak (id *src)
49040b57cec5SDimitry Andric ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,Address AddrWeakObj)49050b57cec5SDimitry Andric llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
49060b57cec5SDimitry Andric Address AddrWeakObj) {
49070b57cec5SDimitry Andric llvm::Type* DestTy = AddrWeakObj.getElementType();
490881ad6265SDimitry Andric llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
4909*0fca6ea1SDimitry Andric AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
49100b57cec5SDimitry Andric llvm::Value *read_weak =
49110b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
491281ad6265SDimitry Andric AddrWeakObjVal, "weakread");
49130b57cec5SDimitry Andric read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
49140b57cec5SDimitry Andric return read_weak;
49150b57cec5SDimitry Andric }
49160b57cec5SDimitry Andric
49170b57cec5SDimitry Andric /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
49180b57cec5SDimitry Andric /// objc_assign_weak (id src, id *dst)
49190b57cec5SDimitry Andric ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)49200b57cec5SDimitry Andric void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
49210b57cec5SDimitry Andric llvm::Value *src, Address dst) {
49220b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
49230b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
49240b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
49250b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
49260b57cec5SDimitry Andric src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
49270b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
49280b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
49290b57cec5SDimitry Andric }
49300b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4931*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4932*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
493381ad6265SDimitry Andric llvm::Value *args[] = { src, dstVal };
49340b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
49350b57cec5SDimitry Andric args, "weakassign");
49360b57cec5SDimitry Andric }
49370b57cec5SDimitry Andric
49380b57cec5SDimitry Andric /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
49390b57cec5SDimitry Andric /// objc_assign_global (id src, id *dst)
49400b57cec5SDimitry Andric ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,bool threadlocal)49410b57cec5SDimitry Andric void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
49420b57cec5SDimitry Andric llvm::Value *src, Address dst,
49430b57cec5SDimitry Andric bool threadlocal) {
49440b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
49450b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
49460b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
49470b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
49480b57cec5SDimitry Andric src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
49490b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
49500b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
49510b57cec5SDimitry Andric }
49520b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4953*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4954*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
495581ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal};
49560b57cec5SDimitry Andric if (!threadlocal)
49570b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
49580b57cec5SDimitry Andric args, "globalassign");
49590b57cec5SDimitry Andric else
49600b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
49610b57cec5SDimitry Andric args, "threadlocalassign");
49620b57cec5SDimitry Andric }
49630b57cec5SDimitry Andric
49640b57cec5SDimitry Andric /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
49650b57cec5SDimitry Andric /// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
49660b57cec5SDimitry Andric ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,llvm::Value * ivarOffset)49670b57cec5SDimitry Andric void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
49680b57cec5SDimitry Andric llvm::Value *src, Address dst,
49690b57cec5SDimitry Andric llvm::Value *ivarOffset) {
49700b57cec5SDimitry Andric assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
49710b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
49720b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
49730b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
49740b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
49750b57cec5SDimitry Andric src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
49760b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
49770b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
49780b57cec5SDimitry Andric }
49790b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4980*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4981*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
498281ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal, ivarOffset};
49830b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
49840b57cec5SDimitry Andric }
49850b57cec5SDimitry Andric
49860b57cec5SDimitry Andric /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
49870b57cec5SDimitry Andric /// objc_assign_strongCast (id src, id *dst)
49880b57cec5SDimitry Andric ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)49890b57cec5SDimitry Andric void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
49900b57cec5SDimitry Andric llvm::Value *src, Address dst) {
49910b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
49920b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
49930b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
49940b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
49950b57cec5SDimitry Andric src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
49960b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
49970b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
49980b57cec5SDimitry Andric }
49990b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5000*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5001*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
500281ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal};
50030b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
50040b57cec5SDimitry Andric args, "strongassign");
50050b57cec5SDimitry Andric }
50060b57cec5SDimitry Andric
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,Address DestPtr,Address SrcPtr,llvm::Value * size)50070b57cec5SDimitry Andric void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
500806c3fb27SDimitry Andric Address DestPtr, Address SrcPtr,
50090b57cec5SDimitry Andric llvm::Value *size) {
5010*0fca6ea1SDimitry Andric llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
5011*0fca6ea1SDimitry Andric SrcPtr.emitRawPointer(CGF), size};
50120b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
50130b57cec5SDimitry Andric }
50140b57cec5SDimitry Andric
50150b57cec5SDimitry Andric /// EmitObjCValueForIvar - Code Gen for ivar reference.
50160b57cec5SDimitry Andric ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)50170b57cec5SDimitry Andric LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
50180b57cec5SDimitry Andric QualType ObjectTy,
50190b57cec5SDimitry Andric llvm::Value *BaseValue,
50200b57cec5SDimitry Andric const ObjCIvarDecl *Ivar,
50210b57cec5SDimitry Andric unsigned CVRQualifiers) {
50220b57cec5SDimitry Andric const ObjCInterfaceDecl *ID =
5023a7dea167SDimitry Andric ObjectTy->castAs<ObjCObjectType>()->getInterface();
50240b57cec5SDimitry Andric return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
50250b57cec5SDimitry Andric EmitIvarOffset(CGF, ID, Ivar));
50260b57cec5SDimitry Andric }
50270b57cec5SDimitry Andric
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)50280b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
50290b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface,
50300b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) {
50310b57cec5SDimitry Andric uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
50320b57cec5SDimitry Andric return llvm::ConstantInt::get(
50330b57cec5SDimitry Andric CGM.getTypes().ConvertType(CGM.getContext().LongTy),
50340b57cec5SDimitry Andric Offset);
50350b57cec5SDimitry Andric }
50360b57cec5SDimitry Andric
50370b57cec5SDimitry Andric /* *** Private Interface *** */
50380b57cec5SDimitry Andric
GetSectionName(StringRef Section,StringRef MachOAttributes)50390b57cec5SDimitry Andric std::string CGObjCCommonMac::GetSectionName(StringRef Section,
50400b57cec5SDimitry Andric StringRef MachOAttributes) {
50410b57cec5SDimitry Andric switch (CGM.getTriple().getObjectFormat()) {
50420b57cec5SDimitry Andric case llvm::Triple::UnknownObjectFormat:
50430b57cec5SDimitry Andric llvm_unreachable("unexpected object file format");
50440b57cec5SDimitry Andric case llvm::Triple::MachO: {
50450b57cec5SDimitry Andric if (MachOAttributes.empty())
50460b57cec5SDimitry Andric return ("__DATA," + Section).str();
50470b57cec5SDimitry Andric return ("__DATA," + Section + "," + MachOAttributes).str();
50480b57cec5SDimitry Andric }
50490b57cec5SDimitry Andric case llvm::Triple::ELF:
5050*0fca6ea1SDimitry Andric assert(Section.starts_with("__") && "expected the name to begin with __");
50510b57cec5SDimitry Andric return Section.substr(2).str();
50520b57cec5SDimitry Andric case llvm::Triple::COFF:
5053*0fca6ea1SDimitry Andric assert(Section.starts_with("__") && "expected the name to begin with __");
50540b57cec5SDimitry Andric return ("." + Section.substr(2) + "$B").str();
50550b57cec5SDimitry Andric case llvm::Triple::Wasm:
5056e8d8bef9SDimitry Andric case llvm::Triple::GOFF:
505781ad6265SDimitry Andric case llvm::Triple::SPIRV:
50580b57cec5SDimitry Andric case llvm::Triple::XCOFF:
505981ad6265SDimitry Andric case llvm::Triple::DXContainer:
50600b57cec5SDimitry Andric llvm::report_fatal_error(
5061e8d8bef9SDimitry Andric "Objective-C support is unimplemented for object file format");
50620b57cec5SDimitry Andric }
50630b57cec5SDimitry Andric
50640b57cec5SDimitry Andric llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
50650b57cec5SDimitry Andric }
50660b57cec5SDimitry Andric
50670b57cec5SDimitry Andric /// EmitImageInfo - Emit the image info marker used to encode some module
50680b57cec5SDimitry Andric /// level information.
50690b57cec5SDimitry Andric ///
50700b57cec5SDimitry Andric /// See: <rdr://4810609&4810587&4810587>
50710b57cec5SDimitry Andric /// struct IMAGE_INFO {
50720b57cec5SDimitry Andric /// unsigned version;
50730b57cec5SDimitry Andric /// unsigned flags;
50740b57cec5SDimitry Andric /// };
50750b57cec5SDimitry Andric enum ImageInfoFlags {
50760b57cec5SDimitry Andric eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
50770b57cec5SDimitry Andric eImageInfo_GarbageCollected = (1 << 1),
50780b57cec5SDimitry Andric eImageInfo_GCOnly = (1 << 2),
50790b57cec5SDimitry Andric eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
50800b57cec5SDimitry Andric
50810b57cec5SDimitry Andric // A flag indicating that the module has no instances of a @synthesize of a
50825f757f3fSDimitry Andric // superclass variable. This flag used to be consumed by the runtime to work
50835f757f3fSDimitry Andric // around miscompile by gcc.
50840b57cec5SDimitry Andric eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
50850b57cec5SDimitry Andric eImageInfo_ImageIsSimulated = (1 << 5),
50860b57cec5SDimitry Andric eImageInfo_ClassProperties = (1 << 6)
50870b57cec5SDimitry Andric };
50880b57cec5SDimitry Andric
EmitImageInfo()50890b57cec5SDimitry Andric void CGObjCCommonMac::EmitImageInfo() {
50900b57cec5SDimitry Andric unsigned version = 0; // Version is unused?
50910b57cec5SDimitry Andric std::string Section =
50920b57cec5SDimitry Andric (ObjCABI == 1)
50930b57cec5SDimitry Andric ? "__OBJC,__image_info,regular"
50940b57cec5SDimitry Andric : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
50950b57cec5SDimitry Andric
50960b57cec5SDimitry Andric // Generate module-level named metadata to convey this information to the
50970b57cec5SDimitry Andric // linker and code-gen.
50980b57cec5SDimitry Andric llvm::Module &Mod = CGM.getModule();
50990b57cec5SDimitry Andric
51000b57cec5SDimitry Andric // Add the ObjC ABI version to the module flags.
51010b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
51020b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
51030b57cec5SDimitry Andric version);
51040b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
51050b57cec5SDimitry Andric llvm::MDString::get(VMContext, Section));
51060b57cec5SDimitry Andric
51075ffd83dbSDimitry Andric auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
51080b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
51090b57cec5SDimitry Andric // Non-GC overrides those files which specify GC.
51105ffd83dbSDimitry Andric Mod.addModuleFlag(llvm::Module::Error,
51115ffd83dbSDimitry Andric "Objective-C Garbage Collection",
51125ffd83dbSDimitry Andric llvm::ConstantInt::get(Int8Ty,0));
51130b57cec5SDimitry Andric } else {
51140b57cec5SDimitry Andric // Add the ObjC garbage collection value.
51150b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error,
51160b57cec5SDimitry Andric "Objective-C Garbage Collection",
51175ffd83dbSDimitry Andric llvm::ConstantInt::get(Int8Ty,
51185ffd83dbSDimitry Andric (uint8_t)eImageInfo_GarbageCollected));
51190b57cec5SDimitry Andric
51200b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
51210b57cec5SDimitry Andric // Add the ObjC GC Only value.
51220b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
51230b57cec5SDimitry Andric eImageInfo_GCOnly);
51240b57cec5SDimitry Andric
51250b57cec5SDimitry Andric // Require that GC be specified and set to eImageInfo_GarbageCollected.
51260b57cec5SDimitry Andric llvm::Metadata *Ops[2] = {
51270b57cec5SDimitry Andric llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
51280b57cec5SDimitry Andric llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
51295ffd83dbSDimitry Andric Int8Ty, eImageInfo_GarbageCollected))};
51300b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
51310b57cec5SDimitry Andric llvm::MDNode::get(VMContext, Ops));
51320b57cec5SDimitry Andric }
51330b57cec5SDimitry Andric }
51340b57cec5SDimitry Andric
51350b57cec5SDimitry Andric // Indicate whether we're compiling this to run on a simulator.
51360b57cec5SDimitry Andric if (CGM.getTarget().getTriple().isSimulatorEnvironment())
51370b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
51380b57cec5SDimitry Andric eImageInfo_ImageIsSimulated);
51390b57cec5SDimitry Andric
51400b57cec5SDimitry Andric // Indicate whether we are generating class properties.
51410b57cec5SDimitry Andric Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
51420b57cec5SDimitry Andric eImageInfo_ClassProperties);
51430b57cec5SDimitry Andric }
51440b57cec5SDimitry Andric
51450b57cec5SDimitry Andric // struct objc_module {
51460b57cec5SDimitry Andric // unsigned long version;
51470b57cec5SDimitry Andric // unsigned long size;
51480b57cec5SDimitry Andric // const char *name;
51490b57cec5SDimitry Andric // Symtab symtab;
51500b57cec5SDimitry Andric // };
51510b57cec5SDimitry Andric
51520b57cec5SDimitry Andric // FIXME: Get from somewhere
51530b57cec5SDimitry Andric static const int ModuleVersion = 7;
51540b57cec5SDimitry Andric
EmitModuleInfo()51550b57cec5SDimitry Andric void CGObjCMac::EmitModuleInfo() {
51560b57cec5SDimitry Andric uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
51570b57cec5SDimitry Andric
51580b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
51590b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ModuleTy);
51600b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, ModuleVersion);
51610b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, Size);
51620b57cec5SDimitry Andric // This used to be the filename, now it is unused. <rdr://4327263>
51630b57cec5SDimitry Andric values.add(GetClassName(StringRef("")));
51640b57cec5SDimitry Andric values.add(EmitModuleSymbols());
51650b57cec5SDimitry Andric CreateMetadataVar("OBJC_MODULES", values,
51660b57cec5SDimitry Andric "__OBJC,__module_info,regular,no_dead_strip",
51670b57cec5SDimitry Andric CGM.getPointerAlign(), true);
51680b57cec5SDimitry Andric }
51690b57cec5SDimitry Andric
EmitModuleSymbols()51700b57cec5SDimitry Andric llvm::Constant *CGObjCMac::EmitModuleSymbols() {
51710b57cec5SDimitry Andric unsigned NumClasses = DefinedClasses.size();
51720b57cec5SDimitry Andric unsigned NumCategories = DefinedCategories.size();
51730b57cec5SDimitry Andric
51740b57cec5SDimitry Andric // Return null if no symbols were defined.
51750b57cec5SDimitry Andric if (!NumClasses && !NumCategories)
51760b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
51770b57cec5SDimitry Andric
51780b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
51790b57cec5SDimitry Andric auto values = builder.beginStruct();
51800b57cec5SDimitry Andric values.addInt(ObjCTypes.LongTy, 0);
51810b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.SelectorPtrTy);
51820b57cec5SDimitry Andric values.addInt(ObjCTypes.ShortTy, NumClasses);
51830b57cec5SDimitry Andric values.addInt(ObjCTypes.ShortTy, NumCategories);
51840b57cec5SDimitry Andric
51850b57cec5SDimitry Andric // The runtime expects exactly the list of defined classes followed
51860b57cec5SDimitry Andric // by the list of defined categories, in a single array.
51870b57cec5SDimitry Andric auto array = values.beginArray(ObjCTypes.Int8PtrTy);
51880b57cec5SDimitry Andric for (unsigned i=0; i<NumClasses; i++) {
51890b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = ImplementedClasses[i];
51900b57cec5SDimitry Andric assert(ID);
51910b57cec5SDimitry Andric if (ObjCImplementationDecl *IMP = ID->getImplementation())
51920b57cec5SDimitry Andric // We are implementing a weak imported interface. Give it external linkage
51930b57cec5SDimitry Andric if (ID->isWeakImported() && !IMP->isWeakImported())
51940b57cec5SDimitry Andric DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
51950b57cec5SDimitry Andric
51965f757f3fSDimitry Andric array.add(DefinedClasses[i]);
51970b57cec5SDimitry Andric }
51980b57cec5SDimitry Andric for (unsigned i=0; i<NumCategories; i++)
51995f757f3fSDimitry Andric array.add(DefinedCategories[i]);
52000b57cec5SDimitry Andric
52010b57cec5SDimitry Andric array.finishAndAddTo(values);
52020b57cec5SDimitry Andric
52030b57cec5SDimitry Andric llvm::GlobalVariable *GV = CreateMetadataVar(
52040b57cec5SDimitry Andric "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
52050b57cec5SDimitry Andric CGM.getPointerAlign(), true);
52065f757f3fSDimitry Andric return GV;
52070b57cec5SDimitry Andric }
52080b57cec5SDimitry Andric
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II)52090b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
52100b57cec5SDimitry Andric IdentifierInfo *II) {
52110b57cec5SDimitry Andric LazySymbols.insert(II);
52120b57cec5SDimitry Andric
52130b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = ClassReferences[II];
52140b57cec5SDimitry Andric
52150b57cec5SDimitry Andric if (!Entry) {
52165f757f3fSDimitry Andric Entry =
52175f757f3fSDimitry Andric CreateMetadataVar("OBJC_CLASS_REFERENCES_", GetClassName(II->getName()),
52180b57cec5SDimitry Andric "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
52190b57cec5SDimitry Andric CGM.getPointerAlign(), true);
52200b57cec5SDimitry Andric }
52210b57cec5SDimitry Andric
5222fe6060f1SDimitry Andric return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5223fe6060f1SDimitry Andric CGF.getPointerAlign());
52240b57cec5SDimitry Andric }
52250b57cec5SDimitry Andric
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)52260b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
52270b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
52280b57cec5SDimitry Andric // If the class has the objc_runtime_visible attribute, we need to
52290b57cec5SDimitry Andric // use the Objective-C runtime to get the class.
52300b57cec5SDimitry Andric if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
52310b57cec5SDimitry Andric return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
52320b57cec5SDimitry Andric
52330b57cec5SDimitry Andric IdentifierInfo *RuntimeName =
52340b57cec5SDimitry Andric &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
52350b57cec5SDimitry Andric return EmitClassRefFromId(CGF, RuntimeName);
52360b57cec5SDimitry Andric }
52370b57cec5SDimitry Andric
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)52380b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
52390b57cec5SDimitry Andric IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
52400b57cec5SDimitry Andric return EmitClassRefFromId(CGF, II);
52410b57cec5SDimitry Andric }
52420b57cec5SDimitry Andric
EmitSelector(CodeGenFunction & CGF,Selector Sel)52430b57cec5SDimitry Andric llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5244480093f4SDimitry Andric return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
52450b57cec5SDimitry Andric }
52460b57cec5SDimitry Andric
EmitSelectorAddr(Selector Sel)5247*0fca6ea1SDimitry Andric ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5248480093f4SDimitry Andric CharUnits Align = CGM.getPointerAlign();
52490b57cec5SDimitry Andric
52500b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
52510b57cec5SDimitry Andric if (!Entry) {
52520b57cec5SDimitry Andric Entry = CreateMetadataVar(
52535f757f3fSDimitry Andric "OBJC_SELECTOR_REFERENCES_", GetMethodVarName(Sel),
52540b57cec5SDimitry Andric "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
52550b57cec5SDimitry Andric Entry->setExternallyInitialized(true);
52560b57cec5SDimitry Andric }
52570b57cec5SDimitry Andric
5258*0fca6ea1SDimitry Andric return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
52590b57cec5SDimitry Andric }
52600b57cec5SDimitry Andric
GetClassName(StringRef RuntimeName)52610b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
52620b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
52630b57cec5SDimitry Andric if (!Entry)
52640b57cec5SDimitry Andric Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
52650b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
52660b57cec5SDimitry Andric }
52670b57cec5SDimitry Andric
GetMethodDefinition(const ObjCMethodDecl * MD)52680b57cec5SDimitry Andric llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
526906c3fb27SDimitry Andric return MethodDefinitions.lookup(MD);
52700b57cec5SDimitry Andric }
52710b57cec5SDimitry Andric
52720b57cec5SDimitry Andric /// GetIvarLayoutName - Returns a unique constant for the given
52730b57cec5SDimitry Andric /// ivar layout bitmap.
GetIvarLayoutName(IdentifierInfo * Ident,const ObjCCommonTypesHelper & ObjCTypes)52740b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
52750b57cec5SDimitry Andric const ObjCCommonTypesHelper &ObjCTypes) {
52760b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
52770b57cec5SDimitry Andric }
52780b57cec5SDimitry Andric
visitRecord(const RecordType * RT,CharUnits offset)52790b57cec5SDimitry Andric void IvarLayoutBuilder::visitRecord(const RecordType *RT,
52800b57cec5SDimitry Andric CharUnits offset) {
52810b57cec5SDimitry Andric const RecordDecl *RD = RT->getDecl();
52820b57cec5SDimitry Andric
52830b57cec5SDimitry Andric // If this is a union, remember that we had one, because it might mess
52840b57cec5SDimitry Andric // up the ordering of layout entries.
52850b57cec5SDimitry Andric if (RD->isUnion())
52860b57cec5SDimitry Andric IsDisordered = true;
52870b57cec5SDimitry Andric
52880b57cec5SDimitry Andric const ASTRecordLayout *recLayout = nullptr;
52890b57cec5SDimitry Andric visitAggregate(RD->field_begin(), RD->field_end(), offset,
52900b57cec5SDimitry Andric [&](const FieldDecl *field) -> CharUnits {
52910b57cec5SDimitry Andric if (!recLayout)
52920b57cec5SDimitry Andric recLayout = &CGM.getContext().getASTRecordLayout(RD);
52930b57cec5SDimitry Andric auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
52940b57cec5SDimitry Andric return CGM.getContext().toCharUnitsFromBits(offsetInBits);
52950b57cec5SDimitry Andric });
52960b57cec5SDimitry Andric }
52970b57cec5SDimitry Andric
52980b57cec5SDimitry Andric template <class Iterator, class GetOffsetFn>
visitAggregate(Iterator begin,Iterator end,CharUnits aggregateOffset,const GetOffsetFn & getOffset)52990b57cec5SDimitry Andric void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
53000b57cec5SDimitry Andric CharUnits aggregateOffset,
53010b57cec5SDimitry Andric const GetOffsetFn &getOffset) {
53020b57cec5SDimitry Andric for (; begin != end; ++begin) {
53030b57cec5SDimitry Andric auto field = *begin;
53040b57cec5SDimitry Andric
53050b57cec5SDimitry Andric // Skip over bitfields.
53060b57cec5SDimitry Andric if (field->isBitField()) {
53070b57cec5SDimitry Andric continue;
53080b57cec5SDimitry Andric }
53090b57cec5SDimitry Andric
53100b57cec5SDimitry Andric // Compute the offset of the field within the aggregate.
53110b57cec5SDimitry Andric CharUnits fieldOffset = aggregateOffset + getOffset(field);
53120b57cec5SDimitry Andric
53130b57cec5SDimitry Andric visitField(field, fieldOffset);
53140b57cec5SDimitry Andric }
53150b57cec5SDimitry Andric }
53160b57cec5SDimitry Andric
53170b57cec5SDimitry Andric /// Collect layout information for the given fields into IvarsInfo.
visitField(const FieldDecl * field,CharUnits fieldOffset)53180b57cec5SDimitry Andric void IvarLayoutBuilder::visitField(const FieldDecl *field,
53190b57cec5SDimitry Andric CharUnits fieldOffset) {
53200b57cec5SDimitry Andric QualType fieldType = field->getType();
53210b57cec5SDimitry Andric
53220b57cec5SDimitry Andric // Drill down into arrays.
53230b57cec5SDimitry Andric uint64_t numElts = 1;
53240b57cec5SDimitry Andric if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
53250b57cec5SDimitry Andric numElts = 0;
53260b57cec5SDimitry Andric fieldType = arrayType->getElementType();
53270b57cec5SDimitry Andric }
53280b57cec5SDimitry Andric // Unlike incomplete arrays, constant arrays can be nested.
53290b57cec5SDimitry Andric while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5330*0fca6ea1SDimitry Andric numElts *= arrayType->getZExtSize();
53310b57cec5SDimitry Andric fieldType = arrayType->getElementType();
53320b57cec5SDimitry Andric }
53330b57cec5SDimitry Andric
53340b57cec5SDimitry Andric assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
53350b57cec5SDimitry Andric
53360b57cec5SDimitry Andric // If we ended up with a zero-sized array, we've done what we can do within
53370b57cec5SDimitry Andric // the limits of this layout encoding.
53380b57cec5SDimitry Andric if (numElts == 0) return;
53390b57cec5SDimitry Andric
53400b57cec5SDimitry Andric // Recurse if the base element type is a record type.
53410b57cec5SDimitry Andric if (auto recType = fieldType->getAs<RecordType>()) {
53420b57cec5SDimitry Andric size_t oldEnd = IvarsInfo.size();
53430b57cec5SDimitry Andric
53440b57cec5SDimitry Andric visitRecord(recType, fieldOffset);
53450b57cec5SDimitry Andric
53460b57cec5SDimitry Andric // If we have an array, replicate the first entry's layout information.
53470b57cec5SDimitry Andric auto numEltEntries = IvarsInfo.size() - oldEnd;
53480b57cec5SDimitry Andric if (numElts != 1 && numEltEntries != 0) {
53490b57cec5SDimitry Andric CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
53500b57cec5SDimitry Andric for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
53510b57cec5SDimitry Andric // Copy the last numEltEntries onto the end of the array, adjusting
53520b57cec5SDimitry Andric // each for the element size.
53530b57cec5SDimitry Andric for (size_t i = 0; i != numEltEntries; ++i) {
53540b57cec5SDimitry Andric auto firstEntry = IvarsInfo[oldEnd + i];
53550b57cec5SDimitry Andric IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
53560b57cec5SDimitry Andric firstEntry.SizeInWords));
53570b57cec5SDimitry Andric }
53580b57cec5SDimitry Andric }
53590b57cec5SDimitry Andric }
53600b57cec5SDimitry Andric
53610b57cec5SDimitry Andric return;
53620b57cec5SDimitry Andric }
53630b57cec5SDimitry Andric
53640b57cec5SDimitry Andric // Classify the element type.
53650b57cec5SDimitry Andric Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
53660b57cec5SDimitry Andric
53670b57cec5SDimitry Andric // If it matches what we're looking for, add an entry.
53680b57cec5SDimitry Andric if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
53690b57cec5SDimitry Andric || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
53700b57cec5SDimitry Andric assert(CGM.getContext().getTypeSizeInChars(fieldType)
53710b57cec5SDimitry Andric == CGM.getPointerSize());
53720b57cec5SDimitry Andric IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
53730b57cec5SDimitry Andric }
53740b57cec5SDimitry Andric }
53750b57cec5SDimitry Andric
53760b57cec5SDimitry Andric /// buildBitmap - This routine does the horsework of taking the offsets of
53770b57cec5SDimitry Andric /// strong/weak references and creating a bitmap. The bitmap is also
53780b57cec5SDimitry Andric /// returned in the given buffer, suitable for being passed to \c dump().
buildBitmap(CGObjCCommonMac & CGObjC,llvm::SmallVectorImpl<unsigned char> & buffer)53790b57cec5SDimitry Andric llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
53800b57cec5SDimitry Andric llvm::SmallVectorImpl<unsigned char> &buffer) {
53810b57cec5SDimitry Andric // The bitmap is a series of skip/scan instructions, aligned to word
53820b57cec5SDimitry Andric // boundaries. The skip is performed first.
53830b57cec5SDimitry Andric const unsigned char MaxNibble = 0xF;
53840b57cec5SDimitry Andric const unsigned char SkipMask = 0xF0, SkipShift = 4;
53850b57cec5SDimitry Andric const unsigned char ScanMask = 0x0F, ScanShift = 0;
53860b57cec5SDimitry Andric
53870b57cec5SDimitry Andric assert(!IvarsInfo.empty() && "generating bitmap for no data");
53880b57cec5SDimitry Andric
53890b57cec5SDimitry Andric // Sort the ivar info on byte position in case we encounterred a
53900b57cec5SDimitry Andric // union nested in the ivar list.
53910b57cec5SDimitry Andric if (IsDisordered) {
53920b57cec5SDimitry Andric // This isn't a stable sort, but our algorithm should handle it fine.
53930b57cec5SDimitry Andric llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
53940b57cec5SDimitry Andric } else {
53955ffd83dbSDimitry Andric assert(llvm::is_sorted(IvarsInfo));
53960b57cec5SDimitry Andric }
53970b57cec5SDimitry Andric assert(IvarsInfo.back().Offset < InstanceEnd);
53980b57cec5SDimitry Andric
53990b57cec5SDimitry Andric assert(buffer.empty());
54000b57cec5SDimitry Andric
54010b57cec5SDimitry Andric // Skip the next N words.
54020b57cec5SDimitry Andric auto skip = [&](unsigned numWords) {
54030b57cec5SDimitry Andric assert(numWords > 0);
54040b57cec5SDimitry Andric
54050b57cec5SDimitry Andric // Try to merge into the previous byte. Since scans happen second, we
54060b57cec5SDimitry Andric // can't do this if it includes a scan.
54070b57cec5SDimitry Andric if (!buffer.empty() && !(buffer.back() & ScanMask)) {
54080b57cec5SDimitry Andric unsigned lastSkip = buffer.back() >> SkipShift;
54090b57cec5SDimitry Andric if (lastSkip < MaxNibble) {
54100b57cec5SDimitry Andric unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
54110b57cec5SDimitry Andric numWords -= claimed;
54120b57cec5SDimitry Andric lastSkip += claimed;
54130b57cec5SDimitry Andric buffer.back() = (lastSkip << SkipShift);
54140b57cec5SDimitry Andric }
54150b57cec5SDimitry Andric }
54160b57cec5SDimitry Andric
54170b57cec5SDimitry Andric while (numWords >= MaxNibble) {
54180b57cec5SDimitry Andric buffer.push_back(MaxNibble << SkipShift);
54190b57cec5SDimitry Andric numWords -= MaxNibble;
54200b57cec5SDimitry Andric }
54210b57cec5SDimitry Andric if (numWords) {
54220b57cec5SDimitry Andric buffer.push_back(numWords << SkipShift);
54230b57cec5SDimitry Andric }
54240b57cec5SDimitry Andric };
54250b57cec5SDimitry Andric
54260b57cec5SDimitry Andric // Scan the next N words.
54270b57cec5SDimitry Andric auto scan = [&](unsigned numWords) {
54280b57cec5SDimitry Andric assert(numWords > 0);
54290b57cec5SDimitry Andric
54300b57cec5SDimitry Andric // Try to merge into the previous byte. Since scans happen second, we can
54310b57cec5SDimitry Andric // do this even if it includes a skip.
54320b57cec5SDimitry Andric if (!buffer.empty()) {
54330b57cec5SDimitry Andric unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
54340b57cec5SDimitry Andric if (lastScan < MaxNibble) {
54350b57cec5SDimitry Andric unsigned claimed = std::min(MaxNibble - lastScan, numWords);
54360b57cec5SDimitry Andric numWords -= claimed;
54370b57cec5SDimitry Andric lastScan += claimed;
54380b57cec5SDimitry Andric buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
54390b57cec5SDimitry Andric }
54400b57cec5SDimitry Andric }
54410b57cec5SDimitry Andric
54420b57cec5SDimitry Andric while (numWords >= MaxNibble) {
54430b57cec5SDimitry Andric buffer.push_back(MaxNibble << ScanShift);
54440b57cec5SDimitry Andric numWords -= MaxNibble;
54450b57cec5SDimitry Andric }
54460b57cec5SDimitry Andric if (numWords) {
54470b57cec5SDimitry Andric buffer.push_back(numWords << ScanShift);
54480b57cec5SDimitry Andric }
54490b57cec5SDimitry Andric };
54500b57cec5SDimitry Andric
54510b57cec5SDimitry Andric // One past the end of the last scan.
54520b57cec5SDimitry Andric unsigned endOfLastScanInWords = 0;
54530b57cec5SDimitry Andric const CharUnits WordSize = CGM.getPointerSize();
54540b57cec5SDimitry Andric
54550b57cec5SDimitry Andric // Consider all the scan requests.
54560b57cec5SDimitry Andric for (auto &request : IvarsInfo) {
54570b57cec5SDimitry Andric CharUnits beginOfScan = request.Offset - InstanceBegin;
54580b57cec5SDimitry Andric
54590b57cec5SDimitry Andric // Ignore scan requests that don't start at an even multiple of the
54600b57cec5SDimitry Andric // word size. We can't encode them.
54610b57cec5SDimitry Andric if ((beginOfScan % WordSize) != 0) continue;
54620b57cec5SDimitry Andric
54630b57cec5SDimitry Andric // Ignore scan requests that start before the instance start.
54640b57cec5SDimitry Andric // This assumes that scans never span that boundary. The boundary
54650b57cec5SDimitry Andric // isn't the true start of the ivars, because in the fragile-ARC case
54660b57cec5SDimitry Andric // it's rounded up to word alignment, but the test above should leave
54670b57cec5SDimitry Andric // us ignoring that possibility.
54680b57cec5SDimitry Andric if (beginOfScan.isNegative()) {
54690b57cec5SDimitry Andric assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
54700b57cec5SDimitry Andric continue;
54710b57cec5SDimitry Andric }
54720b57cec5SDimitry Andric
54730b57cec5SDimitry Andric unsigned beginOfScanInWords = beginOfScan / WordSize;
54740b57cec5SDimitry Andric unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
54750b57cec5SDimitry Andric
54760b57cec5SDimitry Andric // If the scan starts some number of words after the last one ended,
54770b57cec5SDimitry Andric // skip forward.
54780b57cec5SDimitry Andric if (beginOfScanInWords > endOfLastScanInWords) {
54790b57cec5SDimitry Andric skip(beginOfScanInWords - endOfLastScanInWords);
54800b57cec5SDimitry Andric
54810b57cec5SDimitry Andric // Otherwise, start scanning where the last left off.
54820b57cec5SDimitry Andric } else {
54830b57cec5SDimitry Andric beginOfScanInWords = endOfLastScanInWords;
54840b57cec5SDimitry Andric
54850b57cec5SDimitry Andric // If that leaves us with nothing to scan, ignore this request.
54860b57cec5SDimitry Andric if (beginOfScanInWords >= endOfScanInWords) continue;
54870b57cec5SDimitry Andric }
54880b57cec5SDimitry Andric
54890b57cec5SDimitry Andric // Scan to the end of the request.
54900b57cec5SDimitry Andric assert(beginOfScanInWords < endOfScanInWords);
54910b57cec5SDimitry Andric scan(endOfScanInWords - beginOfScanInWords);
54920b57cec5SDimitry Andric endOfLastScanInWords = endOfScanInWords;
54930b57cec5SDimitry Andric }
54940b57cec5SDimitry Andric
54950b57cec5SDimitry Andric if (buffer.empty())
54960b57cec5SDimitry Andric return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
54970b57cec5SDimitry Andric
54980b57cec5SDimitry Andric // For GC layouts, emit a skip to the end of the allocation so that we
54990b57cec5SDimitry Andric // have precise information about the entire thing. This isn't useful
55000b57cec5SDimitry Andric // or necessary for the ARC-style layout strings.
55010b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
55020b57cec5SDimitry Andric unsigned lastOffsetInWords =
55030b57cec5SDimitry Andric (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
55040b57cec5SDimitry Andric if (lastOffsetInWords > endOfLastScanInWords) {
55050b57cec5SDimitry Andric skip(lastOffsetInWords - endOfLastScanInWords);
55060b57cec5SDimitry Andric }
55070b57cec5SDimitry Andric }
55080b57cec5SDimitry Andric
55090b57cec5SDimitry Andric // Null terminate the string.
55100b57cec5SDimitry Andric buffer.push_back(0);
55110b57cec5SDimitry Andric
55120b57cec5SDimitry Andric auto *Entry = CGObjC.CreateCStringLiteral(
55130b57cec5SDimitry Andric reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
55140b57cec5SDimitry Andric return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
55150b57cec5SDimitry Andric }
55160b57cec5SDimitry Andric
55170b57cec5SDimitry Andric /// BuildIvarLayout - Builds ivar layout bitmap for the class
55180b57cec5SDimitry Andric /// implementation for the __strong or __weak case.
55190b57cec5SDimitry Andric /// The layout map displays which words in ivar list must be skipped
55200b57cec5SDimitry Andric /// and which must be scanned by GC (see below). String is built of bytes.
55210b57cec5SDimitry Andric /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
55220b57cec5SDimitry Andric /// of words to skip and right nibble is count of words to scan. So, each
55230b57cec5SDimitry Andric /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
55240b57cec5SDimitry Andric /// represented by a 0x00 byte which also ends the string.
55250b57cec5SDimitry Andric /// 1. when ForStrongLayout is true, following ivars are scanned:
55260b57cec5SDimitry Andric /// - id, Class
55270b57cec5SDimitry Andric /// - object *
55280b57cec5SDimitry Andric /// - __strong anything
55290b57cec5SDimitry Andric ///
55300b57cec5SDimitry Andric /// 2. When ForStrongLayout is false, following ivars are scanned:
55310b57cec5SDimitry Andric /// - __weak anything
55320b57cec5SDimitry Andric ///
55330b57cec5SDimitry Andric llvm::Constant *
BuildIvarLayout(const ObjCImplementationDecl * OMD,CharUnits beginOffset,CharUnits endOffset,bool ForStrongLayout,bool HasMRCWeakIvars)55340b57cec5SDimitry Andric CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
55350b57cec5SDimitry Andric CharUnits beginOffset, CharUnits endOffset,
55360b57cec5SDimitry Andric bool ForStrongLayout, bool HasMRCWeakIvars) {
55370b57cec5SDimitry Andric // If this is MRC, and we're either building a strong layout or there
55380b57cec5SDimitry Andric // are no weak ivars, bail out early.
55390b57cec5SDimitry Andric llvm::Type *PtrTy = CGM.Int8PtrTy;
55400b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
55410b57cec5SDimitry Andric !CGM.getLangOpts().ObjCAutoRefCount &&
55420b57cec5SDimitry Andric (ForStrongLayout || !HasMRCWeakIvars))
55430b57cec5SDimitry Andric return llvm::Constant::getNullValue(PtrTy);
55440b57cec5SDimitry Andric
55450b57cec5SDimitry Andric const ObjCInterfaceDecl *OI = OMD->getClassInterface();
55460b57cec5SDimitry Andric SmallVector<const ObjCIvarDecl*, 32> ivars;
55470b57cec5SDimitry Andric
55480b57cec5SDimitry Andric // GC layout strings include the complete object layout, possibly
55490b57cec5SDimitry Andric // inaccurately in the non-fragile ABI; the runtime knows how to fix this
55500b57cec5SDimitry Andric // up.
55510b57cec5SDimitry Andric //
55520b57cec5SDimitry Andric // ARC layout strings only include the class's ivars. In non-fragile
55530b57cec5SDimitry Andric // runtimes, that means starting at InstanceStart, rounded up to word
55540b57cec5SDimitry Andric // alignment. In fragile runtimes, there's no InstanceStart, so it means
55550b57cec5SDimitry Andric // starting at the offset of the first ivar, rounded up to word alignment.
55560b57cec5SDimitry Andric //
55570b57cec5SDimitry Andric // MRC weak layout strings follow the ARC style.
55580b57cec5SDimitry Andric CharUnits baseOffset;
55590b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
55600b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
55610b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar())
55620b57cec5SDimitry Andric ivars.push_back(IVD);
55630b57cec5SDimitry Andric
55640b57cec5SDimitry Andric if (isNonFragileABI()) {
55650b57cec5SDimitry Andric baseOffset = beginOffset; // InstanceStart
55660b57cec5SDimitry Andric } else if (!ivars.empty()) {
55670b57cec5SDimitry Andric baseOffset =
55680b57cec5SDimitry Andric CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
55690b57cec5SDimitry Andric } else {
55700b57cec5SDimitry Andric baseOffset = CharUnits::Zero();
55710b57cec5SDimitry Andric }
55720b57cec5SDimitry Andric
55730b57cec5SDimitry Andric baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
55740b57cec5SDimitry Andric }
55750b57cec5SDimitry Andric else {
55760b57cec5SDimitry Andric CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
55770b57cec5SDimitry Andric
55780b57cec5SDimitry Andric baseOffset = CharUnits::Zero();
55790b57cec5SDimitry Andric }
55800b57cec5SDimitry Andric
55810b57cec5SDimitry Andric if (ivars.empty())
55820b57cec5SDimitry Andric return llvm::Constant::getNullValue(PtrTy);
55830b57cec5SDimitry Andric
55840b57cec5SDimitry Andric IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
55850b57cec5SDimitry Andric
55860b57cec5SDimitry Andric builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
55870b57cec5SDimitry Andric [&](const ObjCIvarDecl *ivar) -> CharUnits {
55880b57cec5SDimitry Andric return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
55890b57cec5SDimitry Andric });
55900b57cec5SDimitry Andric
55910b57cec5SDimitry Andric if (!builder.hasBitmapData())
55920b57cec5SDimitry Andric return llvm::Constant::getNullValue(PtrTy);
55930b57cec5SDimitry Andric
55940b57cec5SDimitry Andric llvm::SmallVector<unsigned char, 4> buffer;
55950b57cec5SDimitry Andric llvm::Constant *C = builder.buildBitmap(*this, buffer);
55960b57cec5SDimitry Andric
55970b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
55980b57cec5SDimitry Andric printf("\n%s ivar layout for class '%s': ",
55990b57cec5SDimitry Andric ForStrongLayout ? "strong" : "weak",
56000b57cec5SDimitry Andric OMD->getClassInterface()->getName().str().c_str());
56010b57cec5SDimitry Andric builder.dump(buffer);
56020b57cec5SDimitry Andric }
56030b57cec5SDimitry Andric return C;
56040b57cec5SDimitry Andric }
56050b57cec5SDimitry Andric
GetMethodVarName(Selector Sel)56060b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
56070b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
56080b57cec5SDimitry Andric // FIXME: Avoid std::string in "Sel.getAsString()"
56090b57cec5SDimitry Andric if (!Entry)
56100b57cec5SDimitry Andric Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
56110b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
56120b57cec5SDimitry Andric }
56130b57cec5SDimitry Andric
56140b57cec5SDimitry Andric // FIXME: Merge into a single cstring creation function.
GetMethodVarName(IdentifierInfo * ID)56150b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
56160b57cec5SDimitry Andric return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
56170b57cec5SDimitry Andric }
56180b57cec5SDimitry Andric
GetMethodVarType(const FieldDecl * Field)56190b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
56200b57cec5SDimitry Andric std::string TypeStr;
56210b57cec5SDimitry Andric CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
56220b57cec5SDimitry Andric
56230b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
56240b57cec5SDimitry Andric if (!Entry)
56250b57cec5SDimitry Andric Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
56260b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
56270b57cec5SDimitry Andric }
56280b57cec5SDimitry Andric
GetMethodVarType(const ObjCMethodDecl * D,bool Extended)56290b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
56300b57cec5SDimitry Andric bool Extended) {
56310b57cec5SDimitry Andric std::string TypeStr =
56320b57cec5SDimitry Andric CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
56330b57cec5SDimitry Andric
56340b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
56350b57cec5SDimitry Andric if (!Entry)
56360b57cec5SDimitry Andric Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
56370b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
56380b57cec5SDimitry Andric }
56390b57cec5SDimitry Andric
56400b57cec5SDimitry Andric // FIXME: Merge into a single cstring creation function.
GetPropertyName(IdentifierInfo * Ident)56410b57cec5SDimitry Andric llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
56420b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = PropertyNames[Ident];
56430b57cec5SDimitry Andric if (!Entry)
56440b57cec5SDimitry Andric Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
56450b57cec5SDimitry Andric return getConstantGEP(VMContext, Entry, 0, 0);
56460b57cec5SDimitry Andric }
56470b57cec5SDimitry Andric
56480b57cec5SDimitry Andric // FIXME: Merge into a single cstring creation function.
56490b57cec5SDimitry Andric // FIXME: This Decl should be more precise.
56500b57cec5SDimitry Andric llvm::Constant *
GetPropertyTypeString(const ObjCPropertyDecl * PD,const Decl * Container)56510b57cec5SDimitry Andric CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
56520b57cec5SDimitry Andric const Decl *Container) {
56530b57cec5SDimitry Andric std::string TypeStr =
56540b57cec5SDimitry Andric CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
56550b57cec5SDimitry Andric return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
56560b57cec5SDimitry Andric }
56570b57cec5SDimitry Andric
FinishModule()56580b57cec5SDimitry Andric void CGObjCMac::FinishModule() {
56590b57cec5SDimitry Andric EmitModuleInfo();
56600b57cec5SDimitry Andric
56610b57cec5SDimitry Andric // Emit the dummy bodies for any protocols which were referenced but
56620b57cec5SDimitry Andric // never defined.
56630b57cec5SDimitry Andric for (auto &entry : Protocols) {
56640b57cec5SDimitry Andric llvm::GlobalVariable *global = entry.second;
56650b57cec5SDimitry Andric if (global->hasInitializer())
56660b57cec5SDimitry Andric continue;
56670b57cec5SDimitry Andric
56680b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
56690b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
56700b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
56710b57cec5SDimitry Andric values.add(GetClassName(entry.first->getName()));
56720b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
56730b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
56740b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
56750b57cec5SDimitry Andric values.finishAndSetAsInitializer(global);
56760b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(global);
56770b57cec5SDimitry Andric }
56780b57cec5SDimitry Andric
56790b57cec5SDimitry Andric // Add assembler directives to add lazy undefined symbol references
56800b57cec5SDimitry Andric // for classes which are referenced but not defined. This is
56810b57cec5SDimitry Andric // important for correct linker interaction.
56820b57cec5SDimitry Andric //
56830b57cec5SDimitry Andric // FIXME: It would be nice if we had an LLVM construct for this.
56840b57cec5SDimitry Andric if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
56850b57cec5SDimitry Andric CGM.getTriple().isOSBinFormatMachO()) {
56860b57cec5SDimitry Andric SmallString<256> Asm;
56870b57cec5SDimitry Andric Asm += CGM.getModule().getModuleInlineAsm();
56880b57cec5SDimitry Andric if (!Asm.empty() && Asm.back() != '\n')
56890b57cec5SDimitry Andric Asm += '\n';
56900b57cec5SDimitry Andric
56910b57cec5SDimitry Andric llvm::raw_svector_ostream OS(Asm);
56920b57cec5SDimitry Andric for (const auto *Sym : DefinedSymbols)
56930b57cec5SDimitry Andric OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
56940b57cec5SDimitry Andric << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
56950b57cec5SDimitry Andric for (const auto *Sym : LazySymbols)
56960b57cec5SDimitry Andric OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
56970b57cec5SDimitry Andric for (const auto &Category : DefinedCategoryNames)
56980b57cec5SDimitry Andric OS << "\t.objc_category_name_" << Category << "=0\n"
56990b57cec5SDimitry Andric << "\t.globl .objc_category_name_" << Category << "\n";
57000b57cec5SDimitry Andric
57010b57cec5SDimitry Andric CGM.getModule().setModuleInlineAsm(OS.str());
57020b57cec5SDimitry Andric }
57030b57cec5SDimitry Andric }
57040b57cec5SDimitry Andric
CGObjCNonFragileABIMac(CodeGen::CodeGenModule & cgm)57050b57cec5SDimitry Andric CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
57060b57cec5SDimitry Andric : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
57070b57cec5SDimitry Andric ObjCEmptyVtableVar(nullptr) {
57080b57cec5SDimitry Andric ObjCABI = 2;
57090b57cec5SDimitry Andric }
57100b57cec5SDimitry Andric
57110b57cec5SDimitry Andric /* *** */
57120b57cec5SDimitry Andric
ObjCCommonTypesHelper(CodeGen::CodeGenModule & cgm)57130b57cec5SDimitry Andric ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
57140b57cec5SDimitry Andric : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
57150b57cec5SDimitry Andric {
57160b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
57170b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
5718bdd1243dSDimitry Andric unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
57190b57cec5SDimitry Andric
57200b57cec5SDimitry Andric ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
57210b57cec5SDimitry Andric IntTy = CGM.IntTy;
57220b57cec5SDimitry Andric LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
57230b57cec5SDimitry Andric Int8PtrTy = CGM.Int8PtrTy;
5724bdd1243dSDimitry Andric Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
57250b57cec5SDimitry Andric Int8PtrPtrTy = CGM.Int8PtrPtrTy;
57260b57cec5SDimitry Andric
57270b57cec5SDimitry Andric // arm64 targets use "int" ivar offset variables. All others,
57280b57cec5SDimitry Andric // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
57290b57cec5SDimitry Andric if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
57300b57cec5SDimitry Andric IvarOffsetVarTy = IntTy;
57310b57cec5SDimitry Andric else
57320b57cec5SDimitry Andric IvarOffsetVarTy = LongTy;
57330b57cec5SDimitry Andric
57340b57cec5SDimitry Andric ObjectPtrTy =
57350b57cec5SDimitry Andric cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
57360b57cec5SDimitry Andric PtrObjectPtrTy =
57370b57cec5SDimitry Andric llvm::PointerType::getUnqual(ObjectPtrTy);
57380b57cec5SDimitry Andric SelectorPtrTy =
57390b57cec5SDimitry Andric cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
57400b57cec5SDimitry Andric
57410b57cec5SDimitry Andric // I'm not sure I like this. The implicit coordination is a bit
57420b57cec5SDimitry Andric // gross. We should solve this in a reasonable fashion because this
57430b57cec5SDimitry Andric // is a pretty common task (match some runtime data structure with
57440b57cec5SDimitry Andric // an LLVM data structure).
57450b57cec5SDimitry Andric
57460b57cec5SDimitry Andric // FIXME: This is leaked.
57470b57cec5SDimitry Andric // FIXME: Merge with rewriter code?
57480b57cec5SDimitry Andric
57490b57cec5SDimitry Andric // struct _objc_super {
57500b57cec5SDimitry Andric // id self;
57510b57cec5SDimitry Andric // Class cls;
57520b57cec5SDimitry Andric // }
57535f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(
57545f757f3fSDimitry Andric Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
57555f757f3fSDimitry Andric SourceLocation(), &Ctx.Idents.get("_objc_super"));
57560b57cec5SDimitry Andric RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
57570b57cec5SDimitry Andric nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
57580b57cec5SDimitry Andric false, ICIS_NoInit));
57590b57cec5SDimitry Andric RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
57600b57cec5SDimitry Andric nullptr, Ctx.getObjCClassType(), nullptr,
57610b57cec5SDimitry Andric nullptr, false, ICIS_NoInit));
57620b57cec5SDimitry Andric RD->completeDefinition();
57630b57cec5SDimitry Andric
57640b57cec5SDimitry Andric SuperCTy = Ctx.getTagDeclType(RD);
57650b57cec5SDimitry Andric SuperPtrCTy = Ctx.getPointerType(SuperCTy);
57660b57cec5SDimitry Andric
57670b57cec5SDimitry Andric SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
57680b57cec5SDimitry Andric SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
57690b57cec5SDimitry Andric
57700b57cec5SDimitry Andric // struct _prop_t {
57710b57cec5SDimitry Andric // char *name;
57720b57cec5SDimitry Andric // char *attributes;
57730b57cec5SDimitry Andric // }
57740b57cec5SDimitry Andric PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);
57750b57cec5SDimitry Andric
57760b57cec5SDimitry Andric // struct _prop_list_t {
57770b57cec5SDimitry Andric // uint32_t entsize; // sizeof(struct _prop_t)
57780b57cec5SDimitry Andric // uint32_t count_of_properties;
57790b57cec5SDimitry Andric // struct _prop_t prop_list[count_of_properties];
57800b57cec5SDimitry Andric // }
57810b57cec5SDimitry Andric PropertyListTy = llvm::StructType::create(
57820b57cec5SDimitry Andric "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
57830b57cec5SDimitry Andric // struct _prop_list_t *
57840b57cec5SDimitry Andric PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
57850b57cec5SDimitry Andric
57860b57cec5SDimitry Andric // struct _objc_method {
57870b57cec5SDimitry Andric // SEL _cmd;
57880b57cec5SDimitry Andric // char *method_type;
57890b57cec5SDimitry Andric // char *_imp;
57900b57cec5SDimitry Andric // }
57910b57cec5SDimitry Andric MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
5792bdd1243dSDimitry Andric Int8PtrTy, Int8PtrProgramASTy);
57930b57cec5SDimitry Andric
57940b57cec5SDimitry Andric // struct _objc_cache *
57950b57cec5SDimitry Andric CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
57960b57cec5SDimitry Andric CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
57970b57cec5SDimitry Andric }
57980b57cec5SDimitry Andric
ObjCTypesHelper(CodeGen::CodeGenModule & cgm)57990b57cec5SDimitry Andric ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
58000b57cec5SDimitry Andric : ObjCCommonTypesHelper(cgm) {
58010b57cec5SDimitry Andric // struct _objc_method_description {
58020b57cec5SDimitry Andric // SEL name;
58030b57cec5SDimitry Andric // char *types;
58040b57cec5SDimitry Andric // }
58050b57cec5SDimitry Andric MethodDescriptionTy = llvm::StructType::create(
58060b57cec5SDimitry Andric "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);
58070b57cec5SDimitry Andric
58080b57cec5SDimitry Andric // struct _objc_method_description_list {
58090b57cec5SDimitry Andric // int count;
58100b57cec5SDimitry Andric // struct _objc_method_description[1];
58110b57cec5SDimitry Andric // }
58120b57cec5SDimitry Andric MethodDescriptionListTy =
58130b57cec5SDimitry Andric llvm::StructType::create("struct._objc_method_description_list", IntTy,
58140b57cec5SDimitry Andric llvm::ArrayType::get(MethodDescriptionTy, 0));
58150b57cec5SDimitry Andric
58160b57cec5SDimitry Andric // struct _objc_method_description_list *
58170b57cec5SDimitry Andric MethodDescriptionListPtrTy =
58180b57cec5SDimitry Andric llvm::PointerType::getUnqual(MethodDescriptionListTy);
58190b57cec5SDimitry Andric
58200b57cec5SDimitry Andric // Protocol description structures
58210b57cec5SDimitry Andric
58220b57cec5SDimitry Andric // struct _objc_protocol_extension {
58230b57cec5SDimitry Andric // uint32_t size; // sizeof(struct _objc_protocol_extension)
58240b57cec5SDimitry Andric // struct _objc_method_description_list *optional_instance_methods;
58250b57cec5SDimitry Andric // struct _objc_method_description_list *optional_class_methods;
58260b57cec5SDimitry Andric // struct _objc_property_list *instance_properties;
58270b57cec5SDimitry Andric // const char ** extendedMethodTypes;
58280b57cec5SDimitry Andric // struct _objc_property_list *class_properties;
58290b57cec5SDimitry Andric // }
58300b57cec5SDimitry Andric ProtocolExtensionTy = llvm::StructType::create(
58310b57cec5SDimitry Andric "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
58320b57cec5SDimitry Andric MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
58330b57cec5SDimitry Andric PropertyListPtrTy);
58340b57cec5SDimitry Andric
58350b57cec5SDimitry Andric // struct _objc_protocol_extension *
58360b57cec5SDimitry Andric ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
58370b57cec5SDimitry Andric
58380b57cec5SDimitry Andric // Handle recursive construction of Protocol and ProtocolList types
58390b57cec5SDimitry Andric
58400b57cec5SDimitry Andric ProtocolTy =
58410b57cec5SDimitry Andric llvm::StructType::create(VMContext, "struct._objc_protocol");
58420b57cec5SDimitry Andric
58430b57cec5SDimitry Andric ProtocolListTy =
58440b57cec5SDimitry Andric llvm::StructType::create(VMContext, "struct._objc_protocol_list");
58450b57cec5SDimitry Andric ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
58460b57cec5SDimitry Andric llvm::ArrayType::get(ProtocolTy, 0));
58470b57cec5SDimitry Andric
58480b57cec5SDimitry Andric // struct _objc_protocol {
58490b57cec5SDimitry Andric // struct _objc_protocol_extension *isa;
58500b57cec5SDimitry Andric // char *protocol_name;
58510b57cec5SDimitry Andric // struct _objc_protocol **_objc_protocol_list;
58520b57cec5SDimitry Andric // struct _objc_method_description_list *instance_methods;
58530b57cec5SDimitry Andric // struct _objc_method_description_list *class_methods;
58540b57cec5SDimitry Andric // }
58550b57cec5SDimitry Andric ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
58560b57cec5SDimitry Andric llvm::PointerType::getUnqual(ProtocolListTy),
58570b57cec5SDimitry Andric MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
58580b57cec5SDimitry Andric
58590b57cec5SDimitry Andric // struct _objc_protocol_list *
58600b57cec5SDimitry Andric ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
58610b57cec5SDimitry Andric
58620b57cec5SDimitry Andric ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
58630b57cec5SDimitry Andric
58640b57cec5SDimitry Andric // Class description structures
58650b57cec5SDimitry Andric
58660b57cec5SDimitry Andric // struct _objc_ivar {
58670b57cec5SDimitry Andric // char *ivar_name;
58680b57cec5SDimitry Andric // char *ivar_type;
58690b57cec5SDimitry Andric // int ivar_offset;
58700b57cec5SDimitry Andric // }
58710b57cec5SDimitry Andric IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
58720b57cec5SDimitry Andric IntTy);
58730b57cec5SDimitry Andric
58740b57cec5SDimitry Andric // struct _objc_ivar_list *
58750b57cec5SDimitry Andric IvarListTy =
58760b57cec5SDimitry Andric llvm::StructType::create(VMContext, "struct._objc_ivar_list");
58770b57cec5SDimitry Andric IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
58780b57cec5SDimitry Andric
58790b57cec5SDimitry Andric // struct _objc_method_list *
58800b57cec5SDimitry Andric MethodListTy =
58810b57cec5SDimitry Andric llvm::StructType::create(VMContext, "struct._objc_method_list");
58820b57cec5SDimitry Andric MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
58830b57cec5SDimitry Andric
58840b57cec5SDimitry Andric // struct _objc_class_extension *
58850b57cec5SDimitry Andric ClassExtensionTy = llvm::StructType::create(
58860b57cec5SDimitry Andric "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
58870b57cec5SDimitry Andric ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
58880b57cec5SDimitry Andric
58890b57cec5SDimitry Andric ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
58900b57cec5SDimitry Andric
58910b57cec5SDimitry Andric // struct _objc_class {
58920b57cec5SDimitry Andric // Class isa;
58930b57cec5SDimitry Andric // Class super_class;
58940b57cec5SDimitry Andric // char *name;
58950b57cec5SDimitry Andric // long version;
58960b57cec5SDimitry Andric // long info;
58970b57cec5SDimitry Andric // long instance_size;
58980b57cec5SDimitry Andric // struct _objc_ivar_list *ivars;
58990b57cec5SDimitry Andric // struct _objc_method_list *methods;
59000b57cec5SDimitry Andric // struct _objc_cache *cache;
59010b57cec5SDimitry Andric // struct _objc_protocol_list *protocols;
59020b57cec5SDimitry Andric // char *ivar_layout;
59030b57cec5SDimitry Andric // struct _objc_class_ext *ext;
59040b57cec5SDimitry Andric // };
59050b57cec5SDimitry Andric ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
59060b57cec5SDimitry Andric llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
59070b57cec5SDimitry Andric LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
59080b57cec5SDimitry Andric ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
59090b57cec5SDimitry Andric
59100b57cec5SDimitry Andric ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
59110b57cec5SDimitry Andric
59120b57cec5SDimitry Andric // struct _objc_category {
59130b57cec5SDimitry Andric // char *category_name;
59140b57cec5SDimitry Andric // char *class_name;
59150b57cec5SDimitry Andric // struct _objc_method_list *instance_method;
59160b57cec5SDimitry Andric // struct _objc_method_list *class_method;
59170b57cec5SDimitry Andric // struct _objc_protocol_list *protocols;
59180b57cec5SDimitry Andric // uint32_t size; // sizeof(struct _objc_category)
59190b57cec5SDimitry Andric // struct _objc_property_list *instance_properties;// category's @property
59200b57cec5SDimitry Andric // struct _objc_property_list *class_properties;
59210b57cec5SDimitry Andric // }
59220b57cec5SDimitry Andric CategoryTy = llvm::StructType::create(
59230b57cec5SDimitry Andric "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
59240b57cec5SDimitry Andric MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
59250b57cec5SDimitry Andric PropertyListPtrTy);
59260b57cec5SDimitry Andric
59270b57cec5SDimitry Andric // Global metadata structures
59280b57cec5SDimitry Andric
59290b57cec5SDimitry Andric // struct _objc_symtab {
59300b57cec5SDimitry Andric // long sel_ref_cnt;
59310b57cec5SDimitry Andric // SEL *refs;
59320b57cec5SDimitry Andric // short cls_def_cnt;
59330b57cec5SDimitry Andric // short cat_def_cnt;
59340b57cec5SDimitry Andric // char *defs[cls_def_cnt + cat_def_cnt];
59350b57cec5SDimitry Andric // }
59360b57cec5SDimitry Andric SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
59370b57cec5SDimitry Andric SelectorPtrTy, ShortTy, ShortTy,
59380b57cec5SDimitry Andric llvm::ArrayType::get(Int8PtrTy, 0));
59390b57cec5SDimitry Andric SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
59400b57cec5SDimitry Andric
59410b57cec5SDimitry Andric // struct _objc_module {
59420b57cec5SDimitry Andric // long version;
59430b57cec5SDimitry Andric // long size; // sizeof(struct _objc_module)
59440b57cec5SDimitry Andric // char *name;
59450b57cec5SDimitry Andric // struct _objc_symtab* symtab;
59460b57cec5SDimitry Andric // }
59470b57cec5SDimitry Andric ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
59480b57cec5SDimitry Andric Int8PtrTy, SymtabPtrTy);
59490b57cec5SDimitry Andric
59500b57cec5SDimitry Andric // FIXME: This is the size of the setjmp buffer and should be target
59510b57cec5SDimitry Andric // specific. 18 is what's used on 32-bit X86.
59520b57cec5SDimitry Andric uint64_t SetJmpBufferSize = 18;
59530b57cec5SDimitry Andric
59540b57cec5SDimitry Andric // Exceptions
59550b57cec5SDimitry Andric llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
59560b57cec5SDimitry Andric
59570b57cec5SDimitry Andric ExceptionDataTy = llvm::StructType::create(
59580b57cec5SDimitry Andric "struct._objc_exception_data",
59590b57cec5SDimitry Andric llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
59600b57cec5SDimitry Andric }
59610b57cec5SDimitry Andric
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule & cgm)59620b57cec5SDimitry Andric ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
59630b57cec5SDimitry Andric : ObjCCommonTypesHelper(cgm) {
59640b57cec5SDimitry Andric // struct _method_list_t {
59650b57cec5SDimitry Andric // uint32_t entsize; // sizeof(struct _objc_method)
59660b57cec5SDimitry Andric // uint32_t method_count;
59670b57cec5SDimitry Andric // struct _objc_method method_list[method_count];
59680b57cec5SDimitry Andric // }
59690b57cec5SDimitry Andric MethodListnfABITy =
59700b57cec5SDimitry Andric llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
59710b57cec5SDimitry Andric llvm::ArrayType::get(MethodTy, 0));
59720b57cec5SDimitry Andric // struct method_list_t *
59730b57cec5SDimitry Andric MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
59740b57cec5SDimitry Andric
59750b57cec5SDimitry Andric // struct _protocol_t {
59760b57cec5SDimitry Andric // id isa; // NULL
59770b57cec5SDimitry Andric // const char * const protocol_name;
59780b57cec5SDimitry Andric // const struct _protocol_list_t * protocol_list; // super protocols
59790b57cec5SDimitry Andric // const struct method_list_t * const instance_methods;
59800b57cec5SDimitry Andric // const struct method_list_t * const class_methods;
59810b57cec5SDimitry Andric // const struct method_list_t *optionalInstanceMethods;
59820b57cec5SDimitry Andric // const struct method_list_t *optionalClassMethods;
59830b57cec5SDimitry Andric // const struct _prop_list_t * properties;
59840b57cec5SDimitry Andric // const uint32_t size; // sizeof(struct _protocol_t)
59850b57cec5SDimitry Andric // const uint32_t flags; // = 0
59860b57cec5SDimitry Andric // const char ** extendedMethodTypes;
59870b57cec5SDimitry Andric // const char *demangledName;
59880b57cec5SDimitry Andric // const struct _prop_list_t * class_properties;
59890b57cec5SDimitry Andric // }
59900b57cec5SDimitry Andric
59910b57cec5SDimitry Andric // Holder for struct _protocol_list_t *
59920b57cec5SDimitry Andric ProtocolListnfABITy =
59930b57cec5SDimitry Andric llvm::StructType::create(VMContext, "struct._objc_protocol_list");
59940b57cec5SDimitry Andric
59950b57cec5SDimitry Andric ProtocolnfABITy = llvm::StructType::create(
59960b57cec5SDimitry Andric "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
59970b57cec5SDimitry Andric llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
59980b57cec5SDimitry Andric MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
59990b57cec5SDimitry Andric PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
60000b57cec5SDimitry Andric PropertyListPtrTy);
60010b57cec5SDimitry Andric
60020b57cec5SDimitry Andric // struct _protocol_t*
60030b57cec5SDimitry Andric ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
60040b57cec5SDimitry Andric
60050b57cec5SDimitry Andric // struct _protocol_list_t {
60060b57cec5SDimitry Andric // long protocol_count; // Note, this is 32/64 bit
60070b57cec5SDimitry Andric // struct _protocol_t *[protocol_count];
60080b57cec5SDimitry Andric // }
60090b57cec5SDimitry Andric ProtocolListnfABITy->setBody(LongTy,
60100b57cec5SDimitry Andric llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
60110b57cec5SDimitry Andric
60120b57cec5SDimitry Andric // struct _objc_protocol_list*
60130b57cec5SDimitry Andric ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
60140b57cec5SDimitry Andric
60150b57cec5SDimitry Andric // struct _ivar_t {
60160b57cec5SDimitry Andric // unsigned [long] int *offset; // pointer to ivar offset location
60170b57cec5SDimitry Andric // char *name;
60180b57cec5SDimitry Andric // char *type;
60190b57cec5SDimitry Andric // uint32_t alignment;
60200b57cec5SDimitry Andric // uint32_t size;
60210b57cec5SDimitry Andric // }
60220b57cec5SDimitry Andric IvarnfABITy = llvm::StructType::create(
60230b57cec5SDimitry Andric "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
60240b57cec5SDimitry Andric Int8PtrTy, Int8PtrTy, IntTy, IntTy);
60250b57cec5SDimitry Andric
60260b57cec5SDimitry Andric // struct _ivar_list_t {
60270b57cec5SDimitry Andric // uint32 entsize; // sizeof(struct _ivar_t)
60280b57cec5SDimitry Andric // uint32 count;
60290b57cec5SDimitry Andric // struct _iver_t list[count];
60300b57cec5SDimitry Andric // }
60310b57cec5SDimitry Andric IvarListnfABITy =
60320b57cec5SDimitry Andric llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
60330b57cec5SDimitry Andric llvm::ArrayType::get(IvarnfABITy, 0));
60340b57cec5SDimitry Andric
60350b57cec5SDimitry Andric IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
60360b57cec5SDimitry Andric
60370b57cec5SDimitry Andric // struct _class_ro_t {
60380b57cec5SDimitry Andric // uint32_t const flags;
60390b57cec5SDimitry Andric // uint32_t const instanceStart;
60400b57cec5SDimitry Andric // uint32_t const instanceSize;
60410b57cec5SDimitry Andric // uint32_t const reserved; // only when building for 64bit targets
60420b57cec5SDimitry Andric // const uint8_t * const ivarLayout;
60430b57cec5SDimitry Andric // const char *const name;
60440b57cec5SDimitry Andric // const struct _method_list_t * const baseMethods;
60450b57cec5SDimitry Andric // const struct _objc_protocol_list *const baseProtocols;
60460b57cec5SDimitry Andric // const struct _ivar_list_t *const ivars;
60470b57cec5SDimitry Andric // const uint8_t * const weakIvarLayout;
60480b57cec5SDimitry Andric // const struct _prop_list_t * const properties;
60490b57cec5SDimitry Andric // }
60500b57cec5SDimitry Andric
60510b57cec5SDimitry Andric // FIXME. Add 'reserved' field in 64bit abi mode!
60520b57cec5SDimitry Andric ClassRonfABITy = llvm::StructType::create(
60530b57cec5SDimitry Andric "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
60540b57cec5SDimitry Andric MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
60550b57cec5SDimitry Andric Int8PtrTy, PropertyListPtrTy);
60560b57cec5SDimitry Andric
60570b57cec5SDimitry Andric // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
60580b57cec5SDimitry Andric llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
60590b57cec5SDimitry Andric ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
60600b57cec5SDimitry Andric ->getPointerTo();
60610b57cec5SDimitry Andric
60620b57cec5SDimitry Andric // struct _class_t {
60630b57cec5SDimitry Andric // struct _class_t *isa;
60640b57cec5SDimitry Andric // struct _class_t * const superclass;
60650b57cec5SDimitry Andric // void *cache;
60660b57cec5SDimitry Andric // IMP *vtable;
60670b57cec5SDimitry Andric // struct class_ro_t *ro;
60680b57cec5SDimitry Andric // }
60690b57cec5SDimitry Andric
60700b57cec5SDimitry Andric ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
60710b57cec5SDimitry Andric ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
60720b57cec5SDimitry Andric llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
60730b57cec5SDimitry Andric llvm::PointerType::getUnqual(ImpnfABITy),
60740b57cec5SDimitry Andric llvm::PointerType::getUnqual(ClassRonfABITy));
60750b57cec5SDimitry Andric
60760b57cec5SDimitry Andric // LLVM for struct _class_t *
60770b57cec5SDimitry Andric ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
60780b57cec5SDimitry Andric
60790b57cec5SDimitry Andric // struct _category_t {
60800b57cec5SDimitry Andric // const char * const name;
60810b57cec5SDimitry Andric // struct _class_t *const cls;
60820b57cec5SDimitry Andric // const struct _method_list_t * const instance_methods;
60830b57cec5SDimitry Andric // const struct _method_list_t * const class_methods;
60840b57cec5SDimitry Andric // const struct _protocol_list_t * const protocols;
60850b57cec5SDimitry Andric // const struct _prop_list_t * const properties;
60860b57cec5SDimitry Andric // const struct _prop_list_t * const class_properties;
60870b57cec5SDimitry Andric // const uint32_t size;
60880b57cec5SDimitry Andric // }
60890b57cec5SDimitry Andric CategorynfABITy = llvm::StructType::create(
60900b57cec5SDimitry Andric "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
60910b57cec5SDimitry Andric MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
60920b57cec5SDimitry Andric PropertyListPtrTy, IntTy);
60930b57cec5SDimitry Andric
60940b57cec5SDimitry Andric // New types for nonfragile abi messaging.
60950b57cec5SDimitry Andric CodeGen::CodeGenTypes &Types = CGM.getTypes();
60960b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext();
60970b57cec5SDimitry Andric
60980b57cec5SDimitry Andric // MessageRefTy - LLVM for:
60990b57cec5SDimitry Andric // struct _message_ref_t {
61000b57cec5SDimitry Andric // IMP messenger;
61010b57cec5SDimitry Andric // SEL name;
61020b57cec5SDimitry Andric // };
61030b57cec5SDimitry Andric
61040b57cec5SDimitry Andric // First the clang type for struct _message_ref_t
61055f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(
61065f757f3fSDimitry Andric Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
61075f757f3fSDimitry Andric SourceLocation(), &Ctx.Idents.get("_message_ref_t"));
61080b57cec5SDimitry Andric RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
61090b57cec5SDimitry Andric nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
61100b57cec5SDimitry Andric ICIS_NoInit));
61110b57cec5SDimitry Andric RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
61120b57cec5SDimitry Andric nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
61130b57cec5SDimitry Andric false, ICIS_NoInit));
61140b57cec5SDimitry Andric RD->completeDefinition();
61150b57cec5SDimitry Andric
61160b57cec5SDimitry Andric MessageRefCTy = Ctx.getTagDeclType(RD);
61170b57cec5SDimitry Andric MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
61180b57cec5SDimitry Andric MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
61190b57cec5SDimitry Andric
61200b57cec5SDimitry Andric // MessageRefPtrTy - LLVM for struct _message_ref_t*
61210b57cec5SDimitry Andric MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
61220b57cec5SDimitry Andric
61230b57cec5SDimitry Andric // SuperMessageRefTy - LLVM for:
61240b57cec5SDimitry Andric // struct _super_message_ref_t {
61250b57cec5SDimitry Andric // SUPER_IMP messenger;
61260b57cec5SDimitry Andric // SEL name;
61270b57cec5SDimitry Andric // };
61280b57cec5SDimitry Andric SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
61290b57cec5SDimitry Andric ImpnfABITy, SelectorPtrTy);
61300b57cec5SDimitry Andric
61310b57cec5SDimitry Andric // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
61320b57cec5SDimitry Andric SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
61330b57cec5SDimitry Andric
61340b57cec5SDimitry Andric
61350b57cec5SDimitry Andric // struct objc_typeinfo {
61360b57cec5SDimitry Andric // const void** vtable; // objc_ehtype_vtable + 2
61370b57cec5SDimitry Andric // const char* name; // c++ typeinfo string
61380b57cec5SDimitry Andric // Class cls;
61390b57cec5SDimitry Andric // };
61400b57cec5SDimitry Andric EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
61410b57cec5SDimitry Andric llvm::PointerType::getUnqual(Int8PtrTy),
61420b57cec5SDimitry Andric Int8PtrTy, ClassnfABIPtrTy);
61430b57cec5SDimitry Andric EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
61440b57cec5SDimitry Andric }
61450b57cec5SDimitry Andric
ModuleInitFunction()61460b57cec5SDimitry Andric llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
61470b57cec5SDimitry Andric FinishNonFragileABIModule();
61480b57cec5SDimitry Andric
61490b57cec5SDimitry Andric return nullptr;
61500b57cec5SDimitry Andric }
61510b57cec5SDimitry Andric
AddModuleClassList(ArrayRef<llvm::GlobalValue * > Container,StringRef SymbolName,StringRef SectionName)61520b57cec5SDimitry Andric void CGObjCNonFragileABIMac::AddModuleClassList(
61530b57cec5SDimitry Andric ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
61540b57cec5SDimitry Andric StringRef SectionName) {
61550b57cec5SDimitry Andric unsigned NumClasses = Container.size();
61560b57cec5SDimitry Andric
61570b57cec5SDimitry Andric if (!NumClasses)
61580b57cec5SDimitry Andric return;
61590b57cec5SDimitry Andric
61600b57cec5SDimitry Andric SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
61610b57cec5SDimitry Andric for (unsigned i=0; i<NumClasses; i++)
61625f757f3fSDimitry Andric Symbols[i] = Container[i];
61635f757f3fSDimitry Andric
61640b57cec5SDimitry Andric llvm::Constant *Init =
61650b57cec5SDimitry Andric llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
61660b57cec5SDimitry Andric Symbols.size()),
61670b57cec5SDimitry Andric Symbols);
61680b57cec5SDimitry Andric
61690b57cec5SDimitry Andric // Section name is obtained by calling GetSectionName, which returns
61700b57cec5SDimitry Andric // sections in the __DATA segment on MachO.
61710b57cec5SDimitry Andric assert((!CGM.getTriple().isOSBinFormatMachO() ||
61725f757f3fSDimitry Andric SectionName.starts_with("__DATA")) &&
61730b57cec5SDimitry Andric "SectionName expected to start with __DATA on MachO");
61745ffd83dbSDimitry Andric llvm::GlobalVariable *GV = new llvm::GlobalVariable(
61755ffd83dbSDimitry Andric CGM.getModule(), Init->getType(), false,
61765ffd83dbSDimitry Andric llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6177bdd1243dSDimitry Andric GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
61780b57cec5SDimitry Andric GV->setSection(SectionName);
61790b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
61800b57cec5SDimitry Andric }
61810b57cec5SDimitry Andric
FinishNonFragileABIModule()61820b57cec5SDimitry Andric void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
61830b57cec5SDimitry Andric // nonfragile abi has no module definition.
61840b57cec5SDimitry Andric
61850b57cec5SDimitry Andric // Build list of all implemented class addresses in array
61860b57cec5SDimitry Andric // L_OBJC_LABEL_CLASS_$.
61870b57cec5SDimitry Andric
61880b57cec5SDimitry Andric for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
61890b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = ImplementedClasses[i];
61900b57cec5SDimitry Andric assert(ID);
61910b57cec5SDimitry Andric if (ObjCImplementationDecl *IMP = ID->getImplementation())
61920b57cec5SDimitry Andric // We are implementing a weak imported interface. Give it external linkage
61930b57cec5SDimitry Andric if (ID->isWeakImported() && !IMP->isWeakImported()) {
61940b57cec5SDimitry Andric DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
61950b57cec5SDimitry Andric DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
61960b57cec5SDimitry Andric }
61970b57cec5SDimitry Andric }
61980b57cec5SDimitry Andric
61990b57cec5SDimitry Andric AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
62000b57cec5SDimitry Andric GetSectionName("__objc_classlist",
62010b57cec5SDimitry Andric "regular,no_dead_strip"));
62020b57cec5SDimitry Andric
62030b57cec5SDimitry Andric AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
62040b57cec5SDimitry Andric GetSectionName("__objc_nlclslist",
62050b57cec5SDimitry Andric "regular,no_dead_strip"));
62060b57cec5SDimitry Andric
62070b57cec5SDimitry Andric // Build list of all implemented category addresses in array
62080b57cec5SDimitry Andric // L_OBJC_LABEL_CATEGORY_$.
62090b57cec5SDimitry Andric AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
62100b57cec5SDimitry Andric GetSectionName("__objc_catlist",
62110b57cec5SDimitry Andric "regular,no_dead_strip"));
62120b57cec5SDimitry Andric AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
62130b57cec5SDimitry Andric GetSectionName("__objc_catlist2",
62140b57cec5SDimitry Andric "regular,no_dead_strip"));
62150b57cec5SDimitry Andric AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
62160b57cec5SDimitry Andric GetSectionName("__objc_nlcatlist",
62170b57cec5SDimitry Andric "regular,no_dead_strip"));
62180b57cec5SDimitry Andric
62190b57cec5SDimitry Andric EmitImageInfo();
62200b57cec5SDimitry Andric }
62210b57cec5SDimitry Andric
62220b57cec5SDimitry Andric /// isVTableDispatchedSelector - Returns true if SEL is not in the list of
62230b57cec5SDimitry Andric /// VTableDispatchMethods; false otherwise. What this means is that
62240b57cec5SDimitry Andric /// except for the 19 selectors in the list, we generate 32bit-style
62250b57cec5SDimitry Andric /// message dispatch call for all the rest.
isVTableDispatchedSelector(Selector Sel)62260b57cec5SDimitry Andric bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
62270b57cec5SDimitry Andric // At various points we've experimented with using vtable-based
62280b57cec5SDimitry Andric // dispatch for all methods.
62290b57cec5SDimitry Andric switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
62300b57cec5SDimitry Andric case CodeGenOptions::Legacy:
62310b57cec5SDimitry Andric return false;
62320b57cec5SDimitry Andric case CodeGenOptions::NonLegacy:
62330b57cec5SDimitry Andric return true;
62340b57cec5SDimitry Andric case CodeGenOptions::Mixed:
62350b57cec5SDimitry Andric break;
62360b57cec5SDimitry Andric }
62370b57cec5SDimitry Andric
62380b57cec5SDimitry Andric // If so, see whether this selector is in the white-list of things which must
62390b57cec5SDimitry Andric // use the new dispatch convention. We lazily build a dense set for this.
62400b57cec5SDimitry Andric if (VTableDispatchMethods.empty()) {
62410b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("alloc"));
62420b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("class"));
62430b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("self"));
62440b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
62450b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("length"));
62460b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("count"));
62470b57cec5SDimitry Andric
62480b57cec5SDimitry Andric // These are vtable-based if GC is disabled.
62490b57cec5SDimitry Andric // Optimistically use vtable dispatch for hybrid compiles.
62500b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
62510b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("retain"));
62520b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("release"));
62530b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
62540b57cec5SDimitry Andric }
62550b57cec5SDimitry Andric
62560b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
62570b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
62580b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
62590b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
62600b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
62610b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
62620b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
62630b57cec5SDimitry Andric
62640b57cec5SDimitry Andric // These are vtable-based if GC is enabled.
62650b57cec5SDimitry Andric // Optimistically use vtable dispatch for hybrid compiles.
62660b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
62670b57cec5SDimitry Andric VTableDispatchMethods.insert(GetNullarySelector("hash"));
62680b57cec5SDimitry Andric VTableDispatchMethods.insert(GetUnarySelector("addObject"));
62690b57cec5SDimitry Andric
62700b57cec5SDimitry Andric // "countByEnumeratingWithState:objects:count"
6271*0fca6ea1SDimitry Andric const IdentifierInfo *KeyIdents[] = {
62720b57cec5SDimitry Andric &CGM.getContext().Idents.get("countByEnumeratingWithState"),
62730b57cec5SDimitry Andric &CGM.getContext().Idents.get("objects"),
6274*0fca6ea1SDimitry Andric &CGM.getContext().Idents.get("count")};
62750b57cec5SDimitry Andric VTableDispatchMethods.insert(
62760b57cec5SDimitry Andric CGM.getContext().Selectors.getSelector(3, KeyIdents));
62770b57cec5SDimitry Andric }
62780b57cec5SDimitry Andric }
62790b57cec5SDimitry Andric
62800b57cec5SDimitry Andric return VTableDispatchMethods.count(Sel);
62810b57cec5SDimitry Andric }
62820b57cec5SDimitry Andric
62830b57cec5SDimitry Andric /// BuildClassRoTInitializer - generate meta-data for:
62840b57cec5SDimitry Andric /// struct _class_ro_t {
62850b57cec5SDimitry Andric /// uint32_t const flags;
62860b57cec5SDimitry Andric /// uint32_t const instanceStart;
62870b57cec5SDimitry Andric /// uint32_t const instanceSize;
62880b57cec5SDimitry Andric /// uint32_t const reserved; // only when building for 64bit targets
62890b57cec5SDimitry Andric /// const uint8_t * const ivarLayout;
62900b57cec5SDimitry Andric /// const char *const name;
62910b57cec5SDimitry Andric /// const struct _method_list_t * const baseMethods;
62920b57cec5SDimitry Andric /// const struct _protocol_list_t *const baseProtocols;
62930b57cec5SDimitry Andric /// const struct _ivar_list_t *const ivars;
62940b57cec5SDimitry Andric /// const uint8_t * const weakIvarLayout;
62950b57cec5SDimitry Andric /// const struct _prop_list_t * const properties;
62960b57cec5SDimitry Andric /// }
62970b57cec5SDimitry Andric ///
BuildClassRoTInitializer(unsigned flags,unsigned InstanceStart,unsigned InstanceSize,const ObjCImplementationDecl * ID)62980b57cec5SDimitry Andric llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
62990b57cec5SDimitry Andric unsigned flags,
63000b57cec5SDimitry Andric unsigned InstanceStart,
63010b57cec5SDimitry Andric unsigned InstanceSize,
63020b57cec5SDimitry Andric const ObjCImplementationDecl *ID) {
63035ffd83dbSDimitry Andric std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
63040b57cec5SDimitry Andric
63050b57cec5SDimitry Andric CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
63060b57cec5SDimitry Andric CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
63070b57cec5SDimitry Andric
63080b57cec5SDimitry Andric bool hasMRCWeak = false;
63090b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount)
63100b57cec5SDimitry Andric flags |= NonFragileABI_Class_CompiledByARC;
63110b57cec5SDimitry Andric else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
63120b57cec5SDimitry Andric flags |= NonFragileABI_Class_HasMRCWeakIvars;
63130b57cec5SDimitry Andric
63140b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
63150b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
63160b57cec5SDimitry Andric
63170b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, flags);
63180b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, InstanceStart);
63190b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, InstanceSize);
63200b57cec5SDimitry Andric values.add((flags & NonFragileABI_Class_Meta)
63210b57cec5SDimitry Andric ? GetIvarLayoutName(nullptr, ObjCTypes)
63220b57cec5SDimitry Andric : BuildStrongIvarLayout(ID, beginInstance, endInstance));
63230b57cec5SDimitry Andric values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
63240b57cec5SDimitry Andric
63250b57cec5SDimitry Andric // const struct _method_list_t * const baseMethods;
63260b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl*, 16> methods;
63270b57cec5SDimitry Andric if (flags & NonFragileABI_Class_Meta) {
63280b57cec5SDimitry Andric for (const auto *MD : ID->class_methods())
6329480093f4SDimitry Andric if (!MD->isDirectMethod())
63300b57cec5SDimitry Andric methods.push_back(MD);
63310b57cec5SDimitry Andric } else {
63320b57cec5SDimitry Andric for (const auto *MD : ID->instance_methods())
6333480093f4SDimitry Andric if (!MD->isDirectMethod())
63340b57cec5SDimitry Andric methods.push_back(MD);
63350b57cec5SDimitry Andric }
63360b57cec5SDimitry Andric
63370b57cec5SDimitry Andric values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
63380b57cec5SDimitry Andric (flags & NonFragileABI_Class_Meta)
63390b57cec5SDimitry Andric ? MethodListType::ClassMethods
63400b57cec5SDimitry Andric : MethodListType::InstanceMethods,
63410b57cec5SDimitry Andric methods));
63420b57cec5SDimitry Andric
63430b57cec5SDimitry Andric const ObjCInterfaceDecl *OID = ID->getClassInterface();
63440b57cec5SDimitry Andric assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
63450b57cec5SDimitry Andric values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_"
63460b57cec5SDimitry Andric + OID->getObjCRuntimeNameAsString(),
63470b57cec5SDimitry Andric OID->all_referenced_protocol_begin(),
63480b57cec5SDimitry Andric OID->all_referenced_protocol_end()));
63490b57cec5SDimitry Andric
63500b57cec5SDimitry Andric if (flags & NonFragileABI_Class_Meta) {
63510b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
63520b57cec5SDimitry Andric values.add(GetIvarLayoutName(nullptr, ObjCTypes));
63530b57cec5SDimitry Andric values.add(EmitPropertyList(
63540b57cec5SDimitry Andric "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
63550b57cec5SDimitry Andric ID, ID->getClassInterface(), ObjCTypes, true));
63560b57cec5SDimitry Andric } else {
63570b57cec5SDimitry Andric values.add(EmitIvarList(ID));
63580b57cec5SDimitry Andric values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
63590b57cec5SDimitry Andric values.add(EmitPropertyList(
63600b57cec5SDimitry Andric "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
63610b57cec5SDimitry Andric ID, ID->getClassInterface(), ObjCTypes, false));
63620b57cec5SDimitry Andric }
63630b57cec5SDimitry Andric
63640b57cec5SDimitry Andric llvm::SmallString<64> roLabel;
63650b57cec5SDimitry Andric llvm::raw_svector_ostream(roLabel)
63660b57cec5SDimitry Andric << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
63670b57cec5SDimitry Andric : "_OBJC_CLASS_RO_$_")
63680b57cec5SDimitry Andric << ClassName;
63690b57cec5SDimitry Andric
63700b57cec5SDimitry Andric return finishAndCreateGlobal(values, roLabel, CGM);
63710b57cec5SDimitry Andric }
63720b57cec5SDimitry Andric
63730b57cec5SDimitry Andric /// Build the metaclass object for a class.
63740b57cec5SDimitry Andric ///
63750b57cec5SDimitry Andric /// struct _class_t {
63760b57cec5SDimitry Andric /// struct _class_t *isa;
63770b57cec5SDimitry Andric /// struct _class_t * const superclass;
63780b57cec5SDimitry Andric /// void *cache;
63790b57cec5SDimitry Andric /// IMP *vtable;
63800b57cec5SDimitry Andric /// struct class_ro_t *ro;
63810b57cec5SDimitry Andric /// }
63820b57cec5SDimitry Andric ///
63830b57cec5SDimitry Andric llvm::GlobalVariable *
BuildClassObject(const ObjCInterfaceDecl * CI,bool isMetaclass,llvm::Constant * IsAGV,llvm::Constant * SuperClassGV,llvm::Constant * ClassRoGV,bool HiddenVisibility)63840b57cec5SDimitry Andric CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
63850b57cec5SDimitry Andric bool isMetaclass,
63860b57cec5SDimitry Andric llvm::Constant *IsAGV,
63870b57cec5SDimitry Andric llvm::Constant *SuperClassGV,
63880b57cec5SDimitry Andric llvm::Constant *ClassRoGV,
63890b57cec5SDimitry Andric bool HiddenVisibility) {
63900b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
63910b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
63920b57cec5SDimitry Andric values.add(IsAGV);
63930b57cec5SDimitry Andric if (SuperClassGV) {
63940b57cec5SDimitry Andric values.add(SuperClassGV);
63950b57cec5SDimitry Andric } else {
63960b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
63970b57cec5SDimitry Andric }
63980b57cec5SDimitry Andric values.add(ObjCEmptyCacheVar);
63990b57cec5SDimitry Andric values.add(ObjCEmptyVtableVar);
64000b57cec5SDimitry Andric values.add(ClassRoGV);
64010b57cec5SDimitry Andric
64020b57cec5SDimitry Andric llvm::GlobalVariable *GV =
64030b57cec5SDimitry Andric cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
64040b57cec5SDimitry Andric values.finishAndSetAsInitializer(GV);
64050b57cec5SDimitry Andric
64060b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
64070b57cec5SDimitry Andric GV->setSection("__DATA, __objc_data");
6408bdd1243dSDimitry Andric GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
64090b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatCOFF())
64100b57cec5SDimitry Andric if (HiddenVisibility)
64110b57cec5SDimitry Andric GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
64120b57cec5SDimitry Andric return GV;
64130b57cec5SDimitry Andric }
64140b57cec5SDimitry Andric
ImplementationIsNonLazy(const ObjCImplDecl * OD) const64150b57cec5SDimitry Andric bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
64160b57cec5SDimitry Andric const ObjCImplDecl *OD) const {
64170b57cec5SDimitry Andric return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
64180b57cec5SDimitry Andric OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
64190b57cec5SDimitry Andric OD->hasAttr<ObjCNonLazyClassAttr>();
64200b57cec5SDimitry Andric }
64210b57cec5SDimitry Andric
GetClassSizeInfo(const ObjCImplementationDecl * OID,uint32_t & InstanceStart,uint32_t & InstanceSize)64220b57cec5SDimitry Andric void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
64230b57cec5SDimitry Andric uint32_t &InstanceStart,
64240b57cec5SDimitry Andric uint32_t &InstanceSize) {
64250b57cec5SDimitry Andric const ASTRecordLayout &RL =
64260b57cec5SDimitry Andric CGM.getContext().getASTObjCImplementationLayout(OID);
64270b57cec5SDimitry Andric
64280b57cec5SDimitry Andric // InstanceSize is really instance end.
64290b57cec5SDimitry Andric InstanceSize = RL.getDataSize().getQuantity();
64300b57cec5SDimitry Andric
64310b57cec5SDimitry Andric // If there are no fields, the start is the same as the end.
64320b57cec5SDimitry Andric if (!RL.getFieldCount())
64330b57cec5SDimitry Andric InstanceStart = InstanceSize;
64340b57cec5SDimitry Andric else
64350b57cec5SDimitry Andric InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
64360b57cec5SDimitry Andric }
64370b57cec5SDimitry Andric
getStorage(CodeGenModule & CGM,StringRef Name)64380b57cec5SDimitry Andric static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
64390b57cec5SDimitry Andric StringRef Name) {
64400b57cec5SDimitry Andric IdentifierInfo &II = CGM.getContext().Idents.get(Name);
64410b57cec5SDimitry Andric TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
64420b57cec5SDimitry Andric DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
64430b57cec5SDimitry Andric
64440b57cec5SDimitry Andric const VarDecl *VD = nullptr;
6445fe6060f1SDimitry Andric for (const auto *Result : DC->lookup(&II))
64460b57cec5SDimitry Andric if ((VD = dyn_cast<VarDecl>(Result)))
64470b57cec5SDimitry Andric break;
64480b57cec5SDimitry Andric
64490b57cec5SDimitry Andric if (!VD)
64500b57cec5SDimitry Andric return llvm::GlobalValue::DLLImportStorageClass;
64510b57cec5SDimitry Andric if (VD->hasAttr<DLLExportAttr>())
64520b57cec5SDimitry Andric return llvm::GlobalValue::DLLExportStorageClass;
64530b57cec5SDimitry Andric if (VD->hasAttr<DLLImportAttr>())
64540b57cec5SDimitry Andric return llvm::GlobalValue::DLLImportStorageClass;
64550b57cec5SDimitry Andric return llvm::GlobalValue::DefaultStorageClass;
64560b57cec5SDimitry Andric }
64570b57cec5SDimitry Andric
GenerateClass(const ObjCImplementationDecl * ID)64580b57cec5SDimitry Andric void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
64590b57cec5SDimitry Andric if (!ObjCEmptyCacheVar) {
64600b57cec5SDimitry Andric ObjCEmptyCacheVar =
64610b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
64620b57cec5SDimitry Andric llvm::GlobalValue::ExternalLinkage, nullptr,
64630b57cec5SDimitry Andric "_objc_empty_cache");
64640b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatCOFF())
64650b57cec5SDimitry Andric ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
64660b57cec5SDimitry Andric
64670b57cec5SDimitry Andric // Only OS X with deployment version <10.9 use the empty vtable symbol
64680b57cec5SDimitry Andric const llvm::Triple &Triple = CGM.getTarget().getTriple();
64690b57cec5SDimitry Andric if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
64700b57cec5SDimitry Andric ObjCEmptyVtableVar =
64710b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
64720b57cec5SDimitry Andric llvm::GlobalValue::ExternalLinkage, nullptr,
64730b57cec5SDimitry Andric "_objc_empty_vtable");
64740b57cec5SDimitry Andric else
64750b57cec5SDimitry Andric ObjCEmptyVtableVar =
64760b57cec5SDimitry Andric llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
64770b57cec5SDimitry Andric }
64780b57cec5SDimitry Andric
64790b57cec5SDimitry Andric // FIXME: Is this correct (that meta class size is never computed)?
64800b57cec5SDimitry Andric uint32_t InstanceStart =
64810b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
64820b57cec5SDimitry Andric uint32_t InstanceSize = InstanceStart;
64830b57cec5SDimitry Andric uint32_t flags = NonFragileABI_Class_Meta;
64840b57cec5SDimitry Andric
64850b57cec5SDimitry Andric llvm::Constant *SuperClassGV, *IsAGV;
64860b57cec5SDimitry Andric
64870b57cec5SDimitry Andric const auto *CI = ID->getClassInterface();
64880b57cec5SDimitry Andric assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
64890b57cec5SDimitry Andric
64900b57cec5SDimitry Andric // Build the flags for the metaclass.
64910b57cec5SDimitry Andric bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
64920b57cec5SDimitry Andric ? !CI->hasAttr<DLLExportAttr>()
64930b57cec5SDimitry Andric : CI->getVisibility() == HiddenVisibility;
64940b57cec5SDimitry Andric if (classIsHidden)
64950b57cec5SDimitry Andric flags |= NonFragileABI_Class_Hidden;
64960b57cec5SDimitry Andric
64970b57cec5SDimitry Andric // FIXME: why is this flag set on the metaclass?
64980b57cec5SDimitry Andric // ObjC metaclasses have no fields and don't really get constructed.
64990b57cec5SDimitry Andric if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
65000b57cec5SDimitry Andric flags |= NonFragileABI_Class_HasCXXStructors;
65010b57cec5SDimitry Andric if (!ID->hasNonZeroConstructors())
65020b57cec5SDimitry Andric flags |= NonFragileABI_Class_HasCXXDestructorOnly;
65030b57cec5SDimitry Andric }
65040b57cec5SDimitry Andric
65050b57cec5SDimitry Andric if (!CI->getSuperClass()) {
65060b57cec5SDimitry Andric // class is root
65070b57cec5SDimitry Andric flags |= NonFragileABI_Class_Root;
65080b57cec5SDimitry Andric
65090b57cec5SDimitry Andric SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
65100b57cec5SDimitry Andric IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
65110b57cec5SDimitry Andric } else {
65120b57cec5SDimitry Andric // Has a root. Current class is not a root.
65130b57cec5SDimitry Andric const ObjCInterfaceDecl *Root = ID->getClassInterface();
65140b57cec5SDimitry Andric while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
65150b57cec5SDimitry Andric Root = Super;
65160b57cec5SDimitry Andric
65170b57cec5SDimitry Andric const auto *Super = CI->getSuperClass();
65180b57cec5SDimitry Andric IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
65190b57cec5SDimitry Andric SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
65200b57cec5SDimitry Andric }
65210b57cec5SDimitry Andric
65220b57cec5SDimitry Andric llvm::GlobalVariable *CLASS_RO_GV =
65230b57cec5SDimitry Andric BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
65240b57cec5SDimitry Andric
65250b57cec5SDimitry Andric llvm::GlobalVariable *MetaTClass =
65260b57cec5SDimitry Andric BuildClassObject(CI, /*metaclass*/ true,
65270b57cec5SDimitry Andric IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
65280b57cec5SDimitry Andric CGM.setGVProperties(MetaTClass, CI);
65290b57cec5SDimitry Andric DefinedMetaClasses.push_back(MetaTClass);
65300b57cec5SDimitry Andric
65310b57cec5SDimitry Andric // Metadata for the class
65320b57cec5SDimitry Andric flags = 0;
65330b57cec5SDimitry Andric if (classIsHidden)
65340b57cec5SDimitry Andric flags |= NonFragileABI_Class_Hidden;
65350b57cec5SDimitry Andric
65360b57cec5SDimitry Andric if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
65370b57cec5SDimitry Andric flags |= NonFragileABI_Class_HasCXXStructors;
65380b57cec5SDimitry Andric
65390b57cec5SDimitry Andric // Set a flag to enable a runtime optimization when a class has
65400b57cec5SDimitry Andric // fields that require destruction but which don't require
65410b57cec5SDimitry Andric // anything except zero-initialization during construction. This
65420b57cec5SDimitry Andric // is most notably true of __strong and __weak types, but you can
65430b57cec5SDimitry Andric // also imagine there being C++ types with non-trivial default
65440b57cec5SDimitry Andric // constructors that merely set all fields to null.
65450b57cec5SDimitry Andric if (!ID->hasNonZeroConstructors())
65460b57cec5SDimitry Andric flags |= NonFragileABI_Class_HasCXXDestructorOnly;
65470b57cec5SDimitry Andric }
65480b57cec5SDimitry Andric
65490b57cec5SDimitry Andric if (hasObjCExceptionAttribute(CGM.getContext(), CI))
65500b57cec5SDimitry Andric flags |= NonFragileABI_Class_Exception;
65510b57cec5SDimitry Andric
65520b57cec5SDimitry Andric if (!CI->getSuperClass()) {
65530b57cec5SDimitry Andric flags |= NonFragileABI_Class_Root;
65540b57cec5SDimitry Andric SuperClassGV = nullptr;
65550b57cec5SDimitry Andric } else {
65560b57cec5SDimitry Andric // Has a root. Current class is not a root.
65570b57cec5SDimitry Andric const auto *Super = CI->getSuperClass();
65580b57cec5SDimitry Andric SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
65590b57cec5SDimitry Andric }
65600b57cec5SDimitry Andric
65610b57cec5SDimitry Andric GetClassSizeInfo(ID, InstanceStart, InstanceSize);
65620b57cec5SDimitry Andric CLASS_RO_GV =
65630b57cec5SDimitry Andric BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
65640b57cec5SDimitry Andric
65650b57cec5SDimitry Andric llvm::GlobalVariable *ClassMD =
65660b57cec5SDimitry Andric BuildClassObject(CI, /*metaclass*/ false,
65670b57cec5SDimitry Andric MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
65680b57cec5SDimitry Andric CGM.setGVProperties(ClassMD, CI);
65690b57cec5SDimitry Andric DefinedClasses.push_back(ClassMD);
65700b57cec5SDimitry Andric ImplementedClasses.push_back(CI);
65710b57cec5SDimitry Andric
65720b57cec5SDimitry Andric // Determine if this class is also "non-lazy".
65730b57cec5SDimitry Andric if (ImplementationIsNonLazy(ID))
65740b57cec5SDimitry Andric DefinedNonLazyClasses.push_back(ClassMD);
65750b57cec5SDimitry Andric
65760b57cec5SDimitry Andric // Force the definition of the EHType if necessary.
65770b57cec5SDimitry Andric if (flags & NonFragileABI_Class_Exception)
65780b57cec5SDimitry Andric (void) GetInterfaceEHType(CI, ForDefinition);
65790b57cec5SDimitry Andric // Make sure method definition entries are all clear for next implementation.
65800b57cec5SDimitry Andric MethodDefinitions.clear();
65810b57cec5SDimitry Andric }
65820b57cec5SDimitry Andric
65830b57cec5SDimitry Andric /// GenerateProtocolRef - This routine is called to generate code for
65840b57cec5SDimitry Andric /// a protocol reference expression; as in:
65850b57cec5SDimitry Andric /// @code
65860b57cec5SDimitry Andric /// @protocol(Proto1);
65870b57cec5SDimitry Andric /// @endcode
65880b57cec5SDimitry Andric /// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
65890b57cec5SDimitry Andric /// which will hold address of the protocol meta-data.
65900b57cec5SDimitry Andric ///
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)65910b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
65920b57cec5SDimitry Andric const ObjCProtocolDecl *PD) {
65930b57cec5SDimitry Andric
65940b57cec5SDimitry Andric // This routine is called for @protocol only. So, we must build definition
65950b57cec5SDimitry Andric // of protocol's meta-data (not a reference to it!)
6596e8d8bef9SDimitry Andric assert(!PD->isNonRuntimeProtocol() &&
6597e8d8bef9SDimitry Andric "attempting to get a protocol ref to a static protocol.");
65985f757f3fSDimitry Andric llvm::Constant *Init = GetOrEmitProtocol(PD);
65990b57cec5SDimitry Andric
66000b57cec5SDimitry Andric std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
66010b57cec5SDimitry Andric ProtocolName += PD->getObjCRuntimeNameAsString();
66020b57cec5SDimitry Andric
66030b57cec5SDimitry Andric CharUnits Align = CGF.getPointerAlign();
66040b57cec5SDimitry Andric
66050b57cec5SDimitry Andric llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
66060b57cec5SDimitry Andric if (PTGV)
6607fe6060f1SDimitry Andric return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
66080b57cec5SDimitry Andric PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
66090b57cec5SDimitry Andric llvm::GlobalValue::WeakAnyLinkage, Init,
66100b57cec5SDimitry Andric ProtocolName);
66110b57cec5SDimitry Andric PTGV->setSection(GetSectionName("__objc_protorefs",
66120b57cec5SDimitry Andric "coalesced,no_dead_strip"));
66130b57cec5SDimitry Andric PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6614a7dea167SDimitry Andric PTGV->setAlignment(Align.getAsAlign());
66150b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatMachO())
66160b57cec5SDimitry Andric PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
66170b57cec5SDimitry Andric CGM.addUsedGlobal(PTGV);
6618fe6060f1SDimitry Andric return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
66190b57cec5SDimitry Andric }
66200b57cec5SDimitry Andric
66210b57cec5SDimitry Andric /// GenerateCategory - Build metadata for a category implementation.
66220b57cec5SDimitry Andric /// struct _category_t {
66230b57cec5SDimitry Andric /// const char * const name;
66240b57cec5SDimitry Andric /// struct _class_t *const cls;
66250b57cec5SDimitry Andric /// const struct _method_list_t * const instance_methods;
66260b57cec5SDimitry Andric /// const struct _method_list_t * const class_methods;
66270b57cec5SDimitry Andric /// const struct _protocol_list_t * const protocols;
66280b57cec5SDimitry Andric /// const struct _prop_list_t * const properties;
66290b57cec5SDimitry Andric /// const struct _prop_list_t * const class_properties;
66300b57cec5SDimitry Andric /// const uint32_t size;
66310b57cec5SDimitry Andric /// }
66320b57cec5SDimitry Andric ///
GenerateCategory(const ObjCCategoryImplDecl * OCD)66330b57cec5SDimitry Andric void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
66340b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
66350b57cec5SDimitry Andric const char *Prefix = "_OBJC_$_CATEGORY_";
66360b57cec5SDimitry Andric
66370b57cec5SDimitry Andric llvm::SmallString<64> ExtCatName(Prefix);
66380b57cec5SDimitry Andric ExtCatName += Interface->getObjCRuntimeNameAsString();
66390b57cec5SDimitry Andric ExtCatName += "_$_";
66400b57cec5SDimitry Andric ExtCatName += OCD->getNameAsString();
66410b57cec5SDimitry Andric
66420b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
66430b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
66440b57cec5SDimitry Andric values.add(GetClassName(OCD->getIdentifier()->getName()));
66450b57cec5SDimitry Andric // meta-class entry symbol
66460b57cec5SDimitry Andric values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
66470b57cec5SDimitry Andric std::string listName =
66480b57cec5SDimitry Andric (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
66490b57cec5SDimitry Andric
66500b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
66510b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 8> classMethods;
66520b57cec5SDimitry Andric for (const auto *MD : OCD->methods()) {
6653480093f4SDimitry Andric if (MD->isDirectMethod())
6654480093f4SDimitry Andric continue;
66550b57cec5SDimitry Andric if (MD->isInstanceMethod()) {
66560b57cec5SDimitry Andric instanceMethods.push_back(MD);
66570b57cec5SDimitry Andric } else {
66580b57cec5SDimitry Andric classMethods.push_back(MD);
66590b57cec5SDimitry Andric }
66600b57cec5SDimitry Andric }
66610b57cec5SDimitry Andric
6662349cc55cSDimitry Andric auto instanceMethodList = emitMethodList(
6663349cc55cSDimitry Andric listName, MethodListType::CategoryInstanceMethods, instanceMethods);
6664349cc55cSDimitry Andric auto classMethodList = emitMethodList(
6665349cc55cSDimitry Andric listName, MethodListType::CategoryClassMethods, classMethods);
6666349cc55cSDimitry Andric values.add(instanceMethodList);
6667349cc55cSDimitry Andric values.add(classMethodList);
6668349cc55cSDimitry Andric // Keep track of whether we have actual metadata to emit.
6669349cc55cSDimitry Andric bool isEmptyCategory =
6670349cc55cSDimitry Andric instanceMethodList->isNullValue() && classMethodList->isNullValue();
66710b57cec5SDimitry Andric
66720b57cec5SDimitry Andric const ObjCCategoryDecl *Category =
66730b57cec5SDimitry Andric Interface->FindCategoryDeclaration(OCD->getIdentifier());
66740b57cec5SDimitry Andric if (Category) {
66750b57cec5SDimitry Andric SmallString<256> ExtName;
6676349cc55cSDimitry Andric llvm::raw_svector_ostream(ExtName)
6677349cc55cSDimitry Andric << Interface->getObjCRuntimeNameAsString() << "_$_" << OCD->getName();
6678349cc55cSDimitry Andric auto protocolList =
6679349cc55cSDimitry Andric EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_" +
6680349cc55cSDimitry Andric Interface->getObjCRuntimeNameAsString() + "_$_" +
6681349cc55cSDimitry Andric Category->getName(),
6682349cc55cSDimitry Andric Category->protocol_begin(), Category->protocol_end());
6683349cc55cSDimitry Andric auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
6684349cc55cSDimitry Andric OCD, Category, ObjCTypes, false);
6685349cc55cSDimitry Andric auto classPropertyList =
6686349cc55cSDimitry Andric EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
6687349cc55cSDimitry Andric Category, ObjCTypes, true);
6688349cc55cSDimitry Andric values.add(protocolList);
6689349cc55cSDimitry Andric values.add(propertyList);
6690349cc55cSDimitry Andric values.add(classPropertyList);
6691349cc55cSDimitry Andric isEmptyCategory &= protocolList->isNullValue() &&
6692349cc55cSDimitry Andric propertyList->isNullValue() &&
6693349cc55cSDimitry Andric classPropertyList->isNullValue();
66940b57cec5SDimitry Andric } else {
66950b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
66960b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.PropertyListPtrTy);
66970b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.PropertyListPtrTy);
66980b57cec5SDimitry Andric }
66990b57cec5SDimitry Andric
6700349cc55cSDimitry Andric if (isEmptyCategory) {
6701349cc55cSDimitry Andric // Empty category, don't emit any metadata.
6702349cc55cSDimitry Andric values.abandon();
6703349cc55cSDimitry Andric MethodDefinitions.clear();
6704349cc55cSDimitry Andric return;
6705349cc55cSDimitry Andric }
6706349cc55cSDimitry Andric
6707349cc55cSDimitry Andric unsigned Size =
6708349cc55cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
67090b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, Size);
67100b57cec5SDimitry Andric
67110b57cec5SDimitry Andric llvm::GlobalVariable *GCATV =
67120b57cec5SDimitry Andric finishAndCreateGlobal(values, ExtCatName.str(), CGM);
67130b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GCATV);
67140b57cec5SDimitry Andric if (Interface->hasAttr<ObjCClassStubAttr>())
67150b57cec5SDimitry Andric DefinedStubCategories.push_back(GCATV);
67160b57cec5SDimitry Andric else
67170b57cec5SDimitry Andric DefinedCategories.push_back(GCATV);
67180b57cec5SDimitry Andric
67190b57cec5SDimitry Andric // Determine if this category is also "non-lazy".
67200b57cec5SDimitry Andric if (ImplementationIsNonLazy(OCD))
67210b57cec5SDimitry Andric DefinedNonLazyCategories.push_back(GCATV);
67220b57cec5SDimitry Andric // method definition entries must be clear for next implementation.
67230b57cec5SDimitry Andric MethodDefinitions.clear();
67240b57cec5SDimitry Andric }
67250b57cec5SDimitry Andric
67260b57cec5SDimitry Andric /// emitMethodConstant - Return a struct objc_method constant. If
67270b57cec5SDimitry Andric /// forProtocol is true, the implementation will be null; otherwise,
67280b57cec5SDimitry Andric /// the method must have a definition registered with the runtime.
67290b57cec5SDimitry Andric ///
67300b57cec5SDimitry Andric /// struct _objc_method {
67310b57cec5SDimitry Andric /// SEL _cmd;
67320b57cec5SDimitry Andric /// char *method_type;
67330b57cec5SDimitry Andric /// char *_imp;
67340b57cec5SDimitry Andric /// }
emitMethodConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD,bool forProtocol)67350b57cec5SDimitry Andric void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
67360b57cec5SDimitry Andric const ObjCMethodDecl *MD,
67370b57cec5SDimitry Andric bool forProtocol) {
67380b57cec5SDimitry Andric auto method = builder.beginStruct(ObjCTypes.MethodTy);
67395f757f3fSDimitry Andric method.add(GetMethodVarName(MD->getSelector()));
67400b57cec5SDimitry Andric method.add(GetMethodVarType(MD));
67410b57cec5SDimitry Andric
67420b57cec5SDimitry Andric if (forProtocol) {
67430b57cec5SDimitry Andric // Protocol methods have no implementation. So, this entry is always NULL.
6744bdd1243dSDimitry Andric method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
67450b57cec5SDimitry Andric } else {
67460b57cec5SDimitry Andric llvm::Function *fn = GetMethodDefinition(MD);
67470b57cec5SDimitry Andric assert(fn && "no definition for method?");
67485f757f3fSDimitry Andric method.add(fn);
67490b57cec5SDimitry Andric }
67500b57cec5SDimitry Andric
67510b57cec5SDimitry Andric method.finishAndAddTo(builder);
67520b57cec5SDimitry Andric }
67530b57cec5SDimitry Andric
67540b57cec5SDimitry Andric /// Build meta-data for method declarations.
67550b57cec5SDimitry Andric ///
67560b57cec5SDimitry Andric /// struct _method_list_t {
67570b57cec5SDimitry Andric /// uint32_t entsize; // sizeof(struct _objc_method)
67580b57cec5SDimitry Andric /// uint32_t method_count;
67590b57cec5SDimitry Andric /// struct _objc_method method_list[method_count];
67600b57cec5SDimitry Andric /// }
67610b57cec5SDimitry Andric ///
67620b57cec5SDimitry Andric llvm::Constant *
emitMethodList(Twine name,MethodListType kind,ArrayRef<const ObjCMethodDecl * > methods)67630b57cec5SDimitry Andric CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
67640b57cec5SDimitry Andric ArrayRef<const ObjCMethodDecl *> methods) {
67650b57cec5SDimitry Andric // Return null for empty list.
67660b57cec5SDimitry Andric if (methods.empty())
67670b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
67680b57cec5SDimitry Andric
67690b57cec5SDimitry Andric StringRef prefix;
67700b57cec5SDimitry Andric bool forProtocol;
67710b57cec5SDimitry Andric switch (kind) {
67720b57cec5SDimitry Andric case MethodListType::CategoryInstanceMethods:
67730b57cec5SDimitry Andric prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
67740b57cec5SDimitry Andric forProtocol = false;
67750b57cec5SDimitry Andric break;
67760b57cec5SDimitry Andric case MethodListType::CategoryClassMethods:
67770b57cec5SDimitry Andric prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
67780b57cec5SDimitry Andric forProtocol = false;
67790b57cec5SDimitry Andric break;
67800b57cec5SDimitry Andric case MethodListType::InstanceMethods:
67810b57cec5SDimitry Andric prefix = "_OBJC_$_INSTANCE_METHODS_";
67820b57cec5SDimitry Andric forProtocol = false;
67830b57cec5SDimitry Andric break;
67840b57cec5SDimitry Andric case MethodListType::ClassMethods:
67850b57cec5SDimitry Andric prefix = "_OBJC_$_CLASS_METHODS_";
67860b57cec5SDimitry Andric forProtocol = false;
67870b57cec5SDimitry Andric break;
67880b57cec5SDimitry Andric
67890b57cec5SDimitry Andric case MethodListType::ProtocolInstanceMethods:
67900b57cec5SDimitry Andric prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
67910b57cec5SDimitry Andric forProtocol = true;
67920b57cec5SDimitry Andric break;
67930b57cec5SDimitry Andric case MethodListType::ProtocolClassMethods:
67940b57cec5SDimitry Andric prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
67950b57cec5SDimitry Andric forProtocol = true;
67960b57cec5SDimitry Andric break;
67970b57cec5SDimitry Andric case MethodListType::OptionalProtocolInstanceMethods:
67980b57cec5SDimitry Andric prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
67990b57cec5SDimitry Andric forProtocol = true;
68000b57cec5SDimitry Andric break;
68010b57cec5SDimitry Andric case MethodListType::OptionalProtocolClassMethods:
68020b57cec5SDimitry Andric prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
68030b57cec5SDimitry Andric forProtocol = true;
68040b57cec5SDimitry Andric break;
68050b57cec5SDimitry Andric }
68060b57cec5SDimitry Andric
68070b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
68080b57cec5SDimitry Andric auto values = builder.beginStruct();
68090b57cec5SDimitry Andric
68100b57cec5SDimitry Andric // sizeof(struct _objc_method)
68110b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
68120b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, Size);
68130b57cec5SDimitry Andric // method_count
68140b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, methods.size());
68150b57cec5SDimitry Andric auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6816480093f4SDimitry Andric for (auto MD : methods)
68170b57cec5SDimitry Andric emitMethodConstant(methodArray, MD, forProtocol);
68180b57cec5SDimitry Andric methodArray.finishAndAddTo(values);
68190b57cec5SDimitry Andric
68200b57cec5SDimitry Andric llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
68210b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
68225f757f3fSDimitry Andric return GV;
68230b57cec5SDimitry Andric }
68240b57cec5SDimitry Andric
68250b57cec5SDimitry Andric /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
68260b57cec5SDimitry Andric /// the given ivar.
68270b57cec5SDimitry Andric llvm::GlobalVariable *
ObjCIvarOffsetVariable(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)68280b57cec5SDimitry Andric CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
68290b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) {
68300b57cec5SDimitry Andric const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
68310b57cec5SDimitry Andric llvm::SmallString<64> Name("OBJC_IVAR_$_");
68320b57cec5SDimitry Andric Name += Container->getObjCRuntimeNameAsString();
68330b57cec5SDimitry Andric Name += ".";
68340b57cec5SDimitry Andric Name += Ivar->getName();
68350b57cec5SDimitry Andric llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
68360b57cec5SDimitry Andric if (!IvarOffsetGV) {
68370b57cec5SDimitry Andric IvarOffsetGV =
68380b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
68390b57cec5SDimitry Andric false, llvm::GlobalValue::ExternalLinkage,
68400b57cec5SDimitry Andric nullptr, Name.str());
68410b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatCOFF()) {
68420b57cec5SDimitry Andric bool IsPrivateOrPackage =
68430b57cec5SDimitry Andric Ivar->getAccessControl() == ObjCIvarDecl::Private ||
68440b57cec5SDimitry Andric Ivar->getAccessControl() == ObjCIvarDecl::Package;
68450b57cec5SDimitry Andric
68460b57cec5SDimitry Andric const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
68470b57cec5SDimitry Andric
68480b57cec5SDimitry Andric if (ContainingID->hasAttr<DLLImportAttr>())
68490b57cec5SDimitry Andric IvarOffsetGV
68500b57cec5SDimitry Andric ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
68510b57cec5SDimitry Andric else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
68520b57cec5SDimitry Andric IvarOffsetGV
68530b57cec5SDimitry Andric ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
68540b57cec5SDimitry Andric }
68550b57cec5SDimitry Andric }
68560b57cec5SDimitry Andric return IvarOffsetGV;
68570b57cec5SDimitry Andric }
68580b57cec5SDimitry Andric
68590b57cec5SDimitry Andric llvm::Constant *
EmitIvarOffsetVar(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar,unsigned long int Offset)68600b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
68610b57cec5SDimitry Andric const ObjCIvarDecl *Ivar,
68620b57cec5SDimitry Andric unsigned long int Offset) {
68630b57cec5SDimitry Andric llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
68640b57cec5SDimitry Andric IvarOffsetGV->setInitializer(
68650b57cec5SDimitry Andric llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6866bdd1243dSDimitry Andric IvarOffsetGV->setAlignment(
6867bdd1243dSDimitry Andric CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
68680b57cec5SDimitry Andric
68690b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatCOFF()) {
68700b57cec5SDimitry Andric // FIXME: This matches gcc, but shouldn't the visibility be set on the use
68710b57cec5SDimitry Andric // as well (i.e., in ObjCIvarOffsetVariable).
68720b57cec5SDimitry Andric if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
68730b57cec5SDimitry Andric Ivar->getAccessControl() == ObjCIvarDecl::Package ||
68740b57cec5SDimitry Andric ID->getVisibility() == HiddenVisibility)
68750b57cec5SDimitry Andric IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
68760b57cec5SDimitry Andric else
68770b57cec5SDimitry Andric IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
68780b57cec5SDimitry Andric }
68790b57cec5SDimitry Andric
68800b57cec5SDimitry Andric // If ID's layout is known, then make the global constant. This serves as a
68810b57cec5SDimitry Andric // useful assertion: we'll never use this variable to calculate ivar offsets,
68820b57cec5SDimitry Andric // so if the runtime tries to patch it then we should crash.
68830b57cec5SDimitry Andric if (isClassLayoutKnownStatically(ID))
68840b57cec5SDimitry Andric IvarOffsetGV->setConstant(true);
68850b57cec5SDimitry Andric
68860b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
68870b57cec5SDimitry Andric IvarOffsetGV->setSection("__DATA, __objc_ivar");
68880b57cec5SDimitry Andric return IvarOffsetGV;
68890b57cec5SDimitry Andric }
68900b57cec5SDimitry Andric
68910b57cec5SDimitry Andric /// EmitIvarList - Emit the ivar list for the given
68920b57cec5SDimitry Andric /// implementation. The return value has type
68930b57cec5SDimitry Andric /// IvarListnfABIPtrTy.
68940b57cec5SDimitry Andric /// struct _ivar_t {
68950b57cec5SDimitry Andric /// unsigned [long] int *offset; // pointer to ivar offset location
68960b57cec5SDimitry Andric /// char *name;
68970b57cec5SDimitry Andric /// char *type;
68980b57cec5SDimitry Andric /// uint32_t alignment;
68990b57cec5SDimitry Andric /// uint32_t size;
69000b57cec5SDimitry Andric /// }
69010b57cec5SDimitry Andric /// struct _ivar_list_t {
69020b57cec5SDimitry Andric /// uint32 entsize; // sizeof(struct _ivar_t)
69030b57cec5SDimitry Andric /// uint32 count;
69040b57cec5SDimitry Andric /// struct _iver_t list[count];
69050b57cec5SDimitry Andric /// }
69060b57cec5SDimitry Andric ///
69070b57cec5SDimitry Andric
EmitIvarList(const ObjCImplementationDecl * ID)69080b57cec5SDimitry Andric llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
69090b57cec5SDimitry Andric const ObjCImplementationDecl *ID) {
69100b57cec5SDimitry Andric
69110b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
69120b57cec5SDimitry Andric auto ivarList = builder.beginStruct();
69130b57cec5SDimitry Andric ivarList.addInt(ObjCTypes.IntTy,
69140b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
69150b57cec5SDimitry Andric auto ivarCountSlot = ivarList.addPlaceholder();
69160b57cec5SDimitry Andric auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
69170b57cec5SDimitry Andric
69180b57cec5SDimitry Andric const ObjCInterfaceDecl *OID = ID->getClassInterface();
69190b57cec5SDimitry Andric assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
69200b57cec5SDimitry Andric
69210b57cec5SDimitry Andric // FIXME. Consolidate this with similar code in GenerateClass.
69220b57cec5SDimitry Andric
69230b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
69240b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) {
69250b57cec5SDimitry Andric // Ignore unnamed bit-fields.
69260b57cec5SDimitry Andric if (!IVD->getDeclName())
69270b57cec5SDimitry Andric continue;
69280b57cec5SDimitry Andric
69290b57cec5SDimitry Andric auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
69300b57cec5SDimitry Andric ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
69310b57cec5SDimitry Andric ComputeIvarBaseOffset(CGM, ID, IVD)));
69320b57cec5SDimitry Andric ivar.add(GetMethodVarName(IVD->getIdentifier()));
69330b57cec5SDimitry Andric ivar.add(GetMethodVarType(IVD));
69340b57cec5SDimitry Andric llvm::Type *FieldTy =
69350b57cec5SDimitry Andric CGM.getTypes().ConvertTypeForMem(IVD->getType());
69360b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
69370b57cec5SDimitry Andric unsigned Align = CGM.getContext().getPreferredTypeAlign(
69380b57cec5SDimitry Andric IVD->getType().getTypePtr()) >> 3;
69390b57cec5SDimitry Andric Align = llvm::Log2_32(Align);
69400b57cec5SDimitry Andric ivar.addInt(ObjCTypes.IntTy, Align);
69410b57cec5SDimitry Andric // NOTE. Size of a bitfield does not match gcc's, because of the
69420b57cec5SDimitry Andric // way bitfields are treated special in each. But I am told that
69430b57cec5SDimitry Andric // 'size' for bitfield ivars is ignored by the runtime so it does
69440b57cec5SDimitry Andric // not matter. If it matters, there is enough info to get the
69450b57cec5SDimitry Andric // bitfield right!
69460b57cec5SDimitry Andric ivar.addInt(ObjCTypes.IntTy, Size);
69470b57cec5SDimitry Andric ivar.finishAndAddTo(ivars);
69480b57cec5SDimitry Andric }
69490b57cec5SDimitry Andric // Return null for empty list.
69500b57cec5SDimitry Andric if (ivars.empty()) {
69510b57cec5SDimitry Andric ivars.abandon();
69520b57cec5SDimitry Andric ivarList.abandon();
69530b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
69540b57cec5SDimitry Andric }
69550b57cec5SDimitry Andric
69560b57cec5SDimitry Andric auto ivarCount = ivars.size();
69570b57cec5SDimitry Andric ivars.finishAndAddTo(ivarList);
69580b57cec5SDimitry Andric ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
69590b57cec5SDimitry Andric
69600b57cec5SDimitry Andric const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
69610b57cec5SDimitry Andric llvm::GlobalVariable *GV = finishAndCreateGlobal(
69620b57cec5SDimitry Andric ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
69630b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
69645f757f3fSDimitry Andric return GV;
69650b57cec5SDimitry Andric }
69660b57cec5SDimitry Andric
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)69670b57cec5SDimitry Andric llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
69680b57cec5SDimitry Andric const ObjCProtocolDecl *PD) {
69690b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
69700b57cec5SDimitry Andric
6971e8d8bef9SDimitry Andric assert(!PD->isNonRuntimeProtocol() &&
6972e8d8bef9SDimitry Andric "attempting to GetOrEmit a non-runtime protocol");
69730b57cec5SDimitry Andric if (!Entry) {
69740b57cec5SDimitry Andric // We use the initializer as a marker of whether this is a forward
69750b57cec5SDimitry Andric // reference or not. At module finalization we add the empty
69760b57cec5SDimitry Andric // contents for protocols which were referenced but never defined.
69770b57cec5SDimitry Andric llvm::SmallString<64> Protocol;
69780b57cec5SDimitry Andric llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_"
69790b57cec5SDimitry Andric << PD->getObjCRuntimeNameAsString();
69800b57cec5SDimitry Andric
69810b57cec5SDimitry Andric Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
69820b57cec5SDimitry Andric false, llvm::GlobalValue::ExternalLinkage,
69830b57cec5SDimitry Andric nullptr, Protocol);
69840b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatMachO())
69850b57cec5SDimitry Andric Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
69860b57cec5SDimitry Andric }
69870b57cec5SDimitry Andric
69880b57cec5SDimitry Andric return Entry;
69890b57cec5SDimitry Andric }
69900b57cec5SDimitry Andric
69910b57cec5SDimitry Andric /// GetOrEmitProtocol - Generate the protocol meta-data:
69920b57cec5SDimitry Andric /// @code
69930b57cec5SDimitry Andric /// struct _protocol_t {
69940b57cec5SDimitry Andric /// id isa; // NULL
69950b57cec5SDimitry Andric /// const char * const protocol_name;
69960b57cec5SDimitry Andric /// const struct _protocol_list_t * protocol_list; // super protocols
69970b57cec5SDimitry Andric /// const struct method_list_t * const instance_methods;
69980b57cec5SDimitry Andric /// const struct method_list_t * const class_methods;
69990b57cec5SDimitry Andric /// const struct method_list_t *optionalInstanceMethods;
70000b57cec5SDimitry Andric /// const struct method_list_t *optionalClassMethods;
70010b57cec5SDimitry Andric /// const struct _prop_list_t * properties;
70020b57cec5SDimitry Andric /// const uint32_t size; // sizeof(struct _protocol_t)
70030b57cec5SDimitry Andric /// const uint32_t flags; // = 0
70040b57cec5SDimitry Andric /// const char ** extendedMethodTypes;
70050b57cec5SDimitry Andric /// const char *demangledName;
70060b57cec5SDimitry Andric /// const struct _prop_list_t * class_properties;
70070b57cec5SDimitry Andric /// }
70080b57cec5SDimitry Andric /// @endcode
70090b57cec5SDimitry Andric ///
70100b57cec5SDimitry Andric
GetOrEmitProtocol(const ObjCProtocolDecl * PD)70110b57cec5SDimitry Andric llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
70120b57cec5SDimitry Andric const ObjCProtocolDecl *PD) {
70130b57cec5SDimitry Andric llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
70140b57cec5SDimitry Andric
70150b57cec5SDimitry Andric // Early exit if a defining object has already been generated.
70160b57cec5SDimitry Andric if (Entry && Entry->hasInitializer())
70170b57cec5SDimitry Andric return Entry;
70180b57cec5SDimitry Andric
70190b57cec5SDimitry Andric // Use the protocol definition, if there is one.
70200b57cec5SDimitry Andric assert(PD->hasDefinition() &&
70210b57cec5SDimitry Andric "emitting protocol metadata without definition");
70220b57cec5SDimitry Andric PD = PD->getDefinition();
70230b57cec5SDimitry Andric
70240b57cec5SDimitry Andric auto methodLists = ProtocolMethodLists::get(PD);
70250b57cec5SDimitry Andric
70260b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
70270b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
70280b57cec5SDimitry Andric
70290b57cec5SDimitry Andric // isa is NULL
70300b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.ObjectPtrTy);
70310b57cec5SDimitry Andric values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
70320b57cec5SDimitry Andric values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_"
70330b57cec5SDimitry Andric + PD->getObjCRuntimeNameAsString(),
70340b57cec5SDimitry Andric PD->protocol_begin(),
70350b57cec5SDimitry Andric PD->protocol_end()));
70360b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
70370b57cec5SDimitry Andric ProtocolMethodLists::RequiredInstanceMethods));
70380b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
70390b57cec5SDimitry Andric ProtocolMethodLists::RequiredClassMethods));
70400b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
70410b57cec5SDimitry Andric ProtocolMethodLists::OptionalInstanceMethods));
70420b57cec5SDimitry Andric values.add(methodLists.emitMethodList(this, PD,
70430b57cec5SDimitry Andric ProtocolMethodLists::OptionalClassMethods));
70440b57cec5SDimitry Andric values.add(EmitPropertyList(
70450b57cec5SDimitry Andric "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
70460b57cec5SDimitry Andric nullptr, PD, ObjCTypes, false));
70470b57cec5SDimitry Andric uint32_t Size =
70480b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
70490b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, Size);
70500b57cec5SDimitry Andric values.addInt(ObjCTypes.IntTy, 0);
70510b57cec5SDimitry Andric values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_"
70520b57cec5SDimitry Andric + PD->getObjCRuntimeNameAsString(),
70530b57cec5SDimitry Andric methodLists.emitExtendedTypesArray(this),
70540b57cec5SDimitry Andric ObjCTypes));
70550b57cec5SDimitry Andric
70560b57cec5SDimitry Andric // const char *demangledName;
70570b57cec5SDimitry Andric values.addNullPointer(ObjCTypes.Int8PtrTy);
70580b57cec5SDimitry Andric
70590b57cec5SDimitry Andric values.add(EmitPropertyList(
70600b57cec5SDimitry Andric "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
70610b57cec5SDimitry Andric nullptr, PD, ObjCTypes, true));
70620b57cec5SDimitry Andric
70630b57cec5SDimitry Andric if (Entry) {
70640b57cec5SDimitry Andric // Already created, fix the linkage and update the initializer.
70650b57cec5SDimitry Andric Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
70660b57cec5SDimitry Andric values.finishAndSetAsInitializer(Entry);
70670b57cec5SDimitry Andric } else {
70680b57cec5SDimitry Andric llvm::SmallString<64> symbolName;
70690b57cec5SDimitry Andric llvm::raw_svector_ostream(symbolName)
70700b57cec5SDimitry Andric << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
70710b57cec5SDimitry Andric
70720b57cec5SDimitry Andric Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
70730b57cec5SDimitry Andric /*constant*/ false,
70740b57cec5SDimitry Andric llvm::GlobalValue::WeakAnyLinkage);
70750b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatMachO())
70760b57cec5SDimitry Andric Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
70770b57cec5SDimitry Andric
70780b57cec5SDimitry Andric Protocols[PD->getIdentifier()] = Entry;
70790b57cec5SDimitry Andric }
70800b57cec5SDimitry Andric Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
70810b57cec5SDimitry Andric CGM.addUsedGlobal(Entry);
70820b57cec5SDimitry Andric
70830b57cec5SDimitry Andric // Use this protocol meta-data to build protocol list table in section
70840b57cec5SDimitry Andric // __DATA, __objc_protolist
70850b57cec5SDimitry Andric llvm::SmallString<64> ProtocolRef;
70860b57cec5SDimitry Andric llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_"
70870b57cec5SDimitry Andric << PD->getObjCRuntimeNameAsString();
70880b57cec5SDimitry Andric
70890b57cec5SDimitry Andric llvm::GlobalVariable *PTGV =
70900b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
70910b57cec5SDimitry Andric false, llvm::GlobalValue::WeakAnyLinkage, Entry,
70920b57cec5SDimitry Andric ProtocolRef);
70930b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatMachO())
70940b57cec5SDimitry Andric PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7095bdd1243dSDimitry Andric PTGV->setAlignment(
7096bdd1243dSDimitry Andric CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
70970b57cec5SDimitry Andric PTGV->setSection(GetSectionName("__objc_protolist",
70980b57cec5SDimitry Andric "coalesced,no_dead_strip"));
70990b57cec5SDimitry Andric PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
71000b57cec5SDimitry Andric CGM.addUsedGlobal(PTGV);
71010b57cec5SDimitry Andric return Entry;
71020b57cec5SDimitry Andric }
71030b57cec5SDimitry Andric
71040b57cec5SDimitry Andric /// EmitProtocolList - Generate protocol list meta-data:
71050b57cec5SDimitry Andric /// @code
71060b57cec5SDimitry Andric /// struct _protocol_list_t {
71070b57cec5SDimitry Andric /// long protocol_count; // Note, this is 32/64 bit
71080b57cec5SDimitry Andric /// struct _protocol_t[protocol_count];
71090b57cec5SDimitry Andric /// }
71100b57cec5SDimitry Andric /// @endcode
71110b57cec5SDimitry Andric ///
71120b57cec5SDimitry Andric llvm::Constant *
EmitProtocolList(Twine Name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)71130b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
71140b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator begin,
71150b57cec5SDimitry Andric ObjCProtocolDecl::protocol_iterator end) {
71160b57cec5SDimitry Andric // Just return null for empty protocol lists
7117e8d8bef9SDimitry Andric auto Protocols = GetRuntimeProtocolList(begin, end);
7118e8d8bef9SDimitry Andric if (Protocols.empty())
7119e8d8bef9SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7120e8d8bef9SDimitry Andric
7121e8d8bef9SDimitry Andric SmallVector<llvm::Constant *, 16> ProtocolRefs;
7122e8d8bef9SDimitry Andric ProtocolRefs.reserve(Protocols.size());
7123e8d8bef9SDimitry Andric
7124e8d8bef9SDimitry Andric for (const auto *PD : Protocols)
7125e8d8bef9SDimitry Andric ProtocolRefs.push_back(GetProtocolRef(PD));
7126e8d8bef9SDimitry Andric
7127e8d8bef9SDimitry Andric // If all of the protocols in the protocol list are objc_non_runtime_protocol
7128e8d8bef9SDimitry Andric // just return null
7129e8d8bef9SDimitry Andric if (ProtocolRefs.size() == 0)
71300b57cec5SDimitry Andric return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
71310b57cec5SDimitry Andric
71320b57cec5SDimitry Andric // FIXME: We shouldn't need to do this lookup here, should we?
71330b57cec5SDimitry Andric SmallString<256> TmpName;
71340b57cec5SDimitry Andric Name.toVector(TmpName);
71350b57cec5SDimitry Andric llvm::GlobalVariable *GV =
71360b57cec5SDimitry Andric CGM.getModule().getGlobalVariable(TmpName.str(), true);
71370b57cec5SDimitry Andric if (GV)
71385f757f3fSDimitry Andric return GV;
71390b57cec5SDimitry Andric
71400b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
71410b57cec5SDimitry Andric auto values = builder.beginStruct();
71420b57cec5SDimitry Andric auto countSlot = values.addPlaceholder();
71430b57cec5SDimitry Andric
71440b57cec5SDimitry Andric // A null-terminated array of protocols.
71450b57cec5SDimitry Andric auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7146e8d8bef9SDimitry Andric for (auto const &proto : ProtocolRefs)
7147e8d8bef9SDimitry Andric array.add(proto);
71480b57cec5SDimitry Andric auto count = array.size();
71490b57cec5SDimitry Andric array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
71500b57cec5SDimitry Andric
71510b57cec5SDimitry Andric array.finishAndAddTo(values);
71520b57cec5SDimitry Andric values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
71530b57cec5SDimitry Andric
71540b57cec5SDimitry Andric GV = finishAndCreateGlobal(values, Name, CGM);
71550b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(GV);
71565f757f3fSDimitry Andric return GV;
71570b57cec5SDimitry Andric }
71580b57cec5SDimitry Andric
71590b57cec5SDimitry Andric /// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
71600b57cec5SDimitry Andric /// This code gen. amounts to generating code for:
71610b57cec5SDimitry Andric /// @code
71620b57cec5SDimitry Andric /// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
71630b57cec5SDimitry Andric /// @encode
71640b57cec5SDimitry Andric ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)71650b57cec5SDimitry Andric LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
71660b57cec5SDimitry Andric CodeGen::CodeGenFunction &CGF,
71670b57cec5SDimitry Andric QualType ObjectTy,
71680b57cec5SDimitry Andric llvm::Value *BaseValue,
71690b57cec5SDimitry Andric const ObjCIvarDecl *Ivar,
71700b57cec5SDimitry Andric unsigned CVRQualifiers) {
7171a7dea167SDimitry Andric ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
71720b57cec5SDimitry Andric llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
71730b57cec5SDimitry Andric return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
71740b57cec5SDimitry Andric Offset);
71750b57cec5SDimitry Andric }
71760b57cec5SDimitry Andric
71770b57cec5SDimitry Andric llvm::Value *
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)71780b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
71790b57cec5SDimitry Andric const ObjCInterfaceDecl *Interface,
71800b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) {
71810b57cec5SDimitry Andric llvm::Value *IvarOffsetValue;
71820b57cec5SDimitry Andric if (isClassLayoutKnownStatically(Interface)) {
71830b57cec5SDimitry Andric IvarOffsetValue = llvm::ConstantInt::get(
71840b57cec5SDimitry Andric ObjCTypes.IvarOffsetVarTy,
71850b57cec5SDimitry Andric ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
71860b57cec5SDimitry Andric } else {
71870b57cec5SDimitry Andric llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
71880b57cec5SDimitry Andric IvarOffsetValue =
7189fe6060f1SDimitry Andric CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7190fe6060f1SDimitry Andric CGF.getSizeAlign(), "ivar");
71910b57cec5SDimitry Andric if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
71920b57cec5SDimitry Andric cast<llvm::LoadInst>(IvarOffsetValue)
719306c3fb27SDimitry Andric ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7194bdd1243dSDimitry Andric llvm::MDNode::get(VMContext, std::nullopt));
71950b57cec5SDimitry Andric }
71960b57cec5SDimitry Andric
71970b57cec5SDimitry Andric // This could be 32bit int or 64bit integer depending on the architecture.
71980b57cec5SDimitry Andric // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
71990b57cec5SDimitry Andric // as this is what caller always expects.
72000b57cec5SDimitry Andric if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
72010b57cec5SDimitry Andric IvarOffsetValue = CGF.Builder.CreateIntCast(
72020b57cec5SDimitry Andric IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
72030b57cec5SDimitry Andric return IvarOffsetValue;
72040b57cec5SDimitry Andric }
72050b57cec5SDimitry Andric
appendSelectorForMessageRefTable(std::string & buffer,Selector selector)72060b57cec5SDimitry Andric static void appendSelectorForMessageRefTable(std::string &buffer,
72070b57cec5SDimitry Andric Selector selector) {
72080b57cec5SDimitry Andric if (selector.isUnarySelector()) {
72090b57cec5SDimitry Andric buffer += selector.getNameForSlot(0);
72100b57cec5SDimitry Andric return;
72110b57cec5SDimitry Andric }
72120b57cec5SDimitry Andric
72130b57cec5SDimitry Andric for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
72140b57cec5SDimitry Andric buffer += selector.getNameForSlot(i);
72150b57cec5SDimitry Andric buffer += '_';
72160b57cec5SDimitry Andric }
72170b57cec5SDimitry Andric }
72180b57cec5SDimitry Andric
72190b57cec5SDimitry Andric /// Emit a "vtable" message send. We emit a weak hidden-visibility
72200b57cec5SDimitry Andric /// struct, initially containing the selector pointer and a pointer to
72210b57cec5SDimitry Andric /// a "fixup" variant of the appropriate objc_msgSend. To call, we
72220b57cec5SDimitry Andric /// load and call the function pointer, passing the address of the
72230b57cec5SDimitry Andric /// struct as the second parameter. The runtime determines whether
72240b57cec5SDimitry Andric /// the selector is currently emitted using vtable dispatch; if so, it
72250b57cec5SDimitry Andric /// substitutes a stub function which simply tail-calls through the
72260b57cec5SDimitry Andric /// appropriate vtable slot, and if not, it substitues a stub function
72270b57cec5SDimitry Andric /// which tail-calls objc_msgSend. Both stubs adjust the selector
72280b57cec5SDimitry Andric /// argument to correctly point to the selector.
72290b57cec5SDimitry Andric RValue
EmitVTableMessageSend(CodeGenFunction & CGF,ReturnValueSlot returnSlot,QualType resultType,Selector selector,llvm::Value * arg0,QualType arg0Type,bool isSuper,const CallArgList & formalArgs,const ObjCMethodDecl * method)72300b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
72310b57cec5SDimitry Andric ReturnValueSlot returnSlot,
72320b57cec5SDimitry Andric QualType resultType,
72330b57cec5SDimitry Andric Selector selector,
72340b57cec5SDimitry Andric llvm::Value *arg0,
72350b57cec5SDimitry Andric QualType arg0Type,
72360b57cec5SDimitry Andric bool isSuper,
72370b57cec5SDimitry Andric const CallArgList &formalArgs,
72380b57cec5SDimitry Andric const ObjCMethodDecl *method) {
72390b57cec5SDimitry Andric // Compute the actual arguments.
72400b57cec5SDimitry Andric CallArgList args;
72410b57cec5SDimitry Andric
72420b57cec5SDimitry Andric // First argument: the receiver / super-call structure.
72430b57cec5SDimitry Andric if (!isSuper)
72440b57cec5SDimitry Andric arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
72450b57cec5SDimitry Andric args.add(RValue::get(arg0), arg0Type);
72460b57cec5SDimitry Andric
72470b57cec5SDimitry Andric // Second argument: a pointer to the message ref structure. Leave
72480b57cec5SDimitry Andric // the actual argument value blank for now.
72490b57cec5SDimitry Andric args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
72500b57cec5SDimitry Andric
72510b57cec5SDimitry Andric args.insert(args.end(), formalArgs.begin(), formalArgs.end());
72520b57cec5SDimitry Andric
72530b57cec5SDimitry Andric MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
72540b57cec5SDimitry Andric
72550b57cec5SDimitry Andric NullReturnState nullReturn;
72560b57cec5SDimitry Andric
72570b57cec5SDimitry Andric // Find the function to call and the mangled name for the message
72580b57cec5SDimitry Andric // ref structure. Using a different mangled name wouldn't actually
72590b57cec5SDimitry Andric // be a problem; it would just be a waste.
72600b57cec5SDimitry Andric //
72610b57cec5SDimitry Andric // The runtime currently never uses vtable dispatch for anything
72620b57cec5SDimitry Andric // except normal, non-super message-sends.
72630b57cec5SDimitry Andric // FIXME: don't use this for that.
72640b57cec5SDimitry Andric llvm::FunctionCallee fn = nullptr;
72650b57cec5SDimitry Andric std::string messageRefName("_");
72660b57cec5SDimitry Andric if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
72670b57cec5SDimitry Andric if (isSuper) {
72680b57cec5SDimitry Andric fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
72690b57cec5SDimitry Andric messageRefName += "objc_msgSendSuper2_stret_fixup";
72700b57cec5SDimitry Andric } else {
72710b57cec5SDimitry Andric nullReturn.init(CGF, arg0);
72720b57cec5SDimitry Andric fn = ObjCTypes.getMessageSendStretFixupFn();
72730b57cec5SDimitry Andric messageRefName += "objc_msgSend_stret_fixup";
72740b57cec5SDimitry Andric }
72750b57cec5SDimitry Andric } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
72760b57cec5SDimitry Andric fn = ObjCTypes.getMessageSendFpretFixupFn();
72770b57cec5SDimitry Andric messageRefName += "objc_msgSend_fpret_fixup";
72780b57cec5SDimitry Andric } else {
72790b57cec5SDimitry Andric if (isSuper) {
72800b57cec5SDimitry Andric fn = ObjCTypes.getMessageSendSuper2FixupFn();
72810b57cec5SDimitry Andric messageRefName += "objc_msgSendSuper2_fixup";
72820b57cec5SDimitry Andric } else {
72830b57cec5SDimitry Andric fn = ObjCTypes.getMessageSendFixupFn();
72840b57cec5SDimitry Andric messageRefName += "objc_msgSend_fixup";
72850b57cec5SDimitry Andric }
72860b57cec5SDimitry Andric }
72870b57cec5SDimitry Andric assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
72880b57cec5SDimitry Andric messageRefName += '_';
72890b57cec5SDimitry Andric
72900b57cec5SDimitry Andric // Append the selector name, except use underscores anywhere we
72910b57cec5SDimitry Andric // would have used colons.
72920b57cec5SDimitry Andric appendSelectorForMessageRefTable(messageRefName, selector);
72930b57cec5SDimitry Andric
72940b57cec5SDimitry Andric llvm::GlobalVariable *messageRef
72950b57cec5SDimitry Andric = CGM.getModule().getGlobalVariable(messageRefName);
72960b57cec5SDimitry Andric if (!messageRef) {
72970b57cec5SDimitry Andric // Build the message ref structure.
72980b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
72990b57cec5SDimitry Andric auto values = builder.beginStruct();
73000b57cec5SDimitry Andric values.add(cast<llvm::Constant>(fn.getCallee()));
73010b57cec5SDimitry Andric values.add(GetMethodVarName(selector));
73020b57cec5SDimitry Andric messageRef = values.finishAndCreateGlobal(messageRefName,
73030b57cec5SDimitry Andric CharUnits::fromQuantity(16),
73040b57cec5SDimitry Andric /*constant*/ false,
73050b57cec5SDimitry Andric llvm::GlobalValue::WeakAnyLinkage);
73060b57cec5SDimitry Andric messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
73070b57cec5SDimitry Andric messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
73080b57cec5SDimitry Andric }
73090b57cec5SDimitry Andric
73100b57cec5SDimitry Andric bool requiresnullCheck = false;
73110b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount && method)
73120b57cec5SDimitry Andric for (const auto *ParamDecl : method->parameters()) {
7313e8d8bef9SDimitry Andric if (ParamDecl->isDestroyedInCallee()) {
73140b57cec5SDimitry Andric if (!nullReturn.NullBB)
73150b57cec5SDimitry Andric nullReturn.init(CGF, arg0);
73160b57cec5SDimitry Andric requiresnullCheck = true;
73170b57cec5SDimitry Andric break;
73180b57cec5SDimitry Andric }
73190b57cec5SDimitry Andric }
73200b57cec5SDimitry Andric
73210b57cec5SDimitry Andric Address mref =
73220b57cec5SDimitry Andric Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
732381ad6265SDimitry Andric ObjCTypes.MessageRefTy, CGF.getPointerAlign());
73240b57cec5SDimitry Andric
73250b57cec5SDimitry Andric // Update the message ref argument.
7326*0fca6ea1SDimitry Andric args[1].setRValue(RValue::get(mref, CGF));
73270b57cec5SDimitry Andric
73280b57cec5SDimitry Andric // Load the function to call from the message ref table.
73290b57cec5SDimitry Andric Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
73300b57cec5SDimitry Andric llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
73310b57cec5SDimitry Andric
73320b57cec5SDimitry Andric calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
73330b57cec5SDimitry Andric CGCallee callee(CGCalleeInfo(), calleePtr);
73340b57cec5SDimitry Andric
73350b57cec5SDimitry Andric RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
73360b57cec5SDimitry Andric return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
73370b57cec5SDimitry Andric requiresnullCheck ? method : nullptr);
73380b57cec5SDimitry Andric }
73390b57cec5SDimitry Andric
73400b57cec5SDimitry Andric /// Generate code for a message send expression in the nonfragile abi.
73410b57cec5SDimitry Andric CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)73420b57cec5SDimitry Andric CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
73430b57cec5SDimitry Andric ReturnValueSlot Return,
73440b57cec5SDimitry Andric QualType ResultType,
73450b57cec5SDimitry Andric Selector Sel,
73460b57cec5SDimitry Andric llvm::Value *Receiver,
73470b57cec5SDimitry Andric const CallArgList &CallArgs,
73480b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
73490b57cec5SDimitry Andric const ObjCMethodDecl *Method) {
73500b57cec5SDimitry Andric return isVTableDispatchedSelector(Sel)
73510b57cec5SDimitry Andric ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
73520b57cec5SDimitry Andric Receiver, CGF.getContext().getObjCIdType(),
73530b57cec5SDimitry Andric false, CallArgs, Method)
7354480093f4SDimitry Andric : EmitMessageSend(CGF, Return, ResultType, Sel,
73550b57cec5SDimitry Andric Receiver, CGF.getContext().getObjCIdType(),
73560b57cec5SDimitry Andric false, CallArgs, Method, Class, ObjCTypes);
73570b57cec5SDimitry Andric }
73580b57cec5SDimitry Andric
73590b57cec5SDimitry Andric llvm::Constant *
GetClassGlobal(const ObjCInterfaceDecl * ID,bool metaclass,ForDefinition_t isForDefinition)73600b57cec5SDimitry Andric CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
73610b57cec5SDimitry Andric bool metaclass,
73620b57cec5SDimitry Andric ForDefinition_t isForDefinition) {
73630b57cec5SDimitry Andric auto prefix =
73640b57cec5SDimitry Andric (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
73650b57cec5SDimitry Andric return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
73660b57cec5SDimitry Andric isForDefinition,
73670b57cec5SDimitry Andric ID->isWeakImported(),
73680b57cec5SDimitry Andric !isForDefinition
73690b57cec5SDimitry Andric && CGM.getTriple().isOSBinFormatCOFF()
73700b57cec5SDimitry Andric && ID->hasAttr<DLLImportAttr>());
73710b57cec5SDimitry Andric }
73720b57cec5SDimitry Andric
73730b57cec5SDimitry Andric llvm::Constant *
GetClassGlobal(StringRef Name,ForDefinition_t IsForDefinition,bool Weak,bool DLLImport)73740b57cec5SDimitry Andric CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
73750b57cec5SDimitry Andric ForDefinition_t IsForDefinition,
73760b57cec5SDimitry Andric bool Weak, bool DLLImport) {
73770b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes L =
73780b57cec5SDimitry Andric Weak ? llvm::GlobalValue::ExternalWeakLinkage
73790b57cec5SDimitry Andric : llvm::GlobalValue::ExternalLinkage;
73800b57cec5SDimitry Andric
73810b57cec5SDimitry Andric llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
738281ad6265SDimitry Andric if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
73830b57cec5SDimitry Andric auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
73840b57cec5SDimitry Andric nullptr, Name);
73850b57cec5SDimitry Andric
73860b57cec5SDimitry Andric if (DLLImport)
73870b57cec5SDimitry Andric NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
73880b57cec5SDimitry Andric
73890b57cec5SDimitry Andric if (GV) {
73905f757f3fSDimitry Andric GV->replaceAllUsesWith(NewGV);
73910b57cec5SDimitry Andric GV->eraseFromParent();
73920b57cec5SDimitry Andric }
73930b57cec5SDimitry Andric GV = NewGV;
739406c3fb27SDimitry Andric CGM.getModule().insertGlobalVariable(GV);
73950b57cec5SDimitry Andric }
73960b57cec5SDimitry Andric
73970b57cec5SDimitry Andric assert(GV->getLinkage() == L);
73980b57cec5SDimitry Andric return GV;
73990b57cec5SDimitry Andric }
74000b57cec5SDimitry Andric
74010b57cec5SDimitry Andric llvm::Constant *
GetClassGlobalForClassRef(const ObjCInterfaceDecl * ID)74020b57cec5SDimitry Andric CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
74030b57cec5SDimitry Andric llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
74040b57cec5SDimitry Andric NotForDefinition);
74050b57cec5SDimitry Andric
74060b57cec5SDimitry Andric if (!ID->hasAttr<ObjCClassStubAttr>())
74070b57cec5SDimitry Andric return ClassGV;
74080b57cec5SDimitry Andric
74090b57cec5SDimitry Andric ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
74100b57cec5SDimitry Andric
74110b57cec5SDimitry Andric // Stub classes are pointer-aligned. Classrefs pointing at stub classes
74120b57cec5SDimitry Andric // must set the least significant bit set to 1.
74130b57cec5SDimitry Andric auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
74140b57cec5SDimitry Andric return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
74150b57cec5SDimitry Andric }
74160b57cec5SDimitry Andric
74170b57cec5SDimitry Andric llvm::Value *
EmitLoadOfClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,llvm::GlobalVariable * Entry)74180b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
74190b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
74200b57cec5SDimitry Andric llvm::GlobalVariable *Entry) {
74210b57cec5SDimitry Andric if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
74220b57cec5SDimitry Andric // Classrefs pointing at Objective-C stub classes must be loaded by calling
74230b57cec5SDimitry Andric // a special runtime function.
74240b57cec5SDimitry Andric return CGF.EmitRuntimeCall(
74250b57cec5SDimitry Andric ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result");
74260b57cec5SDimitry Andric }
74270b57cec5SDimitry Andric
74280b57cec5SDimitry Andric CharUnits Align = CGF.getPointerAlign();
7429fe6060f1SDimitry Andric return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
74300b57cec5SDimitry Andric }
74310b57cec5SDimitry Andric
74320b57cec5SDimitry Andric llvm::Value *
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II,const ObjCInterfaceDecl * ID)74330b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
74340b57cec5SDimitry Andric IdentifierInfo *II,
74350b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
74360b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = ClassReferences[II];
74370b57cec5SDimitry Andric
74380b57cec5SDimitry Andric if (!Entry) {
74390b57cec5SDimitry Andric llvm::Constant *ClassGV;
74400b57cec5SDimitry Andric if (ID) {
74410b57cec5SDimitry Andric ClassGV = GetClassGlobalForClassRef(ID);
74420b57cec5SDimitry Andric } else {
74430b57cec5SDimitry Andric ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
74440b57cec5SDimitry Andric NotForDefinition);
74450b57cec5SDimitry Andric assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
74460b57cec5SDimitry Andric "classref was emitted with the wrong type?");
74470b57cec5SDimitry Andric }
74480b57cec5SDimitry Andric
74490b57cec5SDimitry Andric std::string SectionName =
74500b57cec5SDimitry Andric GetSectionName("__objc_classrefs", "regular,no_dead_strip");
74510b57cec5SDimitry Andric Entry = new llvm::GlobalVariable(
74520b57cec5SDimitry Andric CGM.getModule(), ClassGV->getType(), false,
74530b57cec5SDimitry Andric getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
74540b57cec5SDimitry Andric "OBJC_CLASSLIST_REFERENCES_$_");
7455a7dea167SDimitry Andric Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
74560b57cec5SDimitry Andric if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
74570b57cec5SDimitry Andric Entry->setSection(SectionName);
74580b57cec5SDimitry Andric
74590b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(Entry);
74600b57cec5SDimitry Andric }
74610b57cec5SDimitry Andric
74620b57cec5SDimitry Andric return EmitLoadOfClassRef(CGF, ID, Entry);
74630b57cec5SDimitry Andric }
74640b57cec5SDimitry Andric
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)74650b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
74660b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
74670b57cec5SDimitry Andric // If the class has the objc_runtime_visible attribute, we need to
74680b57cec5SDimitry Andric // use the Objective-C runtime to get the class.
74690b57cec5SDimitry Andric if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
74700b57cec5SDimitry Andric return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
74710b57cec5SDimitry Andric
74720b57cec5SDimitry Andric return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
74730b57cec5SDimitry Andric }
74740b57cec5SDimitry Andric
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)74750b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
74760b57cec5SDimitry Andric CodeGenFunction &CGF) {
74770b57cec5SDimitry Andric IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
74780b57cec5SDimitry Andric return EmitClassRefFromId(CGF, II, nullptr);
74790b57cec5SDimitry Andric }
74800b57cec5SDimitry Andric
74810b57cec5SDimitry Andric llvm::Value *
EmitSuperClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)74820b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
74830b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
74840b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
74850b57cec5SDimitry Andric
74860b57cec5SDimitry Andric if (!Entry) {
74870b57cec5SDimitry Andric llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
74880b57cec5SDimitry Andric std::string SectionName =
74890b57cec5SDimitry Andric GetSectionName("__objc_superrefs", "regular,no_dead_strip");
74905ffd83dbSDimitry Andric Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
74915ffd83dbSDimitry Andric llvm::GlobalValue::PrivateLinkage, ClassGV,
74920b57cec5SDimitry Andric "OBJC_CLASSLIST_SUP_REFS_$_");
7493a7dea167SDimitry Andric Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
74940b57cec5SDimitry Andric Entry->setSection(SectionName);
74950b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(Entry);
74960b57cec5SDimitry Andric }
74970b57cec5SDimitry Andric
74980b57cec5SDimitry Andric return EmitLoadOfClassRef(CGF, ID, Entry);
74990b57cec5SDimitry Andric }
75000b57cec5SDimitry Andric
75010b57cec5SDimitry Andric /// EmitMetaClassRef - Return a Value * of the address of _class_t
75020b57cec5SDimitry Andric /// meta-data
75030b57cec5SDimitry Andric ///
EmitMetaClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,bool Weak)75040b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
75050b57cec5SDimitry Andric const ObjCInterfaceDecl *ID,
75060b57cec5SDimitry Andric bool Weak) {
75070b57cec5SDimitry Andric CharUnits Align = CGF.getPointerAlign();
75080b57cec5SDimitry Andric llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
75090b57cec5SDimitry Andric if (!Entry) {
75100b57cec5SDimitry Andric auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
75110b57cec5SDimitry Andric std::string SectionName =
75120b57cec5SDimitry Andric GetSectionName("__objc_superrefs", "regular,no_dead_strip");
75135ffd83dbSDimitry Andric Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
75145ffd83dbSDimitry Andric false, llvm::GlobalValue::PrivateLinkage,
75155ffd83dbSDimitry Andric MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
7516a7dea167SDimitry Andric Entry->setAlignment(Align.getAsAlign());
75170b57cec5SDimitry Andric Entry->setSection(SectionName);
75180b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(Entry);
75190b57cec5SDimitry Andric }
75200b57cec5SDimitry Andric
7521fe6060f1SDimitry Andric return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
75220b57cec5SDimitry Andric }
75230b57cec5SDimitry Andric
75240b57cec5SDimitry Andric /// GetClass - Return a reference to the class for the given interface
75250b57cec5SDimitry Andric /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)75260b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
75270b57cec5SDimitry Andric const ObjCInterfaceDecl *ID) {
75280b57cec5SDimitry Andric if (ID->isWeakImported()) {
75290b57cec5SDimitry Andric auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
75300b57cec5SDimitry Andric (void)ClassGV;
75310b57cec5SDimitry Andric assert(!isa<llvm::GlobalVariable>(ClassGV) ||
75320b57cec5SDimitry Andric cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
75330b57cec5SDimitry Andric }
75340b57cec5SDimitry Andric
75350b57cec5SDimitry Andric return EmitClassRef(CGF, ID);
75360b57cec5SDimitry Andric }
75370b57cec5SDimitry Andric
75380b57cec5SDimitry Andric /// Generates a message send where the super is the receiver. This is
75390b57cec5SDimitry Andric /// a message send to self with special delivery semantics indicating
75400b57cec5SDimitry Andric /// which class's method should be called.
75410b57cec5SDimitry Andric CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,const ObjCInterfaceDecl * Class,bool isCategoryImpl,llvm::Value * Receiver,bool IsClassMessage,const CodeGen::CallArgList & CallArgs,const ObjCMethodDecl * Method)75420b57cec5SDimitry Andric CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
75430b57cec5SDimitry Andric ReturnValueSlot Return,
75440b57cec5SDimitry Andric QualType ResultType,
75450b57cec5SDimitry Andric Selector Sel,
75460b57cec5SDimitry Andric const ObjCInterfaceDecl *Class,
75470b57cec5SDimitry Andric bool isCategoryImpl,
75480b57cec5SDimitry Andric llvm::Value *Receiver,
75490b57cec5SDimitry Andric bool IsClassMessage,
75500b57cec5SDimitry Andric const CodeGen::CallArgList &CallArgs,
75510b57cec5SDimitry Andric const ObjCMethodDecl *Method) {
75520b57cec5SDimitry Andric // ...
75530b57cec5SDimitry Andric // Create and init a super structure; this is a (receiver, class)
75540b57cec5SDimitry Andric // pair we will pass to objc_msgSendSuper.
7555*0fca6ea1SDimitry Andric RawAddress ObjCSuper = CGF.CreateTempAlloca(
7556*0fca6ea1SDimitry Andric ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super");
75570b57cec5SDimitry Andric
75580b57cec5SDimitry Andric llvm::Value *ReceiverAsObject =
75590b57cec5SDimitry Andric CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
75600b57cec5SDimitry Andric CGF.Builder.CreateStore(ReceiverAsObject,
75610b57cec5SDimitry Andric CGF.Builder.CreateStructGEP(ObjCSuper, 0));
75620b57cec5SDimitry Andric
75630b57cec5SDimitry Andric // If this is a class message the metaclass is passed as the target.
75640b57cec5SDimitry Andric llvm::Value *Target;
75650b57cec5SDimitry Andric if (IsClassMessage)
75660b57cec5SDimitry Andric Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
75670b57cec5SDimitry Andric else
75680b57cec5SDimitry Andric Target = EmitSuperClassRef(CGF, Class);
75690b57cec5SDimitry Andric
75700b57cec5SDimitry Andric // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
75710b57cec5SDimitry Andric // ObjCTypes types.
75720b57cec5SDimitry Andric llvm::Type *ClassTy =
75730b57cec5SDimitry Andric CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
75740b57cec5SDimitry Andric Target = CGF.Builder.CreateBitCast(Target, ClassTy);
75750b57cec5SDimitry Andric CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
75760b57cec5SDimitry Andric
75770b57cec5SDimitry Andric return (isVTableDispatchedSelector(Sel))
75780b57cec5SDimitry Andric ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
75790b57cec5SDimitry Andric ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
75800b57cec5SDimitry Andric true, CallArgs, Method)
7581480093f4SDimitry Andric : EmitMessageSend(CGF, Return, ResultType, Sel,
75820b57cec5SDimitry Andric ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
75830b57cec5SDimitry Andric true, CallArgs, Method, Class, ObjCTypes);
75840b57cec5SDimitry Andric }
75850b57cec5SDimitry Andric
EmitSelector(CodeGenFunction & CGF,Selector Sel)75860b57cec5SDimitry Andric llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
75870b57cec5SDimitry Andric Selector Sel) {
7588480093f4SDimitry Andric Address Addr = EmitSelectorAddr(Sel);
75890b57cec5SDimitry Andric
75900b57cec5SDimitry Andric llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
759106c3fb27SDimitry Andric LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
7592bdd1243dSDimitry Andric llvm::MDNode::get(VMContext, std::nullopt));
75930b57cec5SDimitry Andric return LI;
75940b57cec5SDimitry Andric }
75950b57cec5SDimitry Andric
EmitSelectorAddr(Selector Sel)7596*0fca6ea1SDimitry Andric ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
75970b57cec5SDimitry Andric llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7598480093f4SDimitry Andric CharUnits Align = CGM.getPointerAlign();
75990b57cec5SDimitry Andric if (!Entry) {
76000b57cec5SDimitry Andric std::string SectionName =
76010b57cec5SDimitry Andric GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
76020b57cec5SDimitry Andric Entry = new llvm::GlobalVariable(
76030b57cec5SDimitry Andric CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
76045f757f3fSDimitry Andric getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
76050b57cec5SDimitry Andric "OBJC_SELECTOR_REFERENCES_");
76060b57cec5SDimitry Andric Entry->setExternallyInitialized(true);
76070b57cec5SDimitry Andric Entry->setSection(SectionName);
7608a7dea167SDimitry Andric Entry->setAlignment(Align.getAsAlign());
76090b57cec5SDimitry Andric CGM.addCompilerUsedGlobal(Entry);
76100b57cec5SDimitry Andric }
76110b57cec5SDimitry Andric
7612*0fca6ea1SDimitry Andric return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
76130b57cec5SDimitry Andric }
76140b57cec5SDimitry Andric
76150b57cec5SDimitry Andric /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
76160b57cec5SDimitry Andric /// objc_assign_ivar (id src, id *dst, ptrdiff_t)
76170b57cec5SDimitry Andric ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,llvm::Value * ivarOffset)76180b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
76190b57cec5SDimitry Andric llvm::Value *src,
76200b57cec5SDimitry Andric Address dst,
76210b57cec5SDimitry Andric llvm::Value *ivarOffset) {
76220b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
76230b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
76240b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
76250b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
76260b57cec5SDimitry Andric src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
76270b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
76280b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
76290b57cec5SDimitry Andric }
76300b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7631*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7632*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
763381ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal, ivarOffset};
76340b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
76350b57cec5SDimitry Andric }
76360b57cec5SDimitry Andric
76370b57cec5SDimitry Andric /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
76380b57cec5SDimitry Andric /// objc_assign_strongCast (id src, id *dst)
76390b57cec5SDimitry Andric ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)76400b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
76410b57cec5SDimitry Andric CodeGen::CodeGenFunction &CGF,
76420b57cec5SDimitry Andric llvm::Value *src, Address dst) {
76430b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
76440b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
76450b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
76460b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
76470b57cec5SDimitry Andric src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
76480b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
76490b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
76500b57cec5SDimitry Andric }
76510b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7652*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7653*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
765481ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal};
76550b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
76560b57cec5SDimitry Andric args, "weakassign");
76570b57cec5SDimitry Andric }
76580b57cec5SDimitry Andric
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,Address DestPtr,Address SrcPtr,llvm::Value * Size)76590b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
766006c3fb27SDimitry Andric CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
76610b57cec5SDimitry Andric llvm::Value *Size) {
7662*0fca6ea1SDimitry Andric llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
7663*0fca6ea1SDimitry Andric SrcPtr.emitRawPointer(CGF), Size};
76640b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
76650b57cec5SDimitry Andric }
76660b57cec5SDimitry Andric
76670b57cec5SDimitry Andric /// EmitObjCWeakRead - Code gen for loading value of a __weak
76680b57cec5SDimitry Andric /// object: objc_read_weak (id *src)
76690b57cec5SDimitry Andric ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,Address AddrWeakObj)76700b57cec5SDimitry Andric llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
76710b57cec5SDimitry Andric CodeGen::CodeGenFunction &CGF,
76720b57cec5SDimitry Andric Address AddrWeakObj) {
76730b57cec5SDimitry Andric llvm::Type *DestTy = AddrWeakObj.getElementType();
767481ad6265SDimitry Andric llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
7675*0fca6ea1SDimitry Andric AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
76760b57cec5SDimitry Andric llvm::Value *read_weak =
76770b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
767881ad6265SDimitry Andric AddrWeakObjVal, "weakread");
76790b57cec5SDimitry Andric read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
76800b57cec5SDimitry Andric return read_weak;
76810b57cec5SDimitry Andric }
76820b57cec5SDimitry Andric
76830b57cec5SDimitry Andric /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
76840b57cec5SDimitry Andric /// objc_assign_weak (id src, id *dst)
76850b57cec5SDimitry Andric ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)76860b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
76870b57cec5SDimitry Andric llvm::Value *src, Address dst) {
76880b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
76890b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
76900b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
76910b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
76920b57cec5SDimitry Andric src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
76930b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
76940b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
76950b57cec5SDimitry Andric }
76960b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7697*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7698*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
769981ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal};
77000b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
77010b57cec5SDimitry Andric args, "weakassign");
77020b57cec5SDimitry Andric }
77030b57cec5SDimitry Andric
77040b57cec5SDimitry Andric /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
77050b57cec5SDimitry Andric /// objc_assign_global (id src, id *dst)
77060b57cec5SDimitry Andric ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,bool threadlocal)77070b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
77080b57cec5SDimitry Andric llvm::Value *src, Address dst,
77090b57cec5SDimitry Andric bool threadlocal) {
77100b57cec5SDimitry Andric llvm::Type * SrcTy = src->getType();
77110b57cec5SDimitry Andric if (!isa<llvm::PointerType>(SrcTy)) {
77120b57cec5SDimitry Andric unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
77130b57cec5SDimitry Andric assert(Size <= 8 && "does not support size > 8");
77140b57cec5SDimitry Andric src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
77150b57cec5SDimitry Andric : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
77160b57cec5SDimitry Andric src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
77170b57cec5SDimitry Andric }
77180b57cec5SDimitry Andric src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7719*0fca6ea1SDimitry Andric llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7720*0fca6ea1SDimitry Andric ObjCTypes.PtrObjectPtrTy);
772181ad6265SDimitry Andric llvm::Value *args[] = {src, dstVal};
77220b57cec5SDimitry Andric if (!threadlocal)
77230b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
77240b57cec5SDimitry Andric args, "globalassign");
77250b57cec5SDimitry Andric else
77260b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
77270b57cec5SDimitry Andric args, "threadlocalassign");
77280b57cec5SDimitry Andric }
77290b57cec5SDimitry Andric
77300b57cec5SDimitry Andric void
EmitSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)77310b57cec5SDimitry Andric CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
77320b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S) {
77330b57cec5SDimitry Andric EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
77340b57cec5SDimitry Andric ObjCTypes.getSyncExitFn());
77350b57cec5SDimitry Andric }
77360b57cec5SDimitry Andric
77370b57cec5SDimitry Andric llvm::Constant *
GetEHType(QualType T)77380b57cec5SDimitry Andric CGObjCNonFragileABIMac::GetEHType(QualType T) {
77390b57cec5SDimitry Andric // There's a particular fixed type info for 'id'.
77400b57cec5SDimitry Andric if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
77410b57cec5SDimitry Andric auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
77420b57cec5SDimitry Andric if (!IDEHType) {
77430b57cec5SDimitry Andric IDEHType =
77440b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
77450b57cec5SDimitry Andric llvm::GlobalValue::ExternalLinkage, nullptr,
77460b57cec5SDimitry Andric "OBJC_EHTYPE_id");
77470b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatCOFF())
77480b57cec5SDimitry Andric IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
77490b57cec5SDimitry Andric }
77500b57cec5SDimitry Andric return IDEHType;
77510b57cec5SDimitry Andric }
77520b57cec5SDimitry Andric
77530b57cec5SDimitry Andric // All other types should be Objective-C interface pointer types.
77540b57cec5SDimitry Andric const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
77550b57cec5SDimitry Andric assert(PT && "Invalid @catch type.");
77560b57cec5SDimitry Andric
77570b57cec5SDimitry Andric const ObjCInterfaceType *IT = PT->getInterfaceType();
77580b57cec5SDimitry Andric assert(IT && "Invalid @catch type.");
77590b57cec5SDimitry Andric
77600b57cec5SDimitry Andric return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
77610b57cec5SDimitry Andric }
77620b57cec5SDimitry Andric
EmitTryStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtTryStmt & S)77630b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
77640b57cec5SDimitry Andric const ObjCAtTryStmt &S) {
77650b57cec5SDimitry Andric EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
77660b57cec5SDimitry Andric ObjCTypes.getObjCEndCatchFn(),
77670b57cec5SDimitry Andric ObjCTypes.getExceptionRethrowFn());
77680b57cec5SDimitry Andric }
77690b57cec5SDimitry Andric
77700b57cec5SDimitry Andric /// EmitThrowStmt - Generate code for a throw statement.
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)77710b57cec5SDimitry Andric void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
77720b57cec5SDimitry Andric const ObjCAtThrowStmt &S,
77730b57cec5SDimitry Andric bool ClearInsertionPoint) {
77740b57cec5SDimitry Andric if (const Expr *ThrowExpr = S.getThrowExpr()) {
77750b57cec5SDimitry Andric llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
77760b57cec5SDimitry Andric Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
77770b57cec5SDimitry Andric llvm::CallBase *Call =
77780b57cec5SDimitry Andric CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
77790b57cec5SDimitry Andric Call->setDoesNotReturn();
77800b57cec5SDimitry Andric } else {
77810b57cec5SDimitry Andric llvm::CallBase *Call =
77820b57cec5SDimitry Andric CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
77830b57cec5SDimitry Andric Call->setDoesNotReturn();
77840b57cec5SDimitry Andric }
77850b57cec5SDimitry Andric
77860b57cec5SDimitry Andric CGF.Builder.CreateUnreachable();
77870b57cec5SDimitry Andric if (ClearInsertionPoint)
77880b57cec5SDimitry Andric CGF.Builder.ClearInsertionPoint();
77890b57cec5SDimitry Andric }
77900b57cec5SDimitry Andric
77910b57cec5SDimitry Andric llvm::Constant *
GetInterfaceEHType(const ObjCInterfaceDecl * ID,ForDefinition_t IsForDefinition)77920b57cec5SDimitry Andric CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
77930b57cec5SDimitry Andric ForDefinition_t IsForDefinition) {
77940b57cec5SDimitry Andric llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
77950b57cec5SDimitry Andric StringRef ClassName = ID->getObjCRuntimeNameAsString();
77960b57cec5SDimitry Andric
77970b57cec5SDimitry Andric // If we don't need a definition, return the entry if found or check
77980b57cec5SDimitry Andric // if we use an external reference.
77990b57cec5SDimitry Andric if (!IsForDefinition) {
78000b57cec5SDimitry Andric if (Entry)
78010b57cec5SDimitry Andric return Entry;
78020b57cec5SDimitry Andric
78030b57cec5SDimitry Andric // If this type (or a super class) has the __objc_exception__
78040b57cec5SDimitry Andric // attribute, emit an external reference.
78050b57cec5SDimitry Andric if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
78060b57cec5SDimitry Andric std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
78070b57cec5SDimitry Andric Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
78080b57cec5SDimitry Andric false, llvm::GlobalValue::ExternalLinkage,
78090b57cec5SDimitry Andric nullptr, EHTypeName);
78100b57cec5SDimitry Andric CGM.setGVProperties(Entry, ID);
78110b57cec5SDimitry Andric return Entry;
78120b57cec5SDimitry Andric }
78130b57cec5SDimitry Andric }
78140b57cec5SDimitry Andric
78150b57cec5SDimitry Andric // Otherwise we need to either make a new entry or fill in the initializer.
78160b57cec5SDimitry Andric assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
78170b57cec5SDimitry Andric
78180b57cec5SDimitry Andric std::string VTableName = "objc_ehtype_vtable";
78190b57cec5SDimitry Andric auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
78200b57cec5SDimitry Andric if (!VTableGV) {
78210b57cec5SDimitry Andric VTableGV =
78220b57cec5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
78230b57cec5SDimitry Andric llvm::GlobalValue::ExternalLinkage, nullptr,
78240b57cec5SDimitry Andric VTableName);
78250b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatCOFF())
78260b57cec5SDimitry Andric VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
78270b57cec5SDimitry Andric }
78280b57cec5SDimitry Andric
78290b57cec5SDimitry Andric llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
78300b57cec5SDimitry Andric ConstantInitBuilder builder(CGM);
78310b57cec5SDimitry Andric auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
78320b57cec5SDimitry Andric values.add(
78330b57cec5SDimitry Andric llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
78340b57cec5SDimitry Andric VTableGV, VTableIdx));
78350b57cec5SDimitry Andric values.add(GetClassName(ClassName));
78360b57cec5SDimitry Andric values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
78370b57cec5SDimitry Andric
78380b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes L = IsForDefinition
78390b57cec5SDimitry Andric ? llvm::GlobalValue::ExternalLinkage
78400b57cec5SDimitry Andric : llvm::GlobalValue::WeakAnyLinkage;
78410b57cec5SDimitry Andric if (Entry) {
78420b57cec5SDimitry Andric values.finishAndSetAsInitializer(Entry);
7843a7dea167SDimitry Andric Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
78440b57cec5SDimitry Andric } else {
78450b57cec5SDimitry Andric Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
78460b57cec5SDimitry Andric CGM.getPointerAlign(),
78470b57cec5SDimitry Andric /*constant*/ false,
78480b57cec5SDimitry Andric L);
78490b57cec5SDimitry Andric if (hasObjCExceptionAttribute(CGM.getContext(), ID))
78500b57cec5SDimitry Andric CGM.setGVProperties(Entry, ID);
78510b57cec5SDimitry Andric }
78520b57cec5SDimitry Andric assert(Entry->getLinkage() == L);
78530b57cec5SDimitry Andric
78540b57cec5SDimitry Andric if (!CGM.getTriple().isOSBinFormatCOFF())
78550b57cec5SDimitry Andric if (ID->getVisibility() == HiddenVisibility)
78560b57cec5SDimitry Andric Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
78570b57cec5SDimitry Andric
78580b57cec5SDimitry Andric if (IsForDefinition)
78590b57cec5SDimitry Andric if (CGM.getTriple().isOSBinFormatMachO())
78600b57cec5SDimitry Andric Entry->setSection("__DATA,__objc_const");
78610b57cec5SDimitry Andric
78620b57cec5SDimitry Andric return Entry;
78630b57cec5SDimitry Andric }
78640b57cec5SDimitry Andric
78650b57cec5SDimitry Andric /* *** */
78660b57cec5SDimitry Andric
78670b57cec5SDimitry Andric CodeGen::CGObjCRuntime *
CreateMacObjCRuntime(CodeGen::CodeGenModule & CGM)78680b57cec5SDimitry Andric CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
78690b57cec5SDimitry Andric switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
78700b57cec5SDimitry Andric case ObjCRuntime::FragileMacOSX:
78710b57cec5SDimitry Andric return new CGObjCMac(CGM);
78720b57cec5SDimitry Andric
78730b57cec5SDimitry Andric case ObjCRuntime::MacOSX:
78740b57cec5SDimitry Andric case ObjCRuntime::iOS:
78750b57cec5SDimitry Andric case ObjCRuntime::WatchOS:
78760b57cec5SDimitry Andric return new CGObjCNonFragileABIMac(CGM);
78770b57cec5SDimitry Andric
78780b57cec5SDimitry Andric case ObjCRuntime::GNUstep:
78790b57cec5SDimitry Andric case ObjCRuntime::GCC:
78800b57cec5SDimitry Andric case ObjCRuntime::ObjFW:
78810b57cec5SDimitry Andric llvm_unreachable("these runtimes are not Mac runtimes");
78820b57cec5SDimitry Andric }
78830b57cec5SDimitry Andric llvm_unreachable("bad runtime");
78840b57cec5SDimitry Andric }
7885