30#include "llvm/ADT/CachedHashString.h"
31#include "llvm/ADT/DenseSet.h"
32#include "llvm/ADT/SetVector.h"
33#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/ADT/SmallString.h"
35#include "llvm/IR/DataLayout.h"
36#include "llvm/IR/InlineAsm.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/LLVMContext.h"
39#include "llvm/IR/Module.h"
40#include "llvm/Support/ScopedPrinter.h"
41#include "llvm/Support/raw_ostream.h"
53class ObjCCommonTypesHelper {
55 llvm::LLVMContext &VMContext;
65 llvm::FunctionCallee getMessageSendFn()
const {
68 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
69 return CGM.CreateRuntimeFunction(
70 llvm::FunctionType::get(ObjectPtrTy, params,
true),
"objc_msgSend",
71 llvm::AttributeList::get(CGM.getLLVMContext(),
72 llvm::AttributeList::FunctionIndex,
73 llvm::Attribute::NonLazyBind));
81 llvm::FunctionCallee getMessageSendStretFn()
const {
82 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
83 return CGM.CreateRuntimeFunction(
84 llvm::FunctionType::get(CGM.VoidTy, params,
true),
85 "objc_msgSend_stret");
93 llvm::FunctionCallee getMessageSendFpretFn()
const {
94 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
95 return CGM.CreateRuntimeFunction(
96 llvm::FunctionType::get(CGM.DoubleTy, params,
true),
97 "objc_msgSend_fpret");
105 llvm::FunctionCallee getMessageSendFp2retFn()
const {
106 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
107 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
108 llvm::Type *resultType =
109 llvm::StructType::get(longDoubleType, longDoubleType);
111 return CGM.CreateRuntimeFunction(
112 llvm::FunctionType::get(resultType, params,
true),
113 "objc_msgSend_fp2ret");
121 llvm::FunctionCallee getMessageSendSuperFn()
const {
122 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
123 return CGM.CreateRuntimeFunction(
124 llvm::FunctionType::get(ObjectPtrTy, params,
true),
125 "objc_msgSendSuper");
132 llvm::FunctionCallee getMessageSendSuperFn2()
const {
133 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
134 return CGM.CreateRuntimeFunction(
135 llvm::FunctionType::get(ObjectPtrTy, params,
true),
136 "objc_msgSendSuper2");
143 llvm::FunctionCallee getMessageSendSuperStretFn()
const {
144 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
145 return CGM.CreateRuntimeFunction(
146 llvm::FunctionType::get(CGM.VoidTy, params,
true),
147 "objc_msgSendSuper_stret");
154 llvm::FunctionCallee getMessageSendSuperStretFn2()
const {
155 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
156 return CGM.CreateRuntimeFunction(
157 llvm::FunctionType::get(CGM.VoidTy, params,
true),
158 "objc_msgSendSuper2_stret");
161 llvm::FunctionCallee getMessageSendSuperFpretFn()
const {
163 return getMessageSendSuperFn();
166 llvm::FunctionCallee getMessageSendSuperFpretFn2()
const {
168 return getMessageSendSuperFn2();
172 CodeGen::CodeGenModule &CGM;
175 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
176 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
177 llvm::PointerType *Int8PtrProgramASTy;
178 llvm::Type *IvarOffsetVarTy;
181 llvm::PointerType *ObjectPtrTy;
184 llvm::PointerType *PtrObjectPtrTy;
187 llvm::PointerType *SelectorPtrTy;
192 QualType SuperPtrCTy;
195 llvm::StructType *SuperTy;
197 llvm::PointerType *SuperPtrTy;
201 llvm::StructType *PropertyTy;
205 llvm::StructType *PropertyListTy;
207 llvm::PointerType *PropertyListPtrTy;
210 llvm::StructType *MethodTy;
215 llvm::PointerType *CachePtrTy;
217 llvm::FunctionCallee getGetPropertyFn() {
218 CodeGen::CodeGenTypes &Types = CGM.getTypes();
219 ASTContext &Ctx = CGM.getContext();
228 return CGM.CreateRuntimeFunction(FTy,
"objc_getProperty");
231 llvm::FunctionCallee getSetPropertyFn() {
232 CodeGen::CodeGenTypes &Types = CGM.getTypes();
233 ASTContext &Ctx = CGM.getContext();
246 return CGM.CreateRuntimeFunction(FTy,
"objc_setProperty");
249 llvm::FunctionCallee getOptimizedSetPropertyFn(
bool atomic,
bool copy) {
250 CodeGen::CodeGenTypes &Types = CGM.getTypes();
251 ASTContext &Ctx = CGM.getContext();
261 SmallVector<CanQualType, 4> Params;
264 Params.push_back(IdType);
265 Params.push_back(SelType);
266 Params.push_back(IdType);
272 name =
"objc_setProperty_atomic_copy";
273 else if (atomic && !copy)
274 name =
"objc_setProperty_atomic";
275 else if (!atomic && copy)
276 name =
"objc_setProperty_nonatomic_copy";
278 name =
"objc_setProperty_nonatomic";
280 return CGM.CreateRuntimeFunction(FTy, name);
283 llvm::FunctionCallee getCopyStructFn() {
284 CodeGen::CodeGenTypes &Types = CGM.getTypes();
285 ASTContext &Ctx = CGM.getContext();
287 SmallVector<CanQualType, 5> Params;
291 Params.push_back(Ctx.
BoolTy);
292 Params.push_back(Ctx.
BoolTy);
295 return CGM.CreateRuntimeFunction(FTy,
"objc_copyStruct");
302 llvm::FunctionCallee getCppAtomicObjectFunction() {
303 CodeGen::CodeGenTypes &Types = CGM.getTypes();
304 ASTContext &Ctx = CGM.getContext();
307 SmallVector<CanQualType, 3> Params;
313 return CGM.CreateRuntimeFunction(FTy,
"objc_copyCppObjectAtomic");
316 llvm::FunctionCallee getEnumerationMutationFn() {
317 CodeGen::CodeGenTypes &Types = CGM.getTypes();
318 ASTContext &Ctx = CGM.getContext();
320 SmallVector<CanQualType, 1> Params;
324 return CGM.CreateRuntimeFunction(FTy,
"objc_enumerationMutation");
327 llvm::FunctionCallee getLookUpClassFn() {
328 CodeGen::CodeGenTypes &Types = CGM.getTypes();
329 ASTContext &Ctx = CGM.getContext();
331 SmallVector<CanQualType, 1> Params;
334 llvm::FunctionType *FTy =
337 return CGM.CreateRuntimeFunction(FTy,
"objc_lookUpClass");
341 llvm::FunctionCallee getGcReadWeakFn() {
343 llvm::Type *args[] = {CGM.DefaultPtrTy};
344 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
345 return CGM.CreateRuntimeFunction(FTy,
"objc_read_weak");
349 llvm::FunctionCallee getGcAssignWeakFn() {
351 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
352 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
353 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_weak");
357 llvm::FunctionCallee getGcAssignGlobalFn() {
359 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
360 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
361 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_global");
365 llvm::FunctionCallee getGcAssignThreadLocalFn() {
367 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
368 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
369 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_threadlocal");
373 llvm::FunctionCallee getGcAssignIvarFn() {
375 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy, CGM.PtrDiffTy};
376 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
377 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_ivar");
381 llvm::FunctionCallee GcMemmoveCollectableFn() {
383 llvm::Type *args[] = {Int8PtrTy, Int8PtrTy, LongTy};
384 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args,
false);
385 return CGM.CreateRuntimeFunction(FTy,
"objc_memmove_collectable");
389 llvm::FunctionCallee getGcAssignStrongCastFn() {
391 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
392 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
393 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_strongCast");
397 llvm::FunctionCallee getExceptionThrowFn() {
399 llvm::Type *args[] = {ObjectPtrTy};
400 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, args,
false);
401 return CGM.CreateRuntimeFunction(FTy,
"objc_exception_throw");
405 llvm::FunctionCallee getExceptionRethrowFn() {
407 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy,
false);
408 return CGM.CreateRuntimeFunction(FTy,
"objc_exception_rethrow");
412 llvm::FunctionCallee getSyncEnterFn() {
414 llvm::Type *args[] = {ObjectPtrTy};
415 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args,
false);
416 return CGM.CreateRuntimeFunction(FTy,
"objc_sync_enter");
420 llvm::FunctionCallee getSyncExitFn() {
422 llvm::Type *args[] = {ObjectPtrTy};
423 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args,
false);
424 return CGM.CreateRuntimeFunction(FTy,
"objc_sync_exit");
427 llvm::FunctionCallee getSendFn(
bool IsSuper)
const {
428 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
431 llvm::FunctionCallee getSendFn2(
bool IsSuper)
const {
432 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
435 llvm::FunctionCallee getSendStretFn(
bool IsSuper)
const {
436 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
439 llvm::FunctionCallee getSendStretFn2(
bool IsSuper)
const {
440 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
443 llvm::FunctionCallee getSendFpretFn(
bool IsSuper)
const {
444 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
447 llvm::FunctionCallee getSendFpretFn2(
bool IsSuper)
const {
448 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
451 llvm::FunctionCallee getSendFp2retFn(
bool IsSuper)
const {
452 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
455 llvm::FunctionCallee getSendFp2RetFn2(
bool IsSuper)
const {
456 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
459 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
464class ObjCTypesHelper :
public ObjCCommonTypesHelper {
467 llvm::StructType *SymtabTy;
469 llvm::PointerType *SymtabPtrTy;
471 llvm::StructType *ModuleTy;
474 llvm::StructType *ProtocolTy;
476 llvm::PointerType *ProtocolPtrTy;
479 llvm::StructType *ProtocolExtensionTy;
482 llvm::PointerType *ProtocolExtensionPtrTy;
485 llvm::StructType *MethodDescriptionTy;
488 llvm::StructType *MethodDescriptionListTy;
491 llvm::PointerType *MethodDescriptionListPtrTy;
493 llvm::StructType *ProtocolListTy;
495 llvm::PointerType *ProtocolListPtrTy;
497 llvm::StructType *CategoryTy;
499 llvm::StructType *ClassTy;
501 llvm::PointerType *ClassPtrTy;
503 llvm::StructType *ClassExtensionTy;
505 llvm::PointerType *ClassExtensionPtrTy;
507 llvm::StructType *IvarTy;
509 llvm::StructType *IvarListTy;
511 llvm::PointerType *IvarListPtrTy;
513 llvm::StructType *MethodListTy;
515 llvm::PointerType *MethodListPtrTy;
518 llvm::StructType *ExceptionDataTy;
521 llvm::FunctionCallee getExceptionTryEnterFn() {
524 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
525 "objc_exception_try_enter");
529 llvm::FunctionCallee getExceptionTryExitFn() {
532 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
533 "objc_exception_try_exit");
537 llvm::FunctionCallee getExceptionExtractFn() {
540 llvm::FunctionType::get(ObjectPtrTy, params,
false),
541 "objc_exception_extract");
545 llvm::FunctionCallee getExceptionMatchFn() {
546 llvm::Type *params[] = {ClassPtrTy, ObjectPtrTy};
548 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
549 "objc_exception_match");
553 llvm::FunctionCallee getSetJmpFn() {
557 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
"_setjmp",
559 llvm::AttributeList::FunctionIndex,
560 llvm::Attribute::NonLazyBind));
564 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
569class ObjCNonFragileABITypesHelper :
public ObjCCommonTypesHelper {
572 llvm::StructType *MethodListnfABITy;
575 llvm::PointerType *MethodListnfABIPtrTy;
578 llvm::StructType *ProtocolnfABITy;
581 llvm::PointerType *ProtocolnfABIPtrTy;
584 llvm::StructType *ProtocolListnfABITy;
587 llvm::PointerType *ProtocolListnfABIPtrTy;
590 llvm::StructType *ClassnfABITy;
593 llvm::PointerType *ClassnfABIPtrTy;
596 llvm::StructType *IvarnfABITy;
599 llvm::StructType *IvarListnfABITy;
602 llvm::PointerType *IvarListnfABIPtrTy;
605 llvm::StructType *ClassRonfABITy;
608 llvm::PointerType *ImpnfABITy;
611 llvm::StructType *CategorynfABITy;
620 llvm::StructType *MessageRefTy;
622 QualType MessageRefCTy;
625 llvm::Type *MessageRefPtrTy;
627 QualType MessageRefCPtrTy;
634 llvm::StructType *SuperMessageRefTy;
637 llvm::PointerType *SuperMessageRefPtrTy;
639 llvm::FunctionCallee getMessageSendFixupFn() {
641 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
643 llvm::FunctionType::get(ObjectPtrTy, params,
true),
644 "objc_msgSend_fixup");
647 llvm::FunctionCallee getMessageSendFpretFixupFn() {
649 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
651 llvm::FunctionType::get(ObjectPtrTy, params,
true),
652 "objc_msgSend_fpret_fixup");
655 llvm::FunctionCallee getMessageSendStretFixupFn() {
657 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
659 llvm::FunctionType::get(ObjectPtrTy, params,
true),
660 "objc_msgSend_stret_fixup");
663 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
666 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
668 llvm::FunctionType::get(ObjectPtrTy, params,
true),
669 "objc_msgSendSuper2_fixup");
672 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
675 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
677 llvm::FunctionType::get(ObjectPtrTy, params,
true),
678 "objc_msgSendSuper2_stret_fixup");
681 llvm::FunctionCallee getObjCEndCatchFn() {
686 llvm::FunctionCallee getObjCBeginCatchFn() {
687 llvm::Type *params[] = {Int8PtrTy};
689 llvm::FunctionType::get(Int8PtrTy, params,
false),
"objc_begin_catch");
697 llvm::FunctionCallee getLoadClassrefFn()
const {
703 llvm::Type *params[] = {Int8PtrPtrTy};
705 llvm::AttributeSet AS = llvm::AttributeSet::get(
707 llvm::Attribute::get(
C, llvm::Attribute::NonLazyBind),
708 llvm::Attribute::getWithMemoryEffects(
709 C, llvm::MemoryEffects::none()),
710 llvm::Attribute::get(
C, llvm::Attribute::NoUnwind),
713 llvm::FunctionType::get(ClassnfABIPtrTy, params,
false),
716 llvm::AttributeList::FunctionIndex, AS));
717 if (!CGM.
getTriple().isOSBinFormatCOFF())
719 ->setLinkage(llvm::Function::ExternalWeakLinkage);
724 llvm::StructType *EHTypeTy;
725 llvm::Type *EHTypePtrTy;
727 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
730enum class ObjCLabelType {
747 SKIP_SCAN(
unsigned _skip = 0,
unsigned _scan = 0)
748 : skip(_skip), scan(_scan) {}
756 enum BLOCK_LAYOUT_OPCODE {
763 BLOCK_LAYOUT_OPERATOR = 0,
769 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
774 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
778 BLOCK_LAYOUT_STRONG = 3,
781 BLOCK_LAYOUT_BYREF = 4,
785 BLOCK_LAYOUT_WEAK = 5,
789 BLOCK_LAYOUT_UNRETAINED = 6
807 enum BLOCK_LAYOUT_OPCODE opcode;
808 CharUnits block_var_bytepos;
809 CharUnits block_var_size;
810 RUN_SKIP(
enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
813 : opcode(
Opcode), block_var_bytepos(BytePos), block_var_size(
Size) {}
817 return block_var_bytepos <
b.block_var_bytepos;
822 llvm::LLVMContext &VMContext;
827 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
831 llvm::SetVector<IdentifierInfo *> LazySymbols;
837 llvm::SetVector<IdentifierInfo *> DefinedSymbols;
840 llvm::StringMap<llvm::GlobalVariable *> ClassNames;
843 llvm::DenseMap<Selector, llvm::GlobalVariable *> MethodVarNames;
846 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
850 llvm::StringMap<llvm::GlobalVariable *> MethodVarTypes;
854 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *> MethodDefinitions;
857 struct DirectMethodInfo {
860 llvm::Function *Thunk;
862 DirectMethodInfo(llvm::Function *Impl, llvm::Function *Thunk =
nullptr)
863 : Implementation(Impl), Thunk(Thunk) {}
868 llvm::DenseMap<const ObjCMethodDecl *, DirectMethodInfo>
869 DirectMethodDefinitions;
872 llvm::DenseMap<std::pair<Selector, StringRef>, llvm::Function *>
876 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> PropertyNames;
879 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> ClassReferences;
882 llvm::DenseMap<Selector, llvm::GlobalVariable *> SelectorReferences;
887 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> Protocols;
891 llvm::DenseSet<IdentifierInfo *> DefinedProtocols;
894 SmallVector<llvm::GlobalValue *, 16> DefinedClasses;
897 SmallVector<const ObjCInterfaceDecl *, 16> ImplementedClasses;
900 SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyClasses;
903 SmallVector<llvm::GlobalValue *, 16> DefinedCategories;
906 SmallVector<llvm::GlobalValue *, 16> DefinedStubCategories;
909 SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyCategories;
913 llvm::WeakTrackingVH ConstantStringClassRef;
914 llvm::WeakTrackingVH ConstantArrayClassRef;
915 llvm::WeakTrackingVH ConstantDictionaryClassRef;
917 llvm::WeakTrackingVH ConstantIntegerNumberClassRef;
918 llvm::WeakTrackingVH ConstantFloatNumberClassRef;
919 llvm::WeakTrackingVH ConstantDoubleNumberClassRef;
922 llvm::StructType *NSConstantStringType =
nullptr;
923 llvm::StructType *NSConstantArrayType =
nullptr;
924 llvm::StructType *NSConstantDictionaryType =
nullptr;
926 llvm::StructType *NSConstantIntegerNumberType =
nullptr;
927 llvm::StructType *NSConstantFloatNumberType =
nullptr;
928 llvm::StructType *NSConstantDoubleNumberType =
nullptr;
930 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
933 llvm::GlobalVariable *DefinedCFBooleanTrue =
nullptr;
934 llvm::GlobalVariable *DefinedCFBooleanFalse =
nullptr;
937 llvm::DenseMap<NSConstantNumberMapInfo, llvm::GlobalVariable *>
941 llvm::GlobalVariable *DefinedEmptyNSDictionary =
nullptr;
942 llvm::GlobalVariable *DefinedEmptyNSArray =
nullptr;
946 llvm::Constant *GetMethodVarName(Selector Sel);
947 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
953 llvm::Constant *GetMethodVarType(
const ObjCMethodDecl *D,
954 bool Extended =
false);
955 llvm::Constant *GetMethodVarType(
const FieldDecl *D);
959 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
962 llvm::Constant *GetPropertyTypeString(
const ObjCPropertyDecl *PD,
963 const Decl *Container);
968 llvm::Constant *GetClassName(StringRef RuntimeName);
970 llvm::Function *GetMethodDefinition(
const ObjCMethodDecl *MD);
979 llvm::Constant *BuildIvarLayout(
const ObjCImplementationDecl *OI,
980 CharUnits beginOffset, CharUnits endOffset,
983 llvm::Constant *BuildStrongIvarLayout(
const ObjCImplementationDecl *OI,
984 CharUnits beginOffset,
985 CharUnits endOffset) {
986 return BuildIvarLayout(OI, beginOffset, endOffset,
true,
false);
989 llvm::Constant *BuildWeakIvarLayout(
const ObjCImplementationDecl *OI,
990 CharUnits beginOffset,
993 return BuildIvarLayout(OI, beginOffset, endOffset,
false,
hasMRCWeakIvars);
1000 CharUnits FieldOffset, CharUnits FieldSize);
1002 void BuildRCBlockVarRecordLayout(
const RecordType *RT, CharUnits BytePos,
1003 bool &HasUnion,
bool ByrefLayout =
false);
1005 void BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
1006 const RecordDecl *RD,
1007 ArrayRef<const FieldDecl *> RecFields,
1008 CharUnits BytePos,
bool &HasUnion,
bool ByrefLayout);
1010 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
1012 llvm::Constant *getBitmapBlockLayout(
bool ComputeByrefLayout);
1016 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
1017 const ObjCCommonTypesHelper &ObjCTypes);
1021 llvm::Constant *EmitPropertyList(Twine Name,
const Decl *Container,
1022 const ObjCContainerDecl *OCD,
1023 const ObjCCommonTypesHelper &ObjCTypes,
1024 bool IsClassProperty);
1029 EmitProtocolMethodTypes(Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
1030 const ObjCCommonTypesHelper &ObjCTypes);
1035 llvm::Constant *GetProtocolRef(
const ObjCProtocolDecl *PD);
1039 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1040 const ObjCInterfaceDecl *ID,
1041 ObjCCommonTypesHelper &ObjCTypes);
1043 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1046 static constexpr llvm::StringLiteral GetNSConstantIntegerNumberSectionName() {
1047 return "__DATA,__objc_intobj,regular,no_dead_strip";
1051 static constexpr llvm::StringLiteral GetNSConstantFloatNumberSectionName() {
1052 return "__DATA,__objc_floatobj,regular,no_dead_strip";
1056 static constexpr llvm::StringLiteral GetNSConstantDoubleNumberSectionName() {
1057 return "__DATA,__objc_doubleobj,regular,no_dead_strip";
1062 static constexpr llvm::StringLiteral
1063 GetNSConstantCollectionStorageSectionName() {
1064 return "__DATA,__objc_arraydata,regular,no_dead_strip";
1068 static constexpr llvm::StringLiteral GetNSConstantArraySectionName() {
1069 return "__DATA,__objc_arrayobj,regular,no_dead_strip";
1073 static constexpr llvm::StringLiteral GetNSConstantDictionarySectionName() {
1074 return "__DATA,__objc_dictobj,regular,no_dead_strip";
1092 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1093 ConstantStructBuilder &
Init,
1094 StringRef Section, CharUnits Align,
1096 llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *
Init,
1097 StringRef Section, CharUnits Align,
1100 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
1101 ObjCLabelType LabelType,
1102 bool ForceNonFragileABI =
false,
1103 bool NullTerminate =
true);
1106 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1107 ReturnValueSlot Return, QualType ResultType,
1108 Selector Sel, llvm::Value *Arg0,
1109 QualType Arg0Ty,
bool IsSuper,
1110 const CallArgList &CallArgs,
1111 const ObjCMethodDecl *OMD,
1112 const ObjCInterfaceDecl *ClassReceiver,
1113 const ObjCCommonTypesHelper &ObjCTypes);
1117 void EmitImageInfo();
1120 CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
1121 : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}
1123 bool isNonFragileABI()
const {
return ObjCABI == 2; }
1126 llvm::GlobalVariable *EmitConstantCFBooleanTrue() {
1127 if (DefinedCFBooleanTrue)
1128 return DefinedCFBooleanTrue;
1131 "The current ABI doesn't support the constant CFBooleanTrue "
1136 DefinedCFBooleanTrue->addAttribute(
"objc_arc_inert");
1137 return DefinedCFBooleanTrue;
1141 llvm::GlobalVariable *EmitConstantCFBooleanFalse() {
1142 if (DefinedCFBooleanFalse)
1143 return DefinedCFBooleanFalse;
1146 "The current ABI doesn't support the constant CFBooleanFalse "
1151 DefinedCFBooleanFalse->addAttribute(
"objc_arc_inert");
1152 return DefinedCFBooleanFalse;
1156 llvm::GlobalVariable *EmitEmptyConstantNSDictionary() {
1157 if (DefinedEmptyNSDictionary)
1158 return DefinedEmptyNSDictionary;
1161 "The current ABI doesn't support an empty constant NSDictionary "
1166 DefinedEmptyNSDictionary->addAttribute(
"objc_arc_inert");
1167 return DefinedEmptyNSDictionary;
1171 llvm::GlobalVariable *EmitEmptyConstantNSArray() {
1172 if (DefinedEmptyNSArray)
1173 return DefinedEmptyNSArray;
1177 "The current ABI doesn't support an empty constant NSArray singleton!");
1181 DefinedEmptyNSArray->addAttribute(
"objc_arc_inert");
1182 return DefinedEmptyNSArray;
1185 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override;
1187 ConstantAddress GenerateConstantNumber(
const bool Value,
1188 const QualType &Ty)
override;
1189 ConstantAddress GenerateConstantNumber(
const llvm::APSInt &
Value,
1190 const QualType &Ty)
override;
1191 ConstantAddress GenerateConstantNumber(
const llvm::APFloat &
Value,
1192 const QualType &Ty)
override;
1194 GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects)
override;
1195 ConstantAddress GenerateConstantDictionary(
1196 const ObjCDictionaryLiteral *E,
1197 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects)
1200 ConstantAddress GenerateConstantNSString(
const StringLiteral *SL);
1201 ConstantAddress GenerateConstantNSNumber(
const bool Value,
1202 const QualType &Ty);
1203 ConstantAddress GenerateConstantNSNumber(
const llvm::APSInt &
Value,
1204 const QualType &Ty);
1205 ConstantAddress GenerateConstantNSNumber(
const llvm::APFloat &
Value,
1206 const QualType &Ty);
1208 GenerateConstantNSArray(
const ArrayRef<llvm::Constant *> &Objects);
1209 ConstantAddress GenerateConstantNSDictionary(
1210 const ObjCDictionaryLiteral *E,
1211 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects);
1214 GenerateMethod(
const ObjCMethodDecl *OMD,
1215 const ObjCContainerDecl *CD =
nullptr)
override;
1217 DirectMethodInfo &GenerateDirectMethod(
const ObjCMethodDecl *OMD,
1218 const ObjCContainerDecl *CD);
1223 llvm::Value *GenerateClassRealization(CodeGenFunction &CGF,
1224 llvm::Value *classObject,
1225 const ObjCInterfaceDecl *OID);
1227 void GenerateDirectMethodsPreconditionCheck(
1228 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
1229 const ObjCContainerDecl *CD)
override;
1231 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1232 const ObjCMethodDecl *OMD,
1233 const ObjCContainerDecl *CD)
override;
1236 GenerateMethodSelectorStub(Selector Sel, StringRef ClassName,
1237 const ObjCCommonTypesHelper &ObjCTypes);
1239 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override;
1245 virtual llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) = 0;
1247 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1248 virtual llvm::Constant *getNSConstantArrayClassRef() = 0;
1249 virtual llvm::Constant *getNSConstantDictionaryClassRef() = 0;
1251 virtual llvm::Constant *getNSConstantIntegerNumberClassRef() = 0;
1252 virtual llvm::Constant *getNSConstantFloatNumberClassRef() = 0;
1253 virtual llvm::Constant *getNSConstantDoubleNumberClassRef() = 0;
1255 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1256 const CGBlockInfo &blockInfo)
override;
1257 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1258 const CGBlockInfo &blockInfo)
override;
1259 std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
1260 const CGBlockInfo &blockInfo)
override;
1262 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1263 QualType T)
override;
1266 void fillRunSkipBlockVars(CodeGenModule &CGM,
const CGBlockInfo &blockInfo);
1267 llvm::GlobalVariable *EmitNSConstantCollectionLiteralArrayStorage(
1268 const ArrayRef<llvm::Constant *> &Elements);
1273enum class MethodListType {
1274 CategoryInstanceMethods,
1275 CategoryClassMethods,
1278 ProtocolInstanceMethods,
1279 ProtocolClassMethods,
1280 OptionalProtocolInstanceMethods,
1281 OptionalProtocolClassMethods,
1286class ProtocolMethodLists {
1289 RequiredInstanceMethods,
1290 RequiredClassMethods,
1291 OptionalInstanceMethods,
1292 OptionalClassMethods
1294 enum { NumProtocolMethodLists = 4 };
1296 static MethodListType getMethodListKind(Kind
kind) {
1298 case RequiredInstanceMethods:
1299 return MethodListType::ProtocolInstanceMethods;
1300 case RequiredClassMethods:
1301 return MethodListType::ProtocolClassMethods;
1302 case OptionalInstanceMethods:
1303 return MethodListType::OptionalProtocolInstanceMethods;
1304 case OptionalClassMethods:
1305 return MethodListType::OptionalProtocolClassMethods;
1307 llvm_unreachable(
"bad kind");
1310 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1312 static ProtocolMethodLists get(
const ObjCProtocolDecl *PD) {
1313 ProtocolMethodLists result;
1315 for (
auto *MD : PD->
methods()) {
1317 (2 *
size_t(MD->isOptional())) + (
size_t(MD->isClassMethod()));
1318 result.Methods[index].push_back(MD);
1324 template <
class Self>
1325 SmallVector<llvm::Constant *, 8> emitExtendedTypesArray(
Self *self)
const {
1332 SmallVector<llvm::Constant *, 8> result;
1335 for (
auto &list : Methods) {
1336 for (
auto MD : list) {
1337 result.push_back(self->GetMethodVarType(MD,
true));
1344 template <
class Self>
1345 llvm::Constant *emitMethodList(
Self *self,
const ObjCProtocolDecl *PD,
1348 getMethodListKind(
kind), Methods[
kind]);
1354class CGObjCMac :
public CGObjCCommonMac {
1356 friend ProtocolMethodLists;
1358 ObjCTypesHelper ObjCTypes;
1362 void EmitModuleInfo();
1366 llvm::Constant *EmitModuleSymbols();
1370 void FinishModule();
1375 llvm::Constant *EmitClassExtension(
const ObjCImplementationDecl *ID,
1376 CharUnits instanceSize,
1381 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
1383 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II);
1385 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
1388 llvm::Value *EmitSuperClassRef(
const ObjCInterfaceDecl *ID);
1395 llvm::Constant *EmitIvarList(
const ObjCImplementationDecl *ID,
bool ForClass);
1400 llvm::Constant *EmitMetaClassRef(
const ObjCInterfaceDecl *ID);
1404 llvm::Constant *EmitMetaClass(
const ObjCImplementationDecl *ID,
1405 llvm::Constant *Protocols,
1406 ArrayRef<const ObjCMethodDecl *> Methods);
1408 void emitMethodConstant(ConstantArrayBuilder &builder,
1409 const ObjCMethodDecl *MD);
1411 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1412 const ObjCMethodDecl *MD);
1416 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1417 ArrayRef<const ObjCMethodDecl *> Methods);
1422 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override;
1428 llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)
override;
1434 llvm::Constant *EmitProtocolExtension(
const ObjCProtocolDecl *PD,
1435 const ProtocolMethodLists &methodLists);
1439 llvm::Constant *EmitProtocolList(Twine Name,
1445 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1446 ConstantAddress EmitSelectorAddr(Selector Sel);
1449 CGObjCMac(CodeGen::CodeGenModule &cgm);
1451 llvm::Constant *getNSConstantStringClassRef()
override;
1452 llvm::Constant *getNSConstantArrayClassRef()
override;
1453 llvm::Constant *getNSConstantDictionaryClassRef()
override;
1455 llvm::Constant *getNSConstantIntegerNumberClassRef()
override;
1456 llvm::Constant *getNSConstantFloatNumberClassRef()
override;
1457 llvm::Constant *getNSConstantDoubleNumberClassRef()
override;
1459 llvm::Function *ModuleInitFunction()
override;
1461 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1462 ReturnValueSlot Return,
1463 QualType ResultType, Selector Sel,
1464 llvm::Value *Receiver,
1465 const CallArgList &CallArgs,
1466 const ObjCInterfaceDecl *
Class,
1467 const ObjCMethodDecl *
Method)
override;
1469 CodeGen::RValue GenerateMessageSendSuper(
1470 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1471 QualType ResultType, Selector Sel,
const ObjCInterfaceDecl *
Class,
1472 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1473 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method)
override;
1475 llvm::Value *GetClass(CodeGenFunction &CGF,
1476 const ObjCInterfaceDecl *ID)
override;
1478 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override;
1479 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override;
1483 llvm::Value *GetSelector(CodeGenFunction &CGF,
1484 const ObjCMethodDecl *
Method)
override;
1486 llvm::Constant *GetEHType(QualType T)
override;
1488 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
1490 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
1492 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override {}
1494 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1495 const ObjCProtocolDecl *PD)
override;
1497 llvm::FunctionCallee GetPropertyGetFunction()
override;
1498 llvm::FunctionCallee GetPropertySetFunction()
override;
1499 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1500 bool copy)
override;
1501 llvm::FunctionCallee GetGetStructFunction()
override;
1502 llvm::FunctionCallee GetSetStructFunction()
override;
1503 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
1504 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
1505 llvm::FunctionCallee EnumerationMutationFunction()
override;
1507 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1508 const ObjCAtTryStmt &S)
override;
1509 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1510 const ObjCAtSynchronizedStmt &S)
override;
1511 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const Stmt &S);
1512 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
1513 bool ClearInsertionPoint =
true)
override;
1514 llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1515 Address AddrWeakObj)
override;
1516 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1517 Address dst)
override;
1518 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1519 Address dest,
bool threadlocal =
false)
override;
1520 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1521 Address dest, llvm::Value *ivarOffset)
override;
1522 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1523 Address dest)
override;
1524 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
1525 Address src, llvm::Value *size)
override;
1527 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1528 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
1529 unsigned CVRQualifiers)
override;
1530 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1532 const ObjCIvarDecl *Ivar)
override;
1535class CGObjCNonFragileABIMac :
public CGObjCCommonMac {
1537 friend ProtocolMethodLists;
1538 ObjCNonFragileABITypesHelper ObjCTypes;
1539 llvm::GlobalVariable *ObjCEmptyCacheVar;
1540 llvm::Constant *ObjCEmptyVtableVar;
1543 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> SuperClassReferences;
1546 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> MetaClassReferences;
1549 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> EHTypeReferences;
1553 llvm::DenseSet<Selector> VTableDispatchMethods;
1556 std::vector<llvm::GlobalValue *> DefinedMetaClasses;
1560 bool isVTableDispatchedSelector(Selector Sel);
1564 void FinishNonFragileABIModule();
1568 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1569 StringRef SymbolName, StringRef SectionName);
1571 llvm::GlobalVariable *
1572 BuildClassRoTInitializer(
unsigned flags,
unsigned InstanceStart,
1573 unsigned InstanceSize,
1574 const ObjCImplementationDecl *ID);
1575 llvm::GlobalVariable *
1576 BuildClassObject(
const ObjCInterfaceDecl *CI,
bool isMetaclass,
1577 llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
1580 void emitMethodConstant(ConstantArrayBuilder &builder,
1581 const ObjCMethodDecl *MD,
bool forProtocol);
1585 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1586 ArrayRef<const ObjCMethodDecl *> Methods);
1593 llvm::Constant *EmitIvarList(
const ObjCImplementationDecl *ID);
1595 llvm::Constant *EmitIvarOffsetVar(
const ObjCInterfaceDecl *ID,
1596 const ObjCIvarDecl *Ivar,
1597 unsigned long int offset);
1602 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override;
1608 llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)
override;
1612 llvm::Constant *EmitProtocolList(Twine Name,
1616 CodeGen::RValue EmitVTableMessageSend(
1617 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1618 QualType ResultType, Selector Sel, llvm::Value *Receiver, QualType Arg0Ty,
1619 bool IsSuper,
const CallArgList &CallArgs,
const ObjCMethodDecl *
Method);
1623 llvm::Constant *GetClassGlobal(StringRef Name,
1625 bool Weak =
false,
bool DLLImport =
false);
1626 llvm::Constant *GetClassGlobal(
const ObjCInterfaceDecl *ID,
bool isMetaclass,
1629 llvm::Constant *GetClassGlobalForClassRef(
const ObjCInterfaceDecl *ID);
1631 llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
1632 const ObjCInterfaceDecl *ID,
1633 llvm::GlobalVariable *Entry);
1637 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
1639 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II,
1640 const ObjCInterfaceDecl *ID);
1642 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
1646 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
1647 const ObjCInterfaceDecl *ID);
1651 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
1652 const ObjCInterfaceDecl *ID,
bool Weak);
1657 llvm::GlobalVariable *ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
1658 const ObjCIvarDecl *Ivar);
1662 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1663 ConstantAddress EmitSelectorAddr(Selector Sel);
1667 llvm::Constant *GetInterfaceEHType(
const ObjCInterfaceDecl *ID,
1670 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1672 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1674 void GetClassSizeInfo(
const ObjCImplementationDecl *OID,
1675 uint32_t &InstanceStart, uint32_t &InstanceSize);
1690 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1692 bool IsIvarOffsetKnownIdempotent(
const CodeGen::CodeGenFunction &CGF,
1693 const ObjCIvarDecl *IV) {
1708 if (
const ObjCMethodDecl *MD =
1709 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1710 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1711 if (
const ObjCInterfaceDecl *ID = MD->getClassInterface())
1716 bool isClassLayoutKnownStatically(
const ObjCInterfaceDecl *ID) {
1719 assert(ID !=
nullptr &&
"Passed a null class to check layout");
1720 for (;
ID !=
nullptr;
ID =
ID->getSuperClass()) {
1723 if (
ID->getIdentifier()->getName() ==
"NSObject")
1728 if (!
ID->getImplementation())
1737 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1739 llvm::Constant *getNSConstantStringClassRef()
override;
1740 llvm::Constant *getNSConstantArrayClassRef()
override;
1741 llvm::Constant *getNSConstantDictionaryClassRef()
override;
1743 llvm::Constant *getNSConstantIntegerNumberClassRef()
override;
1744 llvm::Constant *getNSConstantFloatNumberClassRef()
override;
1745 llvm::Constant *getNSConstantDoubleNumberClassRef()
override;
1747 llvm::Function *ModuleInitFunction()
override;
1749 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1750 ReturnValueSlot Return,
1751 QualType ResultType, Selector Sel,
1752 llvm::Value *Receiver,
1753 const CallArgList &CallArgs,
1754 const ObjCInterfaceDecl *
Class,
1755 const ObjCMethodDecl *
Method)
override;
1757 CodeGen::RValue GenerateMessageSendSuper(
1758 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1759 QualType ResultType, Selector Sel,
const ObjCInterfaceDecl *
Class,
1760 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1761 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method)
override;
1763 llvm::Value *GetClass(CodeGenFunction &CGF,
1764 const ObjCInterfaceDecl *ID)
override;
1766 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override {
1767 return EmitSelector(CGF, Sel);
1769 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override {
1770 return EmitSelectorAddr(Sel);
1775 llvm::Value *GetSelector(CodeGenFunction &CGF,
1776 const ObjCMethodDecl *
Method)
override {
1777 return EmitSelector(CGF,
Method->getSelector());
1780 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
1782 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
1784 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override {}
1786 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1787 const ObjCProtocolDecl *PD)
override;
1789 llvm::Constant *GetEHType(QualType T)
override;
1791 llvm::FunctionCallee GetPropertyGetFunction()
override {
1792 return ObjCTypes.getGetPropertyFn();
1794 llvm::FunctionCallee GetPropertySetFunction()
override {
1795 return ObjCTypes.getSetPropertyFn();
1798 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1799 bool copy)
override {
1800 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1803 llvm::FunctionCallee GetSetStructFunction()
override {
1804 return ObjCTypes.getCopyStructFn();
1807 llvm::FunctionCallee GetGetStructFunction()
override {
1808 return ObjCTypes.getCopyStructFn();
1811 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1812 return ObjCTypes.getCppAtomicObjectFunction();
1815 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1816 return ObjCTypes.getCppAtomicObjectFunction();
1819 llvm::FunctionCallee EnumerationMutationFunction()
override {
1820 return ObjCTypes.getEnumerationMutationFn();
1823 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1824 const ObjCAtTryStmt &S)
override;
1825 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1826 const ObjCAtSynchronizedStmt &S)
override;
1827 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
1828 bool ClearInsertionPoint =
true)
override;
1829 llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1830 Address AddrWeakObj)
override;
1831 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1832 Address edst)
override;
1833 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1834 Address dest,
bool threadlocal =
false)
override;
1835 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1836 Address dest, llvm::Value *ivarOffset)
override;
1837 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1838 Address dest)
override;
1839 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
1840 Address src, llvm::Value *size)
override;
1841 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1842 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
1843 unsigned CVRQualifiers)
override;
1844 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1846 const ObjCIvarDecl *Ivar)
override;
1851struct NullReturnState {
1852 llvm::BasicBlock *NullBB =
nullptr;
1853 NullReturnState() =
default;
1856 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1866 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1874 RValue complete(CodeGenFunction &CGF, ReturnValueSlot returnSlot,
1875 RValue result, QualType resultType,
1876 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method) {
1883 llvm::BasicBlock *contBB =
nullptr;
1886 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1901 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1923 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1925 phi->addIncoming(null, NullBB);
1934 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1947 llvm::Type *scalarTy = callResult.first->getType();
1948 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1951 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1952 real->addIncoming(callResult.first, callBB);
1953 real->addIncoming(scalarZero, NullBB);
1954 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1955 imag->addIncoming(callResult.second, callBB);
1956 imag->addIncoming(scalarZero, NullBB);
1967 llvm::GlobalVariable *
C,
unsigned idx0,
1969 llvm::Value *Idxs[] = {
1970 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1971 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)};
1972 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1979 if (OID->
hasAttr<ObjCExceptionAttr>())
1986static llvm::GlobalValue::LinkageTypes
1988 if (CGM.
getTriple().isOSBinFormatMachO() &&
1989 (Section.empty() || Section.starts_with(
"__DATA")))
1990 return llvm::GlobalValue::InternalLinkage;
1991 return llvm::GlobalValue::PrivateLinkage;
1995static llvm::GlobalVariable *
1998 std::string SectionName;
1999 if (CGM.
getTriple().isOSBinFormatMachO())
2000 SectionName =
"__DATA, __objc_const";
2001 auto *GV = Builder.finishAndCreateGlobal(
2004 GV->setSection(SectionName);
2011 : CGObjCCommonMac(cgm), ObjCTypes(cgm) {
2020 return EmitClassRef(CGF, ID);
2024llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
2025 return EmitSelector(CGF, Sel);
2027Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
2028 return EmitSelectorAddr(Sel);
2030llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF,
2031 const ObjCMethodDecl *
Method) {
2032 return EmitSelector(CGF,
Method->getSelector());
2035llvm::Constant *CGObjCMac::GetEHType(QualType T) {
2047 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
2070CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
2073 : GenerateConstantNSString(SL));
2076ConstantAddress CGObjCCommonMac::GenerateConstantNumber(
const bool Value,
2077 const QualType &Ty) {
2078 return GenerateConstantNSNumber(
Value, Ty);
2082CGObjCCommonMac::GenerateConstantNumber(
const llvm::APSInt &
Value,
2083 const QualType &Ty) {
2084 return GenerateConstantNSNumber(
Value, Ty);
2088CGObjCCommonMac::GenerateConstantNumber(
const llvm::APFloat &
Value,
2089 const QualType &Ty) {
2090 return GenerateConstantNSNumber(
Value, Ty);
2093ConstantAddress CGObjCCommonMac::GenerateConstantArray(
2094 const ArrayRef<llvm::Constant *> &Objects) {
2095 return GenerateConstantNSArray(Objects);
2098ConstantAddress CGObjCCommonMac::GenerateConstantDictionary(
2099 const ObjCDictionaryLiteral *E,
2100 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects) {
2101 return GenerateConstantNSDictionary(E, KeysAndObjects);
2104static llvm::StringMapEntry<llvm::GlobalVariable *> &
2107 StringRef String = Literal->getString();
2108 StringLength = String.size();
2109 return *Map.insert(std::make_pair(String,
nullptr)).first;
2112llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
2113 if (llvm::Value *
V = ConstantStringClassRef)
2117 std::string str = StringClass.empty() ?
"_NSConstantStringClassReference"
2118 :
"_" + StringClass +
"ClassReference";
2120 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
2122 ConstantStringClassRef = GV;
2126llvm::Constant *CGObjCMac::getNSConstantArrayClassRef() {
2127 llvm_unreachable(
"constant array literals not supported for fragile ABI");
2130llvm::Constant *CGObjCMac::getNSConstantDictionaryClassRef() {
2131 llvm_unreachable(
"constant dictionary literals not supported for fragile "
2135llvm::Constant *CGObjCMac::getNSConstantIntegerNumberClassRef() {
2136 llvm_unreachable(
"constant number literals not supported for fragile ABI");
2139llvm::Constant *CGObjCMac::getNSConstantFloatNumberClassRef() {
2140 llvm_unreachable(
"constant number literals not supported for fragile ABI");
2143llvm::Constant *CGObjCMac::getNSConstantDoubleNumberClassRef() {
2144 llvm_unreachable(
"constant number literals not supported for fragile ABI");
2147llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
2148 if (llvm::Value *
V = ConstantStringClassRef)
2152 std::string str = StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
2153 :
"OBJC_CLASS_$_" + StringClass;
2155 ConstantStringClassRef = GV;
2159llvm::Constant *CGObjCNonFragileABIMac::getNSConstantArrayClassRef() {
2160 if (llvm::Value *
V = ConstantArrayClassRef)
2164 std::string Str = ArrayClass.empty() ?
"OBJC_CLASS_$_NSConstantArray"
2165 :
"OBJC_CLASS_$_" + ArrayClass;
2168 ConstantArrayClassRef = GV;
2172llvm::Constant *CGObjCNonFragileABIMac::getNSConstantDictionaryClassRef() {
2173 if (llvm::Value *
V = ConstantDictionaryClassRef)
2176 const std::string &DictionaryClass =
2178 std::string Str = DictionaryClass.empty()
2179 ?
"OBJC_CLASS_$_NSConstantDictionary"
2180 :
"OBJC_CLASS_$_" + DictionaryClass;
2183 ConstantDictionaryClassRef = GV;
2187llvm::Constant *CGObjCNonFragileABIMac::getNSConstantIntegerNumberClassRef() {
2188 if (llvm::Value *
V = ConstantIntegerNumberClassRef)
2191 const std::string &NumberClass =
2193 std::string Str = NumberClass.empty() ?
"OBJC_CLASS_$_NSConstantIntegerNumber"
2194 :
"OBJC_CLASS_$_" + NumberClass;
2197 ConstantIntegerNumberClassRef = GV;
2201llvm::Constant *CGObjCNonFragileABIMac::getNSConstantFloatNumberClassRef() {
2202 if (llvm::Value *
V = ConstantFloatNumberClassRef)
2205 const std::string &NumberClass =
2207 std::string Str = NumberClass.empty() ?
"OBJC_CLASS_$_NSConstantFloatNumber"
2208 :
"OBJC_CLASS_$_" + NumberClass;
2211 ConstantFloatNumberClassRef = GV;
2215llvm::Constant *CGObjCNonFragileABIMac::getNSConstantDoubleNumberClassRef() {
2216 if (llvm::Value *
V = ConstantDoubleNumberClassRef)
2219 const std::string &NumberClass =
2221 std::string Str = NumberClass.empty() ?
"OBJC_CLASS_$_NSConstantDoubleNumber"
2222 :
"OBJC_CLASS_$_" + NumberClass;
2225 ConstantDoubleNumberClassRef = GV;
2230CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
2231 unsigned StringLength = 0;
2232 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
2235 if (
auto *
C = Entry.second)
2236 return ConstantAddress(
C,
C->getValueType(),
2240 llvm::Constant *
Class = getNSConstantStringClassRef();
2243 if (!NSConstantStringType) {
2247 NSConstantStringType =
2249 "struct.__builtin_NSString");
2252 ConstantInitBuilder Builder(CGM);
2253 auto Fields = Builder.beginStruct(NSConstantStringType);
2256 Fields.addSignedPointer(
Class,
2258 GlobalDecl(), QualType());
2262 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2264 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
2265 bool isConstant = !CGM.
getLangOpts().WritableStrings;
2267 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
2269 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2272 GV->setAlignment(llvm::Align(1));
2276 Fields.addInt(CGM.
IntTy, StringLength);
2280 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
2282 llvm::GlobalVariable::PrivateLinkage);
2283 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
2284 const char *NSStringNonFragileABISection =
2285 "__DATA,__objc_stringobj,regular,no_dead_strip";
2288 ? NSStringNonFragileABISection
2292 return ConstantAddress(GV, GV->getValueType(), Alignment);
2296ConstantAddress CGObjCCommonMac::GenerateConstantNSNumber(
const bool Value,
2297 const QualType &Ty) {
2298 llvm::GlobalVariable *Val =
2299 Value ? EmitConstantCFBooleanTrue() : EmitConstantCFBooleanFalse();
2300 return ConstantAddress(Val, Val->getValueType(), CGM.
getPointerAlign());
2312CGObjCCommonMac::GenerateConstantNSNumber(
const llvm::APSInt &
Value,
2313 const QualType &Ty) {
2317 llvm::GlobalVariable *&Entry =
2320 return ConstantAddress(Entry, Entry->getValueType(), Alignment);
2324 std::string ObjCEncodingType;
2325 CodeGenFunction(CGM).getContext().getObjCEncodingForType(Ty,
2328 llvm::Constant *
const Class = getNSConstantIntegerNumberClassRef();
2330 if (!NSConstantIntegerNumberType) {
2331 NSConstantIntegerNumberType = llvm::StructType::create(
2337 "struct.__builtin_NSConstantIntegerNumber");
2340 ConstantInitBuilder Builder(CGM);
2341 auto Fields = Builder.beginStruct(NSConstantIntegerNumberType);
2350 llvm::Constant *IntegerValue =
2351 llvm::ConstantInt::get(CGM.
Int64Ty,
Value.extOrTrunc(64));
2353 Fields.add(IntegerValue);
2356 llvm::GlobalVariable *
const GV = Fields.finishAndCreateGlobal(
2357 "_unnamed_nsconstantintegernumber_", Alignment,
2358 true, llvm::GlobalVariable::PrivateLinkage);
2360 GV->setSection(GetNSConstantIntegerNumberSectionName());
2361 GV->addAttribute(
"objc_arc_inert");
2365 return ConstantAddress(GV, GV->getValueType(), Alignment);
2381CGObjCCommonMac::GenerateConstantNSNumber(
const llvm::APFloat &
Value,
2382 const QualType &Ty) {
2386 llvm::GlobalVariable *&Entry =
2389 return ConstantAddress(Entry, Entry->getValueType(), Alignment);
2393 std::string ObjCEncodingType;
2394 CodeGenFunction(CGM).getContext().getObjCEncodingForType(Ty,
2397 assert((ObjCEncodingType ==
"d" || ObjCEncodingType ==
"f") &&
2398 "Unexpected or unknown ObjCEncodingType used in constant NSNumber");
2400 llvm::GlobalValue::LinkageTypes
Linkage =
2401 llvm::GlobalVariable::PrivateLinkage;
2404 if (ObjCEncodingType ==
"f") {
2405 llvm::Constant *
const Class = getNSConstantFloatNumberClassRef();
2407 if (!NSConstantFloatNumberType) {
2408 NSConstantFloatNumberType = llvm::StructType::create(
2413 "struct.__builtin_NSConstantFloatNumber");
2416 ConstantInitBuilder Builder(CGM);
2417 auto Fields = Builder.beginStruct(NSConstantFloatNumberType);
2423 llvm::Constant *FV = llvm::ConstantFP::get(CGM.
FloatTy,
Value);
2427 llvm::GlobalVariable *
const GV = Fields.finishAndCreateGlobal(
2428 "_unnamed_nsconstantfloatnumber_", Alignment,
2431 GV->setSection(GetNSConstantFloatNumberSectionName());
2432 GV->addAttribute(
"objc_arc_inert");
2436 return ConstantAddress(GV, GV->getValueType(), Alignment);
2439 llvm::Constant *
const Class = getNSConstantDoubleNumberClassRef();
2440 if (!NSConstantDoubleNumberType) {
2442 NSConstantDoubleNumberType = llvm::StructType::create(
2447 "struct.__builtin_NSConstantDoubleNumber");
2450 ConstantInitBuilder Builder(CGM);
2451 auto Fields = Builder.beginStruct(NSConstantDoubleNumberType);
2457 llvm::Constant *DV = llvm::ConstantFP::get(CGM.
DoubleTy,
Value);
2461 llvm::GlobalVariable *
const GV = Fields.finishAndCreateGlobal(
2462 "_unnamed_nsconstantdoublenumber_", Alignment,
2465 GV->setSection(GetNSConstantDoubleNumberSectionName());
2466 GV->addAttribute(
"objc_arc_inert");
2470 return ConstantAddress(GV, GV->getValueType(), Alignment);
2475llvm::GlobalVariable *
2476CGObjCCommonMac::EmitNSConstantCollectionLiteralArrayStorage(
2477 const ArrayRef<llvm::Constant *> &Elements) {
2478 llvm::Type *ElementsTy = Elements[0]->getType();
2479 llvm::ArrayType *ArrayTy = llvm::ArrayType::get(ElementsTy, Elements.size());
2481 llvm::Constant *
const ArrayData = llvm::ConstantArray::get(ArrayTy, Elements);
2483 llvm::GlobalVariable *ObjectsGV =
new llvm::GlobalVariable(
2484 CGM.
getModule(), ArrayTy,
true, llvm::GlobalValue::InternalLinkage,
2485 ArrayData,
"_unnamed_array_storage");
2488 ObjectsGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2489 ObjectsGV->setSection(GetNSConstantCollectionStorageSectionName());
2501ConstantAddress CGObjCCommonMac::GenerateConstantNSArray(
2502 const ArrayRef<llvm::Constant *> &Objects) {
2505 if (Objects.size() == 0) {
2506 llvm::GlobalVariable *GV = EmitEmptyConstantNSArray();
2507 return ConstantAddress(GV, GV->getValueType(), Alignment);
2511 CodeGenTypes &Types = CGM.
getTypes();
2512 llvm::Constant *
const Class = getNSConstantArrayClassRef();
2513 llvm::Type *
const NSUIntegerTy =
2516 if (!NSConstantArrayType) {
2517 NSConstantArrayType = llvm::StructType::create(
2523 "struct.__builtin_NSArray");
2526 ConstantInitBuilder Builder(CGM);
2527 auto Fields = Builder.beginStruct(NSConstantArrayType);
2533 uint64_t ObjectCount = Objects.size();
2534 llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, ObjectCount);
2538 llvm::GlobalVariable *ObjectsGV =
2539 EmitNSConstantCollectionLiteralArrayStorage(Objects);
2540 Fields.add(ObjectsGV);
2543 llvm::GlobalVariable *GV = Fields.finishAndCreateGlobal(
2544 "_unnamed_nsarray_", Alignment,
2545 true, llvm::GlobalValue::PrivateLinkage);
2547 GV->setSection(GetNSConstantArraySectionName());
2548 GV->addAttribute(
"objc_arc_inert");
2550 return ConstantAddress(GV, GV->getValueType(), Alignment);
2563ConstantAddress CGObjCCommonMac::GenerateConstantNSDictionary(
2564 const ObjCDictionaryLiteral *E,
2565 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects) {
2568 if (KeysAndObjects.size() == 0) {
2569 llvm::GlobalVariable *GV = EmitEmptyConstantNSDictionary();
2570 return ConstantAddress(GV, GV->getValueType(), Alignment);
2574 CodeGenTypes &Types = CGM.
getTypes();
2575 llvm::Constant *
const Class = getNSConstantDictionaryClassRef();
2577 llvm::Type *
const NSUIntegerTy =
2580 if (!NSConstantDictionaryType) {
2581 NSConstantDictionaryType = llvm::StructType::create(
2589 "struct.__builtin_NSDictionary");
2592 ConstantInitBuilder Builder(CGM);
2593 auto Fields = Builder.beginStruct(NSConstantDictionaryType);
2599 auto HashOpts(NSDictionaryBuilder::Options::Sorted);
2600 NSDictionaryBuilder DictBuilder(E, KeysAndObjects, HashOpts);
2603 uint64_t const NumElements = DictBuilder.getNumElements();
2605 llvm::Constant *OptionsConstant = llvm::ConstantInt::get(
2606 NSUIntegerTy,
static_cast<uint64_t>(DictBuilder.getOptions()));
2607 Fields.add(OptionsConstant);
2610 llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, NumElements);
2614 SmallVector<llvm::Constant *, 16> SortedKeys, SortedObjects;
2615 SortedKeys.reserve(NumElements);
2616 SortedObjects.reserve(NumElements);
2617 for (
auto &[Key, Obj] : DictBuilder.getElements()) {
2618 SortedKeys.push_back(Key);
2619 SortedObjects.push_back(Obj);
2623 llvm::GlobalVariable *KeysGV =
2624 EmitNSConstantCollectionLiteralArrayStorage(SortedKeys);
2628 llvm::GlobalVariable *ObjectsGV =
2629 EmitNSConstantCollectionLiteralArrayStorage(SortedObjects);
2630 Fields.add(ObjectsGV);
2633 llvm::GlobalVariable *GV = Fields.finishAndCreateGlobal(
2634 "_unnamed_nsdictionary_", Alignment,
2635 true, llvm::GlobalValue::PrivateLinkage);
2637 GV->setSection(GetNSConstantDictionarySectionName());
2638 GV->addAttribute(
"objc_arc_inert");
2640 return ConstantAddress(GV, GV->getValueType(), Alignment);
2648CodeGen::RValue CGObjCMac::GenerateMessageSendSuper(
2649 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2650 Selector Sel,
const ObjCInterfaceDecl *
Class,
bool isCategoryImpl,
2651 llvm::Value *Receiver,
bool IsClassMessage,
2652 const CodeGen::CallArgList &CallArgs,
const ObjCMethodDecl *
Method) {
2657 llvm::Value *ReceiverAsObject =
2658 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2663 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(VMContext);
2665 if (IsClassMessage) {
2666 if (isCategoryImpl) {
2673 Target = EmitClassRef(CGF,
Class->getSuperClass());
2678 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2679 llvm::Value *SuperPtr =
2685 }
else if (isCategoryImpl)
2686 Target = EmitClassRef(CGF,
Class->getSuperClass());
2688 llvm::Value *ClassPtr = EmitSuperClassRef(
Class);
2695 llvm::Type *ClassTy =
2699 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2700 ObjCTypes.SuperPtrCTy,
true, CallArgs,
Method,
Class,
2705CodeGen::RValue CGObjCMac::GenerateMessageSend(
2706 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2707 Selector Sel, llvm::Value *Receiver,
const CallArgList &CallArgs,
2708 const ObjCInterfaceDecl *
Class,
const ObjCMethodDecl *
Method) {
2709 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2714CodeGen::RValue CGObjCCommonMac::EmitMessageSend(
2715 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2716 Selector Sel, llvm::Value *Arg0, QualType Arg0Ty,
bool IsSuper,
2717 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method,
2718 const ObjCInterfaceDecl *ClassReceiver,
2719 const ObjCCommonTypesHelper &ObjCTypes) {
2720 CodeGenTypes &Types = CGM.
getTypes();
2722 llvm::Value *ReceiverValue =
2723 llvm::PoisonValue::get(Types.
ConvertType(Arg0Ty));
2724 llvm::Value *SelValue = llvm::UndefValue::get(Types.
ConvertType(selTy));
2726 CallArgList ActualArgs;
2728 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2735 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2740 "Result type mismatch!");
2742 bool ReceiverCanBeNull =
2743 canMessageReceiverBeNull(CGF,
Method, IsSuper, ClassReceiver, Arg0);
2745 bool RequiresNullCheck =
false;
2746 bool RequiresReceiverValue =
true;
2747 bool RequiresSelValue =
true;
2749 llvm::FunctionCallee
Fn =
nullptr;
2752 auto Info = GenerateDirectMethod(
Method,
Method->getClassInterface());
2753 Fn = Info.Implementation;
2756 RequiresSelValue =
false;
2758 if (ReceiverCanBeNull)
2759 RequiresNullCheck =
true;
2760 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2761 : ObjCTypes.getSendStretFn(IsSuper);
2763 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2764 : ObjCTypes.getSendFpretFn(IsSuper);
2766 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2767 : ObjCTypes.getSendFp2retFn(IsSuper);
2772 RequiresNullCheck =
true;
2774 StringRef ClassName;
2780 if (CGM.
getCodeGenOpts().ObjCMsgSendClassSelectorStubs && ClassReceiver &&
2782 !ClassReceiver->
hasAttr<ObjCClassStubAttr>() &&
2783 !ClassReceiver->
hasAttr<ObjCRuntimeVisibleAttr>() &&
2787 bool UseClassStub = ClassName.data();
2790 (CGM.
getCodeGenOpts().ObjCMsgSendSelectorStubs || UseClassStub)) {
2791 Fn = GenerateMethodSelectorStub(Sel, ClassName, ObjCTypes);
2793 RequiresReceiverValue = !UseClassStub;
2794 RequiresSelValue =
false;
2796 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2797 : ObjCTypes.getSendFn(IsSuper);
2803 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2808 RequiresNullCheck =
false;
2811 if (!RequiresNullCheck &&
Method &&
Method->hasParamDestroyedInCallee())
2812 RequiresNullCheck =
true;
2814 NullReturnState nullReturn;
2815 if (RequiresNullCheck) {
2816 nullReturn.init(CGF, Arg0);
2820 if (RequiresReceiverValue)
2821 ActualArgs[0] = CallArg(
RValue::get(Arg0), Arg0Ty);
2824 if (RequiresSelValue) {
2825 SelValue = GetSelector(CGF, Sel);
2826 ActualArgs[1] = CallArg(
RValue::get(SelValue), selTy);
2829 llvm::CallBase *CallSite;
2832 CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);
2836 if (
Method &&
Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2837 CallSite->setDoesNotReturn();
2840 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2841 RequiresNullCheck ?
Method :
nullptr);
2845 bool pointee =
false) {
2859 switch (ownership) {
2867 llvm_unreachable(
"autoreleasing ivar?");
2869 llvm_unreachable(
"known nonzero");
2871 llvm_unreachable(
"bad objc ownership");
2891 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2892 : Offset(offset), SizeInWords(sizeInWords) {}
2895 bool operator<(
const IvarInfo &other)
const {
return Offset < other.Offset; }
2899class IvarLayoutBuilder {
2904 CharUnits InstanceBegin;
2907 CharUnits InstanceEnd;
2910 bool ForStrongLayout;
2913 bool IsDisordered =
false;
2915 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
2918 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2919 CharUnits instanceEnd,
bool forStrongLayout)
2920 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2921 ForStrongLayout(forStrongLayout) {}
2923 void visitRecord(
const RecordType *RT, CharUnits offset);
2925 template <
class Iterator,
class GetOffsetFn>
2926 void visitAggregate(Iterator begin, Iterator end, CharUnits aggrOffset,
2927 const GetOffsetFn &getOffset);
2929 void visitField(
const FieldDecl *field, CharUnits offset);
2932 void visitBlock(
const CGBlockInfo &blockInfo);
2935 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2937 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2938 llvm::SmallVectorImpl<unsigned char> &buffer);
2940 static void dump(ArrayRef<unsigned char> buffer) {
2941 const unsigned char *
s = buffer.data();
2942 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2944 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2946 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2953CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2954 const CGBlockInfo &blockInfo) {
2956 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2957 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2963 builder.visitBlock(blockInfo);
2965 if (!builder.hasBitmapData())
2968 llvm::SmallVector<unsigned char, 32> buffer;
2969 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2970 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2971 printf(
"\n block variable layout for block: ");
2972 builder.dump(buffer);
2978void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2988 CharUnits lastFieldOffset;
2991 for (
const auto &CI :
blockDecl->captures()) {
2992 const VarDecl *variable = CI.getVariable();
2995 const CGBlockInfo::Capture &capture = blockInfo.
getCapture(variable);
3001 CharUnits fieldOffset = capture.
getOffset();
3005 if (fieldOffset < lastFieldOffset)
3006 IsDisordered =
true;
3007 lastFieldOffset = fieldOffset;
3011 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
3015 assert(!
type->isArrayType() &&
"array variable should not be caught");
3016 if (
const RecordType *record =
type->getAsCanonical<RecordType>()) {
3017 visitRecord(record, fieldOffset);
3026 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
3035CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
bool ByrefLayout) {
3051void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
3053 CharUnits FieldOffset,
3054 CharUnits FieldSize) {
3057 RunSkipBlockVars.push_back(
3058 RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, FieldSize));
3060 RunSkipBlockVars.push_back(
3061 RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, FieldSize));
3063 RunSkipBlockVars.push_back(
3064 RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, FieldSize));
3066 RunSkipBlockVars.push_back(
3067 RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, FieldSize));
3069 RunSkipBlockVars.push_back(
3070 RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, FieldOffset, FieldSize));
3073void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
3074 const RecordDecl *RD,
3075 ArrayRef<const FieldDecl *> RecFields,
3076 CharUnits BytePos,
bool &HasUnion,
3078 bool IsUnion = (RD && RD->
isUnion());
3080 const FieldDecl *MaxField =
nullptr;
3081 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
3085 if (RecFields.empty())
3089 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
3090 const FieldDecl *
Field = RecFields[i];
3094 CharUnits FieldOffset =
3098 if (!
Field->getIdentifier() ||
Field->isBitField()) {
3099 LastFieldBitfieldOrUnnamed =
Field;
3100 LastBitfieldOrUnnamedOffset = FieldOffset;
3104 LastFieldBitfieldOrUnnamed =
nullptr;
3105 QualType FQT =
Field->getType();
3111 BytePos + FieldOffset, HasUnion);
3117 uint64_t ElCount = CArray->getZExtSize();
3118 assert(CArray &&
"only array with known element size is supported");
3119 FQT = CArray->getElementType();
3122 ElCount *= CArray->getZExtSize();
3123 FQT = CArray->getElementType();
3126 int OldIndex = RunSkipBlockVars.size() - 1;
3128 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
3133 for (
int FirstIndex = RunSkipBlockVars.size() - 1; ElIx < ElCount;
3136 for (
int i = OldIndex + 1; i <= FirstIndex; ++i)
3137 RunSkipBlockVars.push_back(
3138 RUN_SKIP(RunSkipBlockVars[i].opcode,
3139 RunSkipBlockVars[i].block_var_bytepos + Size * ElIx,
3140 RunSkipBlockVars[i].block_var_size));
3147 CharUnits UnionIvarSize = FieldSize;
3148 if (UnionIvarSize > MaxUnionSize) {
3149 MaxUnionSize = UnionIvarSize;
3151 MaxFieldOffset = FieldOffset;
3154 UpdateRunSkipBlockVars(
false, getBlockCaptureLifetime(FQT, ByrefLayout),
3155 BytePos + FieldOffset, FieldSize);
3159 if (LastFieldBitfieldOrUnnamed) {
3160 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
3163 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
3164 ((BitFieldSize % ByteSizeInBits) != 0);
3166 Size += LastBitfieldOrUnnamedOffset;
3167 UpdateRunSkipBlockVars(
3169 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
3171 BytePos + LastBitfieldOrUnnamedOffset, Size);
3174 "Expected unnamed");
3177 LastFieldBitfieldOrUnnamed->
getType());
3178 UpdateRunSkipBlockVars(
3180 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
3182 BytePos + LastBitfieldOrUnnamedOffset, FieldSize);
3187 UpdateRunSkipBlockVars(
3188 false, getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
3189 BytePos + MaxFieldOffset, MaxUnionSize);
3192void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
3196 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
3197 SmallVector<const FieldDecl *, 16> Fields(RD->
fields());
3199 const llvm::StructLayout *RecLayout =
3202 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
3214uint64_t CGObjCCommonMac::InlineLayoutInstruction(
3215 SmallVectorImpl<unsigned char> &Layout) {
3217 if (Layout.size() <= 3) {
3218 unsigned size = Layout.size();
3219 unsigned strong_word_count = 0, byref_word_count = 0, weak_word_count = 0;
3221 enum BLOCK_LAYOUT_OPCODE opcode;
3225 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3226 if (opcode == BLOCK_LAYOUT_STRONG)
3227 strong_word_count = (inst & 0xF) + 1;
3231 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3232 if (opcode == BLOCK_LAYOUT_BYREF)
3233 byref_word_count = (inst & 0xF) + 1;
3237 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3238 if (opcode == BLOCK_LAYOUT_WEAK)
3239 weak_word_count = (inst & 0xF) + 1;
3246 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3247 if (opcode == BLOCK_LAYOUT_STRONG) {
3248 strong_word_count = (inst & 0xF) + 1;
3250 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3251 if (opcode == BLOCK_LAYOUT_BYREF)
3252 byref_word_count = (inst & 0xF) + 1;
3253 else if (opcode == BLOCK_LAYOUT_WEAK)
3254 weak_word_count = (inst & 0xF) + 1;
3257 }
else if (opcode == BLOCK_LAYOUT_BYREF) {
3258 byref_word_count = (inst & 0xF) + 1;
3260 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3261 if (opcode == BLOCK_LAYOUT_WEAK)
3262 weak_word_count = (inst & 0xF) + 1;
3271 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3272 if (opcode == BLOCK_LAYOUT_STRONG)
3273 strong_word_count = (inst & 0xF) + 1;
3274 else if (opcode == BLOCK_LAYOUT_BYREF)
3275 byref_word_count = (inst & 0xF) + 1;
3276 else if (opcode == BLOCK_LAYOUT_WEAK)
3277 weak_word_count = (inst & 0xF) + 1;
3289 if (strong_word_count == 16 || byref_word_count == 16 ||
3290 weak_word_count == 16)
3293 unsigned count = (strong_word_count != 0) + (byref_word_count != 0) +
3294 (weak_word_count != 0);
3296 if (size == count) {
3297 if (strong_word_count)
3298 Result = strong_word_count;
3300 if (byref_word_count)
3301 Result += byref_word_count;
3303 if (weak_word_count)
3304 Result += weak_word_count;
3310llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
3311 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
3312 if (RunSkipBlockVars.empty())
3316 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
3320 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
3321 SmallVector<unsigned char, 16> Layout;
3323 unsigned size = RunSkipBlockVars.size();
3324 for (
unsigned i = 0; i < size; i++) {
3325 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
3326 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
3327 CharUnits end_byte_pos = start_byte_pos;
3330 if (opcode == RunSkipBlockVars[j].opcode) {
3331 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
3336 CharUnits size_in_bytes =
3337 end_byte_pos - start_byte_pos + RunSkipBlockVars[j - 1].block_var_size;
3339 CharUnits gap = RunSkipBlockVars[j].block_var_bytepos -
3340 RunSkipBlockVars[j - 1].block_var_bytepos -
3341 RunSkipBlockVars[j - 1].block_var_size;
3342 size_in_bytes += gap;
3345 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
3346 residue_in_bytes = size_in_bytes % WordSizeInBytes;
3347 size_in_bytes -= residue_in_bytes;
3348 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
3351 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
3352 while (size_in_words >= 16) {
3355 unsigned char inst = (opcode << 4) | 0xf;
3356 Layout.push_back(inst);
3357 size_in_words -= 16;
3359 if (size_in_words > 0) {
3362 unsigned char inst = (opcode << 4) | (size_in_words - 1);
3363 Layout.push_back(inst);
3366 unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) |
3368 Layout.push_back(inst);
3372 while (!Layout.empty()) {
3373 unsigned char inst = Layout.back();
3374 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3375 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES ||
3376 opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
3386 if (ComputeByrefLayout)
3387 printf(
"\n Inline BYREF variable layout: ");
3389 printf(
"\n Inline block variable layout: ");
3391 if (
auto numStrong = (
Result & 0xF00) >> 8)
3392 printf(
", BL_STRONG:%d", (
int)numStrong);
3393 if (
auto numByref = (
Result & 0x0F0) >> 4)
3394 printf(
", BL_BYREF:%d", (
int)numByref);
3395 if (
auto numWeak = (
Result & 0x00F) >> 0)
3396 printf(
", BL_WEAK:%d", (
int)numWeak);
3397 printf(
", BL_OPERATOR:0\n");
3402 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
3403 Layout.push_back(inst);
3405 for (
unsigned char C : Layout)
3409 if (ComputeByrefLayout)
3410 printf(
"\n Byref variable layout: ");
3412 printf(
"\n Block variable layout: ");
3413 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
3414 unsigned char inst = BitMap[i];
3415 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
3418 case BLOCK_LAYOUT_OPERATOR:
3422 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
3423 printf(
"BL_NON_OBJECT_BYTES:");
3425 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
3426 printf(
"BL_NON_OBJECT_WORD:");
3428 case BLOCK_LAYOUT_STRONG:
3431 case BLOCK_LAYOUT_BYREF:
3434 case BLOCK_LAYOUT_WEAK:
3437 case BLOCK_LAYOUT_UNRETAINED:
3438 printf(
"BL_UNRETAINED:");
3443 printf(
"%d", (inst & 0xf) + delta);
3451 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::LayoutBitMap,
3459 bool HasCopyDisposeHelpers) {
3461 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
3462 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
3466 }
else if (HasCopyDisposeHelpers) {
3474 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
3477 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
3480 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
3487 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
3488 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
3493void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
3494 const CGBlockInfo &blockInfo) {
3495 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3497 RunSkipBlockVars.clear();
3498 bool hasUnion =
false;
3502 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
3507 const llvm::StructLayout *layout =
3517 for (
const auto &CI :
blockDecl->captures()) {
3518 const VarDecl *variable = CI.getVariable();
3521 const CGBlockInfo::Capture &capture = blockInfo.
getCapture(variable);
3527 CharUnits fieldOffset =
3530 assert(!
type->isArrayType() &&
"array variable should not be caught");
3532 if (
const auto *record =
type->getAsCanonical<RecordType>()) {
3533 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
3536 CharUnits fieldSize;
3541 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
3542 fieldOffset, fieldSize);
3547CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
3548 const CGBlockInfo &blockInfo) {
3549 fillRunSkipBlockVars(CGM, blockInfo);
3550 return getBitmapBlockLayout(
false);
3553std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
3554 const CGBlockInfo &blockInfo) {
3555 fillRunSkipBlockVars(CGM, blockInfo);
3559llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
3561 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3562 assert(!T->
isArrayType() &&
"__block array variable should not be caught");
3563 CharUnits fieldOffset;
3564 RunSkipBlockVars.clear();
3565 bool hasUnion =
false;
3567 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
3569 llvm::Constant *
Result = getBitmapBlockLayout(
true);
3574 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
3578llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
3579 const ObjCProtocolDecl *PD) {
3584 return GetProtocolRef(PD);
3587void CGObjCCommonMac::GenerateProtocol(
const ObjCProtocolDecl *PD) {
3596 GetOrEmitProtocol(PD);
3599llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
3601 return GetOrEmitProtocol(PD);
3603 return GetOrEmitProtocolRef(PD);
3607CGObjCCommonMac::EmitClassRefViaRuntime(CodeGenFunction &CGF,
3608 const ObjCInterfaceDecl *ID,
3609 ObjCCommonTypesHelper &ObjCTypes) {
3610 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
3612 llvm::Value *className = CGF.
CGM
3614 ID->getObjCRuntimeNameAsString()))
3617 className = CGF.
Builder.CreateBitCast(
3619 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3620 call->setDoesNotThrow();
3636llvm::Constant *CGObjCMac::GetOrEmitProtocol(
const ObjCProtocolDecl *PD) {
3637 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3640 if (Entry && Entry->hasInitializer())
3652 auto methodLists = ProtocolMethodLists::get(PD);
3654 ConstantInitBuilder builder(CGM);
3655 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3656 values.add(EmitProtocolExtension(PD, methodLists));
3658 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3660 values.add(methodLists.emitMethodList(
3661 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
3662 values.add(methodLists.emitMethodList(
3663 this, PD, ProtocolMethodLists::RequiredClassMethods));
3667 assert(Entry->hasPrivateLinkage());
3668 values.finishAndSetAsInitializer(Entry);
3670 Entry = values.finishAndCreateGlobal(
3672 false, llvm::GlobalValue::PrivateLinkage);
3673 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3682llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3683 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3689 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3690 false, llvm::GlobalValue::PrivateLinkage,
3691 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3692 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3694 Entry->setAlignment(llvm::Align(4));
3711CGObjCMac::EmitProtocolExtension(
const ObjCProtocolDecl *PD,
3712 const ProtocolMethodLists &methodLists) {
3713 auto optInstanceMethods = methodLists.emitMethodList(
3714 this, PD, ProtocolMethodLists::OptionalInstanceMethods);
3715 auto optClassMethods = methodLists.emitMethodList(
3716 this, PD, ProtocolMethodLists::OptionalClassMethods);
3718 auto extendedMethodTypes = EmitProtocolMethodTypes(
3719 "OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3720 methodLists.emitExtendedTypesArray(
this), ObjCTypes);
3722 auto instanceProperties = EmitPropertyList(
3723 "OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD, ObjCTypes,
false);
3724 auto classProperties =
3725 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3726 PD, ObjCTypes,
true);
3729 if (optInstanceMethods->isNullValue() && optClassMethods->isNullValue() &&
3730 extendedMethodTypes->isNullValue() && instanceProperties->isNullValue() &&
3731 classProperties->isNullValue()) {
3732 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3736 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3738 ConstantInitBuilder builder(CGM);
3739 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3740 values.addInt(ObjCTypes.IntTy, size);
3741 values.add(optInstanceMethods);
3742 values.add(optClassMethods);
3743 values.add(instanceProperties);
3744 values.add(extendedMethodTypes);
3745 values.add(classProperties);
3748 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3760CGObjCMac::EmitProtocolList(Twine name,
3764 auto PDs = GetRuntimeProtocolList(begin, end);
3766 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3768 ConstantInitBuilder builder(CGM);
3769 auto values = builder.beginStruct();
3772 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3775 auto countSlot = values.addPlaceholder();
3777 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3778 for (
const auto *Proto : PDs)
3779 refsArray.add(GetProtocolRef(Proto));
3781 auto count = refsArray.size();
3784 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3786 refsArray.finishAndAddTo(values);
3787 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3790 if (CGM.
getTriple().isOSBinFormatMachO())
3791 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3793 llvm::GlobalVariable *GV =
3794 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3803 if (IsClassProperty != PD->isClassProperty())
3807 Properties.push_back(PD);
3810 for (
const auto *P : Proto->
protocols())
3826llvm::Constant *CGObjCCommonMac::EmitPropertyList(
3827 Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
3828 const ObjCCommonTypesHelper &ObjCTypes,
bool IsClassProperty) {
3829 if (IsClassProperty) {
3833 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3834 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3835 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3838 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3839 llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet;
3841 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3842 for (
const ObjCCategoryDecl *ClassExt : OID->known_extensions())
3843 for (
auto *PD : ClassExt->properties()) {
3844 if (IsClassProperty != PD->isClassProperty())
3846 if (PD->isDirectProperty())
3849 Properties.push_back(PD);
3853 if (IsClassProperty != PD->isClassProperty())
3859 if (PD->isDirectProperty())
3861 Properties.push_back(PD);
3864 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
3865 for (
const auto *P : OID->all_referenced_protocols())
3867 }
else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
3868 for (
const auto *P : CD->protocols())
3873 if (Properties.empty())
3874 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3876 unsigned propertySize =
3879 ConstantInitBuilder builder(CGM);
3880 auto values = builder.beginStruct();
3881 values.addInt(ObjCTypes.IntTy, propertySize);
3882 values.addInt(ObjCTypes.IntTy, Properties.size());
3883 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3884 for (
auto PD : Properties) {
3885 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3887 property.add(GetPropertyTypeString(PD, Container));
3888 property.finishAndAddTo(propertiesArray);
3890 propertiesArray.finishAndAddTo(values);
3893 if (CGM.
getTriple().isOSBinFormatMachO())
3894 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3895 :
"__OBJC,__property,regular,no_dead_strip";
3897 llvm::GlobalVariable *GV =
3898 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3902llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(
3903 Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
3904 const ObjCCommonTypesHelper &ObjCTypes) {
3906 if (MethodTypes.empty())
3907 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3909 llvm::ArrayType *AT =
3910 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, MethodTypes.size());
3911 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3914 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3915 Section =
"__DATA, __objc_const";
3917 llvm::GlobalVariable *GV =
3934void CGObjCMac::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3942 const ObjCCategoryDecl *Category =
3945 SmallString<256> ExtName;
3946 llvm::raw_svector_ostream(ExtName)
3949 ConstantInitBuilder Builder(CGM);
3950 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3952 enum { InstanceMethods, ClassMethods, NumMethodLists };
3953 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3954 for (
const auto *MD : OCD->
methods()) {
3955 if (!MD->isDirectMethod())
3956 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3959 Values.add(GetClassName(OCD->
getName()));
3960 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3961 LazySymbols.insert(
Interface->getIdentifier());
3963 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3964 Methods[InstanceMethods]));
3965 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3966 Methods[ClassMethods]));
3968 Values.add(EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3969 Category->protocol_begin(),
3970 Category->protocol_end()));
3972 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3974 Values.addInt(ObjCTypes.IntTy, Size);
3978 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(), OCD,
3979 Category, ObjCTypes,
false));
3980 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
3981 Category, ObjCTypes,
true));
3983 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3984 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3987 llvm::GlobalVariable *GV = CreateMetadataVar(
3988 "OBJC_CATEGORY_" + ExtName.str(), Values,
3989 "__OBJC,__category,regular,no_dead_strip", CGM.
getPointerAlign(),
true);
3990 DefinedCategories.push_back(GV);
3991 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3993 MethodDefinitions.clear();
4054 if (
auto *RD =
type->getAsRecordDecl()) {
4055 for (
auto *field : RD->
fields()) {
4074 ID->getClassInterface()->all_declared_ivar_begin();
4102void CGObjCMac::GenerateClass(
const ObjCImplementationDecl *ID) {
4103 IdentifierInfo *RuntimeName =
4105 DefinedSymbols.insert(RuntimeName);
4107 std::string ClassName =
ID->getNameAsString();
4110 const_cast<ObjCInterfaceDecl *
>(
ID->getClassInterface());
4111 llvm::Constant *Protocols =
4112 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
4113 Interface->all_referenced_protocol_begin(),
4114 Interface->all_referenced_protocol_end());
4116 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
4119 bool hasMRCWeak =
false;
4134 enum { InstanceMethods, ClassMethods, NumMethodLists };
4135 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
4136 for (
const auto *MD :
ID->methods()) {
4137 if (!MD->isDirectMethod())
4138 Methods[unsigned(MD->isClassMethod())].push_back(MD);
4141 for (
const auto *PID :
ID->property_impls()) {
4143 if (PID->getPropertyDecl()->isDirectProperty())
4145 if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
4146 if (GetMethodDefinition(MD))
4147 Methods[InstanceMethods].push_back(MD);
4148 if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
4149 if (GetMethodDefinition(MD))
4150 Methods[InstanceMethods].push_back(MD);
4154 ConstantInitBuilder builder(CGM);
4155 auto values = builder.beginStruct(ObjCTypes.ClassTy);
4156 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
4157 if (ObjCInterfaceDecl *Super =
Interface->getSuperClass()) {
4159 LazySymbols.insert(Super->getIdentifier());
4161 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
4163 values.addNullPointer(ObjCTypes.ClassPtrTy);
4165 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
4167 values.addInt(ObjCTypes.LongTy, 0);
4168 values.addInt(ObjCTypes.LongTy, Flags);
4169 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
4170 values.add(EmitIvarList(ID,
false));
4171 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
4172 Methods[InstanceMethods]));
4174 values.addNullPointer(ObjCTypes.CachePtrTy);
4175 values.add(Protocols);
4177 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
4180 std::string Name(
"OBJC_CLASS_");
4182 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
4184 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
4186 assert(GV->getValueType() == ObjCTypes.ClassTy &&
4187 "Forward metaclass reference has incorrect type.");
4188 values.finishAndSetAsInitializer(GV);
4189 GV->setSection(Section);
4193 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
4194 DefinedClasses.push_back(GV);
4195 ImplementedClasses.push_back(
Interface);
4197 MethodDefinitions.clear();
4201CGObjCMac::EmitMetaClass(
const ObjCImplementationDecl *ID,
4202 llvm::Constant *Protocols,
4203 ArrayRef<const ObjCMethodDecl *> Methods) {
4210 ConstantInitBuilder builder(CGM);
4211 auto values = builder.beginStruct(ObjCTypes.ClassTy);
4213 const ObjCInterfaceDecl *Root =
ID->getClassInterface();
4214 while (
const ObjCInterfaceDecl *Super = Root->
getSuperClass())
4220 if (ObjCInterfaceDecl *Super =
ID->getClassInterface()->getSuperClass()) {
4221 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
4223 values.addNullPointer(ObjCTypes.ClassPtrTy);
4225 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
4227 values.addInt(ObjCTypes.LongTy, 0);
4228 values.addInt(ObjCTypes.LongTy, Flags);
4229 values.addInt(ObjCTypes.LongTy, Size);
4230 values.add(EmitIvarList(ID,
true));
4232 emitMethodList(
ID->getName(), MethodListType::ClassMethods, Methods));
4234 values.addNullPointer(ObjCTypes.CachePtrTy);
4235 values.add(Protocols);
4237 values.addNullPointer(ObjCTypes.Int8PtrTy);
4242 std::string Name(
"OBJC_METACLASS_");
4243 Name +=
ID->getName();
4246 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
4248 assert(GV->getValueType() == ObjCTypes.ClassTy &&
4249 "Forward metaclass reference has incorrect type.");
4250 values.finishAndSetAsInitializer(GV);
4254 llvm::GlobalValue::PrivateLinkage);
4256 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
4262llvm::Constant *CGObjCMac::EmitMetaClassRef(
const ObjCInterfaceDecl *ID) {
4263 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
4273 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
4275 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
4276 llvm::GlobalValue::PrivateLinkage,
nullptr,
4279 assert(GV->getValueType() == ObjCTypes.ClassTy &&
4280 "Forward metaclass reference has incorrect type.");
4284llvm::Value *CGObjCMac::EmitSuperClassRef(
const ObjCInterfaceDecl *ID) {
4285 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
4286 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
4289 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
4290 llvm::GlobalValue::PrivateLinkage,
nullptr,
4293 assert(GV->getValueType() == ObjCTypes.ClassTy &&
4294 "Forward class metadata reference has incorrect type.");
4309llvm::Constant *CGObjCMac::EmitClassExtension(
const ObjCImplementationDecl *ID,
4310 CharUnits InstanceSize,
4314 llvm::Constant *layout;
4316 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
4323 llvm::Constant *propertyList =
4324 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
4325 : Twine(
"_OBJC_$_PROP_LIST_")) +
4327 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
4330 if (layout->isNullValue() && propertyList->isNullValue()) {
4331 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
4335 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
4337 ConstantInitBuilder builder(CGM);
4338 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
4339 values.addInt(ObjCTypes.IntTy, size);
4341 values.add(propertyList);
4343 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
4344 "__OBJC,__class_ext,regular,no_dead_strip",
4360llvm::Constant *CGObjCMac::EmitIvarList(
const ObjCImplementationDecl *ID,
4368 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
4370 const ObjCInterfaceDecl *OID =
ID->getClassInterface();
4372 ConstantInitBuilder builder(CGM);
4373 auto ivarList = builder.beginStruct();
4374 auto countSlot = ivarList.addPlaceholder();
4375 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
4380 if (!IVD->getDeclName())
4383 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
4384 ivar.add(GetMethodVarName(IVD->getIdentifier()));
4385 ivar.add(GetMethodVarType(IVD));
4386 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
4387 ivar.finishAndAddTo(ivars);
4391 auto count = ivars.size();
4395 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
4398 ivars.finishAndAddTo(ivarList);
4399 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
4401 llvm::GlobalVariable *GV;
4402 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
4403 "__OBJC,__instance_vars,regular,no_dead_strip",
4414void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
4415 const ObjCMethodDecl *MD) {
4416 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
4417 description.add(GetMethodVarName(MD->
getSelector()));
4418 description.add(GetMethodVarType(MD));
4419 description.finishAndAddTo(builder);
4429void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
4430 const ObjCMethodDecl *MD) {
4431 llvm::Function *fn = GetMethodDefinition(MD);
4432 assert(fn &&
"no definition registered for method");
4434 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
4436 method.add(GetMethodVarType(MD));
4438 method.finishAndAddTo(builder);
4455CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
4456 ArrayRef<const ObjCMethodDecl *> methods) {
4459 bool forProtocol =
false;
4461 case MethodListType::CategoryInstanceMethods:
4462 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
4463 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
4464 forProtocol =
false;
4466 case MethodListType::CategoryClassMethods:
4467 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
4468 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
4469 forProtocol =
false;
4471 case MethodListType::InstanceMethods:
4472 prefix =
"OBJC_INSTANCE_METHODS_";
4473 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
4474 forProtocol =
false;
4476 case MethodListType::ClassMethods:
4477 prefix =
"OBJC_CLASS_METHODS_";
4478 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
4479 forProtocol =
false;
4481 case MethodListType::ProtocolInstanceMethods:
4482 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
4483 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
4486 case MethodListType::ProtocolClassMethods:
4487 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
4488 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
4491 case MethodListType::OptionalProtocolInstanceMethods:
4492 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
4493 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
4496 case MethodListType::OptionalProtocolClassMethods:
4497 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
4498 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
4504 if (methods.empty())
4505 return llvm::Constant::getNullValue(
4506 forProtocol ? ObjCTypes.MethodDescriptionListPtrTy
4507 : ObjCTypes.MethodListPtrTy);
4512 ConstantInitBuilder builder(CGM);
4514 values.addInt(ObjCTypes.IntTy, methods.size());
4515 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
4516 for (
auto MD : methods) {
4517 emitMethodDescriptionConstant(methodArray, MD);
4519 methodArray.finishAndAddTo(values);
4521 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
4527 ConstantInitBuilder builder(CGM);
4529 values.addNullPointer(ObjCTypes.Int8PtrTy);
4530 values.addInt(ObjCTypes.IntTy, methods.size());
4531 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
4532 for (
auto MD : methods) {
4534 emitMethodConstant(methodArray, MD);
4536 methodArray.finishAndAddTo(values);
4538 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
4543llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
4544 const ObjCContainerDecl *CD) {
4549 DirectMethodInfo &Info = GenerateDirectMethod(OMD, CD);
4550 Method = Info.Implementation;
4552 auto Name = getSymbolNameForMethod(OMD);
4554 CodeGenTypes &Types = CGM.
getTypes();
4555 llvm::FunctionType *MethodTy =
4557 Method = llvm::Function::Create(
4558 MethodTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
4561 MethodDefinitions.insert(std::make_pair(OMD,
Method));
4566CGObjCCommonMac::DirectMethodInfo &
4567CGObjCCommonMac::GenerateDirectMethod(
const ObjCMethodDecl *OMD,
4568 const ObjCContainerDecl *CD) {
4570 auto I = DirectMethodDefinitions.find(COMD);
4571 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
4573 if (I != DirectMethodDefinitions.end()) {
4585 OldFn = I->second.Implementation;
4588 CodeGenTypes &Types = CGM.
getTypes();
4589 llvm::FunctionType *MethodTy =
4593 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4595 Fn->takeName(OldFn);
4596 OldFn->replaceAllUsesWith(Fn);
4597 OldFn->eraseFromParent();
4600 I->second.Implementation =
Fn;
4603 auto Name = getSymbolNameForMethod(OMD,
false);
4605 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4607 auto [It, inserted] = DirectMethodDefinitions.insert(
4608 std::make_pair(COMD, DirectMethodInfo(Fn)));
4618CGObjCCommonMac::GenerateClassRealization(CodeGenFunction &CGF,
4619 llvm::Value *classObject,
4620 const ObjCInterfaceDecl *OID) {
4627 RValue result = GeneratePossiblySpecializedMessageSend(
4628 CGF, ReturnValueSlot(), ResultType, SelfSel, classObject, Args, OID,
4634void CGObjCCommonMac::GenerateDirectMethodsPreconditionCheck(
4635 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4636 const ObjCContainerDecl *CD) {
4638 bool ReceiverCanBeNull =
true;
4640 auto selfValue = Builder.CreateLoad(selfAddr);
4655 "GenerateDirectMethod() should be called with the Class Interface");
4666 llvm::Value *realizedClass = GenerateClassRealization(CGF, selfValue, OID);
4667 Builder.CreateStore(realizedClass, selfAddr);
4672 ReceiverCanBeNull = isWeakLinkedClass(OID);
4676 if (ReceiverCanBeNull) {
4677 llvm::BasicBlock *SelfIsNilBlock =
4679 llvm::BasicBlock *ContBlock =
4684 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4687 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero), SelfIsNilBlock,
4688 ContBlock, MDHelper.createUnlikelyBranchWeights());
4694 Builder.SetInsertPoint(SelfIsNilBlock);
4695 if (!retTy->isVoidType()) {
4703 Builder.SetInsertPoint(ContBlock);
4707void CGObjCCommonMac::GenerateDirectMethodPrologue(
4708 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4709 const ObjCContainerDecl *CD) {
4711 GenerateDirectMethodsPreconditionCheck(CGF, Fn, OMD, CD);
4720 Builder.CreateStore(GetSelector(CGF, OMD),
4725llvm::Function *CGObjCCommonMac::GenerateMethodSelectorStub(
4726 Selector Sel, StringRef ClassName,
const ObjCCommonTypesHelper &ObjCTypes) {
4727 assert((!ClassName.data() || !ClassName.empty()) &&
4728 "class name cannot be an empty string");
4729 auto Key = std::make_pair(Sel, ClassName);
4730 auto I = MethodSelectorStubs.find(Key);
4732 if (I != MethodSelectorStubs.end())
4735 auto *FnTy = llvm::FunctionType::get(
4736 ObjCTypes.ObjectPtrTy, {ObjCTypes.ObjectPtrTy, ObjCTypes.SelectorPtrTy},
4740 if (ClassName.data())
4741 FnName = (
"objc_msgSendClass$" + Sel.
getAsString() +
"$_OBJC_CLASS_$_" +
4742 llvm::Twine(ClassName))
4750 MethodSelectorStubs.insert(std::make_pair(Key, Fn));
4754llvm::GlobalVariable *
4755CGObjCCommonMac::CreateMetadataVar(Twine Name, ConstantStructBuilder &
Init,
4756 StringRef Section, CharUnits Align,
4758 llvm::GlobalValue::LinkageTypes
LT =
4760 llvm::GlobalVariable *GV =
4761 Init.finishAndCreateGlobal(Name, Align,
false, LT);
4762 if (!Section.empty())
4763 GV->setSection(Section);
4769llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4770 llvm::Constant *
Init,
4774 llvm::Type *Ty =
Init->getType();
4775 llvm::GlobalValue::LinkageTypes
LT =
4777 llvm::GlobalVariable *GV =
4778 new llvm::GlobalVariable(CGM.
getModule(), Ty,
false, LT,
Init, Name);
4779 if (!Section.empty())
4780 GV->setSection(Section);
4787llvm::GlobalVariable *
4788CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4789 bool ForceNonFragileABI,
4790 bool NullTerminate) {
4793 case ObjCLabelType::ClassName:
4794 Label =
"OBJC_CLASS_NAME_";
4796 case ObjCLabelType::MethodVarName:
4797 Label =
"OBJC_METH_VAR_NAME_";
4799 case ObjCLabelType::MethodVarType:
4800 Label =
"OBJC_METH_VAR_TYPE_";
4802 case ObjCLabelType::PropertyName:
4803 Label =
"OBJC_PROP_NAME_ATTR_";
4805 case ObjCLabelType::LayoutBitMap:
4806 Label =
"OBJC_LAYOUT_BITMAP_";
4810 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4814 case ObjCLabelType::ClassName:
4815 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4816 :
"__TEXT,__cstring,cstring_literals";
4818 case ObjCLabelType::MethodVarName:
4819 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4820 :
"__TEXT,__cstring,cstring_literals";
4822 case ObjCLabelType::MethodVarType:
4823 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4824 :
"__TEXT,__cstring,cstring_literals";
4826 case ObjCLabelType::PropertyName:
4827 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4828 :
"__TEXT,__cstring,cstring_literals";
4830 case ObjCLabelType::LayoutBitMap:
4831 Section =
"__TEXT,__cstring,cstring_literals";
4835 llvm::Constant *
Value =
4836 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4837 llvm::GlobalVariable *GV =
new llvm::GlobalVariable(
4839 true, llvm::GlobalValue::PrivateLinkage,
Value, Label);
4840 if (CGM.
getTriple().isOSBinFormatMachO())
4841 GV->setSection(Section);
4842 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4849llvm::Function *CGObjCMac::ModuleInitFunction() {
4855llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4856 return ObjCTypes.getGetPropertyFn();
4859llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4860 return ObjCTypes.getSetPropertyFn();
4863llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4865 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4868llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4869 return ObjCTypes.getCopyStructFn();
4872llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4873 return ObjCTypes.getCopyStructFn();
4876llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4877 return ObjCTypes.getCppAtomicObjectFunction();
4880llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4881 return ObjCTypes.getCppAtomicObjectFunction();
4884llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4885 return ObjCTypes.getEnumerationMutationFn();
4888void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF,
const ObjCAtTryStmt &S) {
4889 return EmitTryOrSynchronizedStmt(CGF, S);
4892void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
4893 const ObjCAtSynchronizedStmt &S) {
4894 return EmitTryOrSynchronizedStmt(CGF, S);
4898struct PerformFragileFinally final : EHScopeStack::Cleanup {
4900 Address SyncArgSlot;
4901 Address CallTryExitVar;
4902 Address ExceptionData;
4903 ObjCTypesHelper &ObjCTypes;
4904 PerformFragileFinally(
const Stmt *S, Address SyncArgSlot,
4905 Address CallTryExitVar, Address ExceptionData,
4906 ObjCTypesHelper *ObjCTypes)
4907 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4908 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4910 void Emit(CodeGenFunction &CGF, Flags flags)
override {
4913 llvm::BasicBlock *FinallyCallExit =
4915 llvm::BasicBlock *FinallyNoCallExit =
4918 FinallyCallExit, FinallyNoCallExit);
4927 if (
const ObjCAtFinallyStmt *FinallyStmt =
4930 if (flags.isForEHCleanup())
4935 llvm::Value *CurCleanupDest =
4938 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4957class FragileHazards {
4958 CodeGenFunction &CGF;
4959 SmallVector<llvm::Value *, 20> Locals;
4960 llvm::DenseSet<llvm::BasicBlock *> BlocksBeforeTry;
4962 llvm::InlineAsm *ReadHazard;
4963 llvm::InlineAsm *WriteHazard;
4965 llvm::FunctionType *GetAsmFnType();
4967 void collectLocals();
4968 void emitReadHazard(CGBuilderTy &Builder);
4971 FragileHazards(CodeGenFunction &CGF);
4973 void emitWriteHazard();
4974 void emitHazardsInNewBlocks();
4983FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4990 for (llvm::BasicBlock &BB : *CGF.
CurFn)
4991 BlocksBeforeTry.insert(&BB);
4993 llvm::FunctionType *AsmFnTy = GetAsmFnType();
5001 std::string Constraint;
5002 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
5008 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
5016 std::string Constraint;
5017 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
5020 Constraint +=
"=*m";
5023 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
5028void FragileHazards::emitWriteHazard() {
5033 for (
auto Pair : llvm::enumerate(Locals))
5036 llvm::Attribute::get(
5041void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
5042 assert(!Locals.empty());
5043 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
5044 call->setDoesNotThrow();
5046 for (
auto Pair : llvm::enumerate(Locals))
5049 llvm::Attribute::get(
5050 Builder.getContext(), llvm::Attribute::ElementType,
5056void FragileHazards::emitHazardsInNewBlocks() {
5063 for (llvm::BasicBlock &BB : *CGF.
CurFn) {
5064 if (BlocksBeforeTry.count(&BB))
5068 for (llvm::BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;
5070 llvm::Instruction &I = *BI;
5089 Builder.SetInsertPoint(&BB, BI);
5090 emitReadHazard(Builder);
5097 if (llvm::Value *Ptr =
V.getBasePointer())
5101void FragileHazards::collectLocals() {
5103 llvm::DenseSet<llvm::Value *> AllocasToIgnore;
5109 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
5110 for (llvm::Instruction &I : Entry)
5112 Locals.push_back(&I);
5115llvm::FunctionType *FragileHazards::GetAsmFnType() {
5116 SmallVector<llvm::Type *, 16> tys(Locals.size());
5117 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
5118 tys[i] = Locals[i]->getType();
5119 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
5230void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5236 CodeGenFunction::JumpDest FinallyEnd =
5241 CodeGenFunction::JumpDest FinallyRethrow =
5251 llvm::Value *SyncArg =
5253 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
5264 ObjCTypes.ExceptionDataTy, CGF.
getPointerAlign(),
"exceptiondata.ptr");
5270 FragileHazards Hazards(CGF);
5289 SyncArgSlot, CallTryExitVar,
5290 ExceptionData, &ObjCTypes);
5296 ExceptionData.emitRawPointer(CGF));
5299 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
5302 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
5305 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
5306 SetJmpResult->setCanReturnTwice();
5312 llvm::Value *DidCatch =
5313 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
5314 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
5322 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
5328 Hazards.emitWriteHazard();
5342 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
5353 llvm::BasicBlock *CatchBlock =
nullptr;
5354 llvm::BasicBlock *CatchHandler =
nullptr;
5365 ExceptionData.emitRawPointer(CGF));
5368 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp.result");
5369 SetJmpResult->setCanReturnTwice();
5371 llvm::Value *Threw =
5372 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
5376 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
5386 bool AllMatched =
false;
5387 for (
const ObjCAtCatchStmt *CatchStmt : AtTryStmt->
catch_stmts()) {
5388 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
5389 const ObjCObjectPointerType *OPT =
nullptr;
5395 OPT = CatchParam->
getType()->
getAs<ObjCObjectPointerType>();
5407 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
5414 EmitInitOfCatchParam(CGF, Caught, CatchParam);
5417 CGF.
EmitStmt(CatchStmt->getCatchBody());
5420 CatchVarCleanups.ForceCleanup();
5426 assert(OPT &&
"Unexpected non-object pointer type in @catch");
5430 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
5431 assert(IDecl &&
"Catch parameter must have Objective-C type!");
5434 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
5436 llvm::Value *matchArgs[] = {
Class, Caught};
5438 ObjCTypes.getExceptionMatchFn(), matchArgs,
"match");
5444 MatchedBlock, NextCatchBlock);
5451 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
5457 llvm::Value *Tmp = CGF.
Builder.CreateBitCast(
5459 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
5461 CGF.
EmitStmt(CatchStmt->getCatchBody());
5464 CatchVarCleanups.ForceCleanup();
5475 if (Caught->use_empty())
5476 Caught->eraseFromParent();
5492 assert(PropagatingExnVar.
isValid());
5494 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
5505 Hazards.emitHazardsInNewBlocks();
5508 CGF.
Builder.restoreIP(TryFallthroughIP);
5515 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
5519 llvm::Value *PropagatingExn;
5520 if (PropagatingExnVar.
isValid()) {
5526 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
5527 PropagatingExn = Caught;
5532 CGF.
Builder.CreateUnreachable();
5535 CGF.
Builder.restoreIP(SavedIP);
5538void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
5539 const ObjCAtThrowStmt &S,
5540 bool ClearInsertionPoint) {
5541 llvm::Value *ExceptionAsObject;
5546 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
5549 "Unexpected rethrow outside @catch block.");
5553 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
5554 ->setDoesNotReturn();
5555 CGF.
Builder.CreateUnreachable();
5558 if (ClearInsertionPoint)
5559 CGF.
Builder.ClearInsertionPoint();
5565llvm::Value *CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
5566 Address AddrWeakObj) {
5568 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
5571 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal,
"weakread");
5572 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
5579void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
5580 llvm::Value *src, Address dst) {
5581 llvm::Type *SrcTy = src->getType();
5584 assert(Size <= 8 && "does not support size > 8
");
5585 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5586 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
5587 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5589 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5590 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5591 ObjCTypes.PtrObjectPtrTy);
5592 llvm::Value *args[] = {src, dstVal};
5593 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
5600void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
5601 llvm::Value *src, Address dst,
5603 llvm::Type *SrcTy = src->getType();
5604 if (!isa<llvm::PointerType>(SrcTy)) {
5605 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
5606 assert(Size <= 8 && "does
not support size > 8
");
5607 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5608 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
5609 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5611 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5612 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5613 ObjCTypes.PtrObjectPtrTy);
5614 llvm::Value *args[] = {src, dstVal};
5616 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
5619 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
5620 "threadlocalassign
");
5626void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
5627 llvm::Value *src, Address dst,
5628 llvm::Value *ivarOffset) {
5629 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset
is NULL");
5630 llvm::Type *SrcTy = src->getType();
5631 if (!isa<llvm::PointerType>(SrcTy)) {
5632 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
5633 assert(Size <= 8 && "does
not support size > 8
");
5634 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5635 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
5636 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5638 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5639 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5640 ObjCTypes.PtrObjectPtrTy);
5641 llvm::Value *args[] = {src, dstVal, ivarOffset};
5642 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
5648void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
5649 llvm::Value *src, Address dst) {
5650 llvm::Type *SrcTy = src->getType();
5651 if (!isa<llvm::PointerType>(SrcTy)) {
5652 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
5653 assert(Size <= 8 && "does
not support size > 8
");
5654 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5655 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
5656 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5658 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5659 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5660 ObjCTypes.PtrObjectPtrTy);
5661 llvm::Value *args[] = {src, dstVal};
5662 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
5666void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
5667 Address DestPtr, Address SrcPtr,
5668 llvm::Value *size) {
5669 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
5670 SrcPtr.emitRawPointer(CGF), size};
5671 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5676LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5678 llvm::Value *BaseValue,
5679 const ObjCIvarDecl *Ivar,
5680 unsigned CVRQualifiers) {
5681 const ObjCInterfaceDecl *ID =
5682 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5683 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5684 EmitIvarOffset(CGF, ID, Ivar));
5687llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5688 const ObjCInterfaceDecl *Interface,
5689 const ObjCIvarDecl *Ivar) {
5690 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5691 return llvm::ConstantInt::get(
5692 CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset);
5695/* *** Private Interface *** */
5697std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5698 StringRef MachOAttributes) {
5699 switch (CGM.getTriple().getObjectFormat()) {
5700 case llvm::Triple::UnknownObjectFormat:
5701 llvm_unreachable("unexpected
object file format
");
5702 case llvm::Triple::MachO: {
5703 if (MachOAttributes.empty())
5704 return ("__DATA,
" + Section).str();
5705 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5707 case llvm::Triple::ELF:
5708 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5709 return Section.substr(2).str();
5710 case llvm::Triple::COFF:
5711 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5712 return (".
" + Section.substr(2) + "$B
").str();
5713 case llvm::Triple::Wasm:
5714 case llvm::Triple::GOFF:
5715 case llvm::Triple::SPIRV:
5716 case llvm::Triple::XCOFF:
5717 case llvm::Triple::DXContainer:
5718 llvm::report_fatal_error(
5719 "Objective-
C support
is unimplemented
for object file format
");
5722 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5734enum ImageInfoFlags {
5735 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5736 eImageInfo_GarbageCollected = (1 << 1),
5737 eImageInfo_GCOnly = (1 << 2),
5738 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5740 eImageInfo_SignedClassRO = (1 << 4), // Reused (was _CorrectedSynthesize)
5741 eImageInfo_ImageIsSimulated = (1 << 5),
5742 eImageInfo_ClassProperties = (1 << 6)
5746void CGObjCCommonMac::EmitImageInfo() {
5747 unsigned version = 0; // Version is unused?
5748 std::string Section =
5750 ? "__OBJC,__image_info,regular
"
5751 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5753 // Generate module-level named metadata to convey this information to the
5754 // linker and code-gen.
5755 llvm::Module &Mod = CGM.getModule();
5757 // Add the ObjC ABI version to the module flags.
5758 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5759 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5761 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5762 llvm::MDString::get(VMContext, Section));
5764 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5765 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5766 // Non-GC overrides those files which specify GC.
5767 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Garbage Collection
",
5768 llvm::ConstantInt::get(Int8Ty, 0));
5770 // Add the ObjC garbage collection value.
5772 llvm::Module::Error, "Objective-
C Garbage Collection
",
5773 llvm::ConstantInt::get(Int8Ty, (uint8_t)eImageInfo_GarbageCollected));
5775 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5776 // Add the ObjC GC Only value.
5777 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5780 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5781 llvm::Metadata *Ops[2] = {
5782 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5783 llvm::ConstantAsMetadata::get(
5784 llvm::ConstantInt::get(Int8Ty, eImageInfo_GarbageCollected))};
5785 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5786 llvm::MDNode::get(VMContext, Ops));
5790 // Indicate whether we're compiling this to run on a simulator.
5791 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5792 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5793 eImageInfo_ImageIsSimulated);
5795 // Indicate whether we are generating class properties.
5796 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5797 eImageInfo_ClassProperties);
5799 // Indicate whether we want enforcement of pointer signing for class_ro_t
5801 if (CGM.getLangOpts().PointerAuthObjcClassROPointers)
5802 Mod.addModuleFlag(llvm::Module::Error,
5803 "Objective-
C Enforce ClassRO
Pointer Signing
",
5804 eImageInfo_SignedClassRO);
5806 Mod.addModuleFlag(llvm::Module::Error,
5807 "Objective-
C Enforce ClassRO
Pointer Signing
",
5808 llvm::ConstantInt::get(Int8Ty, 0));
5811// struct objc_module {
5812// unsigned long version;
5813// unsigned long size;
5818// FIXME: Get from somewhere
5819static const int ModuleVersion = 7;
5821void CGObjCMac::EmitModuleInfo() {
5822 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5824 ConstantInitBuilder builder(CGM);
5825 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5826 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5827 values.addInt(ObjCTypes.LongTy, Size);
5828 // This used to be the filename, now it is unused. <rdr://4327263>
5829 values.add(GetClassName(StringRef("")));
5830 values.add(EmitModuleSymbols());
5831 CreateMetadataVar("OBJC_MODULES
", values,
5832 "__OBJC,__module_info,regular,no_dead_strip
",
5833 CGM.getPointerAlign(), true);
5836llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5837 unsigned NumClasses = DefinedClasses.size();
5838 unsigned NumCategories = DefinedCategories.size();
5840 // Return null if no symbols were defined.
5841 if (!NumClasses && !NumCategories)
5842 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5844 ConstantInitBuilder builder(CGM);
5845 auto values = builder.beginStruct();
5846 values.addInt(ObjCTypes.LongTy, 0);
5847 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5848 values.addInt(ObjCTypes.ShortTy, NumClasses);
5849 values.addInt(ObjCTypes.ShortTy, NumCategories);
5851 // The runtime expects exactly the list of defined classes followed
5852 // by the list of defined categories, in a single array.
5853 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5854 for (unsigned i = 0; i < NumClasses; i++) {
5855 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5857 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5858 // We are implementing a weak imported interface. Give it external linkage
5859 if (ID->isWeakImported() && !IMP->isWeakImported())
5860 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5862 array.add(DefinedClasses[i]);
5864 for (unsigned i = 0; i < NumCategories; i++)
5865 array.add(DefinedCategories[i]);
5867 array.finishAndAddTo(values);
5869 llvm::GlobalVariable *GV = CreateMetadataVar(
5870 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5871 CGM.getPointerAlign(), true);
5875llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5876 IdentifierInfo *II) {
5877 LazySymbols.insert(II);
5879 llvm::GlobalVariable *&Entry = ClassReferences[II];
5883 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5884 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5885 CGM.getPointerAlign(), true);
5888 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5889 CGF.getPointerAlign());
5892llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5893 const ObjCInterfaceDecl *ID) {
5894 // If the class has the objc_runtime_visible attribute, we need to
5895 // use the Objective-C runtime to get the class.
5896 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5897 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5899 IdentifierInfo *RuntimeName =
5900 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5901 return EmitClassRefFromId(CGF, RuntimeName);
5904llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5905 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5906 return EmitClassRefFromId(CGF, II);
5909llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5910 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5913ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5914 CharUnits Align = CGM.getPointerAlign();
5916 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5918 Entry = CreateMetadataVar(
5919 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5920 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5921 Entry->setExternallyInitialized(true);
5924 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5927llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5928 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5930 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5931 return getConstantGEP(VMContext, Entry, 0, 0);
5934llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5935 return MethodDefinitions.lookup(MD);
5941CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5942 const ObjCCommonTypesHelper &ObjCTypes) {
5943 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5946void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
5947 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
5949 // If this is a union, remember that we had one, because it might mess
5950 // up the ordering of layout entries.
5952 IsDisordered = true;
5954 const ASTRecordLayout *recLayout = nullptr;
5955 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5956 [&](const FieldDecl *field) -> CharUnits {
5958 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5960 recLayout->getFieldOffset(field->getFieldIndex());
5961 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5965template <class Iterator, class GetOffsetFn>
5966void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5967 CharUnits aggregateOffset,
5968 const GetOffsetFn &getOffset) {
5969 for (; begin != end; ++begin) {
5970 auto field = *begin;
5972 // Skip over bitfields.
5973 if (field->isBitField()) {
5977 // Compute the offset of the field within the aggregate.
5978 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5980 visitField(field, fieldOffset);
5985void IvarLayoutBuilder::visitField(const FieldDecl *field,
5986 CharUnits fieldOffset) {
5987 QualType fieldType = field->getType();
5989 // Drill down into arrays.
5990 uint64_t numElts = 1;
5991 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5993 fieldType = arrayType->getElementType();
5995 // Unlike incomplete arrays, constant arrays can be nested.
5996 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5997 numElts *= arrayType->getZExtSize();
5998 fieldType = arrayType->getElementType();
6001 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
6003 // If we ended up with a zero-sized array, we've done what we can do within
6004 // the limits of this layout encoding.
6008 // Recurse if the base element type is a record type.
6009 if (const auto *recType = fieldType->getAsCanonical<RecordType>()) {
6010 size_t oldEnd = IvarsInfo.size();
6012 visitRecord(recType, fieldOffset);
6014 // If we have an array, replicate the first entry's layout information.
6015 auto numEltEntries = IvarsInfo.size() - oldEnd;
6016 if (numElts != 1 && numEltEntries != 0) {
6017 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
6018 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
6019 // Copy the last numEltEntries onto the end of the array, adjusting
6020 // each for the element size.
6021 for (size_t i = 0; i != numEltEntries; ++i) {
6022 auto firstEntry = IvarsInfo[oldEnd + i];
6023 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
6024 firstEntry.SizeInWords));
6032 // Classify the element type.
6033 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
6035 // If it matches what we're looking for, add an entry.
6036 if ((ForStrongLayout && GCAttr == Qualifiers::Strong) ||
6037 (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
6038 assert(CGM.getContext().getTypeSizeInChars(fieldType) ==
6039 CGM.getPointerSize());
6040 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
6048IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
6049 llvm::SmallVectorImpl<unsigned char> &buffer) {
6050 // The bitmap is a series of skip/scan instructions, aligned to word
6051 // boundaries. The skip is performed first.
6052 const unsigned char MaxNibble = 0xF;
6053 const unsigned char SkipMask = 0xF0, SkipShift = 4;
6054 const unsigned char ScanMask = 0x0F, ScanShift = 0;
6056 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
6058 // Sort the ivar info on byte position in case we encounterred a
6059 // union nested in the ivar list.
6061 // This isn't a stable sort, but our algorithm should handle it fine.
6062 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
6064 assert(llvm::is_sorted(IvarsInfo));
6066 assert(IvarsInfo.back().Offset < InstanceEnd);
6068 assert(buffer.empty());
6070 // Skip the next N words.
6071 auto skip = [&](unsigned numWords) {
6072 assert(numWords > 0);
6074 // Try to merge into the previous byte. Since scans happen second, we
6075 // can't do this if it includes a scan.
6076 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
6077 unsigned lastSkip = buffer.back() >> SkipShift;
6078 if (lastSkip < MaxNibble) {
6079 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
6080 numWords -= claimed;
6081 lastSkip += claimed;
6082 buffer.back() = (lastSkip << SkipShift);
6086 while (numWords >= MaxNibble) {
6087 buffer.push_back(MaxNibble << SkipShift);
6088 numWords -= MaxNibble;
6091 buffer.push_back(numWords << SkipShift);
6095 // Scan the next N words.
6096 auto scan = [&](unsigned numWords) {
6097 assert(numWords > 0);
6099 // Try to merge into the previous byte. Since scans happen second, we can
6100 // do this even if it includes a skip.
6101 if (!buffer.empty()) {
6102 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
6103 if (lastScan < MaxNibble) {
6104 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
6105 numWords -= claimed;
6106 lastScan += claimed;
6107 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
6111 while (numWords >= MaxNibble) {
6112 buffer.push_back(MaxNibble << ScanShift);
6113 numWords -= MaxNibble;
6116 buffer.push_back(numWords << ScanShift);
6120 // One past the end of the last scan.
6121 unsigned endOfLastScanInWords = 0;
6122 const CharUnits WordSize = CGM.getPointerSize();
6124 // Consider all the scan requests.
6125 for (auto &request : IvarsInfo) {
6126 CharUnits beginOfScan = request.Offset - InstanceBegin;
6128 // Ignore scan requests that don't start at an even multiple of the
6129 // word size. We can't encode them.
6130 if (!beginOfScan.isMultipleOf(WordSize))
6133 // Ignore scan requests that start before the instance start.
6134 // This assumes that scans never span that boundary. The boundary
6135 // isn't the true start of the ivars, because in the fragile-ARC case
6136 // it's rounded up to word alignment, but the test above should leave
6137 // us ignoring that possibility.
6138 if (beginOfScan.isNegative()) {
6139 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
6143 unsigned beginOfScanInWords = beginOfScan / WordSize;
6144 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
6146 // If the scan starts some number of words after the last one ended,
6148 if (beginOfScanInWords > endOfLastScanInWords) {
6149 skip(beginOfScanInWords - endOfLastScanInWords);
6151 // Otherwise, start scanning where the last left off.
6153 beginOfScanInWords = endOfLastScanInWords;
6155 // If that leaves us with nothing to scan, ignore this request.
6156 if (beginOfScanInWords >= endOfScanInWords)
6160 // Scan to the end of the request.
6161 assert(beginOfScanInWords < endOfScanInWords);
6162 scan(endOfScanInWords - beginOfScanInWords);
6163 endOfLastScanInWords = endOfScanInWords;
6167 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
6169 // For GC layouts, emit a skip to the end of the allocation so that we
6170 // have precise information about the entire thing. This isn't useful
6171 // or necessary for the ARC-style layout strings.
6172 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6173 unsigned lastOffsetInWords =
6174 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
6175 if (lastOffsetInWords > endOfLastScanInWords) {
6176 skip(lastOffsetInWords - endOfLastScanInWords);
6180 // Null terminate the string.
6181 buffer.push_back(0);
6183 auto *Entry = CGObjC.CreateCStringLiteral(
6184 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::LayoutBitMap);
6185 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
6205CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
6206 CharUnits beginOffset, CharUnits endOffset,
6207 bool ForStrongLayout, bool HasMRCWeakIvars) {
6208 // If this is MRC, and we're either building a strong layout or there
6209 // are no weak ivars, bail out early.
6210 llvm::Type *PtrTy = CGM.Int8PtrTy;
6211 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
6212 !CGM.getLangOpts().ObjCAutoRefCount &&
6213 (ForStrongLayout || !HasMRCWeakIvars))
6214 return llvm::Constant::getNullValue(PtrTy);
6216 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
6217 SmallVector<const ObjCIvarDecl *, 32> ivars;
6219 // GC layout strings include the complete object layout, possibly
6220 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
6223 // ARC layout strings only include the class's ivars. In non-fragile
6224 // runtimes, that means starting at InstanceStart, rounded up to word
6225 // alignment. In fragile runtimes, there's no InstanceStart, so it means
6226 // starting at the offset of the first ivar, rounded up to word alignment.
6228 // MRC weak layout strings follow the ARC style.
6229 CharUnits baseOffset;
6230 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
6231 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD;
6232 IVD = IVD->getNextIvar())
6233 ivars.push_back(IVD);
6235 if (isNonFragileABI()) {
6236 baseOffset = beginOffset; // InstanceStart
6237 } else if (!ivars.empty()) {
6239 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
6241 baseOffset = CharUnits::Zero();
6244 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
6246 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
6248 baseOffset = CharUnits::Zero();
6252 return llvm::Constant::getNullValue(PtrTy);
6254 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
6256 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
6257 [&](const ObjCIvarDecl *ivar) -> CharUnits {
6258 return CharUnits::fromQuantity(
6259 ComputeIvarBaseOffset(CGM, OMD, ivar));
6262 if (!builder.hasBitmapData())
6263 return llvm::Constant::getNullValue(PtrTy);
6265 llvm::SmallVector<unsigned char, 4> buffer;
6266 llvm::Constant *C = builder.buildBitmap(*this, buffer);
6268 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
6269 printf("\n%
s ivar layout
for class '%s':
",
6270 ForStrongLayout ? "strong
" : "weak
",
6271 OMD->getClassInterface()->getName().str().c_str());
6272 builder.dump(buffer);
6277llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
6278 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
6279 // FIXME: Avoid std::string in "Sel.
getAsString()
"
6282 CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
6283 return getConstantGEP(VMContext, Entry, 0, 0);
6286// FIXME: Merge into a single cstring creation function.
6287llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
6288 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
6291llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
6292 std::string TypeStr;
6293 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
6295 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
6297 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
6298 return getConstantGEP(VMContext, Entry, 0, 0);
6301llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
6303 std::string TypeStr =
6304 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
6306 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
6308 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
6309 return getConstantGEP(VMContext, Entry, 0, 0);
6312// FIXME: Merge into a single cstring creation function.
6313llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
6314 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
6316 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
6317 return getConstantGEP(VMContext, Entry, 0, 0);
6320// FIXME: Merge into a single cstring creation function.
6321// FIXME: This Decl should be more precise.
6323CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
6324 const Decl *Container) {
6325 std::string TypeStr =
6326 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
6327 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
6330void CGObjCMac::FinishModule() {
6333 // Emit the dummy bodies for any protocols which were referenced but
6335 for (auto &entry : Protocols) {
6336 llvm::GlobalVariable *global = entry.second;
6337 if (global->hasInitializer())
6340 ConstantInitBuilder builder(CGM);
6341 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
6342 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
6343 values.add(GetClassName(entry.first->getName()));
6344 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
6345 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
6346 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
6347 values.finishAndSetAsInitializer(global);
6348 CGM.addCompilerUsedGlobal(global);
6351 // Add assembler directives to add lazy undefined symbol references
6352 // for classes which are referenced but not defined. This is
6353 // important for correct linker interaction.
6355 // FIXME: It would be nice if we had an LLVM construct for this.
6356 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
6357 CGM.getTriple().isOSBinFormatMachO()) {
6358 SmallString<256> Asm;
6359 Asm += CGM.getModule().getModuleInlineAsm();
6360 if (!Asm.empty() && Asm.back() != '\n')
6363 llvm::raw_svector_ostream OS(Asm);
6364 for (const auto *Sym : DefinedSymbols)
6365 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
6366 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
6367 for (const auto *Sym : LazySymbols)
6368 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
6369 for (const auto &Category : DefinedCategoryNames)
6370 OS << "\t.objc_category_name_
" << Category << "=0\n
"
6371 << "\t.globl .objc_category_name_
" << Category << "\n
";
6373 CGM.getModule().setModuleInlineAsm(OS.str());
6377CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
6378 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
6379 ObjCEmptyVtableVar(nullptr) {
6385ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
6386 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
6387 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6388 ASTContext &Ctx = CGM.getContext();
6389 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
6391 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
6393 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
6394 Int8PtrTy = CGM.Int8PtrTy;
6395 Int8PtrProgramASTy = llvm::PointerType::get(CGM.getLLVMContext(), ProgramAS);
6396 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
6398 // arm64 targets use "int" ivar offset variables. All others,
6399 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
6400 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
6401 IvarOffsetVarTy = IntTy;
6403 IvarOffsetVarTy = LongTy;
6405 ObjectPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
6406 PtrObjectPtrTy = llvm::PointerType::getUnqual(VMContext);
6408 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
6410 // I'm not sure I like this. The implicit coordination is a bit
6411 // gross. We should solve this in a reasonable fashion because this
6412 // is a pretty common task (match some runtime data structure with
6413 // an LLVM data structure).
6415 // FIXME: This is leaked.
6416 // FIXME: Merge with rewriter code?
6418 // struct _objc_super {
6422 RecordDecl *RD = RecordDecl::Create(
6423 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6424 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
6425 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6426 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
6427 false, ICIS_NoInit));
6428 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6429 nullptr, Ctx.getObjCClassType(), nullptr,
6430 nullptr, false, ICIS_NoInit));
6431 RD->completeDefinition();
6433 SuperCTy = Ctx.getCanonicalTagType(RD);
6434 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
6436 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
6437 SuperPtrTy = llvm::PointerType::getUnqual(VMContext);
6441 // char *attributes;
6443 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
6445 // struct _prop_list_t {
6446 // uint32_t entsize; // sizeof(struct _prop_t)
6447 // uint32_t count_of_properties;
6448 // struct _prop_t prop_list[count_of_properties];
6450 PropertyListTy = llvm::StructType::create(
6451 "struct._prop_list_t
", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
6452 // struct _prop_list_t *
6453 PropertyListPtrTy = llvm::PointerType::getUnqual(VMContext);
6455 // struct _objc_method {
6457 // char *method_type;
6460 MethodTy = llvm::StructType::create("struct._objc_method
", SelectorPtrTy,
6461 Int8PtrTy, Int8PtrProgramASTy);
6463 // struct _objc_cache *
6464 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache
");
6465 CachePtrTy = llvm::PointerType::getUnqual(VMContext);
6468ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
6469 : ObjCCommonTypesHelper(cgm) {
6470 // struct _objc_method_description {
6474 MethodDescriptionTy = llvm::StructType::create(
6475 "struct._objc_method_description
", SelectorPtrTy, Int8PtrTy);
6477 // struct _objc_method_description_list {
6479 // struct _objc_method_description[1];
6481 MethodDescriptionListTy =
6482 llvm::StructType::create("struct._objc_method_description_list
", IntTy,
6483 llvm::ArrayType::get(MethodDescriptionTy, 0));
6485 // struct _objc_method_description_list *
6486 MethodDescriptionListPtrTy = llvm::PointerType::getUnqual(VMContext);
6488 // Protocol description structures
6490 // struct _objc_protocol_extension {
6491 // uint32_t size; // sizeof(struct _objc_protocol_extension)
6492 // struct _objc_method_description_list *optional_instance_methods;
6493 // struct _objc_method_description_list *optional_class_methods;
6494 // struct _objc_property_list *instance_properties;
6495 // const char ** extendedMethodTypes;
6496 // struct _objc_property_list *class_properties;
6498 ProtocolExtensionTy = llvm::StructType::create(
6499 "struct._objc_protocol_extension
", IntTy, MethodDescriptionListPtrTy,
6500 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
6503 // struct _objc_protocol_extension *
6504 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
6506 // Handle construction of Protocol and ProtocolList types
6508 // struct _objc_protocol {
6509 // struct _objc_protocol_extension *isa;
6510 // char *protocol_name;
6511 // struct _objc_protocol **_objc_protocol_list;
6512 // struct _objc_method_description_list *instance_methods;
6513 // struct _objc_method_description_list *class_methods;
6515 ProtocolTy = llvm::StructType::create(
6516 {ProtocolExtensionPtrTy, Int8PtrTy,
6517 llvm::PointerType::getUnqual(VMContext), MethodDescriptionListPtrTy,
6518 MethodDescriptionListPtrTy},
6519 "struct._objc_protocol
");
6522 llvm::StructType::create({llvm::PointerType::getUnqual(VMContext), LongTy,
6523 llvm::ArrayType::get(ProtocolTy, 0)},
6524 "struct._objc_protocol_list
");
6526 // struct _objc_protocol_list *
6527 ProtocolListPtrTy = llvm::PointerType::getUnqual(VMContext);
6529 ProtocolPtrTy = llvm::PointerType::getUnqual(VMContext);
6531 // Class description structures
6533 // struct _objc_ivar {
6538 IvarTy = llvm::StructType::create("struct._objc_ivar
", Int8PtrTy, Int8PtrTy,
6541 // struct _objc_ivar_list *
6542 IvarListTy = llvm::StructType::create(VMContext, "struct._objc_ivar_list
");
6543 IvarListPtrTy = llvm::PointerType::getUnqual(VMContext);
6545 // struct _objc_method_list *
6547 llvm::StructType::create(VMContext, "struct._objc_method_list
");
6548 MethodListPtrTy = llvm::PointerType::getUnqual(VMContext);
6550 // struct _objc_class_extension *
6551 ClassExtensionTy = llvm::StructType::create(
6552 "struct._objc_class_extension
", IntTy, Int8PtrTy, PropertyListPtrTy);
6553 ClassExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
6555 // struct _objc_class {
6557 // Class super_class;
6561 // long instance_size;
6562 // struct _objc_ivar_list *ivars;
6563 // struct _objc_method_list *methods;
6564 // struct _objc_cache *cache;
6565 // struct _objc_protocol_list *protocols;
6566 // char *ivar_layout;
6567 // struct _objc_class_ext *ext;
6569 ClassTy = llvm::StructType::create(
6570 {llvm::PointerType::getUnqual(VMContext),
6571 llvm::PointerType::getUnqual(VMContext), Int8PtrTy, LongTy, LongTy,
6572 LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, ProtocolListPtrTy,
6573 Int8PtrTy, ClassExtensionPtrTy},
6574 "struct._objc_class
");
6576 ClassPtrTy = llvm::PointerType::getUnqual(VMContext);
6578 // struct _objc_category {
6579 // char *category_name;
6580 // char *class_name;
6581 // struct _objc_method_list *instance_method;
6582 // struct _objc_method_list *class_method;
6583 // struct _objc_protocol_list *protocols;
6584 // uint32_t size; // sizeof(struct _objc_category)
6585 // struct _objc_property_list *instance_properties;// category's @property
6586 // struct _objc_property_list *class_properties;
6588 CategoryTy = llvm::StructType::create(
6589 "struct._objc_category
", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
6590 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
6593 // Global metadata structures
6595 // struct _objc_symtab {
6596 // long sel_ref_cnt;
6598 // short cls_def_cnt;
6599 // short cat_def_cnt;
6600 // char *defs[cls_def_cnt + cat_def_cnt];
6602 SymtabTy = llvm::StructType::create("struct._objc_symtab
", LongTy,
6603 SelectorPtrTy, ShortTy, ShortTy,
6604 llvm::ArrayType::get(Int8PtrTy, 0));
6605 SymtabPtrTy = llvm::PointerType::getUnqual(VMContext);
6607 // struct _objc_module {
6609 // long size; // sizeof(struct _objc_module)
6611 // struct _objc_symtab* symtab;
6613 ModuleTy = llvm::StructType::create("struct._objc_module
", LongTy, LongTy,
6614 Int8PtrTy, SymtabPtrTy);
6616 // FIXME: This is the size of the setjmp buffer and should be target
6617 // specific. 18 is what's used on 32-bit X86.
6618 uint64_t SetJmpBufferSize = 18;
6621 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
6623 ExceptionDataTy = llvm::StructType::create(
6624 "struct._objc_exception_data
",
6625 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
6628ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(
6629 CodeGen::CodeGenModule &cgm)
6630 : ObjCCommonTypesHelper(cgm) {
6631 // struct _method_list_t {
6632 // uint32_t entsize; // sizeof(struct _objc_method)
6633 // uint32_t method_count;
6634 // struct _objc_method method_list[method_count];
6637 llvm::StructType::create("struct.__method_list_t
", IntTy, IntTy,
6638 llvm::ArrayType::get(MethodTy, 0));
6639 // struct method_list_t *
6640 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6642 // struct _protocol_t {
6644 // const char * const protocol_name;
6645 // const struct _protocol_list_t * protocol_list; // super protocols
6646 // const struct method_list_t * const instance_methods;
6647 // const struct method_list_t * const class_methods;
6648 // const struct method_list_t *optionalInstanceMethods;
6649 // const struct method_list_t *optionalClassMethods;
6650 // const struct _prop_list_t * properties;
6651 // const uint32_t size; // sizeof(struct _protocol_t)
6652 // const uint32_t flags; // = 0
6653 // const char ** extendedMethodTypes;
6654 // const char *demangledName;
6655 // const struct _prop_list_t * class_properties;
6658 ProtocolnfABITy = llvm::StructType::create(
6659 "struct._protocol_t
", ObjectPtrTy, Int8PtrTy,
6660 llvm::PointerType::getUnqual(VMContext), MethodListnfABIPtrTy,
6661 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
6662 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
6665 // struct _protocol_t*
6666 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6668 // struct _protocol_list_t {
6669 // long protocol_count; // Note, this is 32/64 bit
6670 // struct _protocol_t *[protocol_count];
6672 ProtocolListnfABITy = llvm::StructType::create(
6673 {LongTy, llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)},
6674 "struct._objc_protocol_list
");
6676 // struct _objc_protocol_list*
6677 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6680 // unsigned [long] int *offset; // pointer to ivar offset location
6683 // uint32_t alignment;
6686 IvarnfABITy = llvm::StructType::create(
6687 "struct._ivar_t
", llvm::PointerType::getUnqual(VMContext), Int8PtrTy,
6688 Int8PtrTy, IntTy, IntTy);
6690 // struct _ivar_list_t {
6691 // uint32 entsize; // sizeof(struct _ivar_t)
6693 // struct _iver_t list[count];
6696 llvm::StructType::create("struct._ivar_list_t
", IntTy, IntTy,
6697 llvm::ArrayType::get(IvarnfABITy, 0));
6699 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6701 // struct _class_ro_t {
6702 // uint32_t const flags;
6703 // uint32_t const instanceStart;
6704 // uint32_t const instanceSize;
6705 // uint32_t const reserved; // only when building for 64bit targets
6706 // const uint8_t * const ivarLayout;
6707 // const char *const name;
6708 // const struct _method_list_t * const baseMethods;
6709 // const struct _objc_protocol_list *const baseProtocols;
6710 // const struct _ivar_list_t *const ivars;
6711 // const uint8_t * const weakIvarLayout;
6712 // const struct _prop_list_t * const properties;
6715 // FIXME. Add 'reserved' field in 64bit abi mode!
6716 ClassRonfABITy = llvm::StructType::create(
6717 "struct._class_ro_t
", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6718 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6719 Int8PtrTy, PropertyListPtrTy);
6721 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6722 ImpnfABITy = CGM.DefaultPtrTy;
6724 // struct _class_t {
6725 // struct _class_t *isa;
6726 // struct _class_t * const superclass;
6729 // struct class_ro_t *ro;
6732 ClassnfABITy = llvm::StructType::create(
6733 {llvm::PointerType::getUnqual(VMContext),
6734 llvm::PointerType::getUnqual(VMContext), CachePtrTy,
6735 llvm::PointerType::getUnqual(VMContext),
6736 llvm::PointerType::getUnqual(VMContext)},
6739 // LLVM for struct _class_t *
6740 ClassnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6742 // struct _category_t {
6743 // const char * const name;
6744 // struct _class_t *const cls;
6745 // const struct _method_list_t * const instance_methods;
6746 // const struct _method_list_t * const class_methods;
6747 // const struct _protocol_list_t * const protocols;
6748 // const struct _prop_list_t * const properties;
6749 // const struct _prop_list_t * const class_properties;
6750 // const uint32_t size;
6752 CategorynfABITy = llvm::StructType::create(
6753 "struct._category_t
", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6754 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6755 PropertyListPtrTy, IntTy);
6757 // New types for nonfragile abi messaging.
6758 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6759 ASTContext &Ctx = CGM.getContext();
6761 // MessageRefTy - LLVM for:
6762 // struct _message_ref_t {
6767 // First the clang type for struct _message_ref_t
6768 RecordDecl *RD = RecordDecl::Create(
6769 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6770 SourceLocation(), &Ctx.Idents.get("_message_ref_t
"));
6771 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6772 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
6774 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6775 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6776 false, ICIS_NoInit));
6777 RD->completeDefinition();
6779 MessageRefCTy = Ctx.getCanonicalTagType(RD);
6780 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6781 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
6783 // MessageRefPtrTy - LLVM for struct _message_ref_t*
6784 MessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6786 // SuperMessageRefTy - LLVM for:
6787 // struct _super_message_ref_t {
6788 // SUPER_IMP messenger;
6791 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t
",
6792 ImpnfABITy, SelectorPtrTy);
6794 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6795 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6797 // struct objc_typeinfo {
6798 // const void** vtable; // objc_ehtype_vtable + 2
6799 // const char* name; // c++ typeinfo string
6802 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo
",
6803 llvm::PointerType::getUnqual(VMContext),
6804 Int8PtrTy, ClassnfABIPtrTy);
6805 EHTypePtrTy = llvm::PointerType::getUnqual(VMContext);
6808llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
6809 FinishNonFragileABIModule();
6814void CGObjCNonFragileABIMac::AddModuleClassList(
6815 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6816 StringRef SectionName) {
6817 unsigned NumClasses = Container.size();
6822 SmallVector<llvm::Constant *, 8> Symbols(NumClasses);
6823 for (unsigned i = 0; i < NumClasses; i++)
6824 Symbols[i] = Container[i];
6826 llvm::Constant *Init = llvm::ConstantArray::get(
6827 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Symbols.size()), Symbols);
6829 // Section name is obtained by calling GetSectionName, which returns
6830 // sections in the __DATA segment on MachO.
6831 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6832 SectionName.starts_with("__DATA
")) &&
6833 "SectionName expected to start with __DATA on
MachO");
6834 llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6835 CGM.getModule(), Init->getType(), false,
6836 llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6837 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
6838 GV->setSection(SectionName);
6839 CGM.addCompilerUsedGlobal(GV);
6842void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6843 // nonfragile abi has no module definition.
6845 // Build list of all implemented class addresses in array
6846 // L_OBJC_LABEL_CLASS_$.
6848 for (unsigned i = 0, NumClasses = ImplementedClasses.size(); i < NumClasses;
6850 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6852 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6853 // We are implementing a weak imported interface. Give it external linkage
6854 if (ID->isWeakImported() && !IMP->isWeakImported()) {
6855 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6856 DefinedMetaClasses[i]->setLinkage(
6857 llvm::GlobalVariable::ExternalLinkage);
6862 DefinedClasses, "OBJC_LABEL_CLASS_$
",
6863 GetSectionName("__objc_classlist
", "regular,no_dead_strip
"));
6866 DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$
",
6867 GetSectionName("__objc_nlclslist
", "regular,no_dead_strip
"));
6869 // Build list of all implemented category addresses in array
6870 // L_OBJC_LABEL_CATEGORY_$.
6871 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$
",
6872 GetSectionName("__objc_catlist
", "regular,no_dead_strip
"));
6874 DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$
",
6875 GetSectionName("__objc_catlist2
", "regular,no_dead_strip
"));
6877 DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$
",
6878 GetSectionName("__objc_nlcatlist
", "regular,no_dead_strip
"));
6887bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6888 // At various points we've experimented with using vtable-based
6889 // dispatch for all methods.
6890 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
6891 case CodeGenOptions::Legacy:
6893 case CodeGenOptions::NonLegacy:
6895 case CodeGenOptions::Mixed:
6899 // If so, see whether this selector is in the white-list of things which must
6900 // use the new dispatch convention. We lazily build a dense set for this.
6901 if (VTableDispatchMethods.empty()) {
6902 VTableDispatchMethods.insert(GetNullarySelector("alloc
"));
6903 VTableDispatchMethods.insert(GetNullarySelector("class"));
6904 VTableDispatchMethods.insert(GetNullarySelector("self
"));
6905 VTableDispatchMethods.insert(GetNullarySelector("isFlipped
"));
6906 VTableDispatchMethods.insert(GetNullarySelector("length"));
6907 VTableDispatchMethods.insert(GetNullarySelector("count
"));
6909 // These are vtable-based if GC is disabled.
6910 // Optimistically use vtable dispatch for hybrid compiles.
6911 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
6912 VTableDispatchMethods.insert(GetNullarySelector("retain
"));
6913 VTableDispatchMethods.insert(GetNullarySelector("release
"));
6914 VTableDispatchMethods.insert(GetNullarySelector("autorelease
"));
6917 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone
"));
6918 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass
"));
6919 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector
"));
6920 VTableDispatchMethods.insert(GetUnarySelector("objectForKey
"));
6921 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex
"));
6922 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString
"));
6923 VTableDispatchMethods.insert(GetUnarySelector("isEqual
"));
6925 // These are vtable-based if GC is enabled.
6926 // Optimistically use vtable dispatch for hybrid compiles.
6927 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6928 VTableDispatchMethods.insert(GetNullarySelector("hash
"));
6929 VTableDispatchMethods.insert(GetUnarySelector("addObject
"));
6931 // "countByEnumeratingWithState:objects:count
"
6932 const IdentifierInfo *KeyIdents[] = {
6933 &CGM.getContext().Idents.get("countByEnumeratingWithState
"),
6934 &CGM.getContext().Idents.get("objects
"),
6935 &CGM.getContext().Idents.get("count
")};
6936 VTableDispatchMethods.insert(
6937 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6941 return VTableDispatchMethods.count(Sel);
6959llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
6960 unsigned flags, unsigned InstanceStart, unsigned InstanceSize,
6961 const ObjCImplementationDecl *ID) {
6962 std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
6964 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6965 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6967 bool hasMRCWeak = false;
6968 if (CGM.getLangOpts().ObjCAutoRefCount)
6969 flags |= NonFragileABI_Class_CompiledByARC;
6970 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6971 flags |= NonFragileABI_Class_HasMRCWeakIvars;
6973 ConstantInitBuilder builder(CGM);
6974 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6976 values.addInt(ObjCTypes.IntTy, flags);
6977 values.addInt(ObjCTypes.IntTy, InstanceStart);
6978 values.addInt(ObjCTypes.IntTy, InstanceSize);
6979 values.add((flags & NonFragileABI_Class_Meta)
6980 ? GetIvarLayoutName(nullptr, ObjCTypes)
6981 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6982 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6984 // const struct _method_list_t * const baseMethods;
6985 SmallVector<const ObjCMethodDecl *, 16> methods;
6986 if (flags & NonFragileABI_Class_Meta) {
6987 for (const auto *MD : ID->class_methods())
6988 if (!MD->isDirectMethod())
6989 methods.push_back(MD);
6991 for (const auto *MD : ID->instance_methods())
6992 if (!MD->isDirectMethod())
6993 methods.push_back(MD);
6996 llvm::Constant *MethListPtr = emitMethodList(
6997 ID->getObjCRuntimeNameAsString(),
6998 (flags & NonFragileABI_Class_Meta) ? MethodListType::ClassMethods
6999 : MethodListType::InstanceMethods,
7002 const PointerAuthSchema &MethListSchema =
7003 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
7004 if (!MethListPtr->isNullValue())
7005 values.addSignedPointer(MethListPtr, MethListSchema, GlobalDecl(),
7008 values.add(MethListPtr);
7010 const ObjCInterfaceDecl *OID = ID->getClassInterface();
7011 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer
");
7012 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_
" +
7013 OID->getObjCRuntimeNameAsString(),
7014 OID->all_referenced_protocol_begin(),
7015 OID->all_referenced_protocol_end()));
7017 if (flags & NonFragileABI_Class_Meta) {
7018 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
7019 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
7020 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
7021 ID->getObjCRuntimeNameAsString(),
7022 ID, ID->getClassInterface(), ObjCTypes, true));
7024 values.add(EmitIvarList(ID));
7025 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
7026 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_
" +
7027 ID->getObjCRuntimeNameAsString(),
7028 ID, ID->getClassInterface(), ObjCTypes, false));
7031 llvm::SmallString<64> roLabel;
7032 llvm::raw_svector_ostream(roLabel)
7033 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_
"
7034 : "_OBJC_CLASS_RO_$_
")
7037 return finishAndCreateGlobal(values, roLabel, CGM);
7050llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassObject(
7051 const ObjCInterfaceDecl *CI, bool isMetaclass, llvm::Constant *IsAGV,
7052 llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV,
7053 bool HiddenVisibility) {
7054 ConstantInitBuilder builder(CGM);
7055 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
7056 const PointerAuthOptions &PointerAuthOpts = CGM.getCodeGenOpts().PointerAuth;
7057 values.addSignedPointer(IsAGV, PointerAuthOpts.ObjCIsaPointers, GlobalDecl(),
7060 values.addSignedPointer(SuperClassGV, PointerAuthOpts.ObjCSuperPointers,
7061 GlobalDecl(), QualType());
7063 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
7065 values.add(ObjCEmptyCacheVar);
7066 values.add(ObjCEmptyVtableVar);
7068 values.addSignedPointer(ClassRoGV, PointerAuthOpts.ObjCClassROPointers,
7069 GlobalDecl(), QualType());
7071 llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
7072 GetClassGlobal(CI, isMetaclass, ForDefinition));
7073 values.finishAndSetAsInitializer(GV);
7075 if (CGM.getTriple().isOSBinFormatMachO())
7076 GV->setSection("__DATA, __objc_data
");
7077 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
7078 if (!CGM.getTriple().isOSBinFormatCOFF())
7079 if (HiddenVisibility)
7080 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7081 if (CGM.getCodeGenOpts().ObjCMsgSendClassSelectorStubs && !isMetaclass)
7082 CGM.addUsedGlobal(GV);
7086bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
7087 const ObjCImplDecl *OD) const {
7088 return OD->getClassMethod(GetNullarySelector("load
")) != nullptr ||
7089 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
7090 OD->hasAttr<ObjCNonLazyClassAttr>();
7093void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
7094 uint32_t &InstanceStart,
7095 uint32_t &InstanceSize) {
7096 const ASTRecordLayout &RL =
7097 CGM.getContext().getASTObjCInterfaceLayout(OID->getClassInterface());
7099 // InstanceSize is really instance end.
7100 InstanceSize = RL.getDataSize().getQuantity();
7102 // If there are no fields, the start is the same as the end.
7103 if (!RL.getFieldCount())
7104 InstanceStart = InstanceSize;
7106 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
7109static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
7111 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
7112 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
7113 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
7115 const VarDecl *VD = nullptr;
7116 for (const auto *Result : DC->lookup(&II))
7117 if ((VD = dyn_cast<VarDecl>(Result)))
7121 return llvm::GlobalValue::DLLImportStorageClass;
7122 if (VD->hasAttr<DLLExportAttr>())
7123 return llvm::GlobalValue::DLLExportStorageClass;
7124 if (VD->hasAttr<DLLImportAttr>())
7125 return llvm::GlobalValue::DLLImportStorageClass;
7126 return llvm::GlobalValue::DefaultStorageClass;
7129void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
7130 if (!ObjCEmptyCacheVar) {
7131 ObjCEmptyCacheVar = new llvm::GlobalVariable(
7132 CGM.getModule(), ObjCTypes.CacheTy, false,
7133 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache
");
7134 if (CGM.getTriple().isOSBinFormatCOFF())
7135 ObjCEmptyCacheVar->setDLLStorageClass(
7136 getStorage(CGM, "_objc_empty_cache
"));
7138 // Only OS X with deployment version <10.9 use the empty vtable symbol
7139 const llvm::Triple &Triple = CGM.getTarget().getTriple();
7140 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
7141 ObjCEmptyVtableVar = new llvm::GlobalVariable(
7142 CGM.getModule(), ObjCTypes.ImpnfABITy, false,
7143 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable
");
7145 ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.DefaultPtrTy);
7148 // FIXME: Is this correct (that meta class size is never computed)?
7149 uint32_t InstanceStart =
7150 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
7151 uint32_t InstanceSize = InstanceStart;
7152 uint32_t flags = NonFragileABI_Class_Meta;
7154 llvm::Constant *SuperClassGV, *IsAGV;
7156 const auto *CI = ID->getClassInterface();
7157 assert(CI && "CGObjCNonFragileABIMac::GenerateClass -
class is 0
");
7159 // Build the flags for the metaclass.
7160 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
7161 ? !CI->hasAttr<DLLExportAttr>()
7162 : CI->getVisibility() == HiddenVisibility;
7164 flags |= NonFragileABI_Class_Hidden;
7166 // FIXME: why is this flag set on the metaclass?
7167 // ObjC metaclasses have no fields and don't really get constructed.
7168 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
7169 flags |= NonFragileABI_Class_HasCXXStructors;
7170 if (!ID->hasNonZeroConstructors())
7171 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
7174 if (!CI->getSuperClass()) {
7176 flags |= NonFragileABI_Class_Root;
7178 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
7179 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
7181 // Has a root. Current class is not a root.
7182 const ObjCInterfaceDecl *Root = ID->getClassInterface();
7183 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
7186 const auto *Super = CI->getSuperClass();
7187 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
7188 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
7191 llvm::GlobalVariable *CLASS_RO_GV =
7192 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
7194 llvm::GlobalVariable *MetaTClass = BuildClassObject(
7195 CI, /*metaclass*/ true, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
7196 CGM.setGVProperties(MetaTClass, CI);
7197 DefinedMetaClasses.push_back(MetaTClass);
7199 // Metadata for the class
7202 flags |= NonFragileABI_Class_Hidden;
7204 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
7205 flags |= NonFragileABI_Class_HasCXXStructors;
7207 // Set a flag to enable a runtime optimization when a class has
7208 // fields that require destruction but which don't require
7209 // anything except zero-initialization during construction. This
7210 // is most notably true of __strong and __weak types, but you can
7211 // also imagine there being C++ types with non-trivial default
7212 // constructors that merely set all fields to null.
7213 if (!ID->hasNonZeroConstructors())
7214 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
7217 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
7218 flags |= NonFragileABI_Class_Exception;
7220 if (!CI->getSuperClass()) {
7221 flags |= NonFragileABI_Class_Root;
7222 SuperClassGV = nullptr;
7224 // Has a root. Current class is not a root.
7225 const auto *Super = CI->getSuperClass();
7226 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
7229 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
7231 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
7233 llvm::GlobalVariable *ClassMD =
7234 BuildClassObject(CI, /*metaclass*/ false, MetaTClass, SuperClassGV,
7235 CLASS_RO_GV, classIsHidden);
7236 CGM.setGVProperties(ClassMD, CI);
7237 DefinedClasses.push_back(ClassMD);
7238 ImplementedClasses.push_back(CI);
7240 // Determine if this class is also "non-lazy
".
7241 if (ImplementationIsNonLazy(ID))
7242 DefinedNonLazyClasses.push_back(ClassMD);
7244 // Force the definition of the EHType if necessary.
7245 if (flags & NonFragileABI_Class_Exception)
7246 (void)GetInterfaceEHType(CI, ForDefinition);
7247 // Make sure method definition entries are all clear for next implementation.
7248 MethodDefinitions.clear();
7260CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
7261 const ObjCProtocolDecl *PD) {
7263 // This routine is called for @protocol only. So, we must build definition
7264 // of protocol's meta-data (not a reference to it!)
7265 assert(!PD->isNonRuntimeProtocol() &&
7266 "attempting to get a protocol ref to a
static protocol.
");
7267 llvm::Constant *Init = GetOrEmitProtocol(PD);
7269 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_
");
7270 ProtocolName += PD->getObjCRuntimeNameAsString();
7272 CharUnits Align = CGF.getPointerAlign();
7274 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
7276 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
7277 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
7278 llvm::GlobalValue::WeakAnyLinkage, Init,
7281 GetSectionName("__objc_protorefs
", "coalesced,no_dead_strip
"));
7282 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7283 PTGV->setAlignment(Align.getAsAlign());
7284 if (!CGM.getTriple().isOSBinFormatMachO())
7285 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
7286 CGM.addUsedGlobal(PTGV);
7287 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
7302void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
7303 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
7304 const char *Prefix = "_OBJC_$_CATEGORY_
";
7306 llvm::SmallString<64> ExtCatName(Prefix);
7307 ExtCatName += Interface->getObjCRuntimeNameAsString();
7308 ExtCatName += "_$_
";
7309 ExtCatName += OCD->getNameAsString();
7311 ConstantInitBuilder builder(CGM);
7312 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
7313 values.add(GetClassName(OCD->getIdentifier()->getName()));
7314 // meta-class entry symbol
7315 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
7316 std::string listName =
7317 (Interface->getObjCRuntimeNameAsString() + "_$_
" + OCD->getName()).str();
7319 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
7320 SmallVector<const ObjCMethodDecl *, 8> classMethods;
7321 for (const auto *MD : OCD->methods()) {
7322 if (MD->isDirectMethod())
7324 if (MD->isInstanceMethod()) {
7325 instanceMethods.push_back(MD);
7327 classMethods.push_back(MD);
7331 llvm::Constant *InstanceMethodList = emitMethodList(
7332 listName, MethodListType::CategoryInstanceMethods, instanceMethods);
7333 const PointerAuthSchema &MethListSchema =
7334 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
7335 if (!InstanceMethodList->isNullValue())
7336 values.addSignedPointer(InstanceMethodList, MethListSchema, GlobalDecl(),
7339 values.add(InstanceMethodList);
7341 llvm::Constant *ClassMethodList = emitMethodList(
7342 listName, MethodListType::CategoryClassMethods, classMethods);
7343 if (!ClassMethodList->isNullValue())
7344 values.addSignedPointer(ClassMethodList, MethListSchema, GlobalDecl(),
7347 values.add(ClassMethodList);
7349 // Keep track of whether we have actual metadata to emit.
7350 bool isEmptyCategory =
7351 InstanceMethodList->isNullValue() && ClassMethodList->isNullValue();
7353 const ObjCCategoryDecl *Category =
7354 Interface->FindCategoryDeclaration(OCD->getIdentifier());
7356 SmallString<256> ExtName;
7357 llvm::raw_svector_ostream(ExtName)
7358 << Interface->getObjCRuntimeNameAsString() << "_$_
" << OCD->getName();
7360 EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_
" +
7361 Interface->getObjCRuntimeNameAsString() + "_$_
" +
7362 Category->getName(),
7363 Category->protocol_begin(), Category->protocol_end());
7364 auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_
" + ExtName.str(),
7365 OCD, Category, ObjCTypes, false);
7366 auto classPropertyList =
7367 EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" + ExtName.str(), OCD,
7368 Category, ObjCTypes, true);
7369 values.add(protocolList);
7370 values.add(propertyList);
7371 values.add(classPropertyList);
7372 isEmptyCategory &= protocolList->isNullValue() &&
7373 propertyList->isNullValue() &&
7374 classPropertyList->isNullValue();
7376 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
7377 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
7378 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
7381 if (isEmptyCategory) {
7382 // Empty category, don't emit any metadata.
7384 MethodDefinitions.clear();
7389 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
7390 values.addInt(ObjCTypes.IntTy, Size);
7392 llvm::GlobalVariable *GCATV =
7393 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
7394 CGM.addCompilerUsedGlobal(GCATV);
7395 if (Interface->hasAttr<ObjCClassStubAttr>())
7396 DefinedStubCategories.push_back(GCATV);
7398 DefinedCategories.push_back(GCATV);
7400 // Determine if this category is also "non-lazy
".
7401 if (ImplementationIsNonLazy(OCD))
7402 DefinedNonLazyCategories.push_back(GCATV);
7403 // method definition entries must be clear for next implementation.
7404 MethodDefinitions.clear();
7416void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
7417 const ObjCMethodDecl *MD,
7419 auto method = builder.beginStruct(ObjCTypes.MethodTy);
7420 method.add(GetMethodVarName(MD->getSelector()));
7421 method.add(GetMethodVarType(MD));
7424 // Protocol methods have no implementation. So, this entry is always NULL.
7425 method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
7427 llvm::Function *fn = GetMethodDefinition(MD);
7428 assert(fn && "no definition
for method?
");
7429 if (const PointerAuthSchema &Schema =
7430 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListFunctionPointers) {
7431 llvm::Constant *Bitcast =
7432 llvm::ConstantExpr::getBitCast(fn, ObjCTypes.Int8PtrProgramASTy);
7433 method.addSignedPointer(Bitcast, Schema, GlobalDecl(), QualType());
7438 method.finishAndAddTo(builder);
7449llvm::Constant *CGObjCNonFragileABIMac::emitMethodList(
7450 Twine name, MethodListType kind, ArrayRef<const ObjCMethodDecl *> methods) {
7451 // Return null for empty list.
7452 if (methods.empty())
7453 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
7458 case MethodListType::CategoryInstanceMethods:
7459 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_
";
7460 forProtocol = false;
7462 case MethodListType::CategoryClassMethods:
7463 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_
";
7464 forProtocol = false;
7466 case MethodListType::InstanceMethods:
7467 prefix = "_OBJC_$_INSTANCE_METHODS_
";
7468 forProtocol = false;
7470 case MethodListType::ClassMethods:
7471 prefix = "_OBJC_$_CLASS_METHODS_
";
7472 forProtocol = false;
7475 case MethodListType::ProtocolInstanceMethods:
7476 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_
";
7479 case MethodListType::ProtocolClassMethods:
7480 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_
";
7483 case MethodListType::OptionalProtocolInstanceMethods:
7484 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_
";
7487 case MethodListType::OptionalProtocolClassMethods:
7488 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_
";
7493 ConstantInitBuilder builder(CGM);
7494 auto values = builder.beginStruct();
7496 // sizeof(struct _objc_method)
7497 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
7498 values.addInt(ObjCTypes.IntTy, Size);
7500 values.addInt(ObjCTypes.IntTy, methods.size());
7501 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
7502 for (auto MD : methods)
7503 emitMethodConstant(methodArray, MD, forProtocol);
7504 methodArray.finishAndAddTo(values);
7506 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
7507 CGM.addCompilerUsedGlobal(GV);
7513llvm::GlobalVariable *
7514CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
7515 const ObjCIvarDecl *Ivar) {
7516 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
7517 llvm::SmallString<64> Name("OBJC_IVAR_$_
");
7518 Name += Container->getObjCRuntimeNameAsString();
7520 Name += Ivar->getName();
7521 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
7522 if (!IvarOffsetGV) {
7523 IvarOffsetGV = new llvm::GlobalVariable(
7524 CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
7525 llvm::GlobalValue::ExternalLinkage, nullptr, Name.str());
7526 if (CGM.getTriple().isOSBinFormatCOFF()) {
7527 bool IsPrivateOrPackage =
7528 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
7529 Ivar->getAccessControl() == ObjCIvarDecl::Package;
7531 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
7533 if (ContainingID->hasAttr<DLLImportAttr>())
7534 IvarOffsetGV->setDLLStorageClass(
7535 llvm::GlobalValue::DLLImportStorageClass);
7536 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
7537 IvarOffsetGV->setDLLStorageClass(
7538 llvm::GlobalValue::DLLExportStorageClass);
7541 return IvarOffsetGV;
7545CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
7546 const ObjCIvarDecl *Ivar,
7547 unsigned long int Offset) {
7548 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
7549 IvarOffsetGV->setInitializer(
7550 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
7551 IvarOffsetGV->setAlignment(
7552 CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
7554 if (!CGM.getTriple().isOSBinFormatCOFF()) {
7555 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
7556 // as well (i.e., in ObjCIvarOffsetVariable).
7557 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
7558 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
7559 ID->getVisibility() == HiddenVisibility)
7560 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7562 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
7565 // If ID's layout is known, then make the global constant. This serves as a
7566 // useful assertion: we'll never use this variable to calculate ivar offsets,
7567 // so if the runtime tries to patch it then we should crash.
7568 if (isClassLayoutKnownStatically(ID))
7569 IvarOffsetGV->setConstant(true);
7571 if (CGM.getTriple().isOSBinFormatMachO())
7572 IvarOffsetGV->setSection("__DATA, __objc_ivar
");
7573 return IvarOffsetGV;
7594CGObjCNonFragileABIMac::EmitIvarList(const ObjCImplementationDecl *ID) {
7596 ConstantInitBuilder builder(CGM);
7597 auto ivarList = builder.beginStruct();
7598 ivarList.addInt(ObjCTypes.IntTy,
7599 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
7600 auto ivarCountSlot = ivarList.addPlaceholder();
7601 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
7603 const ObjCInterfaceDecl *OID = ID->getClassInterface();
7604 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface
");
7606 // FIXME. Consolidate this with similar code in GenerateClass.
7608 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD;
7609 IVD = IVD->getNextIvar()) {
7610 // Ignore unnamed bit-fields.
7611 if (!IVD->getDeclName())
7614 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
7615 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
7616 ComputeIvarBaseOffset(CGM, ID, IVD)));
7617 ivar.add(GetMethodVarName(IVD->getIdentifier()));
7618 ivar.add(GetMethodVarType(IVD));
7619 llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType());
7620 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
7622 CGM.getContext().getPreferredTypeAlign(IVD->getType().getTypePtr()) >>
7624 Align = llvm::Log2_32(Align);
7625 ivar.addInt(ObjCTypes.IntTy, Align);
7626 // NOTE. Size of a bitfield does not match gcc's, because of the
7627 // way bitfields are treated special in each. But I am told that
7628 // 'size' for bitfield ivars is ignored by the runtime so it does
7629 // not matter. If it matters, there is enough info to get the
7631 ivar.addInt(ObjCTypes.IntTy, Size);
7632 ivar.finishAndAddTo(ivars);
7634 // Return null for empty list.
7635 if (ivars.empty()) {
7638 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
7641 auto ivarCount = ivars.size();
7642 ivars.finishAndAddTo(ivarList);
7643 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
7645 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_
";
7646 llvm::GlobalVariable *GV = finishAndCreateGlobal(
7647 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
7648 CGM.addCompilerUsedGlobal(GV);
7653CGObjCNonFragileABIMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
7654 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
7656 assert(!PD->isNonRuntimeProtocol() &&
7657 "attempting to GetOrEmit a non-runtime protocol
");
7659 // We use the initializer as a marker of whether this is a forward
7660 // reference or not. At module finalization we add the empty
7661 // contents for protocols which were referenced but never defined.
7662 llvm::SmallString<64> Protocol;
7663 llvm::raw_svector_ostream(Protocol)
7664 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7666 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
7667 false, llvm::GlobalValue::ExternalLinkage,
7669 if (!CGM.getTriple().isOSBinFormatMachO())
7670 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
7697CGObjCNonFragileABIMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
7698 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
7700 // Early exit if a defining object has already been generated.
7701 if (Entry && Entry->hasInitializer())
7704 // Use the protocol definition, if there is one.
7705 assert(PD->hasDefinition() &&
7706 "emitting protocol metadata without definition
");
7707 PD = PD->getDefinition();
7709 auto methodLists = ProtocolMethodLists::get(PD);
7711 ConstantInitBuilder builder(CGM);
7712 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
7715 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7716 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
7717 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_
" +
7718 PD->getObjCRuntimeNameAsString(),
7719 PD->protocol_begin(), PD->protocol_end()));
7720 values.add(methodLists.emitMethodList(
7721 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
7722 values.add(methodLists.emitMethodList(
7723 this, PD, ProtocolMethodLists::RequiredClassMethods));
7724 values.add(methodLists.emitMethodList(
7725 this, PD, ProtocolMethodLists::OptionalInstanceMethods));
7726 values.add(methodLists.emitMethodList(
7727 this, PD, ProtocolMethodLists::OptionalClassMethods));
7729 EmitPropertyList("_OBJC_$_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7730 nullptr, PD, ObjCTypes, false));
7732 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
7733 values.addInt(ObjCTypes.IntTy, Size);
7734 values.addInt(ObjCTypes.IntTy, 0);
7735 values.add(EmitProtocolMethodTypes(
7736 "_OBJC_$_PROTOCOL_METHOD_TYPES_
" + PD->getObjCRuntimeNameAsString(),
7737 methodLists.emitExtendedTypesArray(this), ObjCTypes));
7739 // const char *demangledName;
7740 values.addNullPointer(ObjCTypes.Int8PtrTy);
7742 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
7743 PD->getObjCRuntimeNameAsString(),
7744 nullptr, PD, ObjCTypes, true));
7747 // Already created, fix the linkage and update the initializer.
7748 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
7749 values.finishAndSetAsInitializer(Entry);
7751 llvm::SmallString<64> symbolName;
7752 llvm::raw_svector_ostream(symbolName)
7753 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7755 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7757 llvm::GlobalValue::WeakAnyLinkage);
7758 if (!CGM.getTriple().isOSBinFormatMachO())
7759 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
7761 Protocols[PD->getIdentifier()] = Entry;
7763 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7764 CGM.addUsedGlobal(Entry);
7766 // Use this protocol meta-data to build protocol list table in section
7767 // __DATA, __objc_protolist
7768 llvm::SmallString<64> ProtocolRef;
7769 llvm::raw_svector_ostream(ProtocolRef)
7770 << "_OBJC_LABEL_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7772 llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
7773 CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false,
7774 llvm::GlobalValue::WeakAnyLinkage, Entry, ProtocolRef);
7775 if (!CGM.getTriple().isOSBinFormatMachO())
7776 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7778 CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
7780 GetSectionName("__objc_protolist
", "coalesced,no_dead_strip
"));
7781 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7782 CGM.addUsedGlobal(PTGV);
7794llvm::Constant *CGObjCNonFragileABIMac::EmitProtocolList(
7795 Twine Name, ObjCProtocolDecl::protocol_iterator begin,
7796 ObjCProtocolDecl::protocol_iterator end) {
7797 // Just return null for empty protocol lists
7798 auto Protocols = GetRuntimeProtocolList(begin, end);
7799 if (Protocols.empty())
7800 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7802 SmallVector<llvm::Constant *, 16> ProtocolRefs;
7803 ProtocolRefs.reserve(Protocols.size());
7805 for (const auto *PD : Protocols)
7806 ProtocolRefs.push_back(GetProtocolRef(PD));
7808 // If all of the protocols in the protocol list are objc_non_runtime_protocol
7810 if (ProtocolRefs.size() == 0)
7811 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7813 // FIXME: We shouldn't need to do this lookup here, should we?
7814 SmallString<256> TmpName;
7815 Name.toVector(TmpName);
7816 llvm::GlobalVariable *GV =
7817 CGM.getModule().getGlobalVariable(TmpName.str(), true);
7821 ConstantInitBuilder builder(CGM);
7822 auto values = builder.beginStruct();
7823 auto countSlot = values.addPlaceholder();
7825 // A null-terminated array of protocols.
7826 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7827 for (auto const &proto : ProtocolRefs)
7829 auto count = array.size();
7830 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
7832 array.finishAndAddTo(values);
7833 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
7835 GV = finishAndCreateGlobal(values, Name, CGM);
7836 CGM.addCompilerUsedGlobal(GV);
7846LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
7847 CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue,
7848 const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) {
7849 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
7850 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
7851 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
7856CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7857 const ObjCInterfaceDecl *Interface,
7858 const ObjCIvarDecl *Ivar) {
7859 llvm::Value *IvarOffsetValue;
7860 if (isClassLayoutKnownStatically(Interface)) {
7861 IvarOffsetValue = llvm::ConstantInt::get(
7862 ObjCTypes.IvarOffsetVarTy,
7863 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7865 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7866 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7867 CGF.getSizeAlign(), "ivar
");
7868 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7869 cast<llvm::LoadInst>(IvarOffsetValue)
7870 ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7871 llvm::MDNode::get(VMContext, {}));
7874 // This could be 32bit int or 64bit integer depending on the architecture.
7875 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
7876 // as this is what caller always expects.
7877 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7878 IvarOffsetValue = CGF.Builder.CreateIntCast(
7879 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv
");
7880 return IvarOffsetValue;
7883static void appendSelectorForMessageRefTable(std::string &buffer,
7884 Selector selector) {
7885 if (selector.isUnarySelector()) {
7886 buffer += selector.getNameForSlot(0);
7890 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7891 buffer += selector.getNameForSlot(i);
7906RValue CGObjCNonFragileABIMac::EmitVTableMessageSend(
7907 CodeGenFunction &CGF, ReturnValueSlot returnSlot, QualType resultType,
7908 Selector selector, llvm::Value *arg0, QualType arg0Type, bool isSuper,
7909 const CallArgList &formalArgs, const ObjCMethodDecl *method) {
7910 // Compute the actual arguments.
7913 // First argument: the receiver / super-call structure.
7915 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7916 args.add(RValue::get(arg0), arg0Type);
7918 // Second argument: a pointer to the message ref structure. Leave
7919 // the actual argument value blank for now.
7920 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
7922 llvm::append_range(args, formalArgs);
7924 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
7926 NullReturnState nullReturn;
7928 // Find the function to call and the mangled name for the message
7929 // ref structure. Using a different mangled name wouldn't actually
7930 // be a problem; it would just be a waste.
7932 // The runtime currently never uses vtable dispatch for anything
7933 // except normal, non-super message-sends.
7934 // FIXME: don't use this for that.
7935 llvm::FunctionCallee fn = nullptr;
7936 std::string messageRefName("_
");
7937 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
7939 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7940 messageRefName += "objc_msgSendSuper2_stret_fixup
";
7942 nullReturn.init(CGF, arg0);
7943 fn = ObjCTypes.getMessageSendStretFixupFn();
7944 messageRefName += "objc_msgSend_stret_fixup
";
7946 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7947 fn = ObjCTypes.getMessageSendFpretFixupFn();
7948 messageRefName += "objc_msgSend_fpret_fixup
";
7951 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7952 messageRefName += "objc_msgSendSuper2_fixup
";
7954 fn = ObjCTypes.getMessageSendFixupFn();
7955 messageRefName += "objc_msgSend_fixup
";
7958 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend
");
7959 messageRefName += '_';
7961 // Append the selector name, except use underscores anywhere we
7962 // would have used colons.
7963 appendSelectorForMessageRefTable(messageRefName, selector);
7965 llvm::GlobalVariable *messageRef =
7966 CGM.getModule().getGlobalVariable(messageRefName);
7968 // Build the message ref structure.
7969 ConstantInitBuilder builder(CGM);
7970 auto values = builder.beginStruct();
7971 values.add(cast<llvm::Constant>(fn.getCallee()));
7972 values.add(GetMethodVarName(selector));
7973 messageRef = values.finishAndCreateGlobal(
7974 messageRefName, CharUnits::fromQuantity(16),
7975 /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage);
7976 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
7977 messageRef->setSection(GetSectionName("__objc_msgrefs
", "coalesced
"));
7980 bool requiresnullCheck = false;
7981 if (CGM.getLangOpts().ObjCAutoRefCount && method)
7982 for (const auto *ParamDecl : method->parameters()) {
7983 if (ParamDecl->isDestroyedInCallee()) {
7984 if (!nullReturn.NullBB)
7985 nullReturn.init(CGF, arg0);
7986 requiresnullCheck = true;
7992 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7993 ObjCTypes.MessageRefTy, CGF.getPointerAlign());
7995 // Update the message ref argument.
7996 args[1].setRValue(RValue::get(mref, CGF));
7998 // Load the function to call from the message ref table.
7999 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
8000 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn
");
8002 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
8003 CGCallee callee(CGCalleeInfo(), calleePtr);
8005 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
8006 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
8007 requiresnullCheck ? method : nullptr);
8011CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
8012 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
8013 Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs,
8014 const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) {
8015 return isVTableDispatchedSelector(Sel)
8016 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, Receiver,
8017 CGF.getContext().getObjCIdType(), false,
8019 : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
8020 CGF.getContext().getObjCIdType(), false,
8021 CallArgs, Method, Class, ObjCTypes);
8025CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
8027 ForDefinition_t isForDefinition) {
8029 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
8030 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
8031 isForDefinition, ID->isWeakImported(),
8033 CGM.getTriple().isOSBinFormatCOFF() &&
8034 ID->hasAttr<DLLImportAttr>());
8038CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
8039 ForDefinition_t IsForDefinition,
8040 bool Weak, bool DLLImport) {
8041 llvm::GlobalValue::LinkageTypes L =
8042 Weak ? llvm::GlobalValue::ExternalWeakLinkage
8043 : llvm::GlobalValue::ExternalLinkage;
8045 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
8046 if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
8047 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
8051 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
8054 GV->replaceAllUsesWith(NewGV);
8055 GV->eraseFromParent();
8058 CGM.getModule().insertGlobalVariable(GV);
8061 assert(GV->getLinkage() == L);
8066CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
8067 llvm::Constant *ClassGV =
8068 GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
8070 if (!ID->hasAttr<ObjCClassStubAttr>())
8073 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
8075 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
8076 // must set the least significant bit set to 1.
8077 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
8078 return llvm::ConstantExpr::getPtrAdd(ClassGV, Idx);
8082CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
8083 const ObjCInterfaceDecl *ID,
8084 llvm::GlobalVariable *Entry) {
8085 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
8086 // Classrefs pointing at Objective-C stub classes must be loaded by calling
8087 // a special runtime function.
8088 return CGF.EmitRuntimeCall(ObjCTypes.getLoadClassrefFn(), Entry,
8089 "load_classref_result
");
8092 CharUnits Align = CGF.getPointerAlign();
8093 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
8096llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(
8097 CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) {
8098 llvm::GlobalVariable *&Entry = ClassReferences[II];
8101 llvm::Constant *ClassGV;
8103 ClassGV = GetClassGlobalForClassRef(ID);
8105 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
8107 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
8108 "classref was emitted with the wrong
type?
");
8111 std::string SectionName =
8112 GetSectionName("__objc_classrefs
", "regular,no_dead_strip
");
8113 Entry = new llvm::GlobalVariable(
8114 CGM.getModule(), ClassGV->getType(), false,
8115 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
8116 "OBJC_CLASSLIST_REFERENCES_$_
");
8117 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
8118 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
8119 Entry->setSection(SectionName);
8121 CGM.addCompilerUsedGlobal(Entry);
8124 return EmitLoadOfClassRef(CGF, ID, Entry);
8127llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
8128 const ObjCInterfaceDecl *ID) {
8129 // If the class has the objc_runtime_visible attribute, we need to
8130 // use the Objective-C runtime to get the class.
8131 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
8132 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
8134 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
8138CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
8139 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
8140 return EmitClassRefFromId(CGF, II, nullptr);
8144CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
8145 const ObjCInterfaceDecl *ID) {
8146 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
8149 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
8150 std::string SectionName =
8151 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
8152 Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
8153 llvm::GlobalValue::PrivateLinkage, ClassGV,
8154 "OBJC_CLASSLIST_SUP_REFS_$_
");
8155 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
8156 Entry->setSection(SectionName);
8157 CGM.addCompilerUsedGlobal(Entry);
8160 return EmitLoadOfClassRef(CGF, ID, Entry);
8166llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(
8167 CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, bool Weak) {
8168 CharUnits Align = CGF.getPointerAlign();
8169 llvm::GlobalVariable *&Entry = MetaClassReferences[ID->getIdentifier()];
8171 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
8172 std::string SectionName =
8173 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
8174 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
8175 false, llvm::GlobalValue::PrivateLinkage,
8176 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_
");
8177 Entry->setAlignment(Align.getAsAlign());
8178 Entry->setSection(SectionName);
8179 CGM.addCompilerUsedGlobal(Entry);
8182 return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
8187llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
8188 const ObjCInterfaceDecl *ID) {
8189 if (ID->isWeakImported()) {
8190 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
8192 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
8193 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
8196 return EmitClassRef(CGF, ID);
8202CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(
8203 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
8204 Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl,
8205 llvm::Value *Receiver, bool IsClassMessage,
8206 const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) {
8208 // Create and init a super structure; this is a (receiver, class)
8209 // pair we will pass to objc_msgSendSuper.
8210 RawAddress ObjCSuper = CGF.CreateTempAlloca(
8211 ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super
");
8213 llvm::Value *ReceiverAsObject =
8214 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
8215 CGF.Builder.CreateStore(ReceiverAsObject,
8216 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
8218 // If this is a class message the metaclass is passed as the target.
8219 llvm::Value *Target;
8221 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
8223 Target = EmitSuperClassRef(CGF, Class);
8225 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
8227 llvm::Type *ClassTy =
8228 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
8229 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
8230 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
8232 return (isVTableDispatchedSelector(Sel))
8233 ? EmitVTableMessageSend(
8234 CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
8235 ObjCTypes.SuperPtrCTy, true, CallArgs, Method)
8236 : EmitMessageSend(CGF, Return, ResultType, Sel,
8237 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
8238 true, CallArgs, Method, Class, ObjCTypes);
8241llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
8243 Address Addr = EmitSelectorAddr(Sel);
8245 llvm::LoadInst *LI = CGF.Builder.CreateLoad(Addr);
8246 LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
8247 llvm::MDNode::get(VMContext, {}));
8251ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
8252 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
8253 CharUnits Align = CGM.getPointerAlign();
8255 std::string SectionName =
8256 GetSectionName("__objc_selrefs
", "literal_pointers,no_dead_strip
");
8257 Entry = new llvm::GlobalVariable(
8258 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
8259 getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
8260 "OBJC_SELECTOR_REFERENCES_
");
8261 Entry->setExternallyInitialized(true);
8262 Entry->setSection(SectionName);
8263 Entry->setAlignment(Align.getAsAlign());
8264 CGM.addCompilerUsedGlobal(Entry);
8267 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
8273void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
8274 llvm::Value *src, Address dst,
8275 llvm::Value *ivarOffset) {
8276 llvm::Type *SrcTy = src->getType();
8277 if (!isa<llvm::PointerType>(SrcTy)) {
8278 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
8279 assert(Size <= 8 && "does
not support size > 8
");
8280 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
8281 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
8282 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
8284 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
8285 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
8286 ObjCTypes.PtrObjectPtrTy);
8287 llvm::Value *args[] = {src, dstVal, ivarOffset};
8288 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
8294void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
8295 CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) {
8296 llvm::Type *SrcTy = src->getType();
8297 if (!isa<llvm::PointerType>(SrcTy)) {
8298 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
8299 assert(Size <= 8 && "does
not support size > 8
");
8300 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
8301 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
8302 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
8304 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
8305 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
8306 ObjCTypes.PtrObjectPtrTy);
8307 llvm::Value *args[] = {src, dstVal};
8308 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
8312void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
8313 CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
8314 llvm::Value *Size) {
8315 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
8316 SrcPtr.emitRawPointer(CGF), Size};
8317 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
8324CGObjCNonFragileABIMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
8325 Address AddrWeakObj) {
8326 llvm::Type *DestTy = AddrWeakObj.getElementType();
8327 llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
8328 AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
8329 llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(
8330 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread
");
8331 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
8338void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
8339 llvm::Value *src, Address dst) {
8340 llvm::Type *SrcTy = src->getType();
8341 if (!isa<llvm::PointerType>(SrcTy)) {
8342 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
8343 assert(Size <= 8 && "does
not support size > 8
");
8344 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
8345 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
8346 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
8348 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
8349 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
8350 ObjCTypes.PtrObjectPtrTy);
8351 llvm::Value *args[] = {src, dstVal};
8352 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
8359void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
8360 llvm::Value *src, Address dst,
8362 llvm::Type *SrcTy = src->getType();
8363 if (!isa<llvm::PointerType>(SrcTy)) {
8364 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
8365 assert(Size <= 8 && "does
not support size > 8
");
8366 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
8367 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
8368 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
8370 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
8371 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
8372 ObjCTypes.PtrObjectPtrTy);
8373 llvm::Value *args[] = {src, dstVal};
8375 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
8378 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
8379 "threadlocalassign
");
8382void CGObjCNonFragileABIMac::EmitSynchronizedStmt(
8383 CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) {
8384 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
8385 ObjCTypes.getSyncExitFn());
8388llvm::Constant *CGObjCNonFragileABIMac::GetEHType(QualType T) {
8389 // There's a particular fixed type info for 'id'.
8390 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
8391 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id
");
8393 IDEHType = new llvm::GlobalVariable(
8394 CGM.getModule(), ObjCTypes.EHTypeTy, false,
8395 llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id
");
8396 if (CGM.getTriple().isOSBinFormatCOFF())
8397 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id
"));
8402 // All other types should be Objective-C interface pointer types.
8403 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
8406 const ObjCInterfaceType *IT = PT->getInterfaceType();
8407 assert(IT && "Invalid
@catch type.
");
8409 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
8412void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
8413 const ObjCAtTryStmt &S) {
8414 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
8415 ObjCTypes.getObjCEndCatchFn(),
8416 ObjCTypes.getExceptionRethrowFn());
8420void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
8421 const ObjCAtThrowStmt &S,
8422 bool ClearInsertionPoint) {
8423 if (const Expr *ThrowExpr = S.getThrowExpr()) {
8424 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
8425 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
8426 llvm::CallBase *Call =
8427 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
8428 Call->setDoesNotReturn();
8430 llvm::CallBase *Call =
8431 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
8432 Call->setDoesNotReturn();
8435 CGF.Builder.CreateUnreachable();
8436 if (ClearInsertionPoint)
8437 CGF.Builder.ClearInsertionPoint();
8441CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
8442 ForDefinition_t IsForDefinition) {
8443 llvm::GlobalVariable *&Entry = EHTypeReferences[ID->getIdentifier()];
8444 StringRef ClassName = ID->getObjCRuntimeNameAsString();
8446 // If we don't need a definition, return the entry if found or check
8447 // if we use an external reference.
8448 if (!IsForDefinition) {
8452 // If this type (or a super class) has the __objc_exception__
8453 // attribute, emit an external reference.
8454 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
8455 std::string EHTypeName = ("OBJC_EHTYPE_$_
" + ClassName).str();
8456 Entry = new llvm::GlobalVariable(
8457 CGM.getModule(), ObjCTypes.EHTypeTy, false,
8458 llvm::GlobalValue::ExternalLinkage, nullptr, EHTypeName);
8459 CGM.setGVProperties(Entry, ID);
8464 // Otherwise we need to either make a new entry or fill in the initializer.
8465 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition
");
8467 std::string VTableName = "objc_ehtype_vtable
";
8468 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
8470 VTableGV = new llvm::GlobalVariable(
8471 CGM.getModule(), ObjCTypes.Int8PtrTy, false,
8472 llvm::GlobalValue::ExternalLinkage, nullptr, VTableName);
8473 if (CGM.getTriple().isOSBinFormatCOFF())
8474 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
8477 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
8478 llvm::Constant *VTablePtr = llvm::ConstantExpr::getInBoundsGetElementPtr(
8479 VTableGV->getValueType(), VTableGV, VTableIdx);
8481 ConstantInitBuilder builder(CGM);
8482 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
8483 const PointerAuthSchema &TypeInfoSchema =
8484 CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer;
8485 values.addSignedPointer(VTablePtr, TypeInfoSchema, GlobalDecl(), QualType());
8487 values.add(GetClassName(ClassName));
8488 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
8490 llvm::GlobalValue::LinkageTypes L = IsForDefinition
8491 ? llvm::GlobalValue::ExternalLinkage
8492 : llvm::GlobalValue::WeakAnyLinkage;
8494 values.finishAndSetAsInitializer(Entry);
8495 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
8497 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_
" + ClassName,
8498 CGM.getPointerAlign(),
8499 /*constant*/ false, L);
8500 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
8501 CGM.setGVProperties(Entry, ID);
8503 assert(Entry->getLinkage() == L);
8505 if (!CGM.getTriple().isOSBinFormatCOFF())
8506 if (ID->getVisibility() == HiddenVisibility)
8507 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
8509 if (IsForDefinition)
8510 if (CGM.getTriple().isOSBinFormatMachO())
8511 Entry->setSection("__DATA,__objc_const
");
8518CodeGen::CGObjCRuntime *
8519CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
8520 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
8521 case ObjCRuntime::FragileMacOSX:
8522 return new CGObjCMac(CGM);
8524 case ObjCRuntime::MacOSX:
8525 case ObjCRuntime::iOS:
8526 case ObjCRuntime::WatchOS:
8527 return new CGObjCNonFragileABIMac(CGM);
8529 case ObjCRuntime::GNUstep:
8530 case ObjCRuntime::GCC:
8531 case ObjCRuntime::ObjFW:
8532 llvm_unreachable("these runtimes are
not Mac runtimes
");
8534 llvm_unreachable("bad runtime
");
Defines the clang::ASTContext interface.
@ FragileABI_Class_Meta
Is a meta-class.
@ FragileABI_Class_Hidden
Has hidden visibility.
@ FragileABI_Class_Factory
Apparently: is not a meta-class.
@ FragileABI_Class_HasCXXStructors
Has a non-trivial constructor or destructor.
@ FragileABI_Class_HasMRCWeakIvars
Class implementation was compiled under MRC and has MRC weak ivars.
@ FragileABI_Class_CompiledByARC
Class implementation was compiled under ARC.
static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, bool pointee=false)
static bool hasWeakMember(QualType type)
static std::string getBlockLayoutInfoString(const SmallVectorImpl< CGObjCCommonMac::RUN_SKIP > &RunSkipBlockVars, bool HasCopyDisposeHelpers)
static llvm::StringMapEntry< llvm::GlobalVariable * > & GetConstantStringEntry(llvm::StringMap< llvm::GlobalVariable * > &Map, const StringLiteral *Literal, unsigned &StringLength)
static llvm::GlobalValue::LinkageTypes getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section)
static void addIfPresent(llvm::DenseSet< llvm::Value * > &S, Address V)
@ kCFTaggedObjectID_Integer
static void PushProtocolProperties(llvm::SmallPtrSet< const IdentifierInfo *, 16 > &PropertySet, SmallVectorImpl< const ObjCPropertyDecl * > &Properties, const ObjCProtocolDecl *Proto, bool IsClassProperty)
static llvm::GlobalVariable * finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, const llvm::Twine &Name, CodeGenModule &CGM)
A helper function to create an internal or private global variable.
static bool hasMRCWeakIvars(CodeGenModule &CGM, const ObjCImplementationDecl *ID)
For compatibility, we only want to set the "HasMRCWeakIvars" flag (and actually fill in a layout stri...
@ NonFragileABI_Class_HasCXXDestructorOnly
Class has non-trivial destructors, but zero-initialization is okay.
@ NonFragileABI_Class_Hidden
Has hidden visibility.
@ NonFragileABI_Class_HasCXXStructors
Has a non-trivial constructor or destructor.
@ NonFragileABI_Class_Exception
Has the exception attribute.
@ NonFragileABI_Class_HasIvarReleaser
(Obsolete) ARC-specific: this class has a .release_ivars method
@ NonFragileABI_Class_Root
Is a root class.
@ NonFragileABI_Class_Meta
Is a meta-class.
@ NonFragileABI_Class_HasMRCWeakIvars
Class implementation was compiled under MRC and has MRC weak ivars.
@ NonFragileABI_Class_CompiledByARC
Class implementation was compiled under ARC.
static llvm::Constant * getConstantGEP(llvm::LLVMContext &VMContext, llvm::GlobalVariable *C, unsigned idx0, unsigned idx1)
getConstantGEP() - Help routine to construct simple GEPs.
static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID)
hasObjCExceptionAttribute - Return true if this class or any super class has the objc_exception attri...
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalParamType(QualType T) const
Return the canonical parameter type corresponding to the specific potentially non-canonical one.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getObjCClassType() const
Represents the Objective-C Class type.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
SelectorTable & Selectors
CanQualType getCanonicalSizeType() const
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getObjCIdType() const
Represents the Objective-CC id type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getObjCClassRedefinitionType() const
Retrieve the type that Class has been defined to, which may be different from the built-in Class if C...
QualType getObjCIdRedefinitionType() const
Retrieve the type that id has been defined to, which may be different from the built-in id if id has ...
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getNSUIntegerType() const
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
QualType withConst() const
Retrieves a version of this type with const applied.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
unsigned getIndex() const
CharUnits getOffset() const
const BlockDecl * getBlockDecl() const
llvm::StructType * StructureType
CharUnits BlockHeaderForcedGapOffset
bool NeedsCopyDispose
True if the block has captures that would necessitate custom copy or dispose helper functions if the ...
CharUnits BlockHeaderForcedGapSize
const Capture & getCapture(const VarDecl *var) const
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
Implements runtime-specific code generation functions.
static void destroyCalleeDestroyedArguments(CodeGenFunction &CGF, const ObjCMethodDecl *method, const CallArgList &callArgs)
Destroy the callee-destroyed arguments of the given method, if it has any.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::Type * ConvertType(QualType T)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
JumpDest ReturnBlock
ReturnBlock - Unified return block.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
RawAddress getNormalCleanupDestSlot()
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
RawAddress NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
const llvm::DataLayout & getDataLayout() const
bool ReturnTypeUsesFP2Ret(QualType ResultType)
Return true iff the given type uses 'fp2ret' when used as a return type.
const llvm::Triple & getTriple() const
bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI)
Return true iff the given type uses an argument slot when 'sret' is used as a return type.
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal)
Return a pointer to a constant CFString object for the given string.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD)
Objective-C methods are C functions with some implicit parameters.
llvm::Constant * getPointer() const
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
llvm::Value * getPointer() const
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
clang::ObjCRuntime ObjCRuntime
std::string ObjCConstantIntegerNumberClass
std::string ObjCConstantDoubleNumberClass
std::string ObjCConstantArrayClass
std::string ObjCConstantStringClass
std::string ObjCConstantDictionaryClass
std::string ObjCConstantFloatNumberClass
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
const Expr * getThrowExpr() const
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
catch_range catch_stmts()
method_range methods() const
prop_range properties() const
const ObjCInterfaceDecl * getClassInterface() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for class's metadata.
ObjCInterfaceDecl * getSuperClass() const
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ImplicitParamDecl * getSelfDecl() const
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDirectMethod() const
True if the method is tagged as objc_direct.
Selector getSelector() const
ImplicitParamDecl * getCmdDecl() const
QualType getReturnType() const
bool isClassMethod() const
bool isObjCQualifiedIdType() const
True if this is equivalent to 'id.
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
Represents an Objective-C protocol declaration.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for protocol's metadata.
ObjCProtocolList::iterator protocol_iterator
protocol_iterator protocol_begin() const
protocol_range protocols() const
protocol_iterator protocol_end() const
bool hasConstantEmptyCollections() const
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
bool hasConstantCFBooleans() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
bool isObjCGCStrong() const
true when Type is objc's strong.
bool isObjCGCWeak() const
true when Type is objc's weak.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
field_range fields() const
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
std::string getAsString() const
Derive the full selector name (e.g.
StringLiteral - This represents a string literal expression, e.g.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getCharWidth() const
bool isBlockPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isObjCQualifiedIdType() const
bool isObjCIdType() const
bool isObjCObjectPointerType() const
bool isObjCQualifiedClassType() const
bool isObjCClassType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * castAsCanonical() const
Return this type's canonical type cast to the specified type.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, BlockDecl > blockDecl
Matches block declarations.
bool LT(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
bool isa(CodeGen::Address addr)
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
@ Result
The result type of a method or function.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
@ Type
The name was classified as a type.
U cast(CodeGen::Address addr)
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
CLINKAGE int printf(__constant const char *st,...) __attribute__((format(printf
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
llvm::BasicBlock * getBlock() const
llvm::IntegerType * Int64Ty
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const
llvm::PointerType * DefaultPtrTy
PointerAuthSchema ObjCIsaPointers
The ABI for Objective-C isa pointers.